diff --git a/cloud/gcp/api/gcloud-api-key-restrictions-missing.yaml b/cloud/gcp/api/gcloud-api-key-restrictions-missing.yaml new file mode 100644 index 00000000000..ef3895bdaef --- /dev/null +++ b/cloud/gcp/api/gcloud-api-key-restrictions-missing.yaml @@ -0,0 +1,72 @@ +id: gcloud-api-key-restrictions-missing + +info: + name: Missing API Key API Restrictions + author: princechaddha + severity: medium + description: | + Ensure that the usage of your Google Cloud API keys is restricted to specific APIs such as Cloud Key Management Service (KMS) API, Cloud Storage API, Cloud Monitoring API, and Cloud Logging API. All Google Cloud API keys that are being used for production applications should use API restrictions. + impact: | + API keys without specific API restrictions can be used to access any GCP API, potentially leading to unauthorized access and misuse of resources. Implementing API restrictions helps in limiting the scope of API keys to intended services only. + remediation: | + Apply API restrictions to each Google Cloud API key to limit their usage to specific APIs. This can be managed through the Google Cloud Console or using the gcloud command-line tool. + reference: + - https://cloud.google.com/api-keys/docs/restricting-api-keys + tags: cloud,devops,gcp,gcloud,api-keys,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let apiKey of iterate(template.apiKeys)){ + set("apiKeyUid", apiKey) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud alpha services api-keys list --project=$projectId --format="json(uid)" + + extractors: + - type: json + name: apiKeys + internal: true + json: + - '.[].uid' + + - engine: + - sh + - bash + source: | + gcloud alpha services api-keys describe $apiKeyUid --format="json(restrictions)" + + matchers: + - type: word + part: body + words: + - 'null' + + extractors: + - type: dsl + dsl: + - '"Unrestricted API Key: " + apiKeyUid + " in Project: " + projectId' diff --git a/cloud/gcp/api/gcloud-api-key-unrestricted.yaml b/cloud/gcp/api/gcloud-api-key-unrestricted.yaml new file mode 100644 index 00000000000..f0d93384059 --- /dev/null +++ b/cloud/gcp/api/gcloud-api-key-unrestricted.yaml @@ -0,0 +1,71 @@ +id: gcloud-api-key-unrestricted + +info: + name: Unrestricted API Key Usage + author: princechaddha + severity: medium + description: | + Ensure that the use of Google Cloud API keys is limited to trusted and reliable hosts, HTTP referrers, or applications. An API key application restriction manages the authorization of websites, IP addresses, or Android/iOS mobile applications that can employ your API key. It is crucial that all API keys used in production employ host and application restrictions. By enforcing these restrictions, you can reduce the impact that a compromised API key can have on your applications. + impact: | + API keys without restrictions can be used unrestrictedly, which might lead to unauthorized access and misuse, potentially exposing sensitive data or services. + remediation: | + Apply restrictions to all production API keys to specify the allowed websites, IP addresses, or mobile applications that can use each key, to mitigate potential abuse. + reference: + - https://cloud.google.com/docs/authentication/api-keys#restricting_api_keys + tags: cloud,devops,gcp,gcloud,api-keys,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let uid of iterate(template.uids)){ + set("uid", uid) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud alpha services api-keys list --project $projectId --format="json(uid)" + + extractors: + - type: json + name: uids + internal: true + json: + - '.[].uid' + + - engine: + - sh + - bash + source: | + gcloud alpha services api-keys describe $uid --format="json(restrictions)" + + matchers: + - type: word + words: + - 'null' + + extractors: + - type: dsl + dsl: + - '"Unrestricted API Key: " + uid + " in Project: " + projectId' diff --git a/cloud/gcp/api/gcloud-api-keys-inactive-services.yaml b/cloud/gcp/api/gcloud-api-keys-inactive-services.yaml new file mode 100644 index 00000000000..3eae79d9964 --- /dev/null +++ b/cloud/gcp/api/gcloud-api-keys-inactive-services.yaml @@ -0,0 +1,60 @@ +id: gcloud-api-keys-inactive-services + +info: + name: API Keys Should Only Exist for Active Services + author: princechaddha + severity: low + description: | + Ensure that your Google Cloud projects are using the standard authentication flow as the preferred method for authentication, rather than relying on API keys. API keys are simple encrypted strings that can be used when calling certain APIs which don't need to access private user data. API keys should be exclusively employed for active services when alternative authentication methods are not accessible, otherwise deleted. + impact: | + Using API keys for inactive services can expose your applications to unnecessary security risks. It is advisable to employ standard authentication methods and ensure that API keys are used judiciously and only for active services. + remediation: | + Review and ensure that API keys are only configured for active services. Delete or disable API keys associated with inactive or unnecessary services to minimize security risks. + reference: + - https://cloud.google.com/docs/authentication/api-keys + tags: cloud,devops,gcp,gcloud,api-keys,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud alpha services api-keys list --project=$projectId --format="json(uid)" + + matchers: + - type: word + words: + - 'uid' + + extractors: + - type: json + name: uid + internal: true + json: + - '.[].uid' + + - type: dsl + dsl: + - '"Inactive API Key found: UID: " + uid + " in Project: " + projectId' diff --git a/cloud/gcp/api/gcloud-critical-service-apis-disabled.yaml b/cloud/gcp/api/gcloud-critical-service-apis-disabled.yaml new file mode 100644 index 00000000000..a999e90f05e --- /dev/null +++ b/cloud/gcp/api/gcloud-critical-service-apis-disabled.yaml @@ -0,0 +1,53 @@ +id: gcloud-critical-service-apis-disabled + +info: + name: Critical Service APIs Not Enabled + author: princechaddha + severity: critical + description: | + Ensure that critical service APIs are enabled for your GCP projects to gain access to essential functionalities and services provided by Google Cloud Platform (GCP), manage your project resources efficiently, enhance the security of your cloud environment, and track your usage and billing. The critical service APIs include, but are not limited to, Identity and Access Management (IAM) API, Compute Engine API, Cloud Storage, Google Cloud Pub/Sub API, Cloud Key Management Service (KMS) API, and Cloud Logging API. + impact: | + Disabling critical service APIs can prevent the proper management and security of GCP resources, potentially leading to service disruptions or compromised security. + remediation: | + Enable the necessary service APIs via the GCP Console or the gcloud command-line tool for each project where they are found to be disabled. + reference: + - https://cloud.google.com/service-usage/docs/enable-disable + tags: cloud,devops,gcp,gcloud,api-management,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud services list --project $projectId --enabled --filter=name:iam.googleapis.com --format="json" | jq '.' + + matchers: + - type: word + words: + - '[]' + + extractors: + - type: dsl + dsl: + - '"Critical API not enabled: IAM API in Project: " + projectId' diff --git a/cloud/gcp/api/gcloud-security-center-api-disabled.yaml b/cloud/gcp/api/gcloud-security-center-api-disabled.yaml new file mode 100644 index 00000000000..4c061dee358 --- /dev/null +++ b/cloud/gcp/api/gcloud-security-center-api-disabled.yaml @@ -0,0 +1,54 @@ +id: gcloud-security-center-api-disabled + +info: + name: Security Command Center API Disabled + author: princechaddha + severity: high + description: | + To access historical security findings and asset data in Security Command Center, ensure that the Security Command Center API is enabled within your Google Cloud account. If the API is not enabled, certain security features and monitoring capabilities will be unavailable. + impact: | + Disabling the Security Command Center API may limit visibility and control over security threats, leading to potential vulnerabilities and undetected risks within Google Cloud environments. + remediation: | + Enable the Security Command Center API for each Google Cloud project to maintain proper security monitoring and threat detection capabilities. This can be done through the Google Cloud Console or using the `gcloud services enable securitycenter.googleapis.com` command. + reference: + - https://cloud.google.com/security-command-center/docs/reference/rest + tags: cloud,devops,gcp,gcloud,security-center,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud services list --project $projectId --enabled --filter="name:securitycenter.googleapis.com" --format="json" + + matchers: + - type: word + words: + - '[]' + + extractors: + - type: dsl + dsl: + - '"Security Command Center API is not enabled in Project: " + projectId' diff --git a/cloud/gcp/api/gcloud-vm-os-config-disabled.yaml b/cloud/gcp/api/gcloud-vm-os-config-disabled.yaml new file mode 100644 index 00000000000..90ec468f80e --- /dev/null +++ b/cloud/gcp/api/gcloud-vm-os-config-disabled.yaml @@ -0,0 +1,54 @@ +id: gcloud-cloud-asset-disabled + +info: + name: Cloud Asset Inventory Not Enabled + author: princechaddha + severity: high + description: | + Ensure that Cloud Asset Inventory is enabled for all your GCP projects in order to efficiently manage the history and the inventory of your cloud resources. Google Cloud Asset Inventory is a fully managed metadata inventory service that allows you to view, monitor, analyze, and gain insights for your Google Cloud and Anthos assets. Cloud Asset Inventory is disabled by default in each GCP project. + impact: | + Not having Cloud Asset Inventory enabled can prevent the organization from having a managed and insightful view over its cloud resources, potentially leading to mismanagement and security risks. + remediation: | + Enable the Google Cloud Asset Inventory by activating the Cloud Asset API in each GCP project through the Google Cloud Console or using the `gcloud services enable cloudasset.googleapis.com --project ` command. + reference: + - https://cloud.google.com/asset-inventory/docs + tags: cloud,devops,gcp,gcloud,cloud-asset,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud services list --project $projectId --enabled --filter="name:cloudasset.googleapis.com" --format="json" + + matchers: + - type: word + words: + - '[]' + + extractors: + - type: dsl + dsl: + - '"OS Config service is disabled for Project: " + projectId' diff --git a/cloud/gcp/artifactregistry/gcloud-artifact-registry-public.yaml b/cloud/gcp/artifactregistry/gcloud-artifact-registry-public.yaml new file mode 100644 index 00000000000..985fc92b677 --- /dev/null +++ b/cloud/gcp/artifactregistry/gcloud-artifact-registry-public.yaml @@ -0,0 +1,73 @@ +id: gcloud-artifact-registry-public + +info: + name: Publicly Accessible Artifact Registry Repositories + author: princechaddha + severity: high + description: | + Identify any publicly accessible Artifact Registry repositories within your Google Cloud account and update their IAM policy in order to protect against unauthorized access. To deny access from anonymous and public users, remove the bindings for "allUsers" and "allAuthenticatedUsers" members from the IAM policy associated with your repository. + impact: | + Public accessibility of Artifact Registry repositories can lead to unauthorized data access or data leaks. Restricting access ensures that only authorized entities can view or manipulate the repositories. + remediation: | + Update the IAM policies for each Artifact Registry repository to remove "allUsers" and "allAuthenticatedUsers". This action will ensure that repositories are not exposed to any user on the internet or authenticated users not explicitly granted permission. + reference: + - https://cloud.google.com/artifact-registry/docs/managing/access-control + tags: cloud,devops,gcp,gcloud,artifact-registry,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let repository of iterate(template.repositories)){ + set("repositoryName", repository) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud artifacts repositories list --project $projectId --format="json(name)" + + extractors: + - type: json + name: repositories + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud artifacts repositories get-iam-policy $repositoryName --project $projectId --format=json | jq '.bindings[].members[]' + + matchers: + - type: word + words: + - 'allUsers' + - 'allAuthenticatedUsers' + condition: or + + extractors: + - type: dsl + dsl: + - '"Publicly Accessible Artifact Repository: " + repositoryName + " in Project: " + projectId' diff --git a/cloud/gcp/artifactregistry/gcloud-vuln-scan-missing.yaml b/cloud/gcp/artifactregistry/gcloud-vuln-scan-missing.yaml new file mode 100644 index 00000000000..f62a36f3d27 --- /dev/null +++ b/cloud/gcp/artifactregistry/gcloud-vuln-scan-missing.yaml @@ -0,0 +1,58 @@ +id: gcloud-vuln-scan-missing + +info: + name: Artifact Registry Vulnerability Scanning Not Enabled + author: princechaddha + severity: high + description: | + Ensure that vulnerability scanning for Google Cloud Artifact Registry repositories is enabled in order to find security weaknesses in your container images before deploying them and help prevent security breaches. + impact: | + Disabling vulnerability scanning on Artifact Registry repositories can expose your deployment to undiscovered security vulnerabilities, increasing the risk of security breaches. + remediation: | + Enable the Container Scanning API for each Artifact Registry by visiting the API & services page in the Google Cloud Console and enabling `containerscanning.googleapis.com`. + reference: + - https://cloud.google.com/artifact-registry/docs/vulnerability-scanning + tags: cloud,devops,gcp,gcloud,artifact-registry,container-scanning,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud services list --enabled --project $projectId --format="json(config.name)" + + matchers: + - type: word + words: + - 'containerscanning.googleapis.com' + negative: true + + - type: word + words: + - '"config":' + + extractors: + - type: dsl + dsl: + - '"Vulnerability Scanning not enabled for Artifact Registry in Project: " + projectId' diff --git a/cloud/gcp/bigquery/gcloud-bigquery-cmek-not-enabled.yaml b/cloud/gcp/bigquery/gcloud-bigquery-cmek-not-enabled.yaml new file mode 100644 index 00000000000..8ff2bce9814 --- /dev/null +++ b/cloud/gcp/bigquery/gcloud-bigquery-cmek-not-enabled.yaml @@ -0,0 +1,70 @@ +id: gcloud-bigquery-cmek-not-enabled + +info: + name: BigQuery Dataset Encryption with Customer-Managed Encryption Keys Not Enabled + author: princechaddha + severity: high + description: | + Ensure that all your Google Cloud BigQuery datasets are encrypted using Customer-Managed Encryption Keys (CMEKs) in order to have a more granular control over the dataset encryption/decryption process. Datasets not encrypted with CMEKs may expose sensitive data to higher risks. + impact: | + Using Google-managed keys for dataset encryption limits control over the encryption process and may not meet compliance requirements that specify encryption key management policies. + remediation: | + Update the encryption configuration of your BigQuery datasets to use Customer-Managed Encryption Keys. This can be done by setting the 'defaultEncryptionConfiguration' property of each dataset to use a 'kmsKeyName' that you manage. + reference: + - https://cloud.google.com/bigquery/docs/customer-managed-encryption + tags: cloud,devops,gcp,gcloud,bigquery,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let dataset of iterate(template.datasets)){ + set("datasetId", dataset) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + bq ls --project_id $projectId --format="prettyjson" + + extractors: + - type: json + name: datasets + internal: true + json: + - '.[] | .datasetReference.datasetId' + + - engine: + - sh + - bash + source: | + bq show --format=prettyjson $projectId:$datasetId | jq '.defaultEncryptionConfiguration.kmsKeyName' + + matchers: + - type: word + words: + - 'null' + + extractors: + - type: dsl + dsl: + - '"Dataset without CMEK: " + datasetId + " in Project: " + projectId' diff --git a/cloud/gcp/bigquery/gcloud-bigquery-cmk-not-enabled.yaml b/cloud/gcp/bigquery/gcloud-bigquery-cmk-not-enabled.yaml new file mode 100644 index 00000000000..c9e860a95d4 --- /dev/null +++ b/cloud/gcp/bigquery/gcloud-bigquery-cmk-not-enabled.yaml @@ -0,0 +1,88 @@ +id: gcloud-bigquery-cmk-not-enabled + +info: + name: BigQuery Datasets Not Encrypted with Customer-Managed Keys + author: princechaddha + severity: high + description: | + Ensure that the tables created for your Google Cloud BigQuery datasets are encrypted with Customer-Managed Keys (CMKs) to have more granular control over the data encryption/decryption process. Using CMKs allows you to create, rotate, manage, and destroy your own encryption keys using Google Cloud Key Management Service (Cloud KMS). + impact: | + If BigQuery dataset tables are not encrypted using CMKs, it limits the control over data encryption and decryption, increasing the risk of unauthorized data access. + remediation: | + Configure BigQuery dataset tables to use Customer-Managed Keys (CMKs) for encryption. This can be done in the dataset settings where you specify the encryption key managed in Google Cloud KMS. + reference: + - https://cloud.google.com/bigquery/docs/encryption-customer-managed-keys + tags: cloud,devops,gcp,gcloud,bigquery,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let dataset of iterate(template.datasets)){ + set("datasetId", dataset) + code(3) + for(let table of iterate(template.tables)){ + set("tableName", table) + code(4) + } + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + bq ls --format=prettyjson --project_id $projectId + + extractors: + - type: json + name: datasets + internal: true + json: + - '.[].datasetReference.datasetId' + + - engine: + - sh + - bash + source: | + bq ls --format=prettyjson --project_id $projectId --dataset_id $datasetId + + extractors: + - type: json + name: tables + internal: true + json: + - '.[].tableId' + + - engine: + - sh + - bash + source: | + bq show --format=prettyjson $projectId:$datasetId.$tableName | jq '.encryptionConfiguration.encryptionType' + + matchers: + - type: word + words: + - 'null' + + extractors: + - type: dsl + dsl: + - '"Table Not Encrypted with CMK: " + tableName + " in Dataset: " + datasetId + " of Project: " + projectId' diff --git a/cloud/gcp/bigquery/gcloud-bigquery-public-datasets.yaml b/cloud/gcp/bigquery/gcloud-bigquery-public-datasets.yaml new file mode 100644 index 00000000000..b11f0340d69 --- /dev/null +++ b/cloud/gcp/bigquery/gcloud-bigquery-public-datasets.yaml @@ -0,0 +1,74 @@ +id: gcloud-bigquery-public-datasets + +info: + name: Publicly Accessible BigQuery Datasets + author: princechaddha + severity: high + description: | + Ensure there are no anonymously and/or publicly accessible BigQuery datasets available within your Google Cloud Platform (GCP) account. Google Cloud BigQuery datasets have Identity and Access Management (IAM) policies configured to determine who can have access to these resources. To refuse access from anonymous and public users, remove the bindings for "allUsers" and "allAuthenticatedUsers" members from the IAM policy associated with your datasets. + impact: | + Publicly accessible BigQuery datasets can lead to unauthorized data access or data leaks. Ensuring that access is restricted helps maintain the integrity and confidentiality of your data. + remediation: | + Update the IAM policies for each BigQuery dataset to remove "allUsers" and "allAuthenticatedUsers". This action will ensure that datasets are not exposed to any user on the internet or authenticated users not explicitly granted permission. + reference: + - https://cloud.google.com/bigquery/docs/managing-dataset-access + tags: cloud,devops,gcp,gcloud,bigquery,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let datasetId of iterate(template.datasetIds)){ + set("datasetId", datasetId) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + bq ls --project_id $projectId --format=json + + extractors: + - type: json + name: datasetIds + internal: true + json: + - '.[].datasetId' + + - engine: + - sh + - bash + source: | + bq show --format=prettyjson $projectId:$datasetId | jq '.access[] | select(.role != null and (.specialGroup == "allUsers" or .specialGroup == "allAuthenticatedUsers")) | .role' + + matchers: + - type: word + words: + - 'roles/bigquery.dataViewer' + - 'roles/bigquery.dataEditor' + - 'roles/bigquery.dataOwner' + condition: or + + extractors: + - type: dsl + dsl: + - '"Publicly Accessible BigQuery Dataset: " + datasetId + " in Project: " + projectId' diff --git a/cloud/gcp/cdn/gcloud-backend-bucket-missing-storage.yaml b/cloud/gcp/cdn/gcloud-backend-bucket-missing-storage.yaml new file mode 100644 index 00000000000..5cc79d13986 --- /dev/null +++ b/cloud/gcp/cdn/gcloud-backend-bucket-missing-storage.yaml @@ -0,0 +1,88 @@ +id: gcloud-backend-bucket-missing-storage + +info: + name: Backend Buckets Referencing Missing Storage Buckets + author: princechaddha + severity: high + description: | + Ensure that your Cloud CDN backend buckets are referencing existing storage buckets in order to be able to deliver static content efficiently from the nearest edge location to users, reducing latency and improving performance. + impact: | + Referencing missing storage buckets can lead to a failure in content delivery, increased latency, and a poor user experience. + remediation: | + Verify that each backend bucket is referencing an existing storage bucket. Update the Cloud CDN backend bucket configuration to point to valid and existing storage buckets. + reference: + - https://cloud.google.com/cdn/docs/backends + tags: cloud,devops,gcp,gcloud,cdn,cloud-cdn,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let urlMap of iterate(template.urlMaps)){ + set("urlMapName", urlMap) + code(3) + for(let backendBucket of iterate(template.backendBuckets)){ + set("backendBucketName", backendBucket) + code(4) + } + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute url-maps list --project $projectId --format="json(name,defaultService)" + + extractors: + - type: json + name: urlMaps + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute backend-buckets describe $backendBucket --project $projectId --format="json(bucketName)" + + extractors: + - type: json + name: backendBuckets + internal: true + json: + - '.bucketName' + + - engine: + - sh + - bash + source: | + gcloud storage buckets describe gs://$backendBucket --project $projectId + + matchers: + - type: word + words: + - "404" + + extractors: + - type: dsl + dsl: + - '"Missing Storage Bucket for Backend Bucket: " + backendBucketName + " in URL Map: " + urlMapName + " of Project: " + projectId' diff --git a/cloud/gcp/cdn/gcloud-cdn-backend-bucket.yaml b/cloud/gcp/cdn/gcloud-cdn-backend-bucket.yaml new file mode 100644 index 00000000000..f2f628f6801 --- /dev/null +++ b/cloud/gcp/cdn/gcloud-cdn-backend-bucket.yaml @@ -0,0 +1,53 @@ +id: gcloud-cdn-backend-bucket + +info: + name: Check Cloud CDN Backend Bucket Configuration + author: princechaddha + severity: medium + description: | + Ensure that the Cloud CDN origin associated with your Google Cloud load balancer points to a backend bucket instead of a backend service in order to provide enhanced performance, cost savings, simplified management, and the ability to customize caching rules. + impact: | + Using a backend service as the Cloud CDN origin instead of a backend bucket may lead to increased costs, complex management, and suboptimal caching configurations, impacting performance and operational efficiency. + remediation: | + Reconfigure the Cloud CDN origin to point to a backend bucket instead of a backend service by modifying the associated Google Cloud load balancer's URL map. + reference: + - https://cloud.google.com/cdn/docs/using-cdn + tags: cloud,devops,gcp,gcloud,cloud-cdn,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute url-maps list --project $projectId --format="json(name,defaultService)" + + matchers: + - type: word + words: + - 'backendServices' + + extractors: + - type: dsl + dsl: + - '"Load Balancers in Project: " + projectId + " uses a backend service as CDN origin instead of a backend bucket."' diff --git a/cloud/gcp/cdn/gcloud-cdn-origin-auth-unconfigured.yaml b/cloud/gcp/cdn/gcloud-cdn-origin-auth-unconfigured.yaml new file mode 100644 index 00000000000..27d579735e7 --- /dev/null +++ b/cloud/gcp/cdn/gcloud-cdn-origin-auth-unconfigured.yaml @@ -0,0 +1,71 @@ +id: gcloud-cdn-origin-auth-unconfigured + +info: + name: Unconfigured Cloud CDN Origin Authentication + author: princechaddha + severity: medium + description: | + Ensure that Cloud CDN origins are configured to authenticate access to the content available at backend (backend buckets or backend services) using signed cookies and signed URLs. Signed cookies and URLs are designed to prevent unauthorized users from bypassing the authentication process and accessing sensitive information. + impact: | + If Cloud CDN origins are not properly configured with signed cookies and signed URLs, it could lead to unauthorized access and potential exposure of sensitive information. This configuration is essential for maintaining the security and integrity of content delivery. + remediation: | + Configure your Cloud CDN origins to use signed cookies and URLs by adding signed request keys to your backend services. This will enforce authentication on CDN-cached content, preventing unauthorized access. + reference: + - https://cloud.google.com/cdn/docs/using-signed-urls + tags: cloud,devops,gcp,gcloud,cloud-cdn,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let backendService of iterate(template.backendServices)){ + set("backendServiceName", backendService) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute backend-services list --global --project $projectId --format="json(name,enableCDN)" + + extractors: + - type: json + name: backendServices + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute backend-services describe $backendServiceName --global --format="json(cdnPolicy.signedUrlKeyNames)" + + matchers: + - type: word + words: + - 'null' + + extractors: + - type: dsl + dsl: + - '"Unconfigured Cloud CDN Origin Authentication: " + backendServiceName + " in Project: " + projectId' diff --git a/cloud/gcp/cdn/gcloud-cdn-ssl-enforcement.yaml b/cloud/gcp/cdn/gcloud-cdn-ssl-enforcement.yaml new file mode 100644 index 00000000000..8e265cca1e9 --- /dev/null +++ b/cloud/gcp/cdn/gcloud-cdn-ssl-enforcement.yaml @@ -0,0 +1,89 @@ +id: gcloud-cdn-ssl-enforcement + +info: + name: Cloud CDN SSL/TLS Not Enforced + author: princechaddha + severity: medium + description: | + Ensure that Google Cloud CDN backend bucket origins enforce HTTPS using SSL/TLS certificates in order to handle encrypted traffic. This helps to protect the integrity and confidentiality of the transmitted information. + impact: | + Not enforcing HTTPS can expose data to interception or alteration during transmission, compromising data confidentiality and integrity. + remediation: | + Configure SSL/TLS certificates for Cloud CDN backend bucket origins and ensure all traffic is served over HTTPS by adjusting the forwarding rules and url-maps. + reference: + - https://cloud.google.com/cdn/docs/using-https + tags: cloud,devops,gcp,gcloud,cloud-cdn,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let urlMap of iterate(template.urlMaps)){ + set("urlMapName", urlMap.name) + set("defaultService", urlMap.defaultService) + code(3) + for(let forwardingRule of iterate(template.forwardingRules)){ + set("forwardingRuleName", forwardingRule) + code(4) + } + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute url-maps list --project $projectId --format="json(name,defaultService)" + + extractors: + - type: json + name: urlMaps + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute forwarding-rules list --project $projectId --format="json(name)" + + extractors: + - type: json + name: forwardingRules + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute forwarding-rules describe $forwardingRuleName --project $projectId --global --format="value(portRange)" + + matchers: + - type: word + words: + - '80-80' + + extractors: + - type: dsl + dsl: + - '"SSL/TLS not enforced on Cloud CDN backend bucket origin: " + defaultService + " via URL map: " + urlMapName + " in Project: " + projectId' diff --git a/cloud/gcp/cdn/gcloud-cdn-tls-unenforced.yaml b/cloud/gcp/cdn/gcloud-cdn-tls-unenforced.yaml new file mode 100644 index 00000000000..acda2916429 --- /dev/null +++ b/cloud/gcp/cdn/gcloud-cdn-tls-unenforced.yaml @@ -0,0 +1,85 @@ +id: gcloud-cdn-tls-unenforced + +info: + name: Unenforced SSL/TLS on Cloud CDN Backend Service Origins + author: princechaddha + severity: medium + description: | + Ensure that Google Cloud CDN backend service origins are using SSL/TLS certificates to enforce HTTPS in order to manage encrypted traffic. This helps to protect the integrity and confidentiality of the transmitted information. + impact: | + If SSL/TLS certificates are not enforced, the integrity and confidentiality of the transmitted information through Cloud CDN can be compromised, leading to potential data leaks and security breaches. + remediation: | + Configure SSL/TLS certificates for your Cloud CDN backend service origins to enforce HTTPS and ensure that all communications are securely encrypted. + reference: + - https://cloud.google.com/cdn/docs/using-https + tags: cloud,devops,gcp,gcloud,cloud-cdn,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let service of iterate(template.services)){ + set("serviceName", service) + code(3) + code(4) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute url-maps list --project $projectId --format="json(name,defaultService)" + + extractors: + - type: json + name: services + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute forwarding-rules list --project $projectId + + extractors: + - type: json + name: forwardingRules + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute forwarding-rules describe $forwardingRules --global --format="value(portRange)" + + matchers: + - type: word + words: + - '80-80' + + extractors: + - type: dsl + dsl: + - '"HTTP traffic allowed without SSL/TLS on service: " + serviceName + " in Project: " + projectId' diff --git a/cloud/gcp/certificatemanager/gcloud-certificate-validity-exceeded.yaml b/cloud/gcp/certificatemanager/gcloud-certificate-validity-exceeded.yaml new file mode 100644 index 00000000000..b308c184647 --- /dev/null +++ b/cloud/gcp/certificatemanager/gcloud-certificate-validity-exceeded.yaml @@ -0,0 +1,71 @@ +id: gcloud-certificate-validity-exceeded + +info: + name: Exceeded SSL Certificate Validity Period + author: princechaddha + severity: medium + description: | + Ensure that SSL certificates managed with Google Cloud Certificate Manager don't have a validity period greater than 398 days (13 months). This is to enhance security by reducing the risk of certificate compromise and misuse, while aligning with industry standards and support from modern web browsers. + impact: | + An SSL certificate with a validity period exceeding 398 days poses a higher risk of compromise and misuse. It also fails to comply with industry standards, potentially leading to incompatibilities or security warnings in web browsers. + remediation: | + Review and adjust the renewal configurations for SSL certificates to ensure their validity periods do not exceed 398 days. + reference: + - https://cloud.google.com/certificate-manager/docs + tags: cloud,devops,gcp,gcloud,certificate-manager,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let certificate of iterate(template.certificates)){ + set("certificateName", certificate) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud certificate-manager certificates list --project $projectId --format="json(name)" + + extractors: + - type: json + name: certificates + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud certificate-manager certificates describe $certificateName --project $projectId --format="json(createTime,expireTime)" | jq '[(.expireTime | fromdateiso8601) - (.createTime | fromdateiso8601) < 34444800] | any' + + matchers: + - type: word + words: + - 'false' + + extractors: + - type: dsl + dsl: + - '"Non-compliant SSL Certificate: " + certificateName + " in Project: " + projectId + " with Expiry beyond 398 days"' diff --git a/cloud/gcp/compute/gcloud-disk-image-public-access.yaml b/cloud/gcp/compute/gcloud-disk-image-public-access.yaml new file mode 100644 index 00000000000..fb88481af98 --- /dev/null +++ b/cloud/gcp/compute/gcloud-disk-image-public-access.yaml @@ -0,0 +1,74 @@ +id: gcloud-disk-image-public-access + +info: + name: Disk Images Publicly Shared + author: princechaddha + severity: medium + description: | + Ensure that your virtual machine disk images are not publicly shared with all other Google Cloud Platform (GCP) accounts in order to avoid exposing sensitive or confidential data. If required, you can share your disk images with specific GCP accounts only, without making them public. + impact: | + Publicly shared disk images can expose sensitive application data and configurations to anyone with a Google Cloud account, potentially leading to security breaches. + remediation: | + Remove the "allAuthenticatedUsers" member from the IAM policy of affected disk images using the 'gcloud compute images remove-iam-policy-binding' command or through the Google Cloud Console. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ComputeEngine/publicly-shared-disk-images.html + - https://cloud.google.com/compute/docs/images/managing-access-custom-images + tags: cloud,devops,gcp,gcloud,compute,security,storage,disk-images,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let image of iterate(template.images)){ + image = JSON.parse(image) + set("imageName", image.name) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute images list --project $projectId --no-standard-images --format="json(name)" + + extractors: + - type: json + name: images + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute images get-iam-policy $imageName --project $projectId --format="json(bindings[].members[])" + + matchers: + - type: word + words: + - '"allAuthenticatedUsers"' + + extractors: + - type: dsl + dsl: + - '"Disk image " + imageName + " in project " + projectId + " is publicly shared with all Google Cloud users"' +# digest: 490a00463044022062203c7efa2a71b2995777a4d4dc8082ec16bf50eed5308dd5c128cd9ad9fc5a02201cdaae6dcd643d2e832ffdd35c81bc2174c26c270e72fce928cf7861d635b070:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/compute/gcloud-instance-group-autohealing-disabled.yaml b/cloud/gcp/compute/gcloud-instance-group-autohealing-disabled.yaml new file mode 100644 index 00000000000..7dcfec055e7 --- /dev/null +++ b/cloud/gcp/compute/gcloud-instance-group-autohealing-disabled.yaml @@ -0,0 +1,75 @@ +id: gcloud-instance-group-autohealing-disabled + +info: + name: Instance Group Autohealing Not Enabled + author: princechaddha + severity: high + description: | + Ensure that your Google Cloud Managed Instance Groups (MIGs) are configured with Autohealing feature. Autohealing allows re-creating virtual machine instances when they become unresponsive. Application-based autohealing improves application availability by relying on a health checking signal that detects application-specific issues such as freezing, crashing, or overloading. + impact: | + Without autohealing enabled, your application's availability may be compromised as unhealthy instances will not be automatically detected and replaced, potentially leading to service disruptions. + remediation: | + Enable autohealing for your Managed Instance Groups by configuring a health check that monitors instance health. Configure appropriate check intervals, timeouts, and healthy/unhealthy thresholds based on your application requirements. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ComputeEngine/enable-instance-group-autohealing.html + - https://cloud.google.com/compute/docs/instance-groups/autohealing-instances + tags: cloud,devops,gcp,gcloud,compute,reliability,instance-groups,autohealing,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let instanceGroup of iterate(template.instanceGroups)){ + instanceGroup = JSON.parse(instanceGroup) + set("instanceGroupName", instanceGroup.name) + set("zone", instanceGroup.location) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute instance-groups managed list --project $projectId --format="json(name,location)" + + extractors: + - type: json + name: instanceGroups + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute instance-groups managed describe $instanceGroupName --zone $zone --format="json(autoHealingPolicies[].healthCheck)" | jq '. // "null"' + + matchers: + - type: word + words: + - "null" + + extractors: + - type: dsl + dsl: + - '"Managed Instance Group " + instanceGroupName + " in zone " + zone + " of project " + projectId + " does not have autohealing enabled"' +# digest: 4a0a00473045022019e6c0db3a78c29aa85801e46d9663593e5693ecce3700ec92a55448b242370f0221009fa647c64e2d7bc3c5b021c92b9a07fd4af42b40b6227619a7ad8fa0fb297350:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/compute/gcloud-mig-no-load-balancer.yaml b/cloud/gcp/compute/gcloud-mig-no-load-balancer.yaml new file mode 100644 index 00000000000..2fdebf30a48 --- /dev/null +++ b/cloud/gcp/compute/gcloud-mig-no-load-balancer.yaml @@ -0,0 +1,74 @@ +id: gcloud-mig-no-load-balancer + +info: + name: Managed Instance Group Not Using Load Balancer + author: princechaddha + severity: low + description: | + Ensure that each Managed Instance Group is using a load balancer to act as an instance group frontend. Google Cloud Managed Instance Groups (MIGs) are groups of virtual machine (VM) instances that you control as a single entity. MIGs support rich features such as autoscaling and autohealing, load balancing, multiple zone coverage, and stateful workloads. + impact: | + Without a load balancer, traffic is not evenly distributed among instances, potentially leading to poor performance, reduced availability, and inefficient resource utilization. + remediation: | + Configure a load balancer for your Managed Instance Group by creating a backend service and associating it with your MIG. This ensures even traffic distribution and improved availability. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ComputeEngine/mig-load-balancer-check.html + - https://cloud.google.com/compute/docs/instance-groups/adding-an-instance-group-to-a-load-balancer + tags: cloud,devops,gcp,gcloud,compute,reliability,mig,load-balancer,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let instanceGroup of iterate(template.instanceGroups)){ + set("instanceGroupName", instanceGroup.name) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute instance-groups list --project $projectId --only-managed --format="json(name)" + + extractors: + - type: json + name: instanceGroups + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute backend-services list --project $projectId --format="json(backends[].group)" | grep $instanceGroupName + + matchers: + - type: word + words: + - "name" + negative: true + + extractors: + - type: dsl + dsl: + - '"Managed Instance Group " + instanceGroupName + " in project " + projectId + " is not associated with any load balancer backend service"' +# digest: 490a0046304402206a83098d94cd4b50086d378be11f5bbbf2c759a57511cd922be4797123b429fb0220153f55b1b427a770f3f870fd011866c7bee3e9ef1dda04d7388bddbb98345b13:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/compute/gcloud-mig-single-zone.yaml b/cloud/gcp/compute/gcloud-mig-single-zone.yaml new file mode 100644 index 00000000000..93a3615f137 --- /dev/null +++ b/cloud/gcp/compute/gcloud-mig-single-zone.yaml @@ -0,0 +1,73 @@ +id: gcloud-mig-single-zone + +info: + name: Managed Instance Group Not Configured for Multiple Zones + author: princechaddha + severity: low + description: | + Ensure that Managed Instance Groups (MIGs) are spread across multiple zones within a Google Cloud region for high availability and fault tolerance. Spreading application load across multiple Google Cloud zones with MIGs is crucial for enhancing the availability, resilience, and performance of your application. When you allocate your MIG instances across multiple zones, you can guarantee the continuous availability and functionality of your application even during failures or outages. + impact: | + Single-zone MIGs are vulnerable to zone-level failures, which could cause complete application downtime. This reduces availability and resilience of your applications. + remediation: | + Re-create your Managed Instance Groups with multiple zones configuration. Select "Multiple zones" for location, choose a region and desired zones, and set "Target distribution shape" to "Even" for balanced instance distribution. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ComputeEngine/mig-multiple-zones.html + - https://cloud.google.com/compute/docs/instance-groups/distributing-instances-with-regional-instance-groups + tags: cloud,devops,gcp,gcloud,compute,reliability,mig,zones,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let instanceGroup of iterate(template.instanceGroups)){ + set("instanceGroupName", instanceGroup.name) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute instance-groups list --project $projectId --only-managed --format="json(name)" + + extractors: + - type: json + name: instanceGroups + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute instance-groups managed describe $instanceGroupName --format="json(distributionPolicy.zones)" + + matchers: + - type: word + words: + - "null" + + extractors: + - type: dsl + dsl: + - '"Managed Instance Group " + instanceGroupName + " in project " + projectId + " is not configured to run instances across multiple zones"' +# digest: 4a0a00473045022100e1de26d4a2e7b665e1efaab6f0f4d3b9ef6629a00871961521d7cc1f7dd0ab9d02206815f1ff3ad342befad9bd34835e42ab7c5c9ca473c039f4ff2a3ba8e26bdc4b:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/compute/gcloud-oslogin-disabled.yaml b/cloud/gcp/compute/gcloud-oslogin-disabled.yaml new file mode 100644 index 00000000000..c86d51f9b7d --- /dev/null +++ b/cloud/gcp/compute/gcloud-oslogin-disabled.yaml @@ -0,0 +1,96 @@ +id: gcloud-oslogin-disabled + +info: + name: OS Login Not Enabled for GCP Projects + author: princechaddha + severity: low + description: | + Ensure that the OS Login feature is enabled at the Google Cloud Platform (GCP) project level in order to provide you with centralized and automated SSH key pair management. OS Login ensures that SSH keys are mapped with Google Cloud IAM users, facilitating centralized management of SSH access. + impact: | + Without OS Login enabled, managing SSH access becomes decentralized and complex, making it difficult to handle compromised SSH keys or revoke access for specific users across multiple instances. + remediation: | + Enable OS Login at the project level by setting the "enable-oslogin" metadata key to "TRUE". Note that enabling OS Login disables metadata-based SSH key configurations on all instances within the project. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ComputeEngine/enable-os-login.html + - https://cloud.google.com/compute/docs/oslogin + tags: cloud,devops,gcp,gcloud,compute,security,ssh,oslogin,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + code(3) + for(let instance of iterate(template.instances)){ + instance = JSON.parse(instance) + set("instanceName", instance.name) + set("zone", instance.zone) + code(4) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute project-info describe --project $projectId --format="json(commonInstanceMetadata.items)" | jq '.commonInstanceMetadata.items[]? | select(.key=="enable-oslogin") | .value // "null"' + + matchers: + - type: word + words: + - "FALSE" + - "null" + condition: or + + extractors: + - type: dsl + dsl: + - '"OS Login is not enabled at project level for project " + projectId' + + - engine: + - sh + - bash + source: | + gcloud compute instances list --project $projectId --format="json(name,zone.basename())" + + extractors: + - type: json + name: instances + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute instances describe $instanceName --zone $zone --project $projectId --format="json(metadata.items)" | jq '.items[]? | select(.key=="enable-oslogin") | .value // "null"' + + matchers: + - type: word + words: + - "FALSE" + - "null" + condition: or + + extractors: + - type: dsl + dsl: + - '"OS Login is not enabled for instance " + instanceName + " in zone " + zone + " of project " + projectId' +# digest: 490a0046304402202ce0504ca969da50b11725650d03da00d3c6750f4b662c036493d4ade07e13a20220586299c86cd82610f70156f505baf53fc901929b03bca472875c8ea7ee316ada:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/compute/gcloud-persistent-disks-suspended-vms.yaml b/cloud/gcp/compute/gcloud-persistent-disks-suspended-vms.yaml new file mode 100644 index 00000000000..e0c005b5f40 --- /dev/null +++ b/cloud/gcp/compute/gcloud-persistent-disks-suspended-vms.yaml @@ -0,0 +1,92 @@ +id: gcloud-persistent-disks-suspended-vms + +info: + name: Persistent Disks Attached to Suspended Virtual Machines + author: princechaddha + severity: high + description: | + Ensure that persistent disks are not attached to suspended virtual machine (VM) instances in your Google Cloud environment. Persistent disks attached to suspended VMs continue to incur charges even when the VM is not running, leading to unnecessary costs. + impact: | + Keeping persistent disks attached to suspended VMs results in ongoing storage charges without active utilization, increasing cloud infrastructure costs unnecessarily. + remediation: | + Identify and detach persistent disks from suspended VMs, or delete the disks if they are no longer needed to optimize cloud resource costs. + reference: + - https://cloud.google.com/compute/docs/disks + tags: cloud,devops,gcp,gcloud,compute,storage,cost-optimization,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let disk of iterate(template.disks)){ + disk = JSON.parse(disk) + set("diskName", disk.name) + set("zone", disk.zone) + code(3) + for(let instanceUrl of iterate(template.instanceUrls)){ + set("instanceUrl", instanceUrl) + code(4) + } + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute disks list --project $projectId --format="json(name,zone.basename())" + + extractors: + - type: json + name: disks + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute disks describe $diskName --zone $zone --project $projectId --format="json(users[])" | jq -r '.[] // "null"' + + extractors: + - type: json + name: instanceUrls + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute instances describe $instanceUrl --zone $zone --project $projectId --format="json(status)" + + matchers: + - type: word + words: + - "SUSPENDED" + - "SUSPENDING" + condition: or + + extractors: + - type: dsl + dsl: + - '"Persistent disk " + diskName + " is attached to suspended VM instance in zone " + zone + " of project " + projectId' \ No newline at end of file diff --git a/cloud/gcp/compute/gcloud-vm-automatic-restart-disabled.yaml b/cloud/gcp/compute/gcloud-vm-automatic-restart-disabled.yaml new file mode 100644 index 00000000000..b4aadbd2912 --- /dev/null +++ b/cloud/gcp/compute/gcloud-vm-automatic-restart-disabled.yaml @@ -0,0 +1,75 @@ +id: gcloud-vm-automatic-restart-disabled + +info: + name: VM Instance Automatic Restart Not Enabled + author: princechaddha + severity: medium + description: | + Ensure that Google Cloud Compute Engine service restarts automatically your virtual machine instances when they are terminated due to non-user initiated reasons such as maintenance events, hardware, and software failures. The Automatic Restart feature configures the virtual machine restart behavior when an instance crashes or it is terminated by the system. + impact: | + Without automatic restart enabled, VM instances that crash or are terminated due to system events will not automatically recover, potentially leading to extended service disruptions. + remediation: | + Enable automatic restart for your VM instances. Note that this behavior does not affect any terminations initiated by the user, such as when the instance is taken offline through a user action like calling sudo shutdown. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ComputeEngine/enable-automatic-restart.html + - https://cloud.google.com/compute/docs/instances/setting-instance-scheduling-options + tags: cloud,devops,gcp,gcloud,compute,reliability,automatic-restart,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let instance of iterate(template.instances)){ + instance = JSON.parse(instance) + set("instanceName", instance.name) + set("zone", instance.zone) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute instances list --project $projectId --format="json(name,zone.basename())" + + extractors: + - type: json + name: instances + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute instances describe $instanceName --zone $zone --project $projectId --format="json(scheduling.automaticRestart)" | jq '. // "false"' + + matchers: + - type: word + words: + - "false" + + extractors: + - type: dsl + dsl: + - '"VM instance " + instanceName + " in zone " + zone + " of project " + projectId + " does not have automatic restart enabled"' +# digest: 4a0a00473045022100b65c2875f3d2b7d8c59a176b91612dab5a33d19de1e55092cd45b8037e1079bd02205b7447b94af8f65e345a6996db086f7b92a7e5dd7a977bda00b6c1782534c455:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/compute/gcloud-vm-confidential-computing-disabled.yaml b/cloud/gcp/compute/gcloud-vm-confidential-computing-disabled.yaml new file mode 100644 index 00000000000..6b79e226fcf --- /dev/null +++ b/cloud/gcp/compute/gcloud-vm-confidential-computing-disabled.yaml @@ -0,0 +1,75 @@ +id: gcloud-vm-confidential-computing-disabled + +info: + name: VM Instance Confidential Computing Not Enabled + author: princechaddha + severity: medium + description: | + Ensure that the Confidential Computing security feature is enabled for your Google Cloud virtual machine (VM) instances in order to add protection to your sensitive data in use by keeping it encrypted in memory and using encryption keys that Google doesn't have access to. Confidential Computing is a breakthrough technology which encrypts data while it is being processed. This technology keeps data encrypted in memory, outside the CPU. + impact: | + Without Confidential Computing enabled, sensitive data in memory is not encrypted during processing, potentially exposing it to unauthorized access from the infrastructure provider or malicious insiders. + remediation: | + Re-create your VM instances with Confidential Computing enabled. Note that enabling this feature requires compatible machine types (N2D series) and may change certain instance parameters if they were set to incompatible values. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ComputeEngine/confidential-computing.html + - https://cloud.google.com/compute/confidential-vm/docs/about-cvm + tags: cloud,devops,gcp,gcloud,compute,security,confidential-computing,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let instance of iterate(template.instances)){ + instance = JSON.parse(instance) + set("instanceName", instance.name) + set("zone", instance.zone) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute instances list --project $projectId --format="json(name,zone.basename())" + + extractors: + - type: json + name: instances + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute instances describe $instanceName --zone $zone --project $projectId --format="json(confidentialInstanceConfig.enableConfidentialCompute)" | jq '. // "false"' + + matchers: + - type: word + words: + - "false" + + extractors: + - type: dsl + dsl: + - '"VM instance " + instanceName + " in zone " + zone + " of project " + projectId + " does not have Confidential Computing enabled"' +# digest: 4b0a00483046022100915677ee753b02e80b63bef69da7c0a33c8b86fb4065652d3096f8d1614f78ec022100f720d0e5499f0081e2177fd28f4ce78c5ebc4b04b1383879e64486bb80f0d7e7:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/compute/gcloud-vm-default-service-account-full-access.yaml b/cloud/gcp/compute/gcloud-vm-default-service-account-full-access.yaml new file mode 100644 index 00000000000..d0bf1cfdaed --- /dev/null +++ b/cloud/gcp/compute/gcloud-vm-default-service-account-full-access.yaml @@ -0,0 +1,77 @@ +id: gcloud-vm-default-service-account-full-access + +info: + name: VM Instance Using Default Service Account with Full API Access + author: princechaddha + severity: medium + description: | + Ensure that your Google Compute Engine instances are not configured to use the default service account with the Cloud API access scope set to "Allow full access to all Cloud APIs". The principle of least privilege (POLP), also known as the principle of least authority, is the security concept of giving the user/system/service the minimal set of permissions required to successfully perform its tasks. + impact: | + Using default service accounts with full API access violates the principle of least privilege and could allow compromised instances to make unauthorized API calls to any GCP service. + remediation: | + Either replace the default service account with a custom one having minimal permissions, or change the access scope to "Allow default access" or "Set access for each API" with only required permissions. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ComputeEngine/default-service-accounts-with-full-access-in-use.html + - https://cloud.google.com/compute/docs/access/service-accounts + tags: cloud,devops,gcp,gcloud,compute,security,iam,service-account,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let instance of iterate(template.instances)){ + instance = JSON.parse(instance) + set("instanceName", instance.name) + set("zone", instance.zone) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute instances list --project $projectId --format="json(name,zone.basename())" + + extractors: + - type: json + name: instances + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute instances describe $instanceName --zone $zone --project $projectId --format="json(serviceAccounts[].email,serviceAccounts[].scopes[])" + + matchers: + - type: word + words: + - "compute@developer.gserviceaccount.com" + - "https://www.googleapis.com/auth/cloud-platform" + condition: and + + extractors: + - type: dsl + dsl: + - '"VM instance " + instanceName + " in zone " + zone + " of project " + projectId + " is using the default Compute Engine service account with full API access"' +# digest: 4a0a00473045022100c8c31965cedfe87b79eed22bad29dcf4a16a09807a4c8f7ca6ea3cb190318caf022059deadbebb587d09a8a7e60265664fcaa99f09194d8c9ffdce5b41afd3d834db:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/compute/gcloud-vm-default-service-account.yaml b/cloud/gcp/compute/gcloud-vm-default-service-account.yaml new file mode 100644 index 00000000000..d3eb2771424 --- /dev/null +++ b/cloud/gcp/compute/gcloud-vm-default-service-account.yaml @@ -0,0 +1,75 @@ +id: gcloud-vm-default-service-account + +info: + name: VM Instance Using Default Service Account + author: princechaddha + severity: medium + description: | + Ensure that your Google Compute Engine instances are not configured to use the default Google Cloud service account in order to implement the principle of least privilege (POLP) and secure the access to your cloud resources. The default Compute Engine service account, named -compute@developer.gserviceaccount.com, is associated with the Editor role at the project level, which allows read and write access to most Google Cloud Platform (GCP) services. + impact: | + Using default service accounts with Editor role permissions violates the principle of least privilege and could allow compromised instances to access most GCP services in the project. + remediation: | + Create a new service account with minimal required permissions and update VM instances to use it instead of the default Compute Engine service account. Note that this requires stopping and restarting the instances. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ComputeEngine/default-service-accounts-in-use.html + - https://cloud.google.com/compute/docs/access/service-accounts + tags: cloud,devops,gcp,gcloud,compute,security,iam,service-account,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let instance of iterate(template.instances)){ + instance = JSON.parse(instance) + set("instanceName", instance.name) + set("zone", instance.zone) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute instances list --project $projectId --format="json(name,zone.basename())" + + extractors: + - type: json + name: instances + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute instances describe $instanceName --zone $zone --project $projectId --format="json(serviceAccounts[].email)" + + matchers: + - type: regex + regex: + - "compute@developer.gserviceaccount.com" + + extractors: + - type: dsl + dsl: + - '"VM instance " + instanceName + " in zone " + zone + " of project " + projectId + " is using the default Compute Engine service account"' +# digest: 4b0a0048304602210082c6dc7cf7eba9e4af6a0bcc46773f031ceea53fc4ae2325cc755c8515b400fb022100f6be8de14b60819841f52bfbf90a8f801bec026b3b2f074d8f9b32b975ddda3b:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/compute/gcloud-vm-deletion-protection-disabled.yaml b/cloud/gcp/compute/gcloud-vm-deletion-protection-disabled.yaml new file mode 100644 index 00000000000..875441d42b7 --- /dev/null +++ b/cloud/gcp/compute/gcloud-vm-deletion-protection-disabled.yaml @@ -0,0 +1,75 @@ +id: gcloud-vm-deletion-protection-disabled + +info: + name: VM Instance Deletion Protection Not Enabled + author: princechaddha + severity: medium + description: | + Ensure that your production Google Compute Engine instances have Deletion Protection feature enabled in order to protect them from being accidentally deleted. With Deletion Protection safety feature enabled, you have the guarantee that your VM instances cannot be accidentally deleted and make sure that your production environment remains safe. + impact: | + Without deletion protection enabled, production and mission-critical VM instances are at risk of accidental deletion, which could lead to service disruptions and data loss. + remediation: | + Enable deletion protection for your production VM instances. You can enable this feature for an existing instance regardless of its current status - stopping the instance is not required. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ComputeEngine/enable-deletion-protection.html + - https://cloud.google.com/compute/docs/instances/preventing-accidental-vm-deletion + tags: cloud,devops,gcp,gcloud,compute,security,deletion-protection,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let instance of iterate(template.instances)){ + instance = JSON.parse(instance) + set("instanceName", instance.name) + set("zone", instance.zone) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute instances list --project $projectId --format="json(name,zone.basename())" + + extractors: + - type: json + name: instances + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute instances describe $instanceName --zone $zone --project $projectId --format="json(deletionProtection)" | jq '. // "false"' + + matchers: + - type: word + words: + - "false" + + extractors: + - type: dsl + dsl: + - '"VM instance " + instanceName + " in zone " + zone + " of project " + projectId + " does not have deletion protection enabled"' +# digest: 4b0a00483046022100cbd74fddac91e6f6718e1b16166eac3f38f05a144bda08d372a8fe6532ec3596022100900faebd8a8c01be30facfa4dece312dd011dd1e4bc65a1e86855c4a6c2dd43e:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/compute/gcloud-vm-disk-autodelete-enabled.yaml b/cloud/gcp/compute/gcloud-vm-disk-autodelete-enabled.yaml new file mode 100644 index 00000000000..fa8068a3c19 --- /dev/null +++ b/cloud/gcp/compute/gcloud-vm-disk-autodelete-enabled.yaml @@ -0,0 +1,75 @@ +id: gcloud-vm-disk-autodelete-enabled + +info: + name: Auto-Delete Not Disabled for VM Instance Persistent Disks + author: princechaddha + severity: medium + description: | + Ensure that the Auto-Delete behavior rule is disabled for the persistent disks attached to your Google Cloud virtual machine (VM) instances in order to protect the VM data from being deleted and meet security and compliance requirements. When Auto-Delete is on, the persistent disks are deleted when the associated VM instance is deleted. + impact: | + With Auto-Delete enabled, persistent disks are automatically deleted when their associated VM instances are deleted, potentially causing unintended data loss for mission-critical systems. + remediation: | + Disable Auto-Delete for your VM instance persistent disks using the 'gcloud compute instances set-disk-auto-delete' command or through the Google Cloud Console. This ensures disks are retained after instance deletion. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ComputeEngine/disable-auto-delete.html + - https://cloud.google.com/compute/docs/disks/add-persistent-disk + tags: cloud,devops,gcp,gcloud,compute,security,storage,disk,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let instance of iterate(template.instances)){ + instance = JSON.parse(instance) + set("instanceName", instance.name) + set("zone", instance.zone) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute instances list --project $projectId --format="json(name,zone.basename())" + + extractors: + - type: json + name: instances + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute instances describe $instanceName --zone $zone --project $projectId --format="json(disks[].autoDelete)" + + matchers: + - type: word + words: + - '"autoDelete": true' + + extractors: + - type: dsl + dsl: + - '"VM instance " + instanceName + " in zone " + zone + " of project " + projectId + " has one or more disks with auto-delete enabled"' +# digest: 490a0046304402201dcc54da2489552a74d3253d980b17c0b740e5730f4cf0160164bc2a3e68eb0002200e19f5cae87b938ea2788829ebabaf634e08a5184982bf6319be687307289bbb:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/compute/gcloud-vm-disk-cmk-not-enabled.yaml b/cloud/gcp/compute/gcloud-vm-disk-cmk-not-enabled.yaml new file mode 100644 index 00000000000..7eaa237c05f --- /dev/null +++ b/cloud/gcp/compute/gcloud-vm-disk-cmk-not-enabled.yaml @@ -0,0 +1,91 @@ +id: gcloud-vm-disk-cmk-not-enabled + +info: + name: Virtual Machine Disk Encryption with Customer-Managed Keys Not Enabled + author: princechaddha + severity: high + description: | + Ensure that the persistent disks attached to your Google Compute Engine instances are encrypted with Customer-Managed Keys (CMKs) in order to have a fine control over your sensitive data encryption and decryption process. You can create and manage your own Customer-Managed Keys (CMKs) with Cloud Key Management Service (Cloud KMS). Cloud KMS provides secure and efficient encryption key management, controlled key rotation, and revocation mechanisms. + impact: | + Without CMK encryption, you have limited control over the encryption keys used to protect your VM disk data, potentially exposing sensitive information to unauthorized access. + remediation: | + Configure your Compute Engine persistent disks to use Customer-Managed Keys (CMKs) for encryption by specifying a Cloud KMS key during disk creation or by updating existing disks. + reference: + - https://cloud.google.com/compute/docs/disks/customer-managed-encryption + tags: cloud,devops,gcp,gcloud,compute,encryption,cmk,security,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let instance of iterate(template.instances)){ + instance = JSON.parse(instance) + set("instanceName", instance.name) + set("zone", instance.zone) + code(3) + for(let disk of iterate(template.disks)){ + set("diskName", disk) + code(4) + } + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute instances list --project $projectId --format="json(name,zone.basename())" + + extractors: + - type: json + name: instances + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute instances describe $instanceName --zone $zone --project $projectId --format="json(disks[].deviceName)" + + extractors: + - type: json + name: disks + internal: true + json: + - '.disks[].deviceName' + + - engine: + - sh + - bash + source: | + gcloud compute disks describe $diskName --zone $zone --project $projectId --format="json(diskEncryptionKey.kmsKeyName)" | jq '. // "null"' + + matchers: + - type: word + words: + - "null" + + extractors: + - type: dsl + dsl: + - '"Disk " + diskName + " attached to instance " + instanceName + " in zone " + zone + " of project " + projectId + " is not encrypted with a Customer-Managed Key (CMK)"' +# digest: 4b0a00483046022100f1197f6203d6bacfac6e08930987ea581928f4449c10082e2253b4abadf57732022100a9acbc161f0bee51adc1f22ae7191724c3e8ee33fe93fbaa2bbc41714cd06afc:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/compute/gcloud-vm-disk-csek-disabled.yaml b/cloud/gcp/compute/gcloud-vm-disk-csek-disabled.yaml new file mode 100644 index 00000000000..a358543709f --- /dev/null +++ b/cloud/gcp/compute/gcloud-vm-disk-csek-disabled.yaml @@ -0,0 +1,91 @@ +id: gcloud-vm-disk-csek-disabled + +info: + name: VM Disk Encryption with Customer-Supplied Keys Disabled + author: princechaddha + severity: high + description: | + Ensure that the disks attached to your production Google Compute Engine instances are encrypted with Customer-Supplied Encryption Keys (CSEKs) in order to have complete control over the data-at-rest encryption and decryption process, and meet strict compliance requirements. + impact: | + Without CSEK encryption, you have limited control over the encryption process of your VM disk data, which may not meet strict compliance requirements for sensitive data protection. + remediation: | + Enable Customer-Supplied Encryption Keys (CSEKs) for your VM disks by providing a valid encryption key during disk creation or instance launch. The key must be a 256-bit string encoded in RFC 4648 base64 format. + reference: + - https://cloud.google.com/compute/docs/disks/customer-supplied-encryption + tags: cloud,devops,gcp,gcloud,compute,encryption,csek,security,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let instance of iterate(template.instances)){ + instance = JSON.parse(instance) + set("instanceName", instance.name) + set("zone", instance.zone) + code(3) + for(let disk of iterate(template.disks)){ + set("diskName", disk) + code(4) + } + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute instances list --project $projectId --format="json[](name,zone.basename())" + + extractors: + - type: json + name: instances + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute instances describe $instanceName --zone $zone --project $projectId --format="json(disks[].deviceName)" + + extractors: + - type: json + name: disks + internal: true + json: + - '.disks[].deviceName' + + - engine: + - sh + - bash + source: | + gcloud compute disks describe $diskName --zone $zone --project $projectId --format="json(diskEncryptionKey)" | jq '.sha256 // "null"' + + matchers: + - type: word + words: + - "null" + + extractors: + - type: dsl + dsl: + - '"Disk " + diskName + " attached to instance " + instanceName + " in zone " + zone + " of project " + projectId + " has Customer-Supplied Encryption Keys (CSEKs) disabled"' +# digest: 4b0a00483046022100d91652a863ba25feaf2a47e3dfc856457d48c715a4c15e6b560b400862a10d46022100b034e7aa652b906c29b3685f79e3fd7f71a917c852aedee713c8fb49f8c78a61:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/compute/gcloud-vm-disk-csek-not-enabled.yaml b/cloud/gcp/compute/gcloud-vm-disk-csek-not-enabled.yaml new file mode 100644 index 00000000000..30737423446 --- /dev/null +++ b/cloud/gcp/compute/gcloud-vm-disk-csek-not-enabled.yaml @@ -0,0 +1,91 @@ +id: gcloud-vm-disk-csek-not-enabled + +info: + name: Virtual Machine Disk Encryption with Customer-Supplied Keys Not Enabled + author: princechaddha + severity: high + description: | + Ensure that the disks attached to your production Google Compute Engine instances are encrypted with Customer-Supplied Encryption Keys (CSEKs) in order to have complete control over the data-at-rest encryption and decryption process. CSEKs allow you to provide your own encryption keys that Google Compute Engine uses to protect the Google-generated keys used to encrypt and decrypt your instance data. + impact: | + Without CSEK encryption, you have limited control over the encryption process of your VM disk data. Google Compute Engine service manages the encryption keys, which may not meet strict compliance requirements for sensitive data. + remediation: | + Re-create your VM instances with Customer-Supplied Encryption Keys (CSEKs) by providing a 256-bit string encoded in RFC 4648 standard base64 during instance creation. Note that Compute Engine does not store your CSEKs on its servers and cannot access your protected data unless you provide the required key. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ComputeEngine/enable-encryption-with-csek.html + - https://cloud.google.com/compute/docs/disks/customer-supplied-encryption + tags: cloud,devops,gcp,gcloud,compute,encryption,csek,security,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let instance of iterate(template.instances)){ + instance = JSON.parse(instance) + set("instanceName", instance.name) + set("zone", instance.zone) + code(3) + for(let disk of iterate(template.disks)){ + set("diskName", disk) + code(4) + } + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute instances list --project $projectId --format="json(name,zone.basename())" + + extractors: + - type: json + name: instances + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute instances describe $instanceName --zone $zone --project $projectId --format="json(disks[].deviceName)" + + extractors: + - type: json + name: disks + internal: true + json: + - '.disks[].deviceName' + + - engine: + - sh + - bash + source: | + gcloud compute disks describe $diskName --zone $zone --project $projectId --format="json(diskEncryptionKey.sha256)" | jq '. // "null"' + + matchers: + - type: word + words: + - "null" + + extractors: + - type: dsl + dsl: + - '"Disk " + diskName + " attached to instance " + instanceName + " in zone " + zone + " of project " + projectId + " is not encrypted with a Customer-Supplied Encryption Key (CSEK)"' \ No newline at end of file diff --git a/cloud/gcp/compute/gcloud-vm-ip-forwarding-enabled.yaml b/cloud/gcp/compute/gcloud-vm-ip-forwarding-enabled.yaml new file mode 100644 index 00000000000..b6bfe627ca6 --- /dev/null +++ b/cloud/gcp/compute/gcloud-vm-ip-forwarding-enabled.yaml @@ -0,0 +1,75 @@ +id: gcloud-vm-ip-forwarding-enabled + +info: + name: IP Forwarding Not Disabled for VM Instances + author: princechaddha + severity: medium + description: | + Ensure that IP Forwarding feature is not enabled at the Google Compute Engine instance level for security and compliance reasons, as instances with IP Forwarding enabled act as routers/packet forwarders. Because IP forwarding is rarely required, except when the virtual machine (VM) is used as a network virtual appliance, each Google Cloud VM instance should be reviewed to decide whether IP forwarding is really needed. + impact: | + With IP forwarding enabled, VM instances can act as routers and receive traffic addressed to other destinations, potentially creating security risks if not properly configured and monitored. + remediation: | + Re-create your VM instances with IP forwarding disabled. Note that you cannot disable IP forwarding on an existing instance - you must create a new instance without the IP forwarding option. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ComputeEngine/disable-ip-forwarding.html + - https://cloud.google.com/vpc/docs/using-routes + tags: cloud,devops,gcp,gcloud,compute,security,networking,ip-forwarding,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let instance of iterate(template.instances)){ + instance = JSON.parse(instance) + set("instanceName", instance.name) + set("zone", instance.zone) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute instances list --project $projectId --format="json(name,zone.basename())" + + extractors: + - type: json + name: instances + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute instances describe $instanceName --zone $zone --project $projectId --format="json(canIpForward)" + + matchers: + - type: word + words: + - '"canIpForward": true' + + extractors: + - type: dsl + dsl: + - '"VM instance " + instanceName + " in zone " + zone + " of project " + projectId + " has IP forwarding enabled"' +# digest: 4a0a0047304502206eae014d43559358aec26725c4e8c6b8cab099ce7e2b961f6ee018e1892e1a39022100803492de385bf013b76729d684ea168903bbfc2ddefcbf12fc8de7359f9770fb:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/compute/gcloud-vm-maintenance-terminate.yaml b/cloud/gcp/compute/gcloud-vm-maintenance-terminate.yaml new file mode 100644 index 00000000000..ab58aabd426 --- /dev/null +++ b/cloud/gcp/compute/gcloud-vm-maintenance-terminate.yaml @@ -0,0 +1,75 @@ +id: gcloud-vm-maintenance-terminate + +info: + name: VM Instance Maintenance Policy Set to Terminate + author: princechaddha + severity: high + description: | + Ensure that Google Cloud Compute Engine performs live migration of your virtual machine instances during periodic infrastructure maintenance. The virtual machine maintenance behavior determines whether the VM instances are live migrated or terminated during a maintenance event. To ensure that your Google Cloud VM instances are migrated to new hardware, set "On Host Maintenance" configuration setting to "Migrate". + impact: | + When maintenance policy is set to terminate, VM instances will be shut down during maintenance events, leading to service disruptions and potential data loss. + remediation: | + Configure the maintenance behavior to "MIGRATE" using the gcloud compute instances set-scheduling command or through the Google Cloud Console. This ensures instances are live migrated during maintenance events. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ComputeEngine/configure-maintenance-behavior.html + - https://cloud.google.com/compute/docs/instances/setting-instance-scheduling-options + tags: cloud,devops,gcp,gcloud,compute,reliability,maintenance,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let instance of iterate(template.instances)){ + instance = JSON.parse(instance) + set("instanceName", instance.name) + set("zone", instance.zone) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute instances list --project $projectId --format="json(name,zone.basename())" + + extractors: + - type: json + name: instances + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute instances describe $instanceName --zone $zone --project $projectId --format="json(scheduling.onHostMaintenance)" + + matchers: + - type: word + words: + - '"onHostMaintenance": "TERMINATE"' + + extractors: + - type: dsl + dsl: + - '"VM instance " + instanceName + " in zone " + zone + " of project " + projectId + " is configured to terminate instead of migrate during maintenance events"' +# digest: 4b0a00483046022100c9bea81bf7b49ceb41718896c0dbec9178102d34d43b95ab930a14709b7de369022100d853180bdb971f5dbc098afff9c1def03a36b583370105fe8cf42c7daa4d56c3:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/compute/gcloud-vm-oslogin-2fa-disabled.yaml b/cloud/gcp/compute/gcloud-vm-oslogin-2fa-disabled.yaml new file mode 100644 index 00000000000..7aeeedb84bb --- /dev/null +++ b/cloud/gcp/compute/gcloud-vm-oslogin-2fa-disabled.yaml @@ -0,0 +1,76 @@ +id: gcloud-vm-oslogin-2fa-disabled + +info: + name: OS Login with 2FA Authentication Not Enabled for VM Instances + author: princechaddha + severity: high + description: | + Ensure that the OS Login feature enabled at the virtual machine instance level is configured with Two-Factor Authentication (2FA) in order to help protect the access to your Google Cloud VM instances. Two-Factor Authentication (also known as Multi-Factor Authentication - MFA) provides an additional layer of security on top of the existing credentials. + impact: | + Without 2FA enabled for OS Login, VM instances are more vulnerable to unauthorized access through compromised credentials. + remediation: | + Enable OS Login with 2FA authentication for all VM instances by setting the "enable-oslogin-2fa" metadata key to "TRUE". + reference: + - https://cloud.google.com/compute/docs/oslogin/set-up-oslogin + tags: cloud,devops,gcp,gcloud,compute,security,2fa,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let instance of iterate(template.instances)){ + instance = JSON.parse(instance) + set("instanceName", instance.name) + set("zone", instance.zone) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute instances list --project $projectId --format="json[](name,zone.basename())" + + extractors: + - type: json + name: instances + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute instances describe $instanceName --zone $zone --project $projectId --format="json(metadata.items)" | jq '.items[]? | select(.key=="enable-oslogin-2fa") | .value // "null"' + + matchers: + - type: word + words: + - "FALSE" + - "null" + condition: or + + extractors: + - type: dsl + dsl: + - '"OS Login with 2FA authentication is not enabled for VM instance " + instanceName + " in zone " + zone + " of project " + projectId' +# digest: 4a0a004730450220364f666eb4864a851ab60cf5baaff34e6be2e0d850b4e84d858b8c4f94b85a07022100dd6ceb745138c139a0cbd7c7bceaefe7c64b9cdbf36769aaccb68d50f79bef91:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/compute/gcloud-vm-preemptible-enabled.yaml b/cloud/gcp/compute/gcloud-vm-preemptible-enabled.yaml new file mode 100644 index 00000000000..bbc217a9a66 --- /dev/null +++ b/cloud/gcp/compute/gcloud-vm-preemptible-enabled.yaml @@ -0,0 +1,75 @@ +id: gcloud-vm-preemptible-enabled + +info: + name: VM Instance Preemptibility Not Disabled + author: princechaddha + severity: high + description: | + Ensure that your Google Cloud Platform (GCP) projects are not using preemptible virtual machine instances for production and business-critical applications. A preemptible virtual machine (VM) is an instance that you can create and run at a much lower price than normal instances but it can be terminated sooner due to system demands. + impact: | + Preemptible VM instances can be terminated at any time to free up resources for standard VM instances, making them unsuitable for production workloads and potentially causing service disruptions. + remediation: | + Re-create your VM instances with preemptibility disabled. Note that you cannot disable preemptibility on an existing instance - you must create a new instance without the preemptible option. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ComputeEngine/disable-preemptibility.html + - https://cloud.google.com/compute/docs/instances/preemptible + tags: cloud,devops,gcp,gcloud,compute,reliability,preemptible,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let instance of iterate(template.instances)){ + instance = JSON.parse(instance) + set("instanceName", instance.name) + set("zone", instance.zone) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute instances list --project $projectId --format="json(name,zone.basename())" + + extractors: + - type: json + name: instances + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute instances describe $instanceName --zone $zone --project $projectId --format="json(scheduling.preemptible)" + + matchers: + - type: word + words: + - "true" + + extractors: + - type: dsl + dsl: + - '"VM instance " + instanceName + " in zone " + zone + " of project " + projectId + " is configured as preemptible and may not be suitable for production workloads"' +# digest: 4a0a0047304502201bd8f4e817d360012280fe3e21a7365992f94dac2e5ef8975eff87c0cf88707a0221009b35501b86c181029be866f33b9b3bc6342f9478eab7c37e55b0b9dbc5a18364:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/compute/gcloud-vm-project-ssh-keys-enabled.yaml b/cloud/gcp/compute/gcloud-vm-project-ssh-keys-enabled.yaml new file mode 100644 index 00000000000..ffe76a63cae --- /dev/null +++ b/cloud/gcp/compute/gcloud-vm-project-ssh-keys-enabled.yaml @@ -0,0 +1,75 @@ +id: gcloud-vm-project-ssh-keys-enabled + +info: + name: Block Project-Wide SSH Keys Not Enabled + author: princechaddha + severity: medium + description: | + Ensure that your Google Compute Engine instances are configured to ignore GCP project-wide (shared) public SSH keys and use instance-level SSH keys instead. Project-wide SSH keys can be used to log in to all the VM instances running inside a GCP project. While project-wide SSH keys can ease SSH key management, if compromised, they pose a security risk which can impact all VM instances within the project. + impact: | + Using project-wide SSH keys increases the attack surface - if compromised, an attacker could gain access to all VM instances in the project instead of just a single instance. + remediation: | + Enable "Block Project-Wide SSH Keys" feature for your VM instances and configure instance-specific SSH keys instead. This limits the impact if any single key is compromised. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ComputeEngine/enable-block-project-wide-ssh-keys.html + - https://cloud.google.com/compute/docs/instances/adding-removing-ssh-keys + tags: cloud,devops,gcp,gcloud,compute,security,ssh,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let instance of iterate(template.instances)){ + instance = JSON.parse(instance) + set("instanceName", instance.name) + set("zone", instance.zone) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute instances list --project $projectId --format="json(name,zone.basename())" + + extractors: + - type: json + name: instances + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute instances describe $instanceName --zone $zone --project $projectId --format="json(metadata.items)" + + matchers: + - type: word + words: + - "null" + + extractors: + - type: dsl + dsl: + - '"VM instance " + instanceName + " in zone " + zone + " of project " + projectId + " is not configured to block project-wide SSH keys"' +# digest: 490a0046304402204c4908dadbb8708a82cdf33e438d1a4f32c726be712012a19a55372c1ebcab4c022025609d2041ac3ca02361240aa879c18622377744fdcce751762235ace39f02ee:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/compute/gcloud-vm-public-ip-enabled.yaml b/cloud/gcp/compute/gcloud-vm-public-ip-enabled.yaml new file mode 100644 index 00000000000..14ddeab569f --- /dev/null +++ b/cloud/gcp/compute/gcloud-vm-public-ip-enabled.yaml @@ -0,0 +1,81 @@ +id: gcloud-vm-public-ip-enabled + +info: + name: VM Instance Using Public IP Address + author: princechaddha + severity: high + description: | + Ensure that your Google Compute Engine instances are not configured to have external IP addresses in order to minimize their exposure to the Internet. To reduce attack surface, Google Cloud virtual machine (VM) instances should not have public IP addresses attached. Instead, VM instances should be configured to run behind load balancers. + impact: | + VM instances with public IP addresses are directly exposed to the internet, increasing the attack surface and risk of unauthorized access. + remediation: | + Remove external IP addresses from your VM instances using the 'gcloud compute instances delete-access-config' command or through the Google Cloud Console. Configure instances to run behind load balancers instead. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ComputeEngine/instances-with-public-ip-addresses.html + - https://cloud.google.com/compute/docs/ip-addresses/reserve-static-external-ip-address + tags: cloud,devops,gcp,gcloud,compute,security,networking,public-ip,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let instance of iterate(template.instances)){ + instance = JSON.parse(instance) + set("instanceName", instance.name) + set("zone", instance.zone) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute instances list --project $projectId --format="json(name,zone.basename())" + + extractors: + - type: json + name: instances + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute instances describe $instanceName --zone $zone --project $projectId --format="json(networkInterfaces[].accessConfigs)" + + matchers-condition: and + matchers: + - type: word + words: + - '"natIP":' + negative: true + + - type: word + words: + - '"accessConfigs":' + + extractors: + - type: dsl + dsl: + - '"VM instance " + instanceName + " in zone " + zone + " of project " + projectId + " has a public IP address configured"' +# digest: 4a0a0047304502202b7ed6b33c2626fd72a003030763f6f6789401ef276f7295848b87b764b1df0a022100d46cd0976efcb73588b032690e620130439145d37aa208a172cbf0139ef16ed0:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/compute/gcloud-vm-serial-console-enabled.yaml b/cloud/gcp/compute/gcloud-vm-serial-console-enabled.yaml new file mode 100644 index 00000000000..6a8d53865a4 --- /dev/null +++ b/cloud/gcp/compute/gcloud-vm-serial-console-enabled.yaml @@ -0,0 +1,77 @@ +id: gcloud-vm-serial-console-enabled + +info: + name: Interactive Serial Console Support Not Disabled + author: princechaddha + severity: medium + description: | + Ensure that "Enable connecting to serial ports" configuration setting is disabled for all your production Google Compute Engine instances. The interactive serial console does not support IP-based access restrictions such as IP address whitelists. If enabled, clients can attempt to connect to your instance from any IP address if they know the username, SSH key, project ID, instance name and zone. + impact: | + With interactive serial console enabled, instances are accessible from any IP address without IP-based restrictions, potentially allowing unauthorized access if credentials are compromised. + remediation: | + Disable interactive serial console support by setting the "serial-port-enable" metadata key to "false" for your VM instances to prevent unauthorized access through serial ports. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ComputeEngine/disable-interactive-serial-console-support.html + - https://cloud.google.com/compute/docs/instances/interacting-with-serial-console + tags: cloud,devops,gcp,gcloud,compute,security,serial-console,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let instance of iterate(template.instances)){ + instance = JSON.parse(instance) + set("instanceName", instance.name) + set("zone", instance.zone) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute instances list --project $projectId --format="json(name,zone.basename())" + + extractors: + - type: json + name: instances + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute instances describe $instanceName --zone $zone --project $projectId --format="json(metadata.items)" + + matchers: + - type: word + words: + - '"key": "serial-port-enable"' + - '"value": "true"' + condition: and + + extractors: + - type: dsl + dsl: + - '"VM instance " + instanceName + " in zone " + zone + " of project " + projectId + " has interactive serial console support enabled"' +# digest: 4b0a00483046022100fb1936be7ea91a27b2a6a93218896be1b0b80e928afac18a7db92ea06d908ce7022100e5345b8dd77d9c4f1c75beef07718c79f9eb2f8c972af700e781375f7e0eab10:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/compute/gcloud-vm-shielded-disabled.yaml b/cloud/gcp/compute/gcloud-vm-shielded-disabled.yaml new file mode 100644 index 00000000000..4b95c07255f --- /dev/null +++ b/cloud/gcp/compute/gcloud-vm-shielded-disabled.yaml @@ -0,0 +1,80 @@ +id: gcloud-vm-shielded-disabled + +info: + name: Shielded VM Security Features Not Enabled + author: princechaddha + severity: medium + description: | + Ensure that your Google Compute Engine instances are configured to use Shielded VM security feature for protection against rootkits and bootkits. Google Compute Engine service can enable 3 advanced security components for Shielded VM instances: + - Virtual Trusted Platform Module (vTPM) - validates the guest virtual machine pre-boot and boot integrity, and provides key generation and protection + - Integrity Monitoring - lets you monitor and verify the runtime boot integrity using Google Cloud Operations reports + - Secure boot - protects your VM instances against boot-level and kernel-level malware and rootkits + impact: | + Without Shielded VM features enabled, your VM instances are more vulnerable to rootkits, bootkits, and other advanced threats that can compromise the boot integrity and security of your instances. + remediation: | + Enable Shielded VM security features (vTPM and Integrity Monitoring) for your VM instances. Note that enabling Secure Boot is optional and should only be done if you don't use custom or unsigned drivers, as it may prevent the VM from booting. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ComputeEngine/enable-shielded-vm.html + - https://cloud.google.com/compute/docs/instances/modifying-shielded-vm + tags: cloud,devops,gcp,gcloud,compute,security,shielded-vm,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let instance of iterate(template.instances)){ + instance = JSON.parse(instance) + set("instanceName", instance.name) + set("zone", instance.zone) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute instances list --project $projectId --format="json(name,zone.basename())" + + extractors: + - type: json + name: instances + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute instances describe $instanceName --zone $zone --project $projectId --format="json(shieldedInstanceConfig.enableVtpm,shieldedInstanceConfig.enableIntegrityMonitoring)" + + matchers: + - type: word + words: + - '"enableIntegrityMonitoring": false' + - '"enableVtpm": false' + - 'null' + + extractors: + - type: dsl + dsl: + - '"VM instance " + instanceName + " in zone " + zone + " of project " + projectId + " does not have Shielded VM features (vTPM and Integrity Monitoring) fully enabled"' +# digest: 490a0046304402201e63ea9ca90d5d4f4af37e855e771bb958e8cfff3972e2d53cd26be9f74480720220065a2dbb817838c4710427fd8393099e96034556758d6fb833bdb59751884439:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/dataproc/gcloud-dataproc-no-cmk.yaml b/cloud/gcp/dataproc/gcloud-dataproc-no-cmk.yaml new file mode 100644 index 00000000000..62dc234e7f2 --- /dev/null +++ b/cloud/gcp/dataproc/gcloud-dataproc-no-cmk.yaml @@ -0,0 +1,75 @@ +id: gcloud-dataproc-no-cmk + +info: + name: Dataproc Cluster Not Using Customer-Managed Keys + author: princechaddha + severity: high + description: | + Ensure that your Google Cloud Dataproc clusters on Compute Engine are encrypted with Customer-Managed Keys (CMKs) in order to control the cluster data encryption/decryption process. You can create and manage your own Customer-Managed Keys (CMKs) with Cloud Key Management Service (Cloud KMS). Cloud KMS provides secure and efficient encryption key management, controlled key rotation, and revocation mechanisms. + impact: | + Without Customer-Managed Keys, you have less control over data encryption and key management, potentially impacting compliance requirements and security controls. + remediation: | + Re-create your Dataproc clusters with Customer-Managed Keys using Cloud KMS. Configure a key ring and CMK in Cloud KMS, then specify the key when creating the cluster using the '--gce-pd-kms-key' flag or through the console. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/Dataproc/enable-encryption-with-cmks-for-dataproc-clusters.html + - https://cloud.google.com/dataproc/docs/concepts/configuring-clusters/customer-managed-encryption + tags: cloud,devops,gcp,gcloud,dataproc,security,encryption,cmk,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let cluster of iterate(template.clusters)){ + cluster = JSON.parse(cluster) + set("clusterName", cluster.clusterName) + set("region", cluster.region) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud dataproc clusters list --project $projectId --format="json" + + extractors: + - type: json + name: clusters + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud dataproc clusters describe $clusterName --region $region --project $projectId --format="json(config.encryptionConfig.gcePdKmsKeyName)" + + matchers: + - type: word + words: + - "null" + + extractors: + - type: dsl + dsl: + - '"Dataproc cluster " + clusterName + " in region " + region + " of project " + projectId + " is not encrypted with Customer-Managed Keys"' +# digest: 4a0a00473045022100a0df190ceb4af0cae3c5622018eb9eaa13e7d7c770992ba771d02eef3bca4a6402202aad7fea87f5a4c45f8c41ad4a7d6205162f07ffe9abb57fef092d6bbf896156:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/dataproc/gcloud-dataproc-public-access.yaml b/cloud/gcp/dataproc/gcloud-dataproc-public-access.yaml new file mode 100644 index 00000000000..ac60bed8585 --- /dev/null +++ b/cloud/gcp/dataproc/gcloud-dataproc-public-access.yaml @@ -0,0 +1,75 @@ +id: gcloud-dataproc-public-access + +info: + name: Dataproc Cluster Publicly Accessible + author: princechaddha + severity: high + description: | + Ensure that your Google Cloud Dataproc clusters are not configured with external IP addresses to minimize exposure to the Internet. When external IP addresses are assigned to Dataproc clusters, the cluster instances are exposed directly to the Internet. This increases the attack surface and risks accidental data exposure if firewall rules are misconfigured. + impact: | + Publicly accessible Dataproc clusters increase the attack surface and risk of data exposure, as cluster instances can be directly accessed from the internet. + remediation: | + Re-create your Dataproc clusters with internal IP addresses only by using the '--no-address' flag or enabling 'Internal IP only' in the console. This ensures cluster instances use private IP addresses and communicate over internal networks only. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/Dataproc/publicly-accessible-dataproc-clusters.html + - https://cloud.google.com/dataproc/docs/concepts/configuring-clusters/network + tags: cloud,devops,gcp,gcloud,dataproc,security,networking,public-access,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let cluster of iterate(template.clusters)){ + cluster = JSON.parse(cluster) + set("clusterName", cluster.clusterName) + set("region", cluster.region) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud dataproc clusters list --project $projectId --format="json" + + extractors: + - type: json + name: clusters + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud dataproc clusters describe $clusterName --region $region --project $projectId --format=json + + matchers: + - type: word + words: + - "false" + + extractors: + - type: dsl + dsl: + - '"Dataproc cluster " + clusterName + " in region " + region + " of project " + projectId + " is configured with external IP addresses and is publicly accessible"' +# digest: 4a0a00473045022100f5f8b6b5dc69b287b221c251a23a01a1d8fcff56ef7100979613b3d765b41c8702207811dc210e5a134370cfdd8d5bf0f5142fad59d62060dab7cffad6811e515ae8:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/dns/gcloud-dns-dangling-records.yaml b/cloud/gcp/dns/gcloud-dns-dangling-records.yaml new file mode 100644 index 00000000000..af7889031b4 --- /dev/null +++ b/cloud/gcp/dns/gcloud-dns-dangling-records.yaml @@ -0,0 +1,90 @@ +id: gcloud-dns-dangling-records + +info: + name: Dangling DNS Records Check + author: princechaddha + severity: high + description: | + Ensure that dangling DNS records are removed from your public Cloud DNS zones in order to maintain the integrity and authenticity of your domains/subdomains and to protect against domain hijacking. + impact: | + Dangling DNS records can lead to domain hijacking and misrouting of traffic, compromising the security and reliability of your domain infrastructure. + remediation: | + Regularly audit your DNS records and associated IP addresses. Remove any DNS records that point to IP addresses no longer reserved under your Google Cloud account. + reference: + - https://cloud.google.com/dns/docs + tags: cloud,devops,gcp,gcloud,dns,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let managedZone of iterate(template.managedZones)){ + set("managedZone", managedZone) + code(3) + for(let recordSet of iterate(template.recordSets)){ + recordSet = JSON.parse(recordSet) + set("recordType", recordSet.type) + set("recordData", recordSet.rrdatas) + code(4) + } + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud dns managed-zones list --project $projectId --format="json(name,visibility)" + + extractors: + - type: json + name: managedZones + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud dns record-sets list --zone=$managedZone --format="json(type,rrdatas)" + + extractors: + - type: json + name: recordSets + internal: true + json: + - '{type: .type, rrdatas: .rrdatas[]}' + + - engine: + - sh + - bash + source: | + gcloud compute addresses list --filter "addressType~EXTERNAL" --format="json(name,status,address)" + + matchers: + - type: word + words: + - 'RESERVED' + + extractors: + - type: dsl + dsl: + - '"Dangling DNS Record: Type: " + recordType + " Data: " + recordData + " in Zone: " + managedZone + " of Project: " + projectId' diff --git a/cloud/gcp/dns/gcloud-dns-dnssec-unenabled.yaml b/cloud/gcp/dns/gcloud-dns-dnssec-unenabled.yaml new file mode 100644 index 00000000000..896e1f7f3c3 --- /dev/null +++ b/cloud/gcp/dns/gcloud-dns-dnssec-unenabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-dns-dnssec-unenabled + +info: + name: DNSSEC Not Enabled for Google Cloud DNS Zones + author: princechaddha + severity: medium + description: | + Ensure that DNSSEC security feature is enabled for all your Google Cloud DNS managed zones in order to protect your domains against spoofing and cache poisoning attacks. By default, DNSSEC is not enabled for Google Cloud public DNS managed zones. + impact: | + Not enabling DNSSEC for DNS zones can increase the risk of DNS spoofing and cache poisoning, compromising the security of domain resolutions. + remediation: | + Enable DNSSEC for each Google Cloud DNS managed zone through the Google Cloud Console or using the `gcloud dns managed-zones update` command with the `--dnssec-state=on` flag. + reference: + - https://cloud.google.com/dns/docs/dnssec + tags: cloud,devops,gcp,gcloud,dns,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let managedZone of iterate(template.managedZones)){ + set("managedZoneName", managedZone) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud dns managed-zones list --project $projectId --format="json(name,visibility)" + + extractors: + - type: json + name: managedZones + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud dns managed-zones describe $managedZoneName --project $projectId --format="json(dnssecConfig.state)" + + matchers: + - type: word + words: + - 'off' + + extractors: + - type: dsl + dsl: + - '"DNSSEC not enabled for Managed Zone: " + managedZoneName + " in Project: " + projectId' diff --git a/cloud/gcp/dns/gcloud-dnssec-keysigning-rsasha1.yaml b/cloud/gcp/dns/gcloud-dnssec-keysigning-rsasha1.yaml new file mode 100644 index 00000000000..cfb31144728 --- /dev/null +++ b/cloud/gcp/dns/gcloud-dnssec-keysigning-rsasha1.yaml @@ -0,0 +1,71 @@ +id: gcloud-dnssec-keysigning-rsasha1 + +info: + name: DNSSEC RSASHA1 Algorithm Deprecated Usage + author: princechaddha + severity: medium + description: | + Ensure that Domain Name System Security Extensions (DNSSEC) feature is not using the deprecated RSASHA1 algorithm for the Key-Signing Key (KSK) associated with your DNS managed zone file. + impact: | + Using the deprecated RSASHA1 algorithm in DNSSEC configurations can expose DNS infrastructure to vulnerabilities and compromise the integrity and security of DNS data. + remediation: | + Update the DNSSEC configuration for each DNS managed zone to use more secure algorithms like RSASHA256 or ECDSAP256SHA256 for the Key-Signing Key (KSK). + reference: + - https://cloud.google.com/dns/docs/dnssec-config + tags: cloud,devops,gcp,gcloud,dns,dnssec,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let managedZone of iterate(template.managedZones)){ + set("managedZone", managedZone) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud dns managed-zones list --project $projectId --format="json(name)" + + extractors: + - type: json + name: managedZones + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud dns managed-zones describe $managedZone --project $projectId --format="json(dnssecConfig)" + + matchers: + - type: word + words: + - 'rsasha1' + + extractors: + - type: dsl + dsl: + - '"Deprecated RSASHA1 algorithm found in DNS managed zone: " + managedZone + " in Project: " + projectId' diff --git a/cloud/gcp/dns/gcloud-dnssec-zonesigning-rsasha1.yaml b/cloud/gcp/dns/gcloud-dnssec-zonesigning-rsasha1.yaml new file mode 100644 index 00000000000..aad47a23c63 --- /dev/null +++ b/cloud/gcp/dns/gcloud-dnssec-zonesigning-rsasha1.yaml @@ -0,0 +1,73 @@ +id: gcloud-dnssec-rsasha1-deprecated + +info: + name: DNSSEC RSASHA1 Algorithm Deprecated + author: princechaddha + severity: medium + description: | + Ensure that Domain Name System Security Extensions (DNSSEC) feature is not using the deprecated RSASHA1 algorithm for the Zone-Signing Key (ZSK) associated with your public DNS managed zone. + impact: | + Using RSASHA1 as the zone-signing algorithm in DNSSEC can expose DNS data to increased risks of being compromised due to weaker cryptographic strength. + remediation: | + Update the DNSSEC configuration to use a stronger, more secure signing algorithm like RSASHA256 or ECDSAP256SHA256 for your DNS managed zones. + reference: + - https://cloud.google.com/dns/docs/dnssec-configuring + tags: cloud,devops,gcp,gcloud,dns,dnssec,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let managedZone of iterate(template.managedZones)){ + set("managedZoneName", managedZone) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud dns managed-zones list --project $projectId --format="json(name,visibility)" + + extractors: + - type: json + name: managedZones + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud dns managed-zones describe $managedZoneName --project $projectId --format="json(dnssecConfig)" + + matchers: + - type: word + words: + - 'rsasha1' + - 'zoneSigning' + condition: and + + extractors: + - type: dsl + dsl: + - '"Deprecated RSASHA1 Algorithm used in DNSSEC for Managed Zone: " + managedZoneName + " in Project: " + projectId' diff --git a/cloud/gcp/filestore/gcloud-filestore-deletion-protection-disabled.yaml b/cloud/gcp/filestore/gcloud-filestore-deletion-protection-disabled.yaml new file mode 100644 index 00000000000..8c35b51afd3 --- /dev/null +++ b/cloud/gcp/filestore/gcloud-filestore-deletion-protection-disabled.yaml @@ -0,0 +1,73 @@ +id: gcloud-filestore-deletion-protection-disabled + +info: + name: Filestore Instance Deletion Protection Not Enabled + author: princechaddha + severity: medium + description: | + Ensure that your Google Cloud Filestore instances have Deletion Protection feature enabled in order to protect them from being accidentally deleted. With the Deletion Protection safety feature enabled, your Filestore instances are guaranteed to be protected from accidental deletion, ensuring your data remains safe. + impact: | + Without deletion protection, Filestore instances could be accidentally or maliciously deleted through the console, CLI, or API calls, leading to data loss and service disruption. + remediation: | + Enable deletion protection for your Filestore instances using the 'gcloud filestore instances update' command with the '--deletion-protection' flag or through the Google Cloud Console. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/Filestore/enable-deletion-protection.html + - https://cloud.google.com/filestore/docs/prevent-deletion + tags: cloud,devops,gcp,gcloud,filestore,security,deletion-protection,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let instance of iterate(template.instances)){ + set("instanceName", instance.name) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud filestore instances list --project $projectId --format="json" + + extractors: + - type: json + name: instances + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud filestore instances describe $instanceName --format="json(deletionProtectionEnabled)" + + matchers: + - type: word + words: + - "null" + + extractors: + - type: dsl + dsl: + - '"Filestore instance " + instanceName + " in project " + projectId + " does not have deletion protection enabled"' +# digest: 490a00463044022008930ba92d35fca3b1d4cc8f7894c08aef1ec6484448a4e6a5d35b538b2c70030220166e2426efcfc9b63bc91a8ddbfbbb6a74a8cc69287e44f7e6c43ad29592e4a5:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/filestore/gcloud-filestore-no-backups.yaml b/cloud/gcp/filestore/gcloud-filestore-no-backups.yaml new file mode 100644 index 00000000000..c4693754ea8 --- /dev/null +++ b/cloud/gcp/filestore/gcloud-filestore-no-backups.yaml @@ -0,0 +1,75 @@ +id: gcloud-filestore-no-backups + +info: + name: Filestore Instance Not Using On-Demand Backup + author: princechaddha + severity: high + description: | + Ensure that on-demand backup and restore functionality is in use for your Google Cloud Filestore instances to ensure data protection, disaster recovery, and regulatory compliance. The backup and restore process does not consume provisioned capacity and has no impact on the performance and availability of your Filestore applications. + impact: | + Without backups, data loss from accidental deletion, corruption, or disaster events could lead to extended application downtime and inability to recover critical data. + remediation: | + Create on-demand backups for your Filestore instances using the 'gcloud filestore backups create' command or through the Google Cloud Console. Configure regular backup schedules to ensure point-in-time recovery capabilities. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/Filestore/backup-and-restore.html + - https://cloud.google.com/filestore/docs/backup-restore + tags: cloud,devops,gcp,gcloud,filestore,security,backup,disaster-recovery,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let instance of iterate(template.instances)){ + instance = JSON.parse(instance) + set("instanceName", instance.name) + set("zone", instance.zone) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud filestore instances list --project $projectId --format="json" + + extractors: + - type: json + name: instances + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud filestore backups list --project $projectId --format="json" --filter='"sourceInstance":"$instanceName"' + + matchers: + - type: word + words: + - "[]" + + extractors: + - type: dsl + dsl: + - '"Filestore instance " + instanceName + " in project " + projectId + " has no backups configured for data protection and disaster recovery"' +# digest: 4a0a00473045022050c6789698c907efa0ae129df0e04df4f989f1b989fd06bce8b17a839f45b65e022100ff4aa7abdf9eb85e9dcd26b0304639f2255cdb6f3d8c2d89a0086bb5b580cc90:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/filestore/gcloud-filestore-no-cmek.yaml b/cloud/gcp/filestore/gcloud-filestore-no-cmek.yaml new file mode 100644 index 00000000000..97e980cbbf9 --- /dev/null +++ b/cloud/gcp/filestore/gcloud-filestore-no-cmek.yaml @@ -0,0 +1,74 @@ +id: gcloud-filestore-no-cmek + +info: + name: Filestore Instance Not Using Customer-Managed Encryption Keys + author: princechaddha + severity: high + description: | + Ensure that data stored on your Google Cloud Filestore instances is encrypted at rest with Customer-Managed Encryption Keys (CMEK) instead of Google-managed encryption keys. CMEKs provide greater control over the encryption and decryption process, enabling you to meet stringent compliance requirements. + impact: | + Without Customer-Managed Encryption Keys, you have less control over data encryption and key management, potentially impacting compliance requirements and security controls. + remediation: | + Re-create your Filestore instances with Customer-Managed Encryption Keys using Cloud KMS. Configure a key ring and CMK in Cloud KMS, then specify the key when creating the instance using the '--kms-key' flag or through the console. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/Filestore/instances-encrypted-with-cmeks.html + - https://cloud.google.com/filestore/docs/encryption + tags: cloud,devops,gcp,gcloud,filestore,security,encryption,cmek,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let instance of iterate(template.instances)){ + instance = JSON.parse(instance) + set("instanceName", instance.name) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud filestore instances list --project $projectId --format="json" + + extractors: + - type: json + name: instances + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud filestore instances describe $instanceName --format="json(kmsKeyName)" + + matchers: + - type: word + words: + - "null" + + extractors: + - type: dsl + dsl: + - '"Filestore instance " + instanceName + " in project " + projectId + " is not encrypted with Customer-Managed Keys"' +# digest: 4b0a00483046022100906103c6715e34fd7e8f8f1b222a6a58636ca54f3b733ded2427fa2211d9e43a0221008fda63f37629bdec19bbe066d75e668b1e3811e4387377db14255312a0bd413e:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/filestore/gcloud-filestore-no-vpc-controls.yaml b/cloud/gcp/filestore/gcloud-filestore-no-vpc-controls.yaml new file mode 100644 index 00000000000..63067e81ef2 --- /dev/null +++ b/cloud/gcp/filestore/gcloud-filestore-no-vpc-controls.yaml @@ -0,0 +1,78 @@ +id: gcloud-filestore-no-vpc-controls + +info: + name: Filestore Instance Not Protected by VPC Service Controls + author: princechaddha + severity: medium + description: | + Ensure that VPC Service Controls are used to configure a security perimeter around your Google Cloud Filestore instances. VPC Service Controls is a powerful security tool that allows you to restrict access to your cloud resources, including Filestore instances, to specific networks and clients. This helps prevent data exfiltration and enhances the security posture of your cloud environment. + impact: | + Without VPC Service Controls, Filestore instances may be vulnerable to unauthorized access and data exfiltration, as there is no security perimeter controlling data flow between resources. + remediation: | + Configure VPC Service Controls perimeter to protect your Filestore instances by including the Cloud Filestore API (file.googleapis.com) in the restricted services list and adding your project to the perimeter's protected resources. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/Filestore/use-vpc-service-controls.html + - https://cloud.google.com/vpc-service-controls/docs/supported-products + tags: cloud,devops,gcp,gcloud,filestore,security,networking,vpc,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let perimeter of iterate(template.perimeters)){ + set("perimeterName", perimeter.name) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud access-context-manager perimeters list --project $projectId --format="json" + + extractors: + - type: json + name: perimeters + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud access-context-manager perimeters describe $perimeterName --format="json(status.restrictedServices)" + + matchers-condition: and + matchers: + - type: word + words: + - "file.googleapis.com" + negative: true + + - type: word + words: + - "restrictedServices" + + extractors: + - type: dsl + dsl: + - '"Project " + projectId + " does not have VPC Service Controls configured to protect Filestore instances"' \ No newline at end of file diff --git a/cloud/gcp/filestore/gcloud-filestore-unrestricted-access.yaml b/cloud/gcp/filestore/gcloud-filestore-unrestricted-access.yaml new file mode 100644 index 00000000000..2e7fa91cec8 --- /dev/null +++ b/cloud/gcp/filestore/gcloud-filestore-unrestricted-access.yaml @@ -0,0 +1,74 @@ +id: gcloud-filestore-unrestricted-access + +info: + name: Filestore Instance Client Access Not Restricted by IP + author: princechaddha + severity: medium + description: | + Ensure that client access to your Google Cloud Filestore instances is limited to specific (trusted) IP addresses or IP address ranges in order to protect your data against unauthorized access. By default, Filestore instances provide full (root-level read/write) access to all clients within the same Google Cloud project and VPC network. + impact: | + Granting untrusted clients access exposes Filestore instance data to unapproved access, modification, or deletion. Without IP-based access rules, any client in the same project and VPC can access the instance. + remediation: | + Configure IP-based access rules for your Filestore instances to restrict access to specific IP addresses or ranges. Once configured, any IP address or range not explicitly allowed will be denied access. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/Filestore/restrict-client-access.html + - https://cloud.google.com/filestore/docs/access-control + tags: cloud,devops,gcp,gcloud,filestore,security,networking,access-control,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let instance of iterate(template.instances)){ + instance = JSON.parse(instance) + set("instanceName", instance.name) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud filestore instances list --project $projectId --format="json" + + extractors: + - type: json + name: instances + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud filestore instances describe $instanceName --format="json(fileShares[].nfsExportOptions)" + + matchers: + - type: word + words: + - "null" + + extractors: + - type: dsl + dsl: + - '"Filestore instance " + instanceName + " in project " + projectId + " has unrestricted client access and is not limited to specific IP addresses"' +# digest: 4a0a00473045022100e132d1a4ddbfbd184c1c625c555088141dbd3f4214d4a716fcf9355d5246bde7022021afd440d6eb2b7aa62ec9e0517237832f9584ca9d33114a94d29b4e75695ac8:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/function/gcloud-func-auto-runtime-updates-disabled.yaml b/cloud/gcp/function/gcloud-func-auto-runtime-updates-disabled.yaml new file mode 100644 index 00000000000..3c1d13926fb --- /dev/null +++ b/cloud/gcp/function/gcloud-func-auto-runtime-updates-disabled.yaml @@ -0,0 +1,72 @@ +id: gcloud-func-auto-runtime-updates-disabled + +info: + name: Automatic Runtime Security Updates Disabled in Google Cloud Functions + author: princechaddha + severity: medium + description: | + Ensure that automatic runtime security updates are enabled for your Google Cloud functions in order to keep the functions secure and protected against vulnerabilities without manual intervention. + impact: | + Having automatic runtime security updates disabled can expose Google Cloud functions to vulnerabilities which could be mitigated by timely updates. + remediation: | + Enable automatic runtime security updates for each Google Cloud function by setting the `serviceConfig.minInstanceCount` to a non-null value, ensuring functions are automatically updated with the latest security patches. + reference: + - https://cloud.google.com/functions/docs/securing/managing-security + tags: cloud,devops,gcp,gcloud,google-cloud-functions,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let functionDetail of iterate(template.functions)){ + set("functionName", functionDetail) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud functions list --project $projectId --format="json(name)" + + extractors: + - type: json + name: functions + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud functions describe $functionName --format="json(serviceConfig.minInstanceCount)" + + matchers: + - type: word + words: + - 'null' + condition: or + + extractors: + - type: dsl + dsl: + - '"Automatic Runtime Security Updates Disabled in function: " + functionName + " in Project: " + projectId' diff --git a/cloud/gcp/function/gcloud-func-cmek-not-used.yaml b/cloud/gcp/function/gcloud-func-cmek-not-used.yaml new file mode 100644 index 00000000000..fc5d44542fc --- /dev/null +++ b/cloud/gcp/function/gcloud-func-cmek-not-used.yaml @@ -0,0 +1,73 @@ +id: gcloud-func-cmek-not-used + +info: + name: No Customer-Managed Encryption Keys in Google Cloud Functions + author: princechaddha + severity: high + description: | + Ensure that your Google Cloud functions use Customer-Managed Encryption Keys (CMEK) instead of Google-managed encryption keys to encrypt data at rest. CMEKs provide greater control over the encryption and decryption process, enabling you to meet stringent compliance requirements. + impact: | + Using Google-managed encryption keys instead of CMEKs reduces your ability to control the encryption process and comply with certain regulatory standards. + remediation: | + Configure your Google Cloud functions to use Customer-Managed Encryption Keys (CMEK) to ensure data encryption at rest is managed according to your compliance and security requirements. + reference: + - https://cloud.google.com/functions/docs/securing/managing-encryption-keys + tags: cloud,devops,gcp,gcloud,google-cloud-functions,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let functionName of iterate(template.functions)){ + set("functionName", functionName) + log(functionName) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud functions list --project $projectId --format="json(name)" + + extractors: + - type: json + name: functions + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud functions describe $functionName --format="json(kmsKeyName)" + + matchers: + - type: word + words: + - 'null' + condition: or + + extractors: + - type: dsl + dsl: + - '"Function not using CMEK: " + functionName + " in " + projectId + " project"' diff --git a/cloud/gcp/function/gcloud-func-inactive-svc-acc.yaml b/cloud/gcp/function/gcloud-func-inactive-svc-acc.yaml new file mode 100644 index 00000000000..5a6d4ec3de3 --- /dev/null +++ b/cloud/gcp/function/gcloud-func-inactive-svc-acc.yaml @@ -0,0 +1,91 @@ +id: gcloud-func-inactive-svc-acc + +info: + name: Inactive Service Accounts in Google Cloud Functions + author: princechaddha + severity: high + description: | + Ensure that your Google Cloud functions are referencing existing, active service accounts in order to prevent execution failures and operational disruptions. + impact: | + Using inactive or deleted service accounts in Google Cloud Functions can lead to runtime errors and potential service disruption, affecting the stability and reliability of cloud services. + remediation: | + Verify and update the service accounts associated with your Google Cloud functions to ensure they are active and have the necessary permissions for function execution. + reference: + - https://cloud.google.com/functions/docs/securing/managing-access-iam + tags: cloud,devops,gcp,gcloud,google-cloud-functions,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let functionName of iterate(template.functions)){ + set("functionName", functionName) + code(3) + for(let serviceAccountEmail of iterate(template.serviceAccountEmail)){ + set("serviceAccountEmail", serviceAccountEmail) + code(4) + } + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud functions list --project $projectId --format="json(name)" + + extractors: + - type: json + name: functions + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud functions describe $functionName --format="json(serviceConfig.serviceAccountEmail)" + + extractors: + - type: json + name: serviceAccountEmail + internal: true + json: + - '.[].serviceAccountEmail' + + - engine: + - sh + - bash + source: | + gcloud iam service-accounts describe $serviceAccountEmail --format="json(disabled)" + + matchers: + - type: word + words: + - 'PERMISSION_DENIED:' + - 'ERROR:' + - 'disabled' + condition: or + + extractors: + - type: dsl + dsl: + - '"Inactive Service Account: " + serviceAccountEmail + ", Function: " + functionName + " in " + projectId + " project"' diff --git a/cloud/gcp/function/gcloud-func-min-instances-unset.yaml b/cloud/gcp/function/gcloud-func-min-instances-unset.yaml new file mode 100644 index 00000000000..b457c37dc63 --- /dev/null +++ b/cloud/gcp/function/gcloud-func-min-instances-unset.yaml @@ -0,0 +1,71 @@ +id: gcloud-func-min-instances-unset + +info: + name: Unset Minimum Instances for Cloud Functions + author: princechaddha + severity: medium + description: | + To minimize cold start latency and enhance performance, ensure that your Google Cloud Functions have a sufficient number of warm instances configured. + impact: | + Not setting a minimum number of instances for Google Cloud functions can result in potential cold start delays and degraded performance, especially for critical or latency-sensitive functions. + remediation: | + Configure the serviceConfig.minInstanceCount parameter for your Google Cloud Functions to an appropriate value that suits your workload demands. + reference: + - https://cloud.google.com/functions/docs/scaling#setting_a_minimum_number_of_instances + tags: cloud,devops,gcp,gcloud,google-cloud-functions,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let functionDetail of iterate(template.functions)){ + set("functionName", functionDetail) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud functions list --project $projectId --format="json(name)" + + extractors: + - type: json + name: functions + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud functions describe $functionName --format="json(serviceConfig.minInstanceCount)" + + matchers: + - type: word + words: + - 'null' + + extractors: + - type: dsl + dsl: + - '"Minimum Instances not configured for function: " + functionName + " in " + projectId + " project"' diff --git a/cloud/gcp/function/gcloud-func-missing-labels.yaml b/cloud/gcp/function/gcloud-func-missing-labels.yaml new file mode 100644 index 00000000000..8779e7d1d57 --- /dev/null +++ b/cloud/gcp/function/gcloud-func-missing-labels.yaml @@ -0,0 +1,71 @@ +id: gcloud-func-missing-labels + +info: + name: Missing User-Defined Labels in Google Cloud Functions + author: princechaddha + severity: low + description: | + Ensure that user-defined labels are being used to tag, collect, and organize Google Cloud functions within your Google Cloud Platform (GCP) projects. User-defined labels are a lightweight and efficient way to group together related or associated cloud resources. + impact: | + Not using labels can lead to challenges in managing, identifying, and organizing resources, potentially increasing the complexity of operations and governance. + remediation: | + Define and apply user-defined labels to all Google Cloud functions to enhance resource management capabilities and improve operational efficiency. + reference: + - https://cloud.google.com/resource-manager/docs/creating-managing-labels + tags: cloud,devops,gcp,gcloud,google-cloud-functions,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let functionDetail of iterate(template.functions)){ + set("functionName", functionDetail) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud functions list --project $projectId --format="json(name)" + + extractors: + - type: json + name: functions + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud functions describe $functionName --format="json(labels)" + + matchers: + - type: word + words: + - 'null' + + extractors: + - type: dsl + dsl: + - '"Missing labels for function: " + functionName + " in " + projectId + " project"' diff --git a/cloud/gcp/function/gcloud-func-no-vpc-access.yaml b/cloud/gcp/function/gcloud-func-no-vpc-access.yaml new file mode 100644 index 00000000000..04c907ff7fa --- /dev/null +++ b/cloud/gcp/function/gcloud-func-no-vpc-access.yaml @@ -0,0 +1,71 @@ +id: gcloud-func-no-vpc-access + +info: + name: No Serverless VPC Access in Google Cloud Functions + author: princechaddha + severity: high + description: | + Ensure that your Google Cloud functions are configured to use Serverless VPC Access in order to connect functions directly to your VPC network, allowing access to other VPC resources such as VM instances, MemoryStore instances, or any other cloud resources with an internal IP address. Without Serverless VPC Access, these functions may not be able to communicate efficiently with other resources in the same VPC. + impact: | + Lack of Serverless VPC Access in Google Cloud functions can lead to inefficient or failed communications between your serverless functions and other resources within the same VPC, impacting application performance and increasing latency. + remediation: | + Configure Serverless VPC Access for your Google Cloud functions by setting the vpcConnector parameter to the name of an already configured VPC connector in your project settings. + reference: + - https://cloud.google.com/functions/docs/connecting-vpc + tags: cloud,devops,gcp,gcloud,google-cloud-functions,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let functionName of iterate(template.functions)){ + set("functionName", functionName) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud functions list --project $projectId --format="json(name)" + + extractors: + - type: json + name: functions + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud functions describe $functionName --region=us-central1 --format="json(vpcConnector)" + + matchers: + - type: word + words: + - 'null' + + extractors: + - type: dsl + dsl: + - '"No Serverless VPC Access in function: " + functionName + " in " + projectId + " project"' diff --git a/cloud/gcp/function/gcloud-func-public-access.yaml b/cloud/gcp/function/gcloud-func-public-access.yaml new file mode 100644 index 00000000000..bd7661a25f1 --- /dev/null +++ b/cloud/gcp/function/gcloud-func-public-access.yaml @@ -0,0 +1,74 @@ +id: gcloud-func-public-access + +info: + name: Publicly Accessible Google Cloud Functions + author: princechaddha + severity: high + description: | + Identify any publicly accessible Google Cloud functions within your GCP account and update their IAM policy to protect against unauthorized users sending requests to invoke these functions. To deny access from anonymous and public users, remove the bindings for allUsers and allAuthenticatedUsers members from your function's IAM policy. The allUsers member represents any user on the Internet, while allAuthenticatedUsers represents any user or service account that can sign into Google Cloud Platform (GCP) with a Google account. + impact: | + Allowing public access to Google Cloud functions can lead to unauthorized use and potential security breaches. + remediation: | + Update the IAM policies of your Google Cloud functions to remove allUsers and allAuthenticatedUsers from the bindings to ensure that the functions are not publicly accessible. + reference: + - https://cloud.google.com/functions/docs/securing/managing-access-iam + tags: cloud,devops,gcp,gcloud,google-cloud-functions,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let functionDetail of iterate(template.functions)){ + set("functionName", functionDetail) + log(functionDetail) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud functions list --project $projectId --format="json(name)" + + extractors: + - type: json + name: functions + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud functions get-iam-policy $functionName --project $projectId --format=json + + matchers: + - type: word + words: + - 'allUsers' + - 'allAuthenticatedUsers' + condition: or + + extractors: + - type: dsl + dsl: + - '"Publicly Accessible Function: " + functionName + " in " + projectId + " project"' diff --git a/cloud/gcp/function/gcloud-func-pubsub-dlt-missing.yaml b/cloud/gcp/function/gcloud-func-pubsub-dlt-missing.yaml new file mode 100644 index 00000000000..57370155805 --- /dev/null +++ b/cloud/gcp/function/gcloud-func-pubsub-dlt-missing.yaml @@ -0,0 +1,71 @@ +id: gcloud-func-pubsub-dlt-missing + +info: + name: Configure Dead Lettering for Pub/Sub-Triggered Functions + author: princechaddha + severity: low + description: | + Ensure that Google Cloud functions triggered by Pub/Sub have a Dead-Letter Topic (DLT) configured to handle undeliverable messages. To achieve this, configure your Pub/Sub subscriptions with a maximum number of delivery attempts. If a message cannot be delivered, it will be sent to the designated Dead-Letter Topic (DLT). + impact: | + Not having a Dead-Letter Topic for Pub/Sub-triggered functions can result in lost messages and unhandled failures, affecting the reliability of your application. + remediation: | + Configure a Dead-Letter Topic for each Pub/Sub-triggered function by setting up the necessary Pub/Sub subscription settings. + reference: + - https://cloud.google.com/functions/docs/calling/pubsub#retry + tags: cloud,devops,gcp,gcloud,google-cloud-functions,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let functionDetail of iterate(template.functions)){ + set("functionName", functionDetail) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud functions list --project $projectId --format="json(name, region)" + + extractors: + - type: json + name: functions + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud functions describe $functionName --format="json(eventTrigger.pubsubTopic)" + + matchers: + - type: word + words: + - 'null' + + extractors: + - type: dsl + dsl: + - '"Missing Dead Letter Topic for function: " + functionName + " in Project: " + projectId' diff --git a/cloud/gcp/function/gcloud-func-secrets-unmanaged.yaml b/cloud/gcp/function/gcloud-func-secrets-unmanaged.yaml new file mode 100644 index 00000000000..84a20306d1e --- /dev/null +++ b/cloud/gcp/function/gcloud-func-secrets-unmanaged.yaml @@ -0,0 +1,78 @@ +id: gcloud-func-secrets-unmanaged + +info: + name: Use Secrets Manager for Managing Secrets in Google Cloud Functions + author: princechaddha + severity: medium + description: | + To prevent unauthorized access or accidental exposure of sensitive information, ensure that Secrets Manager service is used to store and manage secrets instead of storing them in cleartext within Cloud Functions environment variables. + impact: | + Storing secrets in environment variables without encryption can expose sensitive information to unauthorized access, potentially leading to security breaches and compliance issues. + remediation: | + Refactor your Google Cloud Functions to use Secrets Manager for managing sensitive configuration settings instead of storing them directly in environment variables. + reference: + - https://cloud.google.com/functions/docs/securing/managing-secrets + tags: cloud,devops,gcp,gcloud,google-cloud-functions,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let functionName of iterate(template.functions)){ + set("functionName", functionName) + log(functionName) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud functions list --project $projectId --format="json(name)" + + extractors: + - type: json + name: functions + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud functions describe $functionName --format="json(serviceConfig.environmentVariables,buildConfig.environmentVariables)" + + matchers: + - type: word + words: + - 'PASSWORD' + - 'API_KEY' + - 'SECRET_KEY' + - 'ACCESS_TOKEN' + - 'TOKEN' + case-insensitive: true + condition: or + + extractors: + - type: dsl + dsl: + - '"Sensitive information found in environment variables for function: " + functionName + ", Project: " + projectId' diff --git a/cloud/gcp/function/gcloud-func-unrestricted-outbound.yaml b/cloud/gcp/function/gcloud-func-unrestricted-outbound.yaml new file mode 100644 index 00000000000..e13f775e9df --- /dev/null +++ b/cloud/gcp/function/gcloud-func-unrestricted-outbound.yaml @@ -0,0 +1,74 @@ +id: gcloud-func-unrestricted-outbound + +info: + name: Unrestricted Outbound Network Access in Google Cloud Functions + author: princechaddha + severity: high + description: | + Ensure that your Google Cloud functions are not configured to allow unrestricted outbound network access in order to prevent security vulnerabilities and minimize cloud costs. To ensure that your function's outbound traffic is restricted to internal IP ranges and can't communicate with external networks or the public Internet, set the VpcConnectorEgressSettings parameter to PRIVATE_RANGES_ONLY. + impact: | + Allowing unrestricted outbound network access can lead to potential security risks such as data exfiltration and increased cloud costs from unexpected external network communications. + remediation: | + Configure the VpcConnectorEgressSettings of your Google Cloud functions to PRIVATE_RANGES_ONLY to ensure all outgoing traffic is limited to internal IP ranges only. + reference: + - https://cloud.google.com/functions/docs/networking/network-settings + tags: cloud,devops,gcp,gcloud,google-cloud-functions,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let functionDetail of iterate(template.functions)){ + set("functionName", functionDetail) + log(functionDetail) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud functions list --project $projectId --format="json(name)" + + extractors: + - type: json + name: functions + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud functions describe $functionName --format="json(serviceConfig.vpcConnectorEgressSettings)" + + matchers: + - type: word + words: + - 'null' + - 'ALL_TRAFFIC' + condition: or + + extractors: + - type: dsl + dsl: + - '"Unrestricted Outbound Network Access in function: " + functionName + ", Region: " + functionRegion + ", Project: " + projectId' diff --git a/cloud/gcp/function/gcp-cloud-func-gen1-deprecated.yaml b/cloud/gcp/function/gcp-cloud-func-gen1-deprecated.yaml new file mode 100644 index 00000000000..01cec50a497 --- /dev/null +++ b/cloud/gcp/function/gcp-cloud-func-gen1-deprecated.yaml @@ -0,0 +1,71 @@ +id: gcp-cloud-func-gen1-deprecated + +info: + name: Deprecated 1st Generation Google Cloud Functions + author: princechaddha + severity: high + description: | + Ensure that none of your Google Cloud functions are 1st (first) generation functions. 1st generation Google Cloud functions are considered deprecated and no longer receive updates or support, making them less secure, less performant, and lacking in new features compared to newer generations. + impact: | + Using deprecated 1st generation functions can expose your applications to security vulnerabilities, degrade performance, and miss out on new features provided by newer generations. + remediation: | + Migrate all 1st generation Google Cloud functions to newer generation runtimes as recommended by Google to ensure continued support and access to the latest features and security enhancements. + reference: + - https://cloud.google.com/functions/docs/migrating + tags: cloud,devops,gcp,gcloud,google-cloud-functions,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let functionDetail of iterate(template.functions)){ + set("functionName", functionDetail) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud functions list --project $projectId --format="json(name)" + + extractors: + - type: json + name: functions + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud functions describe $functionName --format="json(environment)" + + matchers: + - type: word + words: + - 'null' + + extractors: + - type: dsl + dsl: + - '"Deprecated 1st Generation function: " + functionName + " in Project: " + projectId' diff --git a/cloud/gcp/function/gcp-func-default-svc-acc.yaml b/cloud/gcp/function/gcp-func-default-svc-acc.yaml new file mode 100644 index 00000000000..839a1a78b57 --- /dev/null +++ b/cloud/gcp/function/gcp-func-default-svc-acc.yaml @@ -0,0 +1,74 @@ +id: gcp-func-default-svc-acc + +info: + name: Google Cloud Functions Using Default Service Account + author: princechaddha + severity: medium + description: | + Ensure that your Google Cloud functions are configured to use user-managed service accounts instead of the default service account managed by Google Cloud in order to follow the Principle of Least Privilege (POLP) and enhance the security posture of your functions. + impact: | + Using default service accounts can grant more permissions than required to your functions, violating the Principle of Least Privilege and increasing security risks. + remediation: | + Configure your Google Cloud functions to use user-managed service accounts that have only the permissions necessary for the function to operate. + reference: + - https://cloud.google.com/functions/docs/securing/managing-access-iam + tags: cloud,devops,gcp,gcloud,google-cloud-functions,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let functionDetail of iterate(template.functions)){ + set("functionName", functionDetail) + log(functionDetail) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud functions list --project $projectId --format="json(name)" + + extractors: + - type: json + name: functions + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud functions describe $functionName --format="value(serviceConfig.serviceAccountEmail)" + + matchers: + - type: word + words: + - '@appspot.gserviceaccount.com' + - '@developer.gserviceaccount.com' + condition: or + + extractors: + - type: dsl + dsl: + - '"Default Service Account used in function: " + functionName + " in " + projectId + " project"' diff --git a/cloud/gcp/iam/gcloud-access-approval-not-enabled.yaml b/cloud/gcp/iam/gcloud-access-approval-not-enabled.yaml new file mode 100644 index 00000000000..7e3e043ca4a --- /dev/null +++ b/cloud/gcp/iam/gcloud-access-approval-not-enabled.yaml @@ -0,0 +1,54 @@ +id: gcloud-access-approval-not-enabled + +info: + name: Access Approval Not Enabled in GCP Projects + author: princechaddha + severity: high + description: | + Ensure that Access Approval is enabled within your Google Cloud Platform (GCP) account to allow your explicit approval whenever Google personnel need to access your GCP projects. Once enabled, you can delegate users within your organization to approve access requests through IAM. Requests will show the requester's name/ID via email or Pub/Sub message for approval. + impact: | + If Access Approval is not enabled, unauthorized access by Google personnel may occur without your knowledge, leading to potential security risks and data breaches. + remediation: | + Enable Access Approval in your GCP projects to create a new control and logging layer that reveals who in your organization approved or denied access requests. + reference: + - https://cloud.google.com/access-approval/docs/quickstart + tags: cloud,devops,gcp,gcloud,google-cloud-platform,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud access-approval settings get --project $projectId --format="json(enrolledServices)" + + matchers: + - type: word + words: + - 'null' + + extractors: + - type: dsl + dsl: + - '"Access Approval not enabled in Project: " + projectId' diff --git a/cloud/gcp/iam/gcloud-iam-admin-roles.yaml b/cloud/gcp/iam/gcloud-iam-admin-roles.yaml new file mode 100644 index 00000000000..ded115bedfd --- /dev/null +++ b/cloud/gcp/iam/gcloud-iam-admin-roles.yaml @@ -0,0 +1,55 @@ +id: gcloud-iam-admin-roles + +info: + name: IAM Users with Administrative Roles + author: princechaddha + severity: medium + description: | + Ensure that IAM roles with privileged administrative permissions are not assigned to IAM identities (users, groups, and service accounts) to promote least privilege and provide your members (principals) the minimal access required to perform their tasks. When IAM members have administrator privileges (Owner and Editor roles, or roles containing "Admin" or "admin" in their names), they can access, create, and manage cloud resources. + impact: | + Administrative roles grant excessive permissions that violate the principle of least privilege, potentially allowing users to perform unauthorized or accidental changes across resources. + remediation: | + Remove administrative roles (Owner, Editor, and roles containing "Admin" or "admin") from IAM members and replace them with more granular roles that follow the principle of least privilege. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/IAM/roles-with-admin-permissions.html + - https://cloud.google.com/iam/docs/understanding-roles + tags: cloud,devops,gcp,gcloud,iam,security,admin,permissions,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud projects get-iam-policy $projectId --format="json(bindings[?(@.role=='roles/owner' || @.role=='roles/editor' || @.role contains 'admin' || @.role contains 'Admin')])" + + matchers: + - type: word + words: + - '"role":' + + extractors: + - type: dsl + dsl: + - '"Project " + projectId + " has IAM users with administrative roles that grant excessive permissions"' \ No newline at end of file diff --git a/cloud/gcp/iam/gcloud-iam-unrestricted-decryption.yaml b/cloud/gcp/iam/gcloud-iam-unrestricted-decryption.yaml new file mode 100644 index 00000000000..5e4a29d7346 --- /dev/null +++ b/cloud/gcp/iam/gcloud-iam-unrestricted-decryption.yaml @@ -0,0 +1,56 @@ +id: gcloud-iam-unrestricted-decryption + +info: + name: IAM Users with Unrestricted Data Decryption Permissions + author: princechaddha + severity: medium + description: | + Ensure that IAM users with data decryption permissions should use conditions to enforce strict controls, enhancing data protection and reducing risks of unauthorized decryption. For compliance, the Cloud KMS CryptoKey Decrypter (roles/cloudkms.cryptoKeyDecrypter), Cloud KMS Crypto Operator (roles/cloudkms.cryptoOperator), and Cloud KMS CryptoKey Encrypter/Decrypter (roles/cloudkms.cryptoKeyEncrypterDecrypter) roles must have a condition preventing data decryption with any KMS key. + impact: | + Without conditions on decryption permissions, IAM users can decrypt data using any KMS key in the project, potentially leading to unauthorized access to sensitive data. + remediation: | + Add IAM conditions to roles that allow decryption operations, restricting access to specific KMS keys. This can be done using resource.type and resource.name conditions in the IAM policy. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/IAM/decryption-with-all-keys-not-allowed.html + - https://cloud.google.com/kms/docs/reference/permissions-and-roles + tags: cloud,devops,gcp,gcloud,iam,security,encryption,kms,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud projects get-iam-policy $projectId --format="json(bindings[?(@.role=='roles/cloudkms.cryptoKeyDecrypter' || @.role=='roles/cloudkms.cryptoOperator' || @.role=='roles/cloudkms.cryptoKeyEncrypterDecrypter')])" + + matchers: + - type: word + words: + - '"condition":' + negative: true + + extractors: + - type: dsl + dsl: + - '"Project " + projectId + " has IAM users with unrestricted decryption permissions that can access all KMS keys"' \ No newline at end of file diff --git a/cloud/gcp/iam/gcloud-service-account-admin-restriction.yaml b/cloud/gcp/iam/gcloud-service-account-admin-restriction.yaml new file mode 100644 index 00000000000..21219e34120 --- /dev/null +++ b/cloud/gcp/iam/gcloud-service-account-admin-restriction.yaml @@ -0,0 +1,67 @@ +id: gcloud-service-account-admin-restriction + +info: + name: Restrict Administrator Access for Service Accounts + author: princechaddha + severity: medium + description: | + Ensure that your Google Cloud user-managed service accounts are not using privileged (administrator) roles, in order to implement the principle of least privilege and prevent any accidental or intentional modifications that may lead to data leaks and/or data loss. A user-managed service account is an identity that a virtual machine (VM) instance or an application can use to run API requests on your behalf. GCP service accounts can create, modify, or delete resources only if you grant the necessary IAM permissions, at the project or resource level. + impact: | + Using service accounts with administrative privileges can lead to potential over-privileged scenarios, increasing the risk of security breaches and unauthorized access. + remediation: | + Review and minimize the roles assigned to service accounts, ensuring no administrative privileges are granted unless absolutely necessary. + reference: + - https://cloud.google.com/iam/docs/understanding-roles + tags: cloud,devops,gcp,gcloud,google-cloud-iam,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let binding of iterate(template.bindings)){ + set("binding", binding) + javascript(1) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud projects get-iam-policy $projectId --format=json + extractors: + - type: json + name: bindings + internal: true + json: + - '.bindings[]' + +javascript: + - code: | + let binding = JSON.parse(template.binding); + let isAdminRole = ["roles/editor", "roles/owner"].includes(binding.role) || /admin/i.test(binding.role); + let projectId = template.projectId; + if (isAdminRole) { + Export("Service Account with Admin Privileges " + binding.members.join(", ") + " in project " + projectId); + } + + extractors: + - type: dsl + dsl: + - response diff --git a/cloud/gcp/iam/gcp-api-keys-present.yaml b/cloud/gcp/iam/gcp-api-keys-present.yaml new file mode 100644 index 00000000000..1d9a474bb7c --- /dev/null +++ b/cloud/gcp/iam/gcp-api-keys-present.yaml @@ -0,0 +1,65 @@ +id: gcp-api-keys-present + +info: + name: Delete Google Cloud API Keys + author: princechaddha + severity: low + description: | + Ensure that all your Google Cloud projects are using standard authentication flow instead of API keys for authentication. Google Cloud Platform (GCP) API keys are simple encrypted strings that can be used when calling certain APIs which don't need to access private user data. GCP API keys are usually accessible to clients, as they can be publicly viewed from within a browser, making it easy to discover and steal an API key. + impact: | + Using API keys that are publicly accessible can lead to unauthorized access and potential security breaches. + remediation: | + Remove all API keys and replace them with standard authentication methods to secure your applications. + reference: + - https://cloud.google.com/docs/authentication/api-keys + tags: cloud,devops,gcp,gcloud,google-cloud-api,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let apiKey of iterate(template.apiKeys)){ + javascript(1) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud alpha services api-keys list --project=$projectId --format="json(keyId)" + extractors: + - type: json + name: apiKeys + internal: true + json: + - '.[].keyId' + +javascript: + - code: | + let apiKey = template.apiKey; + let projectId = template.projectId; + if (apiKey) { + Export("API key " + apiKey + " found in Project " + projectId); + } + + extractors: + - type: dsl + dsl: + - response diff --git a/cloud/gcp/iam/gcp-iam-primitive-roles.yaml b/cloud/gcp/iam/gcp-iam-primitive-roles.yaml new file mode 100644 index 00000000000..5e8ef23b10b --- /dev/null +++ b/cloud/gcp/iam/gcp-iam-primitive-roles.yaml @@ -0,0 +1,71 @@ +id: gcp-iam-primitive-roles + +info: + name: Minimize the Use of Primitive Roles + author: princechaddha + severity: medium + description: | + For production and security-critical cloud environments, limit the use of primitive roles such as "Owner", "Editor", and "Viewer" for Cloud IAM members. Instead, grant predefined roles to these IAM members to allow the least-permissive access required to perform their tasks (i.e., Principle of Least Privilege – POLP). + impact: | + Using primitive roles can lead to overly broad access and potential security vulnerabilities, as these roles can grant extensive permissions across a wide range of resources. + remediation: | + Replace primitive roles with predefined or custom roles tailored to the specific needs of the users and the minimum permissions they require to perform their tasks. + reference: + - https://cloud.google.com/iam/docs/understanding-roles + tags: cloud,devops,gcp,gcloud,google-cloud-iam,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let binding of iterate(template.bindings)){ + set("binding", binding) + javascript(1) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud projects get-iam-policy $projectId --format=json + + extractors: + - type: json + name: bindings + internal: true + json: + - '.bindings[]' + +javascript: + - code: | + let binding = JSON.parse(template.binding); + let role = binding.role; + let members = binding.members.join(", "); + let projectId = template.projectId; + let primitiveRoles = ["roles/owner", "roles/editor", "roles/viewer"]; + if (primitiveRoles.includes(role)) { + Export("Primitive role " + role + " used by members " + members + " in Project " + projectId); + } + + extractors: + - type: dsl + dsl: + - response diff --git a/cloud/gcp/iam/gcp-iam-separation-duties.yaml b/cloud/gcp/iam/gcp-iam-separation-duties.yaml new file mode 100644 index 00000000000..bab4b0a4f5e --- /dev/null +++ b/cloud/gcp/iam/gcp-iam-separation-duties.yaml @@ -0,0 +1,72 @@ +id: gcp-iam-separation-duties + +info: + name: Enforce Separation of Duties for Service-Account Related Roles + author: princechaddha + severity: medium + description: | + Ensure that separation of duties is enforced for all Google Cloud Platform (GCP) service-account related roles. This security principle prevents fraud and human error by dispersing the tasks and associated privileges for a specific business process among multiple users/members. Specifically, your GCP service accounts should not have the Service Account Admin and Service Account User roles assigned simultaneously. + impact: | + Failure to enforce separation of duties can lead to potential security risks including fraud and error due to excessive privileges assigned to single users. + remediation: | + Review and modify the roles assigned to GCP service accounts ensuring that no service account has both the Service Account Admin and Service Account User roles assigned at the same time. + reference: + - https://cloud.google.com/iam/docs/understanding-roles + tags: cloud,devops,gcp,gcloud,google-cloud-iam,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let binding of iterate(template.bindings)){ + set("binding", binding) + javascript(1) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud projects get-iam-policy $projectId --format="json" + + extractors: + - type: json + name: bindings + internal: true + json: + - '.bindings[]' + +javascript: + - code: | + if (template.binding && Array.isArray(template.binding.members) && template.binding.role) { + let roles = new Set(); + template.binding.members.forEach(member => { + roles.add(template.binding.role); + }); + if (roles.has('roles/iam.serviceAccountAdmin') && roles.has('roles/iam.serviceAccountUser')) { + Export("Violation of SoD: Both Service Account Admin and User roles are assigned to one or more members in Project: " + template.projectId); + } + } + + extractors: + - type: dsl + dsl: + - response diff --git a/cloud/gcp/iam/gcp-iam-service-roles-project-level.yaml b/cloud/gcp/iam/gcp-iam-service-roles-project-level.yaml new file mode 100644 index 00000000000..f352cc1266f --- /dev/null +++ b/cloud/gcp/iam/gcp-iam-service-roles-project-level.yaml @@ -0,0 +1,68 @@ +id: gcp-iam-service-roles-project-level + +info: + name: Service Account Roles at Project Level + author: princechaddha + severity: medium + description: | + Ensure that the Service Account User and Service Account Token Creator roles are assigned to a user for a specific GCP service account rather than to a user at the GCP project level, in order to implement the principle of least privilege (POLP). The principle of least privilege (also known as the principle of minimal privilege) is the practice of providing every user the minimal amount of access required to perform its tasks. The Service Account User (iam.serviceAccountUser) role allows an IAM user to attach a service account to a long-running job service such as an App Engine App or Dataflow Job, whereas the Service Account Token Creator (iam.serviceAccountTokenCreator) role allows a user to directly impersonate the identity of a service account. + impact: | + Assigning critical roles such as Service Account User and Token Creator at the project level can lead to excessive permissions that can be exploited. + remediation: | + Ensure these roles are assigned directly to service accounts and not at the project level to enforce the principle of least privilege. + reference: + - https://cloud.google.com/iam/docs/understanding-roles + tags: cloud,devops,gcp,gcloud,google-cloud-iam,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let binding of iterate(template.bindings)){ + set("binding", binding) + javascript(1); + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud projects get-iam-policy $projectId --format=json + + extractors: + - type: json + name: bindings + internal: true + json: + - '.bindings[]' + +javascript: + - code: | + let binding = JSON.parse(template.binding); + let projectId = template.projectId; + if (binding.role == "roles/iam.serviceAccountUser" && binding.role == "roles/iam.serviceAccountTokenCreator"){ + Export("Service Role Misconfiguration for role " + binding.role + " for member " + binding.members + " in Project " + projectId); + } + + extractors: + - type: dsl + dsl: + - response diff --git a/cloud/gcp/iam/gcp-service-account-user-keys.yaml b/cloud/gcp/iam/gcp-service-account-user-keys.yaml new file mode 100644 index 00000000000..c40e6dc19a3 --- /dev/null +++ b/cloud/gcp/iam/gcp-service-account-user-keys.yaml @@ -0,0 +1,71 @@ +id: gcp-service-account-user-keys + +info: + name: User-Managed Service Account Keys Found + author: princechaddha + severity: medium + description: | + Ensure that your Google Cloud Platform (GCP) user-managed service accounts are using GCP-managed keys instead of user-managed keys for authentication. For user-managed key pairs, key management operations such as key storage, key distribution, key revocation, key recovery, and key rotation, as well as key protection against unauthorized access, are your responsibilities. + impact: | + Using user-managed keys can lead to potential security risks such as unauthorized access if keys are not properly managed and secured. + remediation: | + Transition to using GCP-managed keys for service accounts to ensure key management is handled by Google Cloud, thereby enhancing security and reducing the administrative burden of manual key management. + reference: + - https://cloud.google.com/iam/docs/managing-service-account-keys + tags: cloud,devops,gcp,gcloud,google-cloud-iam,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let email of iterate(template.emails)){ + set("email", email) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud iam service-accounts list --project $projectId --format="json(email)" + + extractors: + - type: json + name: emails + internal: true + json: + - '.[].email' + + - engine: + - sh + - bash + source: | + gcloud iam service-accounts keys list --iam-account=$email --managed-by=user --format="json" + + matchers: + - type: word + words: + - 'KEY_ID' + + extractors: + - type: dsl + dsl: + - '"User-Managed Keys Found in Service Account " + email + " in project " + projectId' diff --git a/cloud/gcp/kms/gcloud-kms-public-access.yaml b/cloud/gcp/kms/gcloud-kms-public-access.yaml new file mode 100644 index 00000000000..0935786cbdb --- /dev/null +++ b/cloud/gcp/kms/gcloud-kms-public-access.yaml @@ -0,0 +1,73 @@ +id: gcloud-kms-public-access + +info: + name: Publicly Accessible Google Cloud KMS Keys + author: princechaddha + severity: high + description: | + Ensure that the IAM policy associated with your Google Cloud Key Management Service (KMS) keys restricts anonymous and/or public access. The KMS cryptographic keys are controlled by Cloud IAM policies, which should not include bindings for "allUsers" and "allAuthenticatedUsers" to prevent public internet access. + impact: | + If a KMS key is accessible to "allUsers" or "allAuthenticatedUsers", it means any internet user can access this cryptographic resource, potentially leading to unauthorized data access or manipulation. + remediation: | + Update the IAM policy for your KMS keys by removing any bindings that include "allUsers" or "allAuthenticatedUsers" to restrict access to authenticated and authorized users only. + reference: + - https://cloud.google.com/kms/docs/restricting-access + tags: cloud,devops,gcp,gcloud,google-kms,gcp-cloud-config + +flow: | + code(1) + for(let keyRing of iterate(template.keyRings)){ + set("keyRing", keyRing) + code(2) + for(let key of iterate(template.keys)){ + set("keyName", key) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud kms keyrings list --location=global --format="json(name)" + + extractors: + - type: json + name: keyRings + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud kms keys list --keyring=$keyRing --location=global --format="json(name)" + + extractors: + - type: json + name: keys + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud kms keys get-iam-policy $keyName --keyring=$keyRing --location=global --format="json" + + matchers: + - type: word + words: + - "allUsers" + - "allAuthenticatedUsers" + condition: or + + extractors: + - type: dsl + dsl: + - '"Public Access found in KMS Key: " + keyName + ", KeyRing: " + keyRing + ", Location: Global"' diff --git a/cloud/gcp/loadbalancing/gcloud-alb-ssl-google-managed.yaml b/cloud/gcp/loadbalancing/gcloud-alb-ssl-google-managed.yaml new file mode 100644 index 00000000000..1feacd2034c --- /dev/null +++ b/cloud/gcp/loadbalancing/gcloud-alb-ssl-google-managed.yaml @@ -0,0 +1,92 @@ +id: gcloud-alb-ssl-google-managed + +info: + name: Use Google-Managed SSL Certificates for Application Load Balancers + author: princechaddha + severity: high + description: | + Ensure that your external Application Load Balancers (ALBs) are configured to use Google-managed SSL certificates instead of self-signed certificates in order to avoid triggering browser warnings and adding distrust for users visiting your site. + impact: | + Using self-signed certificates can lead to browser warnings, which can deter users from visiting your site and reduce the trustworthiness of your service. + remediation: | + Configure your Application Load Balancers to use Google-managed SSL certificates to ensure trust and proper security standards. + reference: + - https://cloud.google.com/load-balancing/docs/ssl-certificates + tags: cloud,devops,gcp,gcloud,google-cloud-load-balancing,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let urlMap of iterate(template.urlMaps)){ + set("urlMap", urlMap) + code(3) + let filteredProxies = template.targetProxies.filter(proxy => proxy.urlMap === urlMap) + for(let proxy of filteredProxies){ + proxy = JSON.parse(proxy) + set("targetProxy", proxy.name) + set("sslCertificate", proxy.sslCertificates[0]) + code(4) + } + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute url-maps list --project $projectId --format="json(name)" + + extractors: + - type: json + name: urlMaps + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute target-https-proxies list --project $projectId --global --format="json(name,urlMap,sslCertificates)" + + extractors: + - type: json + name: targetProxies + internal: true + json: + - '.[] | {name, urlMap, sslCertificates}' + + - engine: + - sh + - bash + source: | + gcloud certificate-manager certificates describe $sslCertificate --project $projectId + + matchers: + - type: word + part: body + words: + - "NOT_FOUND" + + extractors: + - type: dsl + dsl: + - '"ALB with non-managed SSL certificate: " + urlMap + ", Proxy: " + targetProxy + ", Certificate: " + sslCertificate + ", Project: " + projectId' diff --git a/cloud/gcp/loadbalancing/gcloud-approved-external-lb.yaml b/cloud/gcp/loadbalancing/gcloud-approved-external-lb.yaml new file mode 100644 index 00000000000..589696eabd0 --- /dev/null +++ b/cloud/gcp/loadbalancing/gcloud-approved-external-lb.yaml @@ -0,0 +1,92 @@ +id: gcloud-approved-external-lb + +info: + name: Unapproved External Load Balancers in Google Cloud Projects + author: princechaddha + severity: medium + description: | + Ensure that your web applications are using only approved external load balancers to comply with your organization's security and industry requirements. Using unapproved load balancers could expose your applications to vulnerabilities. The approved load balancers must be defined in the conformity rule settings, in the Trend Cloud One™ – Conformity account console. + impact: | + Using unapproved load balancers can expose web applications to potential security vulnerabilities. + remediation: | + Ensure all used external load balancers are approved in the Trend Cloud One™ – Conformity account console. Replace unapproved load balancers with approved ones. + reference: + - https://cloud.google.com/load-balancing/docs + tags: cloud,devops,gcp,gcloud,google-cloud-load-balancing,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let urlMap of iterate(template.urlMaps)){ + set("urlMap", urlMap) + code(3) + for(let targetHttpProxy of iterate(template.targetHttpProxies)){ + set("targetHttpProxy", targetHttpProxy) + code(4) + for(let forwardingRule of iterate(template.forwardingRules)){ + log(forwardingRule) + code(5) + } + } + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute url-maps list --project $projectId --format="json(name)" + + extractors: + - type: json + name: urlMaps + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute target-http-proxies list --project $projectId --format="json(name,urlMap)" + + extractors: + - type: json + name: targetHttpProxies + internal: true + json: + - '.[] | {name: .name, urlMap: .urlMap}' + + - engine: + - sh + - bash + source: | + gcloud compute forwarding-rules list --project $projectId --format="json(name,loadBalancingScheme,target)" + + matchers: + - type: word + words: + - 'EXTERNAL_MANAGED' + + extractors: + - type: dsl + dsl: + - '"Unapproved External Load Balancer in project: " + projectId + ", Load Balancer: " + name' diff --git a/cloud/gcp/loadbalancing/gcloud-https-lb-logging-disabled.yaml b/cloud/gcp/loadbalancing/gcloud-https-lb-logging-disabled.yaml new file mode 100644 index 00000000000..40fbd9b1cf7 --- /dev/null +++ b/cloud/gcp/loadbalancing/gcloud-https-lb-logging-disabled.yaml @@ -0,0 +1,88 @@ +id: gcloud-https-lb-logging-disabled + +info: + name: Logging Disabled on HTTP(S) Load Balancers + author: princechaddha + severity: high + description: | + Ensure that your Google Cloud HTTP(S) load balancers are configured to log all network traffic. Enabling logging on HTTP(S) load balancers is crucial for diagnosing issues and ensuring transparency in traffic management. + impact: | + Not having logging enabled on HTTP(S) load balancers can obscure the visibility into traffic patterns and potential security threats, making it difficult to perform accurate diagnostics and incident response. + remediation: | + Enable logging on all Google Cloud HTTP(S) load balancers by configuring the logConfig.enable setting to true in the backend services settings. + reference: + - https://cloud.google.com/load-balancing/docs/https + tags: cloud,devops,gcp,gcloud,google-cloud-load-balancing,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let urlMapName of iterate(template.urlMaps)){ + set("urlMapName", urlMapName) + code(3) + for(let backendServiceName of iterate(template.backendServices)){ + set("backendServiceName", backendServiceName) + code(4) + } + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute url-maps list --project $projectId --format="json(name)" + + extractors: + - type: json + name: urlMaps + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute url-maps describe $urlMapName --project $projectId --format="json(defaultService)" + + extractors: + - type: json + name: backendServices + internal: true + json: + - '.defaultService' + + - engine: + - sh + - bash + source: | + gcloud compute backend-services describe $backendServiceName --project $projectId --format="json(logConfig.enable)" + + matchers: + - type: word + words: + - 'false' + + extractors: + - type: dsl + dsl: + - '"Logging is disabled on load balancer " + urlMapName + " on backend service " + backendServiceName + " in project " + projectId' diff --git a/cloud/gcp/loadbalancing/gcloud-lb-backend-unsecured.yaml b/cloud/gcp/loadbalancing/gcloud-lb-backend-unsecured.yaml new file mode 100644 index 00000000000..6c418513aa6 --- /dev/null +++ b/cloud/gcp/loadbalancing/gcloud-lb-backend-unsecured.yaml @@ -0,0 +1,89 @@ +id: gcloud-lb-backend-unsecured + +info: + name: Unsecured Backend Services in Google Cloud Load Balancers + author: princechaddha + severity: medium + description: | + Ensure that the backend services associated with your Google Cloud load balancers are protected with edge security policies provided by the Cloud Armor service in order to shield your backend services from a range of potential attacks. Edge security policies let you control access to your cloud resources at the Google Cloud Platform (GCP) network edge. + impact: | + Without edge security policies, backend services are vulnerable to a variety of network-based attacks, which can compromise data integrity and availability. + remediation: | + Attach an edge security policy to your backend services via the Google Cloud Console or using the Cloud Armor APIs to enhance security at your network's edge. + reference: + - https://cloud.google.com/armor/docs/security-policy-overview + tags: cloud,devops,gcp,gcloud,google-cloud-load-balancer,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let urlMapName of iterate(template.urlMaps)){ + set("urlMapName", urlMapName) + code(3) + for(let backendService of iterate(template.backendServices)){ + set("backendService", backendService) + log(backendService) + code(4) + } + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute url-maps list --project $projectId --format="json(name)" + + extractors: + - type: json + name: urlMaps + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute url-maps describe $urlMapName --format="json(defaultService)" + + extractors: + - type: json + name: backendServices + internal: true + json: + - '.defaultService' + + - engine: + - sh + - bash + source: | + gcloud compute backend-services describe $backendService --format="json(securityPolicy)" + + matchers: + - type: word + words: + - 'null' + + extractors: + - type: dsl + dsl: + - '"Unsecured Backend Service " + backendService + " for URL Map " + urlMapName + " in Project " + projectId' diff --git a/cloud/gcp/loadbalancing/gcloud-loadbalancer-https-unenforced.yaml b/cloud/gcp/loadbalancing/gcloud-loadbalancer-https-unenforced.yaml new file mode 100644 index 00000000000..032ef9d3508 --- /dev/null +++ b/cloud/gcp/loadbalancing/gcloud-loadbalancer-https-unenforced.yaml @@ -0,0 +1,89 @@ +id: gcloud-loadbalancer-https-unenforced + +info: + name: Enable HTTPS for Google Cloud Load Balancers + author: princechaddha + severity: high + description: | + Ensure that your Google Cloud Platform (GCP) load balancers are configured to use valid SSL/TLS certificates to handle encrypted web traffic. SSL certificate resources contain SSL certificate information that the load balancer uses to terminate SSL/TLS when HTTPS clients connect to it. + impact: | + Load balancers without SSL/TLS certification are vulnerable to data breaches as unencrypted data can be easily intercepted and manipulated. + remediation: | + Configure your load balancers to use valid SSL/TLS certificates and enable HTTPS to ensure encrypted communications between clients and the load balancer. + reference: + - https://cloud.google.com/load-balancing/docs/ssl-certificates + tags: cloud,devops,gcp,gcloud,google-cloud-load-balancer,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let urlMap of iterate(template.urlMaps)){ + set("urlMap", urlMap) + code(3) + let httpsUnenforced = true; + for(let targetProxy of iterate(template.targetProxies)){ + if(urlMap === targetProxy.urlMap){ + httpsUnenforced = false; + break; + } + } + if(httpsUnenforced){ + javascript(1); + } + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute url-maps list --project $projectId --format="json(name)" + + extractors: + - type: json + name: urlMaps + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute target-https-proxies list --project $projectId --format="json(name, urlMap)" + + extractors: + - type: json + name: targetProxies + internal: true + json: + - '.[] | {name: .name, urlMap: .urlMap}' + +javascript: + - code: | + let urlMap = template.urlMap; + let projectId = template.projectId; + Export("HTTPS Not Enforced: URL Map " + urlMap + " in Project " + projectId); + + extractors: + - type: dsl + dsl: + - response diff --git a/cloud/gcp/loadbalancing/gcloud-ssl-policy-insecure-ciphers.yaml b/cloud/gcp/loadbalancing/gcloud-ssl-policy-insecure-ciphers.yaml new file mode 100644 index 00000000000..06f183c56d5 --- /dev/null +++ b/cloud/gcp/loadbalancing/gcloud-ssl-policy-insecure-ciphers.yaml @@ -0,0 +1,93 @@ +id: gcloud-ssl-policy-insecure-ciphers + +info: + name: Insecure SSL Cipher Suites in GCP Load Balancers + author: princechaddha + severity: medium + description: | + This check scans SSL policies of Google Cloud HTTPS and SSL Proxy load balancers to identify insecure cipher suites. It ensures SSL policies use TLS 1.2 with secure profiles and exclude weak ciphers. + impact: | + Insecure cipher suites can lead to vulnerabilities, allowing attackers to decrypt or intercept data. + remediation: | + Ensure SSL policies use MODERN or RESTRICTED profiles, or a secure CUSTOM profile without weak ciphers. + reference: + - https://cloud.google.com/load-balancing/docs/ssl-policies + tags: cloud,devops,gcp,gcloud,google-cloud-load-balancing,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let proxy of iterate(template.httpsProxies)){ + set("sslPolicy", proxy.sslPolicy) + code(4) + } + code(3) + for(let proxy of iterate(template.sslProxies)){ + set("sslPolicy", proxy.sslPolicy) + code(4) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + internal: true + name: projectIds + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute target-https-proxies list --project $projectId --format="json(name,sslPolicy)" + + extractors: + - type: json + internal: true + name: httpsProxies + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute target-ssl-proxies list --project $projectId --format="json(name,sslPolicy)" + + extractors: + - type: json + internal: true + name: sslProxies + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute ssl-policies describe $sslPolicy --format="json(minTlsVersion,profile,enabledFeatures)" + + matchers: + - type: word + words: + - 'TLS_1_0' + - 'TLS_RSA_WITH_AES_128_GCM_SHA256' + - 'TLS_RSA_WITH_AES_256_GCM_SHA384' + - 'TLS_RSA_WITH_AES_128_CBC_SHA' + - 'TLS_RSA_WITH_AES_256_CBC_SHA' + - 'TLS_RSA_WITH_3DES_EDE_CBC_SHA' + + - type: dsl + dsl: + - '"Insecure SSL Policy Detected in Proxy: " + sslPolicy + " in Project: " + projectId' diff --git a/cloud/gcp/logging/gcloud-enable-data-access-audit-logging.yaml b/cloud/gcp/logging/gcloud-enable-data-access-audit-logging.yaml new file mode 100644 index 00000000000..9864e56d96b --- /dev/null +++ b/cloud/gcp/logging/gcloud-enable-data-access-audit-logging.yaml @@ -0,0 +1,61 @@ +id: gcloud-enable-data-access-audit-logging + +info: + name: Enable Data Access Audit Logging for All Critical Service APIs + author: princechaddha + severity: medium + description: | + Ensure that data access audit logging is enabled for all critical service APIs in your Google Cloud project for security, compliance, and troubleshooting purposes. The critical service APIs that you can enable for your GCP project include but are not limited to Identity and Access Management (IAM) API (iam.googleapis.com), Compute Engine API (compute.googleapis.com), Cloud Storage (storage-component.googleapis.com), Google Cloud Pub/Sub API (pubsub.googleapis.com), Cloud Key Management Service (KMS) API (cloudkms.googleapis.com), and Cloud Logging API (logging.googleapis.com). + impact: | + Without enabling data access audit logging, you may miss critical details for compliance, security investigations, and operational troubleshooting, exposing your environment to potential risks. + remediation: | + Configure the IAM policy of your Google Cloud project to include the "auditConfigs" configuration object that enables data access audit logging for all critical APIs. + reference: + - https://cloud.google.com/logging/docs/audit/configure-data-access + tags: cloud,devops,gcp,gcloud,google-cloud-iam,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud projects get-iam-policy $projectId --format=json + + matchers-condition: and + matchers: + - type: word + words: + - '"auditConfigs"' + condition: and + negative: true + + - type: word + words: + - '"bindings":' + + extractors: + - type: dsl + dsl: + - '"Audit logging not enabled for all services in project: " + projectId' diff --git a/cloud/gcp/logging/gcloud-global-logging-not-enabled.yaml b/cloud/gcp/logging/gcloud-global-logging-not-enabled.yaml new file mode 100644 index 00000000000..ac330f421d4 --- /dev/null +++ b/cloud/gcp/logging/gcloud-global-logging-not-enabled.yaml @@ -0,0 +1,68 @@ +id: gcloud-logging-global-buckets-check + +info: + name: Logging Buckets Not Configured with Global Location + author: princechaddha + severity: medium + description: | + Checks if Cloud Logging buckets are configured with a global location scope to ensure centralized log management and consistent access control. + impact: | + Logging buckets not configured with a global location can result in fragmented log storage and difficulty in maintaining centralized logging practices. + remediation: | + Update Cloud Logging buckets to use the global location scope to enable centralized logging across all regions. + reference: + - https://cloud.google.com/logging/docs/export/configure_export_v2 + tags: cloud,devops,gcp,gcloud,google-cloud-logging,logging-buckets,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for (let bucket of template.buckets) { + set("bucket", bucket); + javascript(1); + }} + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud logging buckets list --project $projectId --format="json(name,location)" + + extractors: + - type: json + name: buckets + internal: true + json: + - '.[].name' + +javascript: + - code: | + bucket = template.bucket + log(bucket) + if (!bucket.includes('/global/')) { + let result = `Bucket '${bucket}' is not configured with a global location.`; + Export(result); + } + + extractors: + - type: dsl + dsl: + - response diff --git a/cloud/gcp/logging/gcloud-iam-ownership-monitoring-disabled.yaml b/cloud/gcp/logging/gcloud-iam-ownership-monitoring-disabled.yaml new file mode 100644 index 00000000000..2033a9d3feb --- /dev/null +++ b/cloud/gcp/logging/gcloud-iam-ownership-monitoring-disabled.yaml @@ -0,0 +1,107 @@ +id: gcloud-iam-ownership-monitoring-disabled + +info: + name: Enable Project Ownership Assignments Monitoring + author: princechaddha + severity: medium + description: | + Ensure that each Google Cloud Platform (GCP) project has configured an alerting policy to monitor IAM ownership assignments. The alerting policy should trigger notifications whenever the "Owner" role is granted or removed for any IAM member. + impact: | + Without monitoring IAM ownership assignments, unauthorized role changes may go undetected, leading to potential security risks and non-compliance with organizational policies. + remediation: | + Configure a GCP alerting policy to monitor IAM ownership assignments by using a logs-based metric with the required filter. Ensure the alerting policy is enabled and properly configured with valid notification channels. + reference: + - https://cloud.google.com/logging/docs/export/configure_export_v2 + - https://cloud.google.com/monitoring/alerts/concepts-indepth + tags: cloud,devops,gcp,gcloud,iam,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let loggingMetric of iterate(template.loggingMetrics)){ + set("loggingMetric", loggingMetric) + code(3) + for(let alertPolicy of iterate(template.alertPolicies)){ + set("alertPolicy", alertPolicy) + code(4) + } + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud logging metrics list --project=$projectId --format="json(name)" + + extractors: + - type: json + name: loggingMetrics + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud logging metrics describe $loggingMetric --project=$projectId --format="json(filter)" + + matchers: + - type: regex + regex: + - 'resource\.type=global AND \(protoPayload\.serviceName=cloudresourcemanager\.googleapis\.com\) AND \(ProjectOwnership OR projectOwnerInvitee\) OR \(protoPayload\.serviceData\.policyDelta\.bindingDeltas\.action=REMOVE AND protoPayload\.serviceData\.policyDelta\.bindingDeltas\.role=roles/owner\) OR \(protoPayload\.serviceData\.policyDelta\.bindingDeltas\.action=ADD AND protoPayload\.serviceData\.policyDelta\.bindingDeltas\.role=roles/owner\)' + + extractors: + - type: dsl + dsl: + - '"Metric filter valid for monitoring ownership changes in project: " + projectId + ", metric: " + loggingMetric' + + - engine: + - sh + - bash + source: | + gcloud alpha monitoring policies list --project=$projectId --format="json(name)" + + extractors: + - type: json + name: alertPolicies + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud alpha monitoring policies describe $alertPolicy --project=$projectId --format="json(enabled,conditions,notificationChannels)" + + matchers: + - type: word + words: + - '"enabled": false' + - '"notificationChannels": []' + condition: or + + extractors: + - type: dsl + dsl: + - '"Non-compliant alerting policy detected: " + alertPolicy + " in project: " + projectId' \ No newline at end of file diff --git a/cloud/gcp/logging/gcloud-log-retention-period-insufficient.yaml b/cloud/gcp/logging/gcloud-log-retention-period-insufficient.yaml new file mode 100644 index 00000000000..9b11eb6531e --- /dev/null +++ b/cloud/gcp/logging/gcloud-log-retention-period-insufficient.yaml @@ -0,0 +1,83 @@ +id: gcloud-log-retention-period-insufficient + +info: + name: Insufficient Log Data Retention Period in Cloud Logging Buckets + author: princechaddha + severity: high + description: | + For security, reliability, and compliance purposes, ensure that your Cloud Logging buckets are configured with a data retention period of 365 days or more. A Cloud Logging bucket is a container that stores log data from cloud services such as Compute Engine and App Engine. The retention period represents the number of days to retain log data for a user-defined log bucket and also for the _Default log bucket. + impact: | + Configuring a log retention period of less than 365 days can lead to potential data loss, hinder forensic investigations, and result in non-compliance with data retention policies. + remediation: | + Update the retention period for your Cloud Logging buckets to 365 days or more using the Google Cloud CLI or the Console to ensure compliance with best practices. + reference: + - https://cloud.google.com/logging/docs/export/configure_storage + tags: cloud,devops,gcp,gcloud,google-cloud-logging,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let bucket of iterate(template.buckets)){ + set("bucket", bucket); + code(3) + set("retentionDays", template.retentionDays); + javascript(1) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud logging buckets list --project=$projectId --format="json(name.basename())" + + extractors: + - type: json + name: buckets + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud logging buckets describe $bucket --project=$projectId --location=global --format="json(retentionDays)" + + extractors: + - type: json + name: retentionDays + internal: true + json: + - '.retentionDays' + +javascript: + - code: | + let retentionDays = template.retentionDays + if (retentionDays < 365) { + let result = `Bucket '${template.bucket}' in project '${template.projectId}' has insufficient log retention period (${retentionDays} days).`; + Export(result); + } + + extractors: + - type: dsl + dsl: + - response diff --git a/cloud/gcp/logging/gcloud-logging-sink-not-configured.yaml b/cloud/gcp/logging/gcloud-logging-sink-not-configured.yaml new file mode 100644 index 00000000000..9b0fcc17a68 --- /dev/null +++ b/cloud/gcp/logging/gcloud-logging-sink-not-configured.yaml @@ -0,0 +1,55 @@ +id: gcloud-logging-sink-not-configured + +info: + name: Export All Log Entries Using Sinks Not Configured + author: princechaddha + severity: medium + description: | + Ensure there is at least one sink used to export copies of all the log entries available within your Google Cloud Platform (GCP) project. A sink is an object created to hold a log query and a destination. You can export logs by creating one or more log sinks that include a log query and an export destination. As Google Cloud Logging service receives new log entries, they are compared against each sink. If a log entry matches a sink object query, then a copy of the log entry is written to the sink's export destination. + impact: | + If no sinks are configured to export all log entries, critical log data might be lost or inaccessible for analysis, leading to potential security risks and compliance violations. + remediation: | + Create a log sink with a blank filter to export all log entries within the project. Ensure the export destination aligns with your organizational logging strategy. + reference: + - https://cloud.google.com/logging/docs/export/configure_export_v2 + tags: cloud,devops,gcp,gcloud,google-cloud-logging,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud logging sinks list --project=$projectId --format="json(name,filter)" + + matchers: + - type: word + words: + - '(empty filter)' + condition: and + + extractors: + - type: dsl + dsl: + - '"No log sinks configured to export all entries in project: " + projectId' diff --git a/cloud/gcp/logging/gcloud-logs-router-cmek-not-enabled.yaml b/cloud/gcp/logging/gcloud-logs-router-cmek-not-enabled.yaml new file mode 100644 index 00000000000..08b01ff859c --- /dev/null +++ b/cloud/gcp/logging/gcloud-logs-router-cmek-not-enabled.yaml @@ -0,0 +1,34 @@ +id: gcloud-logs-router-cmek-not-enabled + +info: + name: Logs Router Encryption with Customer-Managed Keys Not Enabled + author: princechaddha + severity: high + description: | + Ensure that Google Cloud Logs Router data is encrypted with Customer-Managed Keys (CMKs) to provide full control over your data encryption and decryption process and to help meet compliance requirements. Using Cloud Key Management Service (Cloud KMS), you can create and manage your CMKs, ensuring secure and efficient encryption key management, controlled key rotation, and revocation mechanisms. + impact: | + Without Customer-Managed Keys (CMKs) encryption, your Logs Router data may not meet organizational compliance requirements and is not protected by keys you control, potentially exposing sensitive information to unauthorized access. + remediation: | + Enable Customer-Managed Keys (CMKs) for Logs Router encryption within your GCP organization by configuring Cloud KMS keys and associating them with the Logs Router service. Ensure the CMKs are properly managed and rotated per compliance requirements. + reference: + - https://cloud.google.com/logging/docs/routing/managed-encryption + tags: cloud,devops,gcp,gcloud,google-cloud-logging,gcp-cloud-config + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud alpha logging cmek-settings describe --organization=$organization --format="json(kmsKeyName)" + + matchers: + - type: word + words: + - 'null' + + extractors: + - type: dsl + dsl: + - '"Logs Router Encryption with CMK not enabled for your organization"' diff --git a/cloud/gcp/logging/gcloud-vpc-network-changes-monitoring-not-enabled.yaml b/cloud/gcp/logging/gcloud-vpc-network-changes-monitoring-not-enabled.yaml new file mode 100644 index 00000000000..55f93e3defe --- /dev/null +++ b/cloud/gcp/logging/gcloud-vpc-network-changes-monitoring-not-enabled.yaml @@ -0,0 +1,144 @@ +id: gcloud-vpc-network-changes-monitoring-not-enabled + +info: + name: Enable VPC Network Changes Monitoring + author: princechaddha + severity: medium + description: | + Ensure that each Google Cloud Platform (GCP) project has configured an alerting policy that is triggered each time a Virtual Private Cloud (VPC) network change is made. The log filter pattern used to recognize VPC network changes is "resource.type=gce_network AND protoPayload.methodName=beta.compute.networks.insert OR protoPayload.methodName=beta.compute.networks.patch OR protoPayload.methodName=v1.compute.networks.delete OR protoPayload.methodName=v1.compute.networks.removePeering OR protoPayload.methodName=v1.compute.networks.addPeering". + impact: | + If VPC network changes monitoring is not enabled, critical network modifications may go undetected, leading to potential security risks and compliance violations. + remediation: | + Configure a logs-based metric with the specified filter pattern and create an alerting policy to monitor Virtual Private Cloud (VPC) network changes for all GCP projects. + reference: + - https://cloud.google.com/monitoring/alerts + - https://cloud.google.com/logging/docs/audit + tags: cloud,devops,gcp,gcloud,vpc,google-cloud-monitoring,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let metric of iterate(template.metrics)){ + set("metricName", metric) + code(3) + } + for(let policy of iterate(template.policies)){ + set("policyName", policy) + code(4) + for(let channel of iterate(template.channels)){ + set("channelName", channel) + code(5) + } + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud logging metrics list --project=$projectId --format="json(name)" + + extractors: + - type: json + name: metrics + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud logging metrics describe $metricName --project=$projectId --format="json(filter)" + + matchers: + - type: word + words: + - 'resource.type=gce_network' + - 'protoPayload.methodName=beta.compute.networks.insert' + - 'protoPayload.methodName=beta.compute.networks.patch' + - 'protoPayload.methodName=v1.compute.networks.delete' + - 'protoPayload.methodName=v1.compute.networks.removePeering' + - 'protoPayload.methodName=v1.compute.networks.addPeering' + condition: or + + extractors: + - type: dsl + dsl: + - '"Missing logs-based metric with required filter in project: " + projectId + ", Metric: " + metricName' + + - engine: + - sh + - bash + source: | + gcloud alpha monitoring policies list --project=$projectId --format="json(name)" + + extractors: + - type: json + name: policies + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud alpha monitoring policies describe $policyName --project=$projectId --format="json(conditions,enabled)" + + matchers: + - type: word + words: + - '"enabled": false' + + extractors: + - type: dsl + dsl: + - '"Alerting policy not enabled or missing required condition in project: " + projectId + ", Policy: " + policyName' + + - engine: + - sh + - bash + source: | + gcloud alpha monitoring channels list --project=$projectId --format="json(name)" + + extractors: + - type: json + name: channels + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud alpha monitoring channels describe $channelName --project=$projectId --format="json(enabled)" + + matchers: + - type: word + words: + - '"enabled": false' + + extractors: + - type: dsl + dsl: + - '"Notification channel not enabled or misconfigured in project: " + projectId + ", Channel: " + channelName' diff --git a/cloud/gcp/nat/gcloud-iam-least-privilege-nat.yaml b/cloud/gcp/nat/gcloud-iam-least-privilege-nat.yaml new file mode 100644 index 00000000000..6179c6be545 --- /dev/null +++ b/cloud/gcp/nat/gcloud-iam-least-privilege-nat.yaml @@ -0,0 +1,58 @@ +id: gcloud-iam-least-privilege-nat + +info: + name: Least Privilege Access for Cloud NAT Management + author: princechaddha + severity: medium + description: | + Ensure that IAM roles with administrative permissions are not assigned to IAM identities (users, groups, and service accounts) managing Cloud NAT resources. This helps enforce the Principle of Least Privilege (POLP) by granting members (principals) only the minimum access necessary to complete their tasks. + impact: | + Assigning administrative permissions to IAM identities managing Cloud NAT resources can result in over-privileged access, increasing the risk of security incidents and non-compliance with security best practices. + remediation: | + Review the IAM roles assigned to IAM identities managing Cloud NAT and ensure only least-privilege roles such as `roles/compute.networkUser` are assigned. + reference: + - https://cloud.google.com/iam/docs/understanding-roles + - https://cloud.google.com/nat/docs/overview + tags: cloud,devops,gcp,gcloud,iam,cloud-nat,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud projects get-iam-policy $projectId --format="json(bindings)" + + matchers: + - type: word + words: + - '"roles/owner"' + - '"roles/editor"' + - '"roles/compute.networkAdmin"' + condition: or + + extractors: + - type: dsl + dsl: + - '"Overprivileged role found in project: " + projectId' diff --git a/cloud/gcp/nat/gcloud-nat-logging-disabled.yaml b/cloud/gcp/nat/gcloud-nat-logging-disabled.yaml new file mode 100644 index 00000000000..1974b7e03a1 --- /dev/null +++ b/cloud/gcp/nat/gcloud-nat-logging-disabled.yaml @@ -0,0 +1,106 @@ +id: gcloud-nat-logging-disabled + +info: + name: Logging Disabled for Cloud NAT Gateways + author: princechaddha + severity: medium + description: | + Ensure that logging is enabled for your Google Cloud NAT gateways in order to log NAT connections and errors for audit and troubleshooting purposes. When logging is enabled, a log entry is generated in two scenarios: when a network connection using NAT is successfully created and when a packet is dropped due to the unavailability of NAT ports. + impact: | + If logging is disabled for Cloud NAT gateways, it can lead to the loss of critical audit and troubleshooting information, hindering effective network monitoring and issue resolution. + remediation: | + Enable logging for your Google Cloud NAT gateways by setting the `logConfig.enable` parameter to `True`. This ensures that all NAT connection and error activities are logged appropriately. + reference: + - https://cloud.google.com/nat/docs/logging + tags: cloud,devops,gcp,gcloud,google-cloud-nat,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let network of iterate(template.networks)){ + set("network", network) + code(3) + for(let router of iterate(template.routers)){ + set("router", router) + code(4) + for(let nat of iterate(template.nats)){ + set("nat", nat) + code(5) + } + } + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute networks list --project=$projectId --format="json(name)" + + extractors: + - type: json + name: networks + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute routers list --project=$projectId --filter="network:($network)" --format="json(name,region)" + + extractors: + - type: json + name: routers + internal: true + json: + - '.[].name' + - '.[].region' + + - engine: + - sh + - bash + source: | + gcloud compute routers nats list --region=$region --router=$router --format="json(name)" + + extractors: + - type: json + name: nats + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute routers nats describe $nat --region=$region --router=$router --format="json(logConfig.enable)" + + matchers: + - type: word + words: + - 'False' + + extractors: + - type: dsl + dsl: + - '"Logging is disabled for Cloud NAT Gateway: " + nat + " in Router: " + router + " of Network: " + network + " in Project: " + projectId' diff --git a/cloud/gcp/nat/gcloud-nat-private-subnet-disabled.yaml b/cloud/gcp/nat/gcloud-nat-private-subnet-disabled.yaml new file mode 100644 index 00000000000..72ac3492f66 --- /dev/null +++ b/cloud/gcp/nat/gcloud-nat-private-subnet-disabled.yaml @@ -0,0 +1,121 @@ +id: gcloud-nat-private-subnet-disabled + +info: + name: Cloud NAT Not Enabled for Private Subnets + author: princechaddha + severity: medium + description: | + Ensure that Cloud NAT is enabled for all private VPC subnets that require outbound access. Cloud NAT enables your VMs and container pods to establish outbound connections to the Internet or other Virtual Private Cloud (VPC) networks. It utilizes a Cloud NAT gateway to manage these connections efficiently. + impact: | + If Cloud NAT is not enabled, private subnets may not have outbound access, leading to connectivity issues and potential misconfigurations for workloads requiring internet or inter-network communication. + remediation: | + Configure Cloud NAT for all private subnets that require outbound access. Use Compute Engine routers to define NAT configuration and associate them with your VPC subnets. + reference: + - https://cloud.google.com/nat/docs/overview + tags: cloud,devops,gcp,gcloud,google-cloud-nat,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let networkName of iterate(template.networks)){ + set("networkName", networkName) + code(3) + for(let subnetDetail of iterate(template.subnets)){ + set("subnetDetail", subnetDetail) + code(4) + } + code(5) + for(let natGateway of iterate(template.natGateways)){ + set("natGateway", natGateway) + javascript(1) + } + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute networks list --project $projectId --format="json(name)" + + extractors: + - type: json + name: networks + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute networks subnets list --network=$networkName --project=$projectId --format="json(selfLink,privateIpGoogleAccess)" + + extractors: + - type: json + name: subnets + internal: true + json: + - '.[] | {selfLink, privateIpGoogleAccess}' + + - engine: + - sh + - bash + source: | + gcloud compute routers list --project=$projectId --filter="network:($networkName)" --format="json(name,region)" + + extractors: + - type: json + name: routers + internal: true + json: + - '.[] | {name, region}' + + - engine: + - sh + - bash + source: | + gcloud compute routers nats list --router=$router.name --region=$router.region --format="json(name,subnetworks)" + + extractors: + - type: json + name: natGateways + internal: true + json: + - '.[] | {name, subnetworks}' + +javascript: + - code: | + let subnet = template.subnetDetail; + let natGateways = template.natGateways; + let privateIpGoogleAccess = subnet.privateIpGoogleAccess; + + if (privateIpGoogleAccess === "true") { + let natEnabled = natGateways.some(gw => gw.subnetworks.includes(subnet.selfLink)); + if (!natEnabled) { + Export(`Cloud NAT is not enabled for private subnet: ${subnet.selfLink} in project: ${template.projectId}`); + } + } + + extractors: + - type: dsl + dsl: + - response diff --git a/cloud/gcp/nat/gcloud-nat-static-ip-unconfigured.yaml b/cloud/gcp/nat/gcloud-nat-static-ip-unconfigured.yaml new file mode 100644 index 00000000000..f54aa49c9ce --- /dev/null +++ b/cloud/gcp/nat/gcloud-nat-static-ip-unconfigured.yaml @@ -0,0 +1,105 @@ +id: gcloud-nat-static-ip-unconfigured + +info: + name: Cloud NAT Gateways Not Configured with Reserved Static IPs + author: princechaddha + severity: medium + description: | + Ensure that your Google Cloud NAT gateways are configured to use static reserved external IPs in order to maintain consistent outbound IP addresses, which are critical for services requiring IP allowlisting, auditing, or compliance. + impact: | + Without static reserved external IPs, Cloud NAT gateways may use ephemeral IPs, causing disruptions in services requiring IP-based restrictions and compliance requirements. + remediation: | + Configure your Google Cloud NAT gateways to use static reserved external IPs by reserving external IPs and attaching them to the NAT configuration. + reference: + - https://cloud.google.com/nat/docs/using-nat + tags: cloud,devops,gcp,gcloud,google-cloud-nat,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let networkName of iterate(template.networks)){ + set("networkName", networkName) + code(3) + for(let routerName of iterate(template.routers)){ + set("routerName", routerName) + code(4) + for(let natName of iterate(template.nats)){ + set("natName", natName) + code(5) + } + } + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute networks list --project=$projectId --format="json(name)" + + extractors: + - type: json + name: networks + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute routers list --project=$projectId --filter="network:($networkName)" --format="json(name)" + + extractors: + - type: json + name: routers + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute routers nats list --region=$region --router=$routerName --format="json(name)" + + extractors: + - type: json + name: nats + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute routers nats describe $natName --region=$region --router=$routerName --format="json(natIps)" + + matchers: + - type: word + words: + - 'null' + + extractors: + - type: dsl + dsl: + - '"Cloud NAT gateway " + natName + " under Router " + routerName + " in Network " + networkName + " of Project " + projectId + " does not have static reserved external IPs configured."' diff --git a/cloud/gcp/nat/gcloud-nat-subnet-unrestricted.yaml b/cloud/gcp/nat/gcloud-nat-subnet-unrestricted.yaml new file mode 100644 index 00000000000..771e38a2904 --- /dev/null +++ b/cloud/gcp/nat/gcloud-nat-subnet-unrestricted.yaml @@ -0,0 +1,106 @@ +id: gcloud-nat-subnet-unrestricted + +info: + name: NAT Gateway Subnets Not Restricted to Specific VPCs + author: princechaddha + severity: medium + description: | + Ensure that your Google Cloud NAT gateways are mapped only to specific VPC subnets to maintain controlled and secure outbound Internet access, minimize unintended traffic exposure, and optimize resource usage within your network design. This promotes network isolation and ensures adherence to your organization's stringent compliance requirements. + impact: | + NAT gateways associated with unrestricted subnets can result in unauthorized network access, unintended traffic exposure, and compliance violations. + remediation: | + Restrict your Cloud NAT gateways to specific VPC subnets by defining subnet mappings in the NAT configuration settings. Review and update your network configurations to ensure adherence to your organization's security policies. + reference: + - https://cloud.google.com/nat/docs/using-nat + tags: cloud,devops,gcp,gcloud,google-cloud-nat,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let vpcNetwork of iterate(template.vpcNetworks)){ + set("vpcNetwork", vpcNetwork) + code(3) + for(let router of iterate(template.routers)){ + set("router", router) + code(4) + for(let natGateway of iterate(template.natGateways)){ + set("natGateway", natGateway) + code(5) + } + } + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute networks list --project $projectId --format="json(name)" + + extractors: + - type: json + name: vpcNetworks + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute routers list --project $projectId --filter="network:($vpcNetwork)" --format="json(name)" + + extractors: + - type: json + name: routers + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute routers nats list --router=$router --project=$projectId --format="json(name)" + + extractors: + - type: json + name: natGateways + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute routers nats describe $natGateway --router=$router --project=$projectId --format="json(subnetworks)" + + matchers: + - type: word + words: + - 'ALL_IP_RANGES' + condition: and + + extractors: + - type: dsl + dsl: + - '"NAT gateway " + natGateway + " under router " + router + " in project " + projectId + " is associated with unrestricted subnets."' diff --git a/cloud/gcp/pubsub/gcloud-pubsub-cmek-disabled.yaml b/cloud/gcp/pubsub/gcloud-pubsub-cmek-disabled.yaml new file mode 100644 index 00000000000..e3d5c40c70d --- /dev/null +++ b/cloud/gcp/pubsub/gcloud-pubsub-cmek-disabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-pubsub-cmek-disabled + +info: + name: Pub/Sub Topics Not Encrypted with Customer-Managed Encryption Keys + author: princechaddha + severity: high + description: | + Ensure that your Google Cloud Pub/Sub topics are encrypted using Customer-Managed Encryption Keys (CMEKs) to have full control over the data encryption and decryption process. Customer-Managed Encryption Keys (CMEKs) allow you to create and manage your own encryption keys with Cloud Key Management Service (Cloud KMS). + impact: | + Not using CMEKs for Pub/Sub topics can result in less control over data encryption and potential exposure to unauthorized access. + remediation: | + Configure your Pub/Sub topics to use Customer-Managed Encryption Keys (CMEKs) by specifying a Cloud KMS key during the topic creation or update process. + reference: + - https://cloud.google.com/pubsub/docs/encryption + tags: cloud,devops,gcp,gcloud,google-cloud-pubsub,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let pubsubTopic of iterate(template.topics)){ + set("pubsubTopic", pubsubTopic) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud pubsub topics list --project $projectId --format="json(name)" + + extractors: + - type: json + name: topics + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud pubsub topics describe $pubsubTopic --format="json(kmsKeyName)" + + matchers: + - type: word + words: + - 'null' + + extractors: + - type: dsl + dsl: + - '"Pub/Sub Topic " + pubsubTopic + " in project " + projectId + " is not encrypted with Customer-Managed Encryption Key (CMEK)"' diff --git a/cloud/gcp/pubsub/gcloud-pubsub-crossproject-access.yaml b/cloud/gcp/pubsub/gcloud-pubsub-crossproject-access.yaml new file mode 100644 index 00000000000..adbeafd73da --- /dev/null +++ b/cloud/gcp/pubsub/gcloud-pubsub-crossproject-access.yaml @@ -0,0 +1,72 @@ +id: gcloud-pubsub-crossproject-access + +info: + name: Pub/Sub Subscription Cross-Project Access + author: princechaddha + severity: high + description: | + Ensure that your Google Cloud Pub/Sub subscriptions are configured to allow access only to trusted GCP projects to protect against unauthorized cross-project access. The list with the trusted GCP projects must be defined in the conformity rule settings, in the Trend Cloud One™ – Conformity account console. + impact: | + Allowing access to Pub/Sub subscriptions from untrusted GCP projects can lead to unauthorized data access, privilege escalation, and potential data exfiltration. + remediation: | + Restrict access to Pub/Sub subscriptions by configuring IAM policies to include only trusted service accounts or users. Ensure roles such as "roles/pubsub.subscriber", "roles/pubsub.editor", or "roles/pubsub.admin" are only assigned to trusted principals. + reference: + - https://cloud.google.com/pubsub/docs/access-control + - https://cloudone.trendmicro.com/docs/conformity + tags: cloud,devops,gcp,gcloud,google-cloud-pubsub,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let pubsubSubscription of iterate(template.subscriptions)){ + set("subscriptionName", pubsubSubscription) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud pubsub subscriptions list --project $projectId --format="json(name)" + + extractors: + - type: json + name: subscriptions + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud pubsub subscriptions get-iam-policy $subscriptionName --format=json | jq '.bindings[]' + + matchers: + - type: word + words: + - '@' + + extractors: + - type: dsl + dsl: + - '"Pub/Sub subscription " + subscriptionName + " in project " + projectId + " has cross-project access configured with one or more untrusted members."' diff --git a/cloud/gcp/pubsub/gcloud-pubsub-deadletter-disabled.yaml b/cloud/gcp/pubsub/gcloud-pubsub-deadletter-disabled.yaml new file mode 100644 index 00000000000..c9a6bc6447e --- /dev/null +++ b/cloud/gcp/pubsub/gcloud-pubsub-deadletter-disabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-pubsub-deadletter-disabled + +info: + name: Dead Letter Topic Not Enabled for Google Pub/Sub Subscriptions + author: princechaddha + severity: low + description: | + Ensure that each Google Cloud Pub/Sub subscription is configured to use a dead-letter topic (DLQ) to capture undeliverable messages. Pub/Sub subscriptions allow for a maximum number of delivery attempts. Messages that cannot be delivered after the maximum attempts are sent to the dead-letter topic, ensuring they can be reviewed and handled appropriately. + impact: | + Subscriptions without a dead-letter topic may result in loss of undeliverable messages, leading to potential data loss and reduced message reliability. + remediation: | + Configure a dead-letter topic for all Google Cloud Pub/Sub subscriptions to capture undeliverable messages. This ensures messages can be retained and addressed later. + reference: + - https://cloud.google.com/pubsub/docs/dead-letter-topics + tags: cloud,devops,gcp,gcloud,google-cloud-pubsub,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let topicName of iterate(template.topics)){ + set("pubsubTopic", topicName) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud pubsub topics list --project $projectId --format="json(name)" + + extractors: + - type: json + name: topics + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud pubsub subscriptions describe $pubsubTopic --format="json(deadLetterPolicy.deadLetterTopic)" + + matchers: + - type: word + words: + - 'null' + + extractors: + - type: dsl + dsl: + - '"Dead Letter Topic not enabled for Pub/Sub subscription: " + pubsubTopic + " in project: " + projectId' diff --git a/cloud/gcp/pubsub/gcloud-pubsub-publicly-accessible.yaml b/cloud/gcp/pubsub/gcloud-pubsub-publicly-accessible.yaml new file mode 100644 index 00000000000..b12ea7219de --- /dev/null +++ b/cloud/gcp/pubsub/gcloud-pubsub-publicly-accessible.yaml @@ -0,0 +1,73 @@ +id: gcloud-pubsub-publicly-accessible + +info: + name: Publicly Accessible Pub/Sub Topics + author: princechaddha + severity: high + description: | + Identify any publicly accessible Pub/Sub topics within your Google Cloud account and update their IAM policy to prevent unauthorized access and sensitive data exposure. To achieve this, remove the bindings for "allUsers" and "allAuthenticatedUsers" members from your topic's IAM policy. "allUsers" is a special member identifier representing any user on the internet, including both authenticated and unauthenticated users. Similarly, "allAuthenticatedUsers" represents any user or service account that can sign in to Google Cloud Platform (GCP) with a Google account. + impact: | + Publicly accessible Pub/Sub topics can lead to unauthorized access and data leaks, compromising sensitive information and increasing security risks. + remediation: | + Remove "allUsers" and "allAuthenticatedUsers" from the IAM policy bindings of your Pub/Sub topics. This ensures only authorized identities have access to the topics. + reference: + - https://cloud.google.com/pubsub/docs/access-control + tags: cloud,devops,gcp,gcloud,google-cloud-pubsub,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let topic of iterate(template.pubsubTopics)){ + set("pubsubTopic", topic) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud pubsub topics list --project $projectId --format="json(name)" + + extractors: + - type: json + name: pubsubTopics + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud pubsub topics get-iam-policy $pubsubTopic --format=json | jq '.bindings[].members[]' + + matchers: + - type: word + words: + - 'allUsers' + - 'allAuthenticatedUsers' + condition: or + + extractors: + - type: dsl + dsl: + - '"Publicly Accessible Pub/Sub Topic found: " + pubsubTopic + " in project: " + projectId' diff --git a/cloud/gcp/resourcemanager/gcloud-org-allowed-apis.yaml b/cloud/gcp/resourcemanager/gcloud-org-allowed-apis.yaml new file mode 100644 index 00000000000..255ae503df2 --- /dev/null +++ b/cloud/gcp/resourcemanager/gcloud-org-allowed-apis.yaml @@ -0,0 +1,55 @@ +id: gcloud-org-allowed-apis + +info: + name: Google Cloud APIs and Services Not Restricted + author: princechaddha + severity: medium + description: | + Ensure that all the Google Cloud APIs and services restricted within your organization are defined using the "Restrict allowed Google Cloud APIs and services" organization policy. This constraint policy helps you achieve regulatory compliance by defining the set of cloud services and APIs that cannot be used within your GCP organization. + impact: | + By default, all Google Cloud APIs and services are allowed. Without restrictions, users can enable any API or service, potentially leading to increased attack surface and compliance violations. + remediation: | + Configure the "Restrict allowed Google Cloud APIs and services" policy at the organization level to explicitly deny specific APIs. Note that only certain APIs can be restricted: compute.googleapis.com, deploymentmanager.googleapis.com, dns.googleapis.com, doubleclicksearch.googleapis.com, replicapool.googleapis.com, replicapoolupdater.googleapis.com, and resourceviews.googleapis.com. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ResourceManager/allowed-apis-and-services.html + - https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints + tags: cloud,devops,gcp,gcloud,resourcemanager,security,api,services,gcp-cloud-config + +flow: | + code(1) + for(let orgId of iterate(template.orgIds)){ + set("orgId", orgId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud organizations list --format="json(name)" + + extractors: + - type: json + name: orgIds + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud alpha resource-manager org-policies describe serviceuser.services --organization=$orgId --effective --format="json(listPolicy.allValues)" + + matchers: + - type: word + words: + - "ALLOW" + + extractors: + - type: dsl + dsl: + - '"Organization " + orgId + " has not restricted Google Cloud APIs and services, allowing all services to be enabled"' \ No newline at end of file diff --git a/cloud/gcp/resourcemanager/gcloud-org-allowed-external-ips.yaml b/cloud/gcp/resourcemanager/gcloud-org-allowed-external-ips.yaml new file mode 100644 index 00000000000..fb37520f5e8 --- /dev/null +++ b/cloud/gcp/resourcemanager/gcloud-org-allowed-external-ips.yaml @@ -0,0 +1,55 @@ +id: gcloud-org-allowed-external-ips + +info: + name: Organization Policy for Allowed External IPs Not Configured + author: princechaddha + severity: medium + description: | + Ensure that "Define Allowed External IPs for VM Instances" constraint policy is enforced at the GCP organization level in order to enable you to define the set of virtual machine (VM) instances that are allowed to use external IP addresses. This constraint helps you to minimize your instance's exposure to the Internet. + impact: | + By default, all Google Cloud virtual machine instances are allowed to use external IP addresses. Without proper constraints, this increases the attack surface as instances may be unnecessarily exposed to the internet. + remediation: | + Configure the "Define Allowed External IPs for VM Instances" policy at the organization level to explicitly specify which VM instances are allowed to have external IP addresses. Use the format: projects//zones//instances/. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ResourceManager/allowed-external-ips.html + - https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints + tags: cloud,devops,gcp,gcloud,resourcemanager,security,networking,organization,gcp-cloud-config + +flow: | + code(1) + for(let orgId of iterate(template.orgIds)){ + set("orgId", orgId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud organizations list --format="json(name)" + + extractors: + - type: json + name: orgIds + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud alpha resource-manager org-policies describe compute.vmExternalIpAccess --organization=$orgId --effective --format="json(listPolicy.allValues)" + + matchers: + - type: word + words: + - "ALLOW" + + extractors: + - type: dsl + dsl: + - '"Organization " + orgId + " allows all VM instances to use external IP addresses, increasing exposure to the internet"' \ No newline at end of file diff --git a/cloud/gcp/resourcemanager/gcloud-org-auto-iam-grants.yaml b/cloud/gcp/resourcemanager/gcloud-org-auto-iam-grants.yaml new file mode 100644 index 00000000000..fa2f41b77fc --- /dev/null +++ b/cloud/gcp/resourcemanager/gcloud-org-auto-iam-grants.yaml @@ -0,0 +1,56 @@ +id: gcloud-org-auto-iam-grants + +info: + name: Automatic IAM Role Grants for Default Service Accounts Not Disabled + author: princechaddha + severity: medium + description: | + Ensure that "Disable Automatic IAM Grants for Default Service Accounts" policy is enforced for your Google Cloud Platform (GCP) organizations and projects in order to deactivate the automatic IAM role grant for default service accounts. When a default service account is created, it is automatically granted the Editor role ("roles/editor") on your project. + impact: | + When automatic IAM grants are enabled, default service accounts automatically receive Editor role permissions, which violates the principle of least privilege and increases security risks. + remediation: | + Enable the "Disable Automatic IAM Grants for Default Service Accounts" policy at the organization level using the 'gcloud alpha resource-manager org-policies enable-enforce' command or through the Google Cloud Console. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ResourceManager/disable-automatic-role-grants.html + - https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints + tags: cloud,devops,gcp,gcloud,resourcemanager,security,iam,organization,gcp-cloud-config + +flow: | + code(1) + for(let orgId of iterate(template.orgIds)){ + set("orgId", orgId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud organizations list --format="json(name)" + + extractors: + - type: json + name: orgIds + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud alpha resource-manager org-policies describe iam.automaticIamGrantsForDefaultServiceAccounts --organization=$orgId --effective --format="json(booleanPolicy)" + + matchers: + - type: word + words: + - "{}" + + extractors: + - type: dsl + dsl: + - '"Organization " + orgId + " has not disabled automatic IAM role grants for default service accounts"' +# digest: 490a0046304402207f8bbb5e1e04bf20ebccd250e3651f3287b8f213efb09bb4f1ff07fb73d887540220760072d96e67df4cc2dc6d912fbc26a6f0b5de2443e66f57d060a8342f9649ec:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/resourcemanager/gcloud-org-default-network.yaml b/cloud/gcp/resourcemanager/gcloud-org-default-network.yaml new file mode 100644 index 00000000000..5f37480b52d --- /dev/null +++ b/cloud/gcp/resourcemanager/gcloud-org-default-network.yaml @@ -0,0 +1,55 @@ +id: gcloud-org-default-network + +info: + name: Default Network Creation Not Disabled + author: princechaddha + severity: medium + description: | + Ensure that "Skip Default Network Creation" constraint policy is enforced for your Google Cloud Platform (GCP) organizations in order to follow security best practices and meet networking requirements. Once enabled, this constraint skips the creation of the default Virtual Private Cloud (VPC) network and related resources during Google Cloud project creation. + impact: | + By default, a default network and supporting resources are automatically created when you launch a new Google Cloud project. The default VPC comes with predefined, over-permissive firewall rules that are not included in audit logging, potentially creating security risks. + remediation: | + Enable the "Skip Default Network Creation" policy at the organization level using the 'gcloud alpha resource-manager org-policies enable-enforce' command with the compute.skipDefaultNetworkCreation constraint. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ResourceManager/disable-default-network-creation.html + - https://cloud.google.com/vpc/docs/vpc-network-overview + tags: cloud,devops,gcp,gcloud,resourcemanager,security,networking,vpc,gcp-cloud-config + +flow: | + code(1) + for(let orgId of iterate(template.orgIds)){ + set("orgId", orgId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud organizations list --format="json(name)" + + extractors: + - type: json + name: orgIds + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud alpha resource-manager org-policies describe compute.skipDefaultNetworkCreation --organization=$orgId --effective --format="json(booleanPolicy)" + + matchers: + - type: word + words: + - "{}" + + extractors: + - type: dsl + dsl: + - '"Organization " + orgId + " has not disabled default network creation, allowing automatic creation of over-permissive VPC networks"' \ No newline at end of file diff --git a/cloud/gcp/resourcemanager/gcloud-org-detailed-audit-logging.yaml b/cloud/gcp/resourcemanager/gcloud-org-detailed-audit-logging.yaml new file mode 100644 index 00000000000..64d40dfa414 --- /dev/null +++ b/cloud/gcp/resourcemanager/gcloud-org-detailed-audit-logging.yaml @@ -0,0 +1,55 @@ +id: gcloud-org-detailed-audit-logging + +info: + name: Detailed Audit Logging Mode Not Enabled + author: princechaddha + severity: medium + description: | + Ensure that "Google Cloud Platform - Detailed Audit Logging Mode" policy is enforced at the organization level in order to enable Detailed Audit Logging feature for the supported Cloud Storage resources available within your GCP organization. When Detailed Audit Logging is enforced, both the request and response are included in Cloud Audit logs. + impact: | + Without detailed audit logging, you have limited visibility into Cloud Storage operations as request and response details are not captured in audit logs, making it harder to meet compliance requirements like SEC Rule 17a-4(f). + remediation: | + Enable the "Google Cloud Platform - Detailed Audit Logging Mode" policy at the organization level using the 'gcloud alpha resource-manager org-policies enable-enforce' command with the gcp.detailedAuditLoggingMode constraint. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ResourceManager/enable-detailed-audit-logging.html + - https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints + tags: cloud,devops,gcp,gcloud,resourcemanager,security,audit,logging,gcp-cloud-config + +flow: | + code(1) + for(let orgId of iterate(template.orgIds)){ + set("orgId", orgId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud organizations list --format="json(name)" + + extractors: + - type: json + name: orgIds + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud alpha resource-manager org-policies describe gcp.detailedAuditLoggingMode --organization=$orgId --effective --format="json(booleanPolicy)" + + matchers: + - type: word + words: + - "{}" + + extractors: + - type: dsl + dsl: + - '"Organization " + orgId + " has not enabled detailed audit logging mode for Cloud Storage resources"' \ No newline at end of file diff --git a/cloud/gcp/resourcemanager/gcloud-org-guest-attributes.yaml b/cloud/gcp/resourcemanager/gcloud-org-guest-attributes.yaml new file mode 100644 index 00000000000..e3605d67598 --- /dev/null +++ b/cloud/gcp/resourcemanager/gcloud-org-guest-attributes.yaml @@ -0,0 +1,56 @@ +id: gcloud-org-guest-attributes + +info: + name: Guest Attributes of Compute Engine Metadata Not Disabled + author: princechaddha + severity: medium + description: | + Ensure that "Disable Guest Attributes of Compute Engine Metadata" organization policy is enforced in order to disable Compute Engine API access to the guest attributes configured for the virtual machines instances that belong to your project, folder, or organization. Guest attributes are a specific type of custom metadata that your cloud applications can write to while running on your virtual machine (VM) instance. + impact: | + By default, any application or user on your VM instance can both read and write data to the guest attribute metadata values, which could lead to unauthorized access or data exposure. + remediation: | + Enable the "Disable Guest Attributes of Compute Engine Metadata" policy at the organization level using the 'gcloud alpha resource-manager org-policies enable-enforce' command with the compute.disableGuestAttributesAccess constraint. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ResourceManager/disable-using-guest-attributes.html + - https://cloud.google.com/compute/docs/metadata/guest-attributes + tags: cloud,devops,gcp,gcloud,resourcemanager,security,compute,metadata,gcp-cloud-config + +flow: | + code(1) + for(let orgId of iterate(template.orgIds)){ + set("orgId", orgId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud organizations list --format="json(name)" + + extractors: + - type: json + name: orgIds + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud alpha resource-manager org-policies describe compute.disableGuestAttributesAccess --organization=$orgId --effective --format="json(booleanPolicy)" + + matchers: + - type: word + words: + - "{}" + + extractors: + - type: dsl + dsl: + - '"Organization " + orgId + " has not disabled guest attributes for Compute Engine metadata"' +# digest: 4a0a00473045022100b86999d758d6b080f6c768b3afe9458714c0713702c63a8d58629637fe5fd9b00220355e00d211b75b6d7632f1c5e997d3cb19f495de4792b525a7dcab13822ddf61:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/resourcemanager/gcloud-org-ip-forwarding.yaml b/cloud/gcp/resourcemanager/gcloud-org-ip-forwarding.yaml new file mode 100644 index 00000000000..1570f09458c --- /dev/null +++ b/cloud/gcp/resourcemanager/gcloud-org-ip-forwarding.yaml @@ -0,0 +1,55 @@ +id: gcloud-org-ip-forwarding + +info: + name: VM IP Forwarding Not Restricted + author: princechaddha + severity: medium + description: | + Ensure that the virtual machine (VM) instances allowed to use IP forwarding, that belong to your project, folder, or organization, are defined using the "Restrict VM IP Forwarding" policy. This constraint policy helps you improve security and achieve regulatory compliance by explicitly defining the resource name of the VM instances allowed to use IP forwarding. + impact: | + By default, any virtual machine instance can enable IP forwarding in any VPC network. When IP forwarding is enabled on a VM's network interface, it allows the VM to act as a router and receive traffic addressed to other destinations, which could be exploited for malicious purposes. + remediation: | + Configure the "Restrict VM IP Forwarding" policy at the organization level to explicitly specify which VM instances can use IP forwarding. Use the format projects//zones//instances/ or under: prefix for broader scopes. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ResourceManager/enable-ip-forwarding-restriction-policy.html + - https://cloud.google.com/vpc/docs/using-instance-ip-forwarding + tags: cloud,devops,gcp,gcloud,resourcemanager,security,networking,ip-forwarding,gcp-cloud-config + +flow: | + code(1) + for(let orgId of iterate(template.orgIds)){ + set("orgId", orgId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud organizations list --format="json(name)" + + extractors: + - type: json + name: orgIds + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud alpha resource-manager org-policies describe compute.vmCanIpForward --organization=$orgId --effective --format="json(listPolicy.allValues)" + + matchers: + - type: word + words: + - "ALLOW" + + extractors: + - type: dsl + dsl: + - '"Organization " + orgId + " has not restricted VM IP forwarding, allowing any instance to act as a router"' \ No newline at end of file diff --git a/cloud/gcp/resourcemanager/gcloud-org-load-balancer-types.yaml b/cloud/gcp/resourcemanager/gcloud-org-load-balancer-types.yaml new file mode 100644 index 00000000000..b6aee172134 --- /dev/null +++ b/cloud/gcp/resourcemanager/gcloud-org-load-balancer-types.yaml @@ -0,0 +1,55 @@ +id: gcloud-org-load-balancer-types + +info: + name: Load Balancer Creation Not Restricted by Type + author: princechaddha + severity: medium + description: | + Ensure that only compliant load balancer types can be used to create Google Cloud load balancers for the GCP projects and folders within your organization. The list of allowed load balancer types can only include values from the following list: INTERNAL_TCP_UDP, INTERNAL_HTTP_HTTPS, EXTERNAL_NETWORK_TCP_UDP, EXTERNAL_TCP_PROXY, EXTERNAL_SSL_PROXY, EXTERNAL_HTTP_HTTPS. + impact: | + By default, creation of all types of Google Cloud load balancers is allowed. Without restrictions, users can create any type of load balancer, potentially violating internal compliance requirements. + remediation: | + Configure the "Restrict Load Balancer Creation Based on Load Balancer Types" policy at the organization level to explicitly specify which load balancer types are allowed. Use the 'in:' prefix followed by INTERNAL or EXTERNAL to include all internal or external types. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ResourceManager/restrict-load-balancer-creation-based-on-type.html + - https://cloud.google.com/load-balancing/docs/load-balancer-types + tags: cloud,devops,gcp,gcloud,resourcemanager,security,load-balancer,networking,gcp-cloud-config + +flow: | + code(1) + for(let orgId of iterate(template.orgIds)){ + set("orgId", orgId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud organizations list --format="json(name)" + + extractors: + - type: json + name: orgIds + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud alpha resource-manager org-policies describe compute.restrictLoadBalancerCreationForTypes --organization=$orgId --effective --format="json(listPolicy.allValues)" + + matchers: + - type: word + words: + - "ALLOW" + + extractors: + - type: dsl + dsl: + - '"Organization " + orgId + " has not restricted load balancer creation by type, allowing all load balancer types to be created"' \ No newline at end of file diff --git a/cloud/gcp/resourcemanager/gcloud-org-os-login.yaml b/cloud/gcp/resourcemanager/gcloud-org-os-login.yaml new file mode 100644 index 00000000000..a1c4adb6615 --- /dev/null +++ b/cloud/gcp/resourcemanager/gcloud-org-os-login.yaml @@ -0,0 +1,55 @@ +id: gcloud-org-os-login + +info: + name: OS Login Not Required + author: princechaddha + severity: medium + description: | + Ensure that "Require OS Login" constraint policy is enforced at the GCP organization level in order to enable OS Login feature on all newly created Google Cloud projects within your organization. The OS Login provides you with centralized and automated SSH key pair management. + impact: | + By default, the OS Login feature is disabled for all GCP projects. Without enforced OS Login, SSH keys are not automatically mapped with Cloud IAM users, making it harder to manage access control and revoke compromised credentials. + remediation: | + Enable the "Require OS Login" policy at the organization level using the 'gcloud alpha resource-manager org-policies enable-enforce' command with the compute.requireOsLogin constraint. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ResourceManager/enquire-os-login.html + - https://cloud.google.com/compute/docs/oslogin + tags: cloud,devops,gcp,gcloud,resourcemanager,security,compute,ssh,gcp-cloud-config + +flow: | + code(1) + for(let orgId of iterate(template.orgIds)){ + set("orgId", orgId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud organizations list --format="json(name)" + + extractors: + - type: json + name: orgIds + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud alpha resource-manager org-policies describe compute.requireOsLogin --organization=$orgId --effective --format="json(booleanPolicy)" + + matchers: + - type: word + words: + - "{}" + + extractors: + - type: dsl + dsl: + - '"Organization " + orgId + " has not enforced OS Login requirement for centralized SSH key management"' \ No newline at end of file diff --git a/cloud/gcp/resourcemanager/gcloud-org-resource-locations.yaml b/cloud/gcp/resourcemanager/gcloud-org-resource-locations.yaml new file mode 100644 index 00000000000..a490db7b827 --- /dev/null +++ b/cloud/gcp/resourcemanager/gcloud-org-resource-locations.yaml @@ -0,0 +1,55 @@ +id: gcloud-org-resource-locations + +info: + name: Resource Location Restrictions Not Configured + author: princechaddha + severity: medium + description: | + Ensure that the locations where location-based cloud resources can be created within your GCP organization are defined using the "Google Cloud Platform - Resource Location Restriction" organization policy. This constraint policy helps you achieve regulatory compliance by explicitly defining the locations allowed to deploy Google Cloud resources for your organization. You can specify multi-regions such as "asia" and "europe" and individual regions such as "us-east1" or "europe-west2" as allowed locations. + impact: | + Without location restrictions, cloud resources can be deployed to any location, potentially violating data residency requirements and regulatory compliance standards. This could lead to data being stored in unauthorized regions. + remediation: | + Configure the "Google Cloud Platform - Resource Location Restriction" policy at the organization level to explicitly specify allowed locations. Use the 'in:' prefix followed by location strings (e.g., in:us-locations, in:us-west1-locations) to define allowed regions. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ResourceManager/resource-location-restriction.html + - https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints + tags: cloud,devops,gcp,gcloud,resourcemanager,security,compliance,location,gcp-cloud-config + +flow: | + code(1) + for(let orgId of iterate(template.orgIds)){ + set("orgId", orgId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud organizations list --format="json(name)" + + extractors: + - type: json + name: orgIds + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud alpha resource-manager org-policies describe gcp.resourceLocations --organization=$orgId --effective --format="json(listPolicy.allValues)" + + matchers: + - type: word + words: + - "ALLOW" + + extractors: + - type: dsl + dsl: + - '"Organization " + orgId + " has not restricted resource locations, allowing resources to be created in any region"' \ No newline at end of file diff --git a/cloud/gcp/resourcemanager/gcloud-org-service-account-creation.yaml b/cloud/gcp/resourcemanager/gcloud-org-service-account-creation.yaml new file mode 100644 index 00000000000..4b712a5babd --- /dev/null +++ b/cloud/gcp/resourcemanager/gcloud-org-service-account-creation.yaml @@ -0,0 +1,55 @@ +id: gcloud-org-service-account-creation + +info: + name: Service Account Creation Not Disabled + author: princechaddha + severity: medium + description: | + Ensure that the creation of Cloud IAM service accounts is prevented within your Google Cloud organization through the "Disable Service Account Creation" organization policy. This allows you to easily centralize the management of your service accounts while not restricting the other permissions that your developers and administrators have on the projects within the organization. + impact: | + By default, service accounts can be created by users based on their IAM roles and permissions. If compromised, these service accounts could be used without your knowledge to access Google Cloud resources. + remediation: | + Enable the "Disable Service Account Creation" policy at the organization level using the 'gcloud alpha resource-manager org-policies enable-enforce' command with the iam.disableServiceAccountCreation constraint. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ResourceManager/prevent-service-account-creation.html + - https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints + tags: cloud,devops,gcp,gcloud,resourcemanager,security,iam,service-account,gcp-cloud-config + +flow: | + code(1) + for(let orgId of iterate(template.orgIds)){ + set("orgId", orgId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud organizations list --format="json(name)" + + extractors: + - type: json + name: orgIds + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud alpha resource-manager org-policies describe iam.disableServiceAccountCreation --organization=$orgId --effective --format="json(booleanPolicy)" + + matchers: + - type: word + words: + - "{}" + + extractors: + - type: dsl + dsl: + - '"Organization " + orgId + " has not disabled service account creation, allowing users to create new service accounts"' \ No newline at end of file diff --git a/cloud/gcp/resourcemanager/gcloud-org-service-account-key-creation.yaml b/cloud/gcp/resourcemanager/gcloud-org-service-account-key-creation.yaml new file mode 100644 index 00000000000..71918718a1f --- /dev/null +++ b/cloud/gcp/resourcemanager/gcloud-org-service-account-key-creation.yaml @@ -0,0 +1,55 @@ +id: gcloud-org-service-account-key-creation + +info: + name: Service Account Key Creation Not Disabled + author: princechaddha + severity: high + description: | + Ensure that the creation of user-managed service account keys is disabled within your Google Cloud project, folder, or the entire organization through the "Disable Service Account Key Creation" organization policy. This allows you to control the use of unmanaged long-term credentials for your Cloud IAM service accounts. When this resource constraint is enabled, user-managed keys cannot be created for service accounts in projects/folders/organizations affected by the constraint. + impact: | + User-managed keys are extremely powerful credentials, and they can pose a security risk if they are not managed correctly. If the user-managed service account keys are compromised, anyone who has access to these credentials will be able to access your GCP resources through their associated service account. + remediation: | + Enable the "Disable Service Account Key Creation" policy at the organization level using the 'gcloud alpha resource-manager org-policies enable-enforce' command with the iam.disableServiceAccountKeyCreation constraint. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ResourceManager/disable-service-account-key-creation.html + - https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints + tags: cloud,devops,gcp,gcloud,resourcemanager,security,iam,service-account,gcp-cloud-config + +flow: | + code(1) + for(let orgId of iterate(template.orgIds)){ + set("orgId", orgId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud organizations list --format="json(name)" + + extractors: + - type: json + name: orgIds + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud alpha resource-manager org-policies describe iam.disableServiceAccountKeyCreation --organization=$orgId --effective --format="json(booleanPolicy)" + + matchers: + - type: word + words: + - "{}" + + extractors: + - type: dsl + dsl: + - '"Organization " + orgId + " has not disabled service account key creation, allowing users to create unmanaged keys"' \ No newline at end of file diff --git a/cloud/gcp/resourcemanager/gcloud-org-service-account-key-upload.yaml b/cloud/gcp/resourcemanager/gcloud-org-service-account-key-upload.yaml new file mode 100644 index 00000000000..591a7f8c4d7 --- /dev/null +++ b/cloud/gcp/resourcemanager/gcloud-org-service-account-key-upload.yaml @@ -0,0 +1,56 @@ +id: gcloud-org-service-account-key-upload + +info: + name: Service Account Key Upload Not Disabled + author: princechaddha + severity: medium + description: | + Ensure that user-managed service account key upload is disabled within your Google Cloud project, folder, or the entire organization, through the "Disable Service Account Key Upload" organization policy. This allows you to control the upload process of unmanaged long-term credentials for your Cloud IAM service accounts. By default, users can upload keys to service accounts based on their Cloud IAM roles and permissions. + impact: | + User-managed keys are extremely powerful credentials and they can pose a security risk if not managed correctly. If compromised, anyone with these credentials can access GCP resources through the associated service account. + remediation: | + Enable the "Disable Service Account Key Upload" policy at the organization level using the 'gcloud alpha resource-manager org-policies enable-enforce' command with the iam.disableServiceAccountKeyUpload constraint. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ResourceManager/disable-service-account-key-upload.html + - https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints + tags: cloud,devops,gcp,gcloud,resourcemanager,security,iam,service-account,gcp-cloud-config + +flow: | + code(1) + for(let orgId of iterate(template.orgIds)){ + set("orgId", orgId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud organizations list --format="json(name)" + + extractors: + - type: json + name: orgIds + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud alpha resource-manager org-policies describe iam.disableServiceAccountKeyUpload --organization=$orgId --effective --format="json(booleanPolicy)" + + matchers: + - type: word + words: + - "{}" + + extractors: + - type: dsl + dsl: + - '"Organization " + orgId + " has not disabled service account key upload, allowing users to upload unmanaged keys"' +# digest: 4a0a00473045022100c2ebad6d1bb7d41213885bd61eb4b5d61840e28f02544a11fcb773f7924708fc022034fdc279e99d56cfc6e18a2af13cfbddd3f59c4276f3ba15aa107e5797cfded2:46366314a226e6e09736af12eeb345c0 \ No newline at end of file diff --git a/cloud/gcp/resourcemanager/gcloud-org-shared-vpc-subnets.yaml b/cloud/gcp/resourcemanager/gcloud-org-shared-vpc-subnets.yaml new file mode 100644 index 00000000000..fdded2a0f0a --- /dev/null +++ b/cloud/gcp/resourcemanager/gcloud-org-shared-vpc-subnets.yaml @@ -0,0 +1,55 @@ +id: gcloud-org-shared-vpc-subnets + +info: + name: Shared VPC Subnetworks Not Restricted + author: princechaddha + severity: medium + description: | + Ensure that the set of shared VPC subnetworks that eligible Google Cloud resources can use, are defined using the "Restrict Shared VPC Subnetworks" constraint policy. The allowed list of VPC subnetworks must be specified in the following form: projects//regions//subnetworks/. You can also define the list of allowed subnetworks in a project, folder, or organization. + impact: | + By default, eligible Google Cloud resources can use any shared Virtual Private Cloud (VPC) subnetwork. Without restrictions, resources could be deployed in unauthorized or non-compliant network segments. + remediation: | + Configure the "Restrict Shared VPC Subnetworks" policy at the organization level to explicitly specify which VPC subnetworks can be used. Use the format projects//regions//subnetworks/ or under: prefix for broader scopes. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ResourceManager/restrict-shared-vps-subnetworks.html + - https://cloud.google.com/vpc/docs/shared-vpc + tags: cloud,devops,gcp,gcloud,resourcemanager,security,networking,vpc,gcp-cloud-config + +flow: | + code(1) + for(let orgId of iterate(template.orgIds)){ + set("orgId", orgId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud organizations list --format="json(name)" + + extractors: + - type: json + name: orgIds + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud alpha resource-manager org-policies describe compute.restrictSharedVpcSubnetworks --organization=$orgId --effective --format="json(listPolicy.allValues)" + + matchers: + - type: word + words: + - "ALLOW" + + extractors: + - type: dsl + dsl: + - '"Organization " + orgId + " has not restricted shared VPC subnetworks, allowing resources to use any shared subnet"' \ No newline at end of file diff --git a/cloud/gcp/resourcemanager/gcloud-org-sql-authorized-networks.yaml b/cloud/gcp/resourcemanager/gcloud-org-sql-authorized-networks.yaml new file mode 100644 index 00000000000..3e050d130d6 --- /dev/null +++ b/cloud/gcp/resourcemanager/gcloud-org-sql-authorized-networks.yaml @@ -0,0 +1,55 @@ +id: gcloud-org-sql-authorized-networks + +info: + name: Cloud SQL Authorized Networks Not Restricted + author: princechaddha + severity: medium + description: | + Ensure that "Restrict Authorized Networks on Cloud SQL instances" policy is enforced for your Google Cloud Platform (GCP) organization to deny IAM members to add authorized networks in order to provide access to your security-critical SQL database instances. By default, authorized networks can be added to any Cloud SQL database instance. + impact: | + Without restricting authorized networks, Cloud SQL instances can be configured to allow access from any IP address, potentially exposing databases to unauthorized access from the internet. + remediation: | + Enable the "Restrict Authorized Networks on Cloud SQL instances" policy at the organization level using the 'gcloud alpha resource-manager org-policies enable-enforce' command with the sql.restrictAuthorizedNetworks constraint. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ResourceManager/restrict-authorized-networks.html + - https://cloud.google.com/sql/docs/mysql/authorize-networks + tags: cloud,devops,gcp,gcloud,resourcemanager,security,sql,networking,gcp-cloud-config + +flow: | + code(1) + for(let orgId of iterate(template.orgIds)){ + set("orgId", orgId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud organizations list --format="json(name)" + + extractors: + - type: json + name: orgIds + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud alpha resource-manager org-policies describe sql.restrictAuthorizedNetworks --organization=$orgId --effective --format="json(booleanPolicy)" + + matchers: + - type: word + words: + - "{}" + + extractors: + - type: dsl + dsl: + - '"Organization " + orgId + " has not restricted authorized networks for Cloud SQL instances, allowing potential public access"' \ No newline at end of file diff --git a/cloud/gcp/resourcemanager/gcloud-org-sql-default-encryption.yaml b/cloud/gcp/resourcemanager/gcloud-org-sql-default-encryption.yaml new file mode 100644 index 00000000000..e55ad24c109 --- /dev/null +++ b/cloud/gcp/resourcemanager/gcloud-org-sql-default-encryption.yaml @@ -0,0 +1,55 @@ +id: gcloud-org-sql-default-encryption + +info: + name: Default Google-Managed Encryption for Cloud SQL Not Restricted + author: princechaddha + severity: medium + description: | + Ensure that the use of Google-managed encryption keys for Cloud SQL database instances is disabled at the GCP organization level in order to enforce the use of Customer-Managed Keys (CMKs) and have full control over SQL database encryption/decryption process. Note: This organization policy is not retroactive, therefore any existing database instances using Google-managed encryption are not impacted unless they are updated or refreshed. + impact: | + By default, Google-managed encryption is allowed for all Cloud SQL instances. Without enforcing CMK usage, you have less control over the encryption keys that protect your SQL databases. + remediation: | + Enable the "Restrict Default Google-Managed Encryption for Cloud SQL Instances" policy at the organization level using the 'gcloud alpha resource-manager org-policies enable-enforce' command with the sql.disableDefaultEncryptionCreation constraint. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ResourceManager/restrict-default-encryption-for-sql-instances.html + - https://cloud.google.com/sql/docs/mysql/customer-managed-encryption-keys + tags: cloud,devops,gcp,gcloud,resourcemanager,security,sql,encryption,cmk,gcp-cloud-config + +flow: | + code(1) + for(let orgId of iterate(template.orgIds)){ + set("orgId", orgId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud organizations list --format="json(name)" + + extractors: + - type: json + name: orgIds + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud alpha resource-manager org-policies describe sql.disableDefaultEncryptionCreation --organization=$orgId --effective --format="json(booleanPolicy)" + + matchers: + - type: word + words: + - "{}" + + extractors: + - type: dsl + dsl: + - '"Organization " + orgId + " has not disabled default Google-managed encryption for Cloud SQL instances"' \ No newline at end of file diff --git a/cloud/gcp/resourcemanager/gcloud-org-sql-public-ip.yaml b/cloud/gcp/resourcemanager/gcloud-org-sql-public-ip.yaml new file mode 100644 index 00000000000..fdb35c91244 --- /dev/null +++ b/cloud/gcp/resourcemanager/gcloud-org-sql-public-ip.yaml @@ -0,0 +1,55 @@ +id: gcloud-org-sql-public-ip + +info: + name: Public IP Access for Cloud SQL Instances Not Restricted + author: princechaddha + severity: medium + description: | + Ensure that "Restrict Public IP access on Cloud SQL instances" policy is enforced for your Google Cloud organizations. Due to strict security and compliance regulations, you can't allow GCP members to configure security-critical database instances with public IPs. For highly sensitive workloads, the access to the SQL database instances can be made only through private IP addresses or Google Cloud SQL Proxy. + impact: | + Without restricting public IP access, Cloud SQL instances can be configured with public IP addresses, potentially exposing sensitive databases to unauthorized access from the internet. + remediation: | + Enable the "Restrict Public IP access on Cloud SQL instances" policy at the organization level using the 'gcloud alpha resource-manager org-policies enable-enforce' command with the sql.restrictPublicIp constraint. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ResourceManager/restrict-public-ip-access-at-organization-level.html + - https://cloud.google.com/sql/docs/mysql/configure-ip + tags: cloud,devops,gcp,gcloud,resourcemanager,security,sql,networking,gcp-cloud-config + +flow: | + code(1) + for(let orgId of iterate(template.orgIds)){ + set("orgId", orgId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud organizations list --format="json(name)" + + extractors: + - type: json + name: orgIds + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud alpha resource-manager org-policies describe sql.restrictPublicIp --organization=$orgId --effective --format="json(booleanPolicy)" + + matchers: + - type: word + words: + - "{}" + + extractors: + - type: dsl + dsl: + - '"Organization " + orgId + " has not restricted public IP access for Cloud SQL instances, allowing databases to be exposed to the internet"' \ No newline at end of file diff --git a/cloud/gcp/resourcemanager/gcloud-org-trusted-images.yaml b/cloud/gcp/resourcemanager/gcloud-org-trusted-images.yaml new file mode 100644 index 00000000000..a711e6556c4 --- /dev/null +++ b/cloud/gcp/resourcemanager/gcloud-org-trusted-images.yaml @@ -0,0 +1,55 @@ +id: gcloud-org-trusted-images + +info: + name: Trusted Image Projects Not Defined + author: princechaddha + severity: medium + description: | + Ensure that only images from trusted Google Cloud Platform (GCP) projects are allowed as the source for boot disks for new virtual machine instances. By enforcing the "Define Trusted Image Projects" policy at the GCP organization level, you can restrict access to disk images so that project members can create boot disks only from images that contain approved software meeting strict security requirements. + impact: | + By default, project members can create persistent disks or copy images using any public or private images they can access through their Cloud IAM roles. Without restrictions, this could allow the use of untrusted or malicious disk images. + remediation: | + Configure the "Define Trusted Image Projects" policy at the organization level to explicitly specify trusted projects. Use the format projects/ where is the ID of the trusted Google Cloud project that shares approved disk images. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ResourceManager/disk-image-restriction.html + - https://cloud.google.com/compute/docs/images/restricting-image-access + tags: cloud,devops,gcp,gcloud,resourcemanager,security,compute,images,gcp-cloud-config + +flow: | + code(1) + for(let orgId of iterate(template.orgIds)){ + set("orgId", orgId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud organizations list --format="json(name)" + + extractors: + - type: json + name: orgIds + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud alpha resource-manager org-policies describe compute.trustedImageProjects --organization=$orgId --effective --format="json(listPolicy.allValues)" + + matchers: + - type: word + words: + - "ALLOW" + + extractors: + - type: dsl + dsl: + - '"Organization " + orgId + " has not restricted disk image usage to trusted projects, allowing use of any accessible image"' \ No newline at end of file diff --git a/cloud/gcp/resourcemanager/gcloud-org-uniform-bucket-access.yaml b/cloud/gcp/resourcemanager/gcloud-org-uniform-bucket-access.yaml new file mode 100644 index 00000000000..d5c2544b4f6 --- /dev/null +++ b/cloud/gcp/resourcemanager/gcloud-org-uniform-bucket-access.yaml @@ -0,0 +1,55 @@ +id: gcloud-org-uniform-bucket-access + +info: + name: Uniform Bucket-Level Access Not Enforced + author: princechaddha + severity: medium + description: | + Ensure that "Enforce uniform bucket-level access" policy is enabled for your Google Cloud Platform (GCP) organization in order to enforce uniform bucket-level access for all Google Cloud Storage buckets available in your organization. Enforcing uniform bucket-level access disables Access Control Lists (ACLs) for all Cloud Storage resources (buckets and objects) so that access is granted exclusively through Cloud IAM service. + impact: | + Without enforced uniform bucket-level access, buckets may use legacy ACLs which are less secure and more complex to manage than Cloud IAM permissions, potentially leading to misconfigured access controls. + remediation: | + Enable the "Enforce uniform bucket-level access" policy at the organization level using the 'gcloud alpha resource-manager org-policies enable-enforce' command with the storage.uniformBucketLevelAccess constraint. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ResourceManager/enforce-uniform-bucket-level-access-constraint.html + - https://cloud.google.com/storage/docs/uniform-bucket-level-access + tags: cloud,devops,gcp,gcloud,resourcemanager,security,storage,bucket,gcp-cloud-config + +flow: | + code(1) + for(let orgId of iterate(template.orgIds)){ + set("orgId", orgId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud organizations list --format="json(name)" + + extractors: + - type: json + name: orgIds + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud alpha resource-manager org-policies describe storage.uniformBucketLevelAccess --organization=$orgId --effective --format="json(booleanPolicy)" + + matchers: + - type: word + words: + - "{}" + + extractors: + - type: dsl + dsl: + - '"Organization " + orgId + " has not enforced uniform bucket-level access for Cloud Storage buckets"' \ No newline at end of file diff --git a/cloud/gcp/resourcemanager/gcloud-org-vpc-peering.yaml b/cloud/gcp/resourcemanager/gcloud-org-vpc-peering.yaml new file mode 100644 index 00000000000..a5f0d0a8bf4 --- /dev/null +++ b/cloud/gcp/resourcemanager/gcloud-org-vpc-peering.yaml @@ -0,0 +1,55 @@ +id: gcloud-org-vpc-peering + +info: + name: VPC Peering Usage Not Restricted + author: princechaddha + severity: medium + description: | + Ensure that the VPC networks that are allowed to be peered with the networks created for your project, folder, or organization, are defined using the "Restrict VPC Peering Usage" constraint policy. This constraint helps you achieve regulatory compliance by explicitly defining the resource name of each Virtual Private Cloud (VPC) network allowed for VPC peering. + impact: | + By default, anyone with the right permissions can peer your VPC network with any other network within your organization. Without restrictions, this can pose a major security risk when peering development and production networks or if someone peers your VPC with a malicious entity. + remediation: | + Configure the "Restrict VPC Peering Usage" policy at the organization level to explicitly specify which VPC networks can be peered. Use the format projects//global/networks/ or under: prefix for broader scopes. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ResourceManager/restrict-vpc-peering-usage.html + - https://cloud.google.com/vpc/docs/vpc-peering + tags: cloud,devops,gcp,gcloud,resourcemanager,security,networking,vpc,gcp-cloud-config + +flow: | + code(1) + for(let orgId of iterate(template.orgIds)){ + set("orgId", orgId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud organizations list --format="json(name)" + + extractors: + - type: json + name: orgIds + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud alpha resource-manager org-policies describe compute.restrictVpcPeering --organization=$orgId --effective --format="json(listPolicy.allValues)" + + matchers: + - type: word + words: + - "ALLOW" + + extractors: + - type: dsl + dsl: + - '"Organization " + orgId + " has not restricted VPC peering usage, allowing networks to be peered with any other network"' \ No newline at end of file diff --git a/cloud/gcp/resourcemanager/gcloud-org-vpn-peer-ips.yaml b/cloud/gcp/resourcemanager/gcloud-org-vpn-peer-ips.yaml new file mode 100644 index 00000000000..b591bb136af --- /dev/null +++ b/cloud/gcp/resourcemanager/gcloud-org-vpn-peer-ips.yaml @@ -0,0 +1,55 @@ +id: gcloud-org-vpn-peer-ips + +info: + name: VPN Peer IP Addresses Not Restricted + author: princechaddha + severity: medium + description: | + Ensure that only trusted IPv4 addresses can be configured as VPN peer IPs within your Google Cloud organization. By enforcing the "Restrict VPN Peer IPs" constraint policy, you can control the IP addresses that can be configured as VPN peer IPs within your Google Cloud organization in order to meet security and compliance requirements. + impact: | + By default, any IP address can be a VPN peer IP for a Virtual Private Cloud (VPC) network. Without restrictions, this could allow unauthorized or malicious networks to establish VPN connections with your VPC. + remediation: | + Configure the "Restrict VPN Peer IPs" policy at the organization level to explicitly specify which IPv4 addresses can be configured as VPN peer IPs. Use space-separated IP addresses in the policy configuration. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ResourceManager/restrict-vpn-peer-ips.html + - https://cloud.google.com/vpc/docs/using-vpn + tags: cloud,devops,gcp,gcloud,resourcemanager,security,networking,vpn,gcp-cloud-config + +flow: | + code(1) + for(let orgId of iterate(template.orgIds)){ + set("orgId", orgId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud organizations list --format="json(name)" + + extractors: + - type: json + name: orgIds + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud alpha resource-manager org-policies describe compute.restrictVpnPeerIPs --organization=$orgId --effective --format="json(listPolicy.allValues)" + + matchers: + - type: word + words: + - "ALLOW" + + extractors: + - type: dsl + dsl: + - '"Organization " + orgId + " has not restricted VPN peer IP addresses, allowing any IP to be configured as a VPN peer"' \ No newline at end of file diff --git a/cloud/gcp/resourcemanager/gcloud-org-workload-identity.yaml b/cloud/gcp/resourcemanager/gcloud-org-workload-identity.yaml new file mode 100644 index 00000000000..242a7fc1303 --- /dev/null +++ b/cloud/gcp/resourcemanager/gcloud-org-workload-identity.yaml @@ -0,0 +1,55 @@ +id: gcloud-org-workload-identity + +info: + name: Workload Identity Cluster Creation Not Disabled + author: princechaddha + severity: medium + description: | + Ensure that "Disable Workload Identity Cluster Creation" policy is enforced at the GCP organization level in order to require that any new Google Kubernetes Engine (GKE) clusters have the Workload Identity feature disabled at the time of their creation. This constraint policy is useful when you want to tightly control service account access in your organization by disabling Workload Identity in addition to service account creation and service account key creation. + impact: | + With Workload Identity enabled, GKE service can assert Kubernetes service account identities that can be authorized to access Google Cloud resources. This could lead to unintended access if not properly controlled. + remediation: | + Enable the "Disable Workload Identity Cluster Creation" policy at the organization level using the 'gcloud alpha resource-manager org-policies enable-enforce' command with the iam.disableWorkloadIdentityClusterCreation constraint. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ResourceManager/disable-workload-identity-cluster-creation.html + - https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints + tags: cloud,devops,gcp,gcloud,resourcemanager,security,gke,kubernetes,workload-identity,gcp-cloud-config + +flow: | + code(1) + for(let orgId of iterate(template.orgIds)){ + set("orgId", orgId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud organizations list --format="json(name)" + + extractors: + - type: json + name: orgIds + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud alpha resource-manager org-policies describe iam.disableWorkloadIdentityClusterCreation --organization=$orgId --effective --format="json(booleanPolicy)" + + matchers: + - type: word + words: + - "{}" + + extractors: + - type: dsl + dsl: + - '"Organization " + orgId + " has not disabled Workload Identity for GKE cluster creation, potentially allowing uncontrolled service account access"' \ No newline at end of file diff --git a/cloud/gcp/run/gcloud-run-services-user-labels-missing.yaml b/cloud/gcp/run/gcloud-run-services-user-labels-missing.yaml new file mode 100644 index 00000000000..fd3e7a03995 --- /dev/null +++ b/cloud/gcp/run/gcloud-run-services-user-labels-missing.yaml @@ -0,0 +1,72 @@ +id: gcloud-run-services-user-labels-missing + +info: + name: Missing User-Defined Labels in Cloud Run Services + author: princechaddha + severity: low + description: | + Ensure that user-defined labels are being used to tag, collect, and organize Cloud Run services within your Google Cloud Platform (GCP) projects. User-defined labels are a lightweight and efficient way to group together related or associated cloud resources. + impact: | + Not using user-defined labels for Cloud Run services can lead to difficulties in managing, organizing, and categorizing resources, especially in large-scale environments. + remediation: | + Add user-defined labels to Cloud Run services to improve resource management. Ensure that the labels are meaningful and adhere to organizational standards for resource grouping. + reference: + - https://cloud.google.com/run/docs/configuring/labels + tags: cloud,devops,gcp,gcloud,google-cloud-run,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let serviceDetail of iterate(template.services)){ + set("serviceName", serviceDetail.metadata.name) + set("serviceLocation", serviceDetail.metadata.labels['cloud.googleapis.com/location']) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud run services list --project $projectId --format="json(metadata.name, metadata.labels)" + + extractors: + - type: json + name: services + internal: true + json: + - '.[].metadata' + + - engine: + - sh + - bash + source: | + gcloud run services describe $serviceName --region=$serviceLocation --format="json(metadata.labels)" + + matchers: + - type: word + words: + - 'cloud.googleapis.com' + + extractors: + - type: dsl + dsl: + - '"Service " + serviceName + " in Location " + serviceLocation + " of Project " + projectId + " does not have user-defined labels for resource management."' diff --git a/cloud/gcp/sql/gcloud-mysql-local-infile-enabled.yaml b/cloud/gcp/sql/gcloud-mysql-local-infile-enabled.yaml new file mode 100644 index 00000000000..bb7a8b58bda --- /dev/null +++ b/cloud/gcp/sql/gcloud-mysql-local-infile-enabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-mysql-local-infile-enabled + +info: + name: Local Infile Enabled in MySQL Database Instances + author: princechaddha + severity: medium + description: | + Ensure that the local_infile database flag is disabled for your Google Cloud MySQL database instances in order to follow data security best practices. The local_infile flag allows loading data from a local file to a database table, which could pose a security risk if misused. + impact: | + Enabling the local_infile flag may lead to potential security vulnerabilities, such as unauthorized access to local files or data exfiltration. + remediation: | + Disable the local_infile flag in your MySQL database instance configuration to enhance security and prevent potential misuse of the feature. + reference: + - https://cloud.google.com/sql/docs/mysql/flags + tags: cloud,devops,gcp,gcloud,google-cloud-sql,mysql,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter='DATABASE_VERSION:MYSQL*' --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe asass --project gcp-templates-442409 --format=json | jq '.settings.databaseFlags // [] | map(select(.name=="local_infile")) | .[].value' + + matchers: + - type: word + words: + - 'on' + + extractors: + - type: dsl + dsl: + - '"The local_infile flag is enabled for MySQL instance " + sqlInstance + " in project " + projectId' diff --git a/cloud/gcp/sql/gcloud-mysql-pitr-disabled.yaml b/cloud/gcp/sql/gcloud-mysql-pitr-disabled.yaml new file mode 100644 index 00000000000..8d473f25d1a --- /dev/null +++ b/cloud/gcp/sql/gcloud-mysql-pitr-disabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-mysql-pitr-disabled + +info: + name: Point-in-Time Recovery Disabled for MySQL Instances + author: princechaddha + severity: medium + description: | + Ensure that the Point-in-Time Recovery (PITR) feature is enabled for all MySQL database instances deployed within your Google Cloud Platform (GCP) account. This feature allows you to recover data from a specific point in time at a minimal cost. Automated backups and binary logging must be enabled for your MySQL database instances to use PITR. + impact: | + If Point-in-Time Recovery is not enabled, you may lose critical data and have limited options for data recovery during incidents. + remediation: | + Enable binary logging and configure automated backups for your MySQL database instances to ensure that the PITR feature is enabled. + reference: + - https://cloud.google.com/sql/docs/mysql/backup-recovery/pitr + tags: cloud,devops,gcp,gcloud,google-cloud-sql,azure-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter="DATABASE_VERSION:MYSQL*" --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --project $projectId --format="value(settings.backupConfiguration.binaryLogEnabled)" + + matchers: + - type: word + words: + - 'False' + + extractors: + - type: dsl + dsl: + - '"Point-in-Time Recovery is not enabled for MySQL instance " + sqlInstance + " in project " + projectId' diff --git a/cloud/gcp/sql/gcloud-mysql-slowquerylog-disabled.yaml b/cloud/gcp/sql/gcloud-mysql-slowquerylog-disabled.yaml new file mode 100644 index 00000000000..09e152b859b --- /dev/null +++ b/cloud/gcp/sql/gcloud-mysql-slowquerylog-disabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-mysql-slowquerylog-disabled + +info: + name: Slow Query Log Disabled for MySQL Database Servers + author: princechaddha + severity: medium + description: | + Ensure that the "slow_query_log" database flag is enabled for your Google Cloud MySQL database instances in order to simplify the task of finding inefficient or time-consuming SQL queries for your MySQL databases. By default, the "slow_query_log" database flag is not enabled for Google Cloud MySQL instances. + impact: | + Disabling the "slow_query_log" flag makes it difficult to identify and optimize slow or inefficient queries, leading to potential database performance degradation and increased costs. + remediation: | + Enable the "slow_query_log" flag for MySQL database instances in Google Cloud to log and analyze slow SQL queries, improving database performance and query efficiency. + reference: + - https://cloud.google.com/sql/docs/mysql/flags + tags: cloud,devops,gcp,gcloud,google-cloud-sql,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter='DATABASE_VERSION:MYSQL*' --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --format="json(settings.databaseFlags)" + + matchers: + - type: word + words: + - '"off"' + + extractors: + - type: dsl + dsl: + - '"The slow_query_log flag is disabled for MySQL instance " + sqlInstance + " in project: " + projectId' diff --git a/cloud/gcp/sql/gcloud-pg-log-error-verbosity-flag-not-configured.yaml b/cloud/gcp/sql/gcloud-pg-log-error-verbosity-flag-not-configured.yaml new file mode 100644 index 00000000000..a8f6a0ab11d --- /dev/null +++ b/cloud/gcp/sql/gcloud-pg-log-error-verbosity-flag-not-configured.yaml @@ -0,0 +1,71 @@ +id: gcloud-pg-log-error-verbosity-flag-not-configured + +info: + name: Log Error Verbosity Flag Not Configured Properly for PostgreSQL Instances + author: princechaddha + severity: medium + description: | + Ensure that the "log_error_verbosity" database flag configured for your Google Cloud PostgreSQL database instances is set to DEFAULT or to a stricter value. The "log_error_verbosity" flag determines the level of detail recorded in the server log for logged messages. Valid values are TERSE, DEFAULT, and VERBOSE, with TERSE being the most restrictive and VERBOSE providing the most detail. + impact: | + An improperly configured "log_error_verbosity" flag can result in either insufficient logging, which hinders troubleshooting and auditing, or excessive logging, which can impact performance and increase storage costs. + remediation: | + Set the "log_error_verbosity" flag to DEFAULT or a stricter value (e.g., TERSE) to balance logging detail and performance, as per your organization's logging policy. + reference: + - https://cloud.google.com/sql/docs/postgres/flags + tags: cloud,devops,gcp,gcloud,google-cloud-sql,postgresql,logging,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter=DATABASE_VERSION:POSTGRES* --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --project $projectId --format=json | jq -r '.settings.databaseFlags[]? | select(.name=="log_error_verbosity") | .value // "null"' + + matchers: + - type: word + words: + - 'null' + + extractors: + - type: dsl + dsl: + - '"The log_error_verbosity flag is not configured properly or is set to an inappropriate value for PostgreSQL instance " + sqlInstance + " in project " + projectId' diff --git a/cloud/gcp/sql/gcloud-pg-log-executor-stats-enabled.yaml b/cloud/gcp/sql/gcloud-pg-log-executor-stats-enabled.yaml new file mode 100644 index 00000000000..df143595e6a --- /dev/null +++ b/cloud/gcp/sql/gcloud-pg-log-executor-stats-enabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-pg-log-executor-stats-enabled + +info: + name: Log Executor Stats Enabled in PostgreSQL Database Instances + author: princechaddha + severity: medium + description: | + Ensure that the log_executor_stats database flag is turned off for your Google Cloud PostgreSQL database instances in order to avoid performance issues caused by excessive logging. The log_executor_stats flag enables a crude profiling method for logging PostgreSQL executor performance statistics. The PostgreSQL executor is responsible for executing the plan handed over by the PostgreSQL planner/optimizer. The task of the PostgreSQL planner/optimizer is to create an optimal execution plan. + impact: | + Enabling the log_executor_stats flag may lead to significant performance degradation due to excessive logging, impacting the database's overall efficiency. + remediation: | + Disable the log_executor_stats flag in your PostgreSQL database instance configuration to prevent performance issues caused by excessive logging. + reference: + - https://cloud.google.com/sql/docs/postgres/flags + tags: cloud,devops,gcp,gcloud,google-cloud-sql,postgresql,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter='DATABASE_VERSION:POSTGRES*' --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --project $projectId --format=json | jq '.settings.databaseFlags // [] | map(select(.name == "log_executor_stats")) | .[].value' + + matchers: + - type: word + words: + - 'on' + + extractors: + - type: dsl + dsl: + - '"The log_executor_stats flag is enabled for PostgreSQL instance " + sqlInstance + " in project " + projectId' diff --git a/cloud/gcp/sql/gcloud-pg-log-min-duration-statement-enabled.yaml b/cloud/gcp/sql/gcloud-pg-log-min-duration-statement-enabled.yaml new file mode 100644 index 00000000000..5e101fee942 --- /dev/null +++ b/cloud/gcp/sql/gcloud-pg-log-min-duration-statement-enabled.yaml @@ -0,0 +1,78 @@ +id: gcloud-pg-log-min-duration-statement-enabled + +info: + name: Log Min Duration Statement Enabled in PostgreSQL Database Instances + author: princechaddha + severity: medium + description: | + Ensure that the log_min_duration_statement database flag is set to -1 (i.e., disabled) for all your Google Cloud PostgreSQL database instances. The log_min_duration_statement flag controls the minimum execution time of a statement for it to be logged. Setting it to any value other than -1 can result in excessive logging and potential performance issues. + impact: | + Enabling the log_min_duration_statement flag with a value other than -1 may cause excessive logging, leading to potential performance degradation and unnecessary storage usage. + remediation: | + Set the log_min_duration_statement flag to -1 in your PostgreSQL database instance configuration to disable logging based on statement duration. + reference: + - https://cloud.google.com/sql/docs/postgres/flags + tags: cloud,devops,gcp,gcloud,google-cloud-sql,postgresql,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter='DATABASE_VERSION:POSTGRES*' --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --project $projectId --format=json | jq '.settings.databaseFlags // [] | .[] | select(.name=="log_min_duration_statement") | .value' + + matchers-condition: and + matchers: + - type: word + part: body + words: + - "-1" + negative: true + + - type: regex + regex: + - '^(?:100|[1-9][0-9]?)$' + + extractors: + - type: dsl + dsl: + - '"The log_min_duration_statement flag is set to a non-compliant value for PostgreSQL instance " + sqlInstance + " in project " + projectId' diff --git a/cloud/gcp/sql/gcloud-pg-log-min-error-statement-flag-not-configured.yaml b/cloud/gcp/sql/gcloud-pg-log-min-error-statement-flag-not-configured.yaml new file mode 100644 index 00000000000..ef68932bdfd --- /dev/null +++ b/cloud/gcp/sql/gcloud-pg-log-min-error-statement-flag-not-configured.yaml @@ -0,0 +1,71 @@ +id: gcloud-pg-log-min-error-statement-flag-not-configured + +info: + name: Log Min Error Statement Flag Not Configured Properly for PostgreSQL Instances + author: princechaddha + severity: medium + description: | + Ensure that the "log_min_error_statement" database flag configured for your Google Cloud PostgreSQL database instances has the appropriate severity level in accordance with your organization's logging policy. The "log_min_error_statement" flag defines the minimum severity level for error statements to be logged. Valid levels include DEBUG5, DEBUG4, DEBUG3, DEBUG2, DEBUG1, INFO, NOTICE, WARNING, ERROR, LOG, FATAL, and PANIC. + impact: | + An improperly configured "log_min_error_statement" flag can result in insufficient error logging, making it difficult to troubleshoot or audit issues, or excessive logging, which can impact performance and increase storage costs. + remediation: | + Set the "log_min_error_statement" flag to the appropriate severity level (e.g., FATAL) as per your organization's logging policy to balance logging effectiveness and performance. + reference: + - https://cloud.google.com/sql/docs/postgres/flags + tags: cloud,devops,gcp,gcloud,google-cloud-sql,postgresql,logging,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter=DATABASE_VERSION:POSTGRES* --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --project $projectId --format=json | jq -r '.settings.databaseFlags[]? | select(.name=="log_min_error_statement") | .value // "null"' + + matchers: + - type: word + words: + - 'null' + + extractors: + - type: dsl + dsl: + - '"The log_min_error_statement flag is not configured properly or is set to an inappropriate value for PostgreSQL instance " + sqlInstance + " in project " + projectId' diff --git a/cloud/gcp/sql/gcloud-pg-log-min-messages-flag-not-configured.yaml b/cloud/gcp/sql/gcloud-pg-log-min-messages-flag-not-configured.yaml new file mode 100644 index 00000000000..9a7eacc12e7 --- /dev/null +++ b/cloud/gcp/sql/gcloud-pg-log-min-messages-flag-not-configured.yaml @@ -0,0 +1,71 @@ +id: gcloud-pg-log-min-messages-flag-not-configured + +info: + name: Log Min Messages Flag Not Configured Properly for PostgreSQL Instances + author: princechaddha + severity: medium + description: | + Ensure that the "log_min_messages" database flag configured for your Google Cloud PostgreSQL database instances has the appropriate severity level in accordance with your organization's logging policy. The "log_min_messages" flag defines the minimum severity level for messages to be logged. Valid levels include DEBUG5, DEBUG4, DEBUG3, DEBUG2, DEBUG1, INFO, NOTICE, WARNING, ERROR, LOG, FATAL, and PANIC. + impact: | + An improperly configured "log_min_messages" flag can result in insufficient logging, making it difficult to troubleshoot or audit issues, or excessive logging, which can impact performance and increase storage costs. + remediation: | + Set the "log_min_messages" flag to the appropriate severity level (e.g., ERROR) as per your organization's logging policy to balance logging effectiveness and performance. + reference: + - https://cloud.google.com/sql/docs/postgres/flags + tags: cloud,devops,gcp,gcloud,google-cloud-sql,postgresql,logging,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter=DATABASE_VERSION:POSTGRES* --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --project $projectId --format=json | jq -r '.settings.databaseFlags[]? | select(.name=="log_min_messages") | .value // "null"' + + matchers: + - type: word + words: + - 'null' + + extractors: + - type: dsl + dsl: + - '"The log_min_messages flag is not configured properly or is set to an inappropriate value for PostgreSQL instance " + sqlInstance + " in project " + projectId' diff --git a/cloud/gcp/sql/gcloud-pg-log-parser-stats-enabled.yaml b/cloud/gcp/sql/gcloud-pg-log-parser-stats-enabled.yaml new file mode 100644 index 00000000000..e6e4bad3ef1 --- /dev/null +++ b/cloud/gcp/sql/gcloud-pg-log-parser-stats-enabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-pg-log-parser-stats-enabled + +info: + name: Log Parser Stats Enabled in PostgreSQL Database Instances + author: princechaddha + severity: medium + description: | + Ensure that the "log_parser_stats" database flag is turned off for your Google Cloud PostgreSQL database instances in order to avoid performance issues caused by excessive logging. The PostgreSQL planner (PostgreSQL optimizer) is responsible for parsing and verifying the syntax of each query received by the database server. If the syntax is correct, a parse tree is built up; otherwise, an error is generated. The "log_parser_stats" flag controls the inclusion of parser performance statistics within PostgreSQL logs for each query made to the database. + impact: | + Enabling the "log_parser_stats" flag may lead to significant performance degradation due to excessive logging, impacting the database's overall efficiency. + remediation: | + Disable the "log_parser_stats" flag in your PostgreSQL database instance configuration to prevent performance issues caused by excessive logging. + reference: + - https://cloud.google.com/sql/docs/postgres/flags + tags: cloud,devops,gcp,gcloud,google-cloud-sql,postgresql,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter='DATABASE_VERSION:POSTGRES*' --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --project $projectId --format=json | jq '.settings.databaseFlags // [] | map(select(.name=="log_parser_stats")) | .[].value' + + matchers: + - type: word + words: + - 'on' + + extractors: + - type: dsl + dsl: + - '"The log_parser_stats flag is enabled for PostgreSQL instance " + sqlInstance + " in project " + projectId' diff --git a/cloud/gcp/sql/gcloud-pg-log-planner-stats-enabled.yaml b/cloud/gcp/sql/gcloud-pg-log-planner-stats-enabled.yaml new file mode 100644 index 00000000000..12e4ddc1fcc --- /dev/null +++ b/cloud/gcp/sql/gcloud-pg-log-planner-stats-enabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-pg-log-planner-stats-enabled + +info: + name: Log Planner Stats Enabled in PostgreSQL Database Instances + author: princechaddha + severity: medium + description: | + Ensure that the log_planner_stats database flag is disabled for your Google Cloud PostgreSQL database instances in order to avoid performance issues caused by excessive logging. The log_planner_stats flag controls the inclusion of PostgreSQL planner performance statistics in the PostgreSQL logs for each query. + impact: | + Enabling the log_planner_stats flag may lead to significant performance degradation due to excessive logging, impacting the database's overall efficiency. + remediation: | + Disable the log_planner_stats flag in your PostgreSQL database instance configuration to prevent performance issues caused by excessive logging. + reference: + - https://cloud.google.com/sql/docs/postgres/flags + tags: cloud,devops,gcp,gcloud,google-cloud-sql,postgresql,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter='DATABASE_VERSION:POSTGRES*' --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --project $projectId --format=json | jq '.settings.databaseFlags // [] | .[] | select(.name=="log_planner_stats") | .value' + + matchers: + - type: word + words: + - 'on' + + extractors: + - type: dsl + dsl: + - '"The log_planner_stats flag is enabled for PostgreSQL instance " + sqlInstance + " in project " + projectId' diff --git a/cloud/gcp/sql/gcloud-pg-log-statement-flag-not-configured.yaml b/cloud/gcp/sql/gcloud-pg-log-statement-flag-not-configured.yaml new file mode 100644 index 00000000000..e40b51cc42d --- /dev/null +++ b/cloud/gcp/sql/gcloud-pg-log-statement-flag-not-configured.yaml @@ -0,0 +1,71 @@ +id: gcloud-pg-log-statement-flag-not-configured + +info: + name: Log Statement Flag Not Configured Properly for PostgreSQL Database Instances + author: princechaddha + severity: medium + description: | + Ensure that the "log_statement" database flag configured for your Google Cloud PostgreSQL database instances has the appropriate value (logging level) in accordance with your organization's logging policy. The "log_statement" flag controls which SQL statements are logged, with valid values being: none, ddl, mod, and all. + impact: | + An improperly configured "log_statement" flag can result in either excessive logging, which impacts performance, or insufficient logging, which hinders troubleshooting and auditing. + remediation: | + Set the "log_statement" flag to the appropriate value (e.g., mod) based on your organization's logging policy to balance performance and logging requirements. + reference: + - https://cloud.google.com/sql/docs/postgres/flags + tags: cloud,devops,gcp,gcloud,google-cloud-sql,postgresql,logging,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter=DATABASE_VERSION:POSTGRES* --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --project $projectId --format=json | jq -r '.settings.databaseFlags[]? | select(.name=="log_statement") | .value // "null"' + + matchers: + - type: word + words: + - 'null' + + extractors: + - type: dsl + dsl: + - '"The log_statement flag is not configured or is set to an inappropriate value for PostgreSQL instance " + sqlInstance + " in project " + projectId' diff --git a/cloud/gcp/sql/gcloud-pg-log-statement-stats-enabled.yaml b/cloud/gcp/sql/gcloud-pg-log-statement-stats-enabled.yaml new file mode 100644 index 00000000000..3343b00b62a --- /dev/null +++ b/cloud/gcp/sql/gcloud-pg-log-statement-stats-enabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-pg-log-statement-stats-enabled + +info: + name: Log Statement Stats Enabled in PostgreSQL Database Instances + author: princechaddha + severity: medium + description: | + Ensure that the "log_statement_stats" database flag is disabled for your Google Cloud PostgreSQL database instances in order to avoid performance issues caused by excessive logging. The "log_statement_stats" configuration flag controls the inclusion of end-to-end performance statistics within PostgreSQL logs for each SQL query. + impact: | + Enabling the "log_statement_stats" flag may lead to significant performance degradation due to excessive logging, impacting the database's overall efficiency. + remediation: | + Disable the "log_statement_stats" flag in your PostgreSQL database instance configuration to prevent performance issues caused by excessive logging. + reference: + - https://cloud.google.com/sql/docs/postgres/flags + tags: cloud,devops,gcp,gcloud,google-cloud-sql,postgresql,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter='DATABASE_VERSION:POSTGRES*' --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --project $projectId --format=json | jq '.settings.databaseFlags // [] | map(select(.name=="log_statement_stats")) | .[].value' + + matchers: + - type: word + words: + - 'on' + + extractors: + - type: dsl + dsl: + - '"The log_statement_stats flag is enabled for PostgreSQL instance " + sqlInstance + " in project " + projectId' diff --git a/cloud/gcp/sql/gcloud-postgresql-log-checkpoints-disabled.yaml b/cloud/gcp/sql/gcloud-postgresql-log-checkpoints-disabled.yaml new file mode 100644 index 00000000000..190f3af44e7 --- /dev/null +++ b/cloud/gcp/sql/gcloud-postgresql-log-checkpoints-disabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-postgresql-log-checkpoints-disabled + +info: + name: PostgreSQL Log Checkpoints Flag Disabled + author: princechaddha + severity: medium + description: | + Ensure that the "log_checkpoints" database flag is enabled for all PostgreSQL database instances available within your Google Cloud Platform (GCP) account. The "log_checkpoints" flag allows checkpoints and restart points to be logged in the PostgreSQL server log. By default, this flag is disabled, and enabling it ensures better tracking and debugging of database operations. + impact: | + Disabling the "log_checkpoints" flag may result in limited visibility into checkpoint operations, making it difficult to troubleshoot and monitor PostgreSQL database activities effectively. + remediation: | + Enable the "log_checkpoints" flag for all PostgreSQL database instances by updating the database configuration using the Google Cloud Console or gcloud CLI. + reference: + - https://cloud.google.com/sql/docs/postgres/flags + tags: cloud,devops,gcp,gcloud,google-cloud-sql,postgresql,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter='DATABASE_VERSION:POSTGRES*' --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --format="json(settings.databaseFlags)" + + matchers: + - type: word + words: + - 'off' + + extractors: + - type: dsl + dsl: + - '"PostgreSQL Log Checkpoints flag is disabled in database instance: " + sqlInstance + " in project: " + projectId' diff --git a/cloud/gcp/sql/gcloud-postgresql-log-disconnections-unenabled.yaml b/cloud/gcp/sql/gcloud-postgresql-log-disconnections-unenabled.yaml new file mode 100644 index 00000000000..a74a874a599 --- /dev/null +++ b/cloud/gcp/sql/gcloud-postgresql-log-disconnections-unenabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-postgresql-log-disconnections-unenabled + +info: + name: Log Disconnections Flag Not Enabled for PostgreSQL Instances + author: princechaddha + severity: medium + description: | + Ensure that the "log_disconnections" database flag is enabled for all your Google Cloud PostgreSQL database instances. When this flag is enabled, PostgreSQL database logs the end of each session. The log output provides information similar to the one generated by the "log_connections" flag, plus the duration of the session. The database flag can be changed at the session start, and it cannot be changed during a session. + impact: | + Not enabling the "log_disconnections" flag may result in missing critical information about session terminations and their durations, which could be valuable for debugging and auditing. + remediation: | + Enable the "log_disconnections" flag for all Google Cloud PostgreSQL database instances by updating the database flag in the configuration settings. + reference: + - https://cloud.google.com/sql/docs/postgres/flags + tags: cloud,devops,gcp,gcloud,google-cloud-sql,postgresql,azure-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter='DATABASE_VERSION:POSTGRES*' --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --project $projectId --format=json | jq '.settings.databaseFlags[]? | select(.name=="log_disconnections") | .value' + + matchers: + - type: word + words: + - 'off' + + extractors: + - type: dsl + dsl: + - '"Log Disconnections flag is not enabled for PostgreSQL instance " + sqlInstance + " in project: " + projectId' diff --git a/cloud/gcp/sql/gcloud-postgresql-log-hostname-disabled.yaml b/cloud/gcp/sql/gcloud-postgresql-log-hostname-disabled.yaml new file mode 100644 index 00000000000..1637c851535 --- /dev/null +++ b/cloud/gcp/sql/gcloud-postgresql-log-hostname-disabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-postgresql-log-hostname-disabled + +info: + name: Log Hostname Flag Disabled for PostgreSQL Database Instances + author: princechaddha + severity: medium + description: | + Ensure that the "log_hostname" database flag is enabled for your Google Cloud PostgreSQL database instances in order to assist with incident response and tracking usage in an environment utilizing dynamic IP addresses. There is a potential cost to server performance caused by hostname logging. + impact: | + If the "log_hostname" flag is disabled, tracking and responding to incidents in dynamic IP address environments becomes more challenging, reducing the visibility of database activity and increasing the risk of undetected malicious activity. + remediation: | + Enable the "log_hostname" database flag for all PostgreSQL database instances in your Google Cloud environment to ensure proper logging and traceability. + reference: + - https://cloud.google.com/sql/docs/postgres/configure-instance-settings + tags: cloud,devops,gcp,gcloud,google-cloud-sql,postgresql,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter='DATABASE_VERSION:POSTGRES*' --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --project=$projectId --format=json | jq '.settings.databaseFlags // [] | map(select(.name=="log_hostname")) | .[].value' + + matchers: + - type: word + words: + - 'off' + + extractors: + - type: dsl + dsl: + - '"Log Hostname flag is disabled for PostgreSQL instance: " + sqlInstance + " in project: " + projectId' diff --git a/cloud/gcp/sql/gcloud-postgresql-logtempfiles-disabled.yaml b/cloud/gcp/sql/gcloud-postgresql-logtempfiles-disabled.yaml new file mode 100644 index 00000000000..dda2516e75b --- /dev/null +++ b/cloud/gcp/sql/gcloud-postgresql-logtempfiles-disabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-postgresql-logtempfiles-disabled + +info: + name: Log Temporary Files Flag Disabled in PostgreSQL Database Instances + author: princechaddha + severity: medium + description: | + Ensure that the "log_temp_files" database flag is set to 0 (enabled) for all your Google Cloud PostgreSQL database instances. PostgreSQL database engine can create temporary files for actions such as sorting, hashing, and temporary query results when these operations exceed the amount of memory specified for the "work_mem" setting. Setting "log_temp_files" flag to 0 causes all temporary file information to be logged, while positive configuration values log only files whose size is greater than or equal to the specified number of kilobytes. + impact: | + If the "log_temp_files" flag is not enabled, temporary file operations will not be logged, which may lead to challenges in diagnosing performance issues and compliance tracking. + remediation: | + Set the "log_temp_files" database flag to 0 for your PostgreSQL database instances to ensure temporary file operations are logged. + reference: + - https://cloud.google.com/sql/docs/postgres/configure-database-flags + tags: cloud,devops,gcp,google-cloud-sql,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter='DATABASE_VERSION:POSTGRES*' --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --project $projectId --format=json | jq '.settings.databaseFlags // [] | .[] | select(.name=="log_temp_files") | .value' + + matchers: + - type: word + words: + - '-1' + + extractors: + - type: dsl + dsl: + - '"log_temp_files flag is disabled for PostgreSQL instance: " + sqlInstance + " in project: " + projectId' diff --git a/cloud/gcp/sql/gcloud-sql-auto-storage-disabled.yaml b/cloud/gcp/sql/gcloud-sql-auto-storage-disabled.yaml new file mode 100644 index 00000000000..4991c51339d --- /dev/null +++ b/cloud/gcp/sql/gcloud-sql-auto-storage-disabled.yaml @@ -0,0 +1,72 @@ +id: gcloud-sql-auto-storage-disabled + +info: + name: Automatic Storage Increase Disabled for Google Cloud SQL Instances + author: princechaddha + severity: high + description: | + Ensure that the Automatic Storage Increase feature is enabled for your production Google Cloud SQL database instances. This feature prevents database servers from running out of storage space and becoming read-only, disrupting normal operations. When a database instance runs out of available space, it can drop existing connections and cause downtime, potentially violating the Google Cloud SQL Service Level Agreement (SLA). + impact: | + If Automatic Storage Increase is disabled, Cloud SQL database instances may run out of space, leading to service disruptions, dropped connections, and downtime. + remediation: | + Enable the Automatic Storage Increase feature for your Google Cloud SQL database instances to prevent storage exhaustion and ensure uninterrupted operations. + reference: + - https://cloud.google.com/sql/docs/overview#automatic-storage-increase + tags: cloud,devops,gcp,gcloud,google-cloud-sql,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --format="value(settings.storageAutoResize)" + + matchers: + - type: word + words: + - 'False' + condition: or + + extractors: + - type: dsl + dsl: + - '"Automatic Storage Increase is disabled for SQL instance " + sqlInstance + " in project " + projectId' diff --git a/cloud/gcp/sql/gcloud-sql-auto-storage-limit-not-configured.yaml b/cloud/gcp/sql/gcloud-sql-auto-storage-limit-not-configured.yaml new file mode 100644 index 00000000000..84db1ae6959 --- /dev/null +++ b/cloud/gcp/sql/gcloud-sql-auto-storage-limit-not-configured.yaml @@ -0,0 +1,71 @@ +id: gcloud-sql-auto-storage-limit-not-configured + +info: + name: Automatic Storage Increase Limit Not Configured for Cloud SQL + author: princechaddha + severity: medium + description: | + Ensure that an optimal limit is configured for the Automatic Storage Increase feature within your Cloud SQL database instance settings to avoid unexpected charges on your Google Cloud bill. Having no limit or an excessively high limit for this feature can lead to unplanned costs. + impact: | + Without an appropriate storage increase limit, unexpected charges may occur due to unlimited or excessive storage usage. + remediation: | + Configure an appropriate limit for the Automatic Storage Increase feature in your Cloud SQL database instance settings to control costs and maintain predictability. + reference: + - https://cloud.google.com/sql/docs/configure-storage + tags: cloud,devops,gcp,gcloud,google-cloud-sql,storage,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --project $projectId --format="value(settings.storageAutoResizeLimit)" | jq -r 'if . == null then "null" else . end' + + matchers: + - type: word + words: + - '0' + + extractors: + - type: dsl + dsl: + - '"The automatic storage increase limit is not configured or is set to unlimited for SQL instance " + sqlInstance + " in project " + projectId' diff --git a/cloud/gcp/sql/gcloud-sql-backups-disabled.yaml b/cloud/gcp/sql/gcloud-sql-backups-disabled.yaml new file mode 100644 index 00000000000..eadc8a8a117 --- /dev/null +++ b/cloud/gcp/sql/gcloud-sql-backups-disabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-sql-backups-disabled + +info: + name: Automated Backups Not Enabled for Cloud SQL Instances + author: princechaddha + severity: medium + description: | + Ensure that automated (scheduled) backups are created for all Cloud SQL database instances available within your Google Cloud Platform (GCP) account, in order to protect against data deletion and/or data corruption. + impact: | + If automated backups are not enabled, there is a risk of data loss or corruption with no way to recover the lost or damaged data, potentially affecting business continuity and compliance requirements. + remediation: | + Enable automated backups for all Cloud SQL database instances in your GCP account to ensure regular backups are taken to safeguard against data issues. + reference: + - https://cloud.google.com/sql/docs/mysql/backup-recovery/backups + tags: cloud,devops,gcp,gcloud,google-cloud-sql,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --format="value(settings.backupConfiguration.enabled)" + + matchers: + - type: word + words: + - 'False' + + extractors: + - type: dsl + dsl: + - '"Automated backups are not enabled for SQL Instance: " + sqlInstance + " in project: " + projectId' diff --git a/cloud/gcp/sql/gcloud-sql-cmk-not-enabled.yaml b/cloud/gcp/sql/gcloud-sql-cmk-not-enabled.yaml new file mode 100644 index 00000000000..f135c2559aa --- /dev/null +++ b/cloud/gcp/sql/gcloud-sql-cmk-not-enabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-sql-cmk-not-enabled + +info: + name: Cloud SQL Instance Encryption with Customer-Managed Keys Not Enabled + author: princechaddha + severity: high + description: | + Ensure that your Google Cloud SQL database instances are encrypted with Customer-Managed Keys (CMKs) in order to have a fine control over your data encryption and decryption process. You can create and manage your own Customer-Managed Keys (CMKs) with Cloud Key Management Service (Cloud KMS). Cloud KMS provides secure and efficient encryption key management, controlled key rotation, and revocation mechanisms. + impact: | + Not encrypting Google Cloud SQL database instances with Customer-Managed Keys (CMKs) can result in reduced security, lack of control over encryption keys, and potential regulatory compliance issues. + remediation: | + Configure Cloud SQL instances to use Customer-Managed Keys (CMKs) for encryption by enabling encryption with Cloud KMS and specifying a key for each database instance. + reference: + - https://cloud.google.com/sql/docs/mysql/configure-cmek + tags: cloud,devops,gcp,gcloud,google-cloud-sql,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --format="json(diskEncryptionConfiguration.kmsKeyName)" + + matchers: + - type: word + words: + - 'null' + + extractors: + - type: dsl + dsl: + - '"Cloud SQL instance " + sqlInstance + " in project " + projectId + " is not encrypted with a Customer-Managed Key (CMK)"' diff --git a/cloud/gcp/sql/gcloud-sql-contained-db-authentication-enabled.yaml b/cloud/gcp/sql/gcloud-sql-contained-db-authentication-enabled.yaml new file mode 100644 index 00000000000..47dd7d15120 --- /dev/null +++ b/cloud/gcp/sql/gcloud-sql-contained-db-authentication-enabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-sql-contained-db-authentication-enabled + +info: + name: Contained Database Authentication Enabled in SQL Server Database Instances + author: princechaddha + severity: medium + description: | + Ensure that the "contained database authentication" database flag is disabled for your Google Cloud SQL Server database instances. This flag, when enabled, allows databases to contain their authentication and can potentially lead to security vulnerabilities. + impact: | + Enabling the "contained database authentication" flag can introduce security risks by allowing databases to manage authentication independently, bypassing centralized security controls. + remediation: | + Disable the "contained database authentication" flag in your SQL Server database instance configuration to enhance security and enforce centralized authentication. + reference: + - https://cloud.google.com/sql/docs/sqlserver/flags + tags: cloud,devops,gcp,gcloud,google-cloud-sql,sqlserver,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter=DATABASE_VERSION:SQLSERVER* --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --project $projectId --format=json | jq -r '.settings.databaseFlags[]? | select(.name=="contained database authentication") | .value // "null"' + + matchers: + - type: word + words: + - 'on' + + extractors: + - type: dsl + dsl: + - '"The contained database authentication flag is enabled for SQL Server instance " + sqlInstance + " in project " + projectId' diff --git a/cloud/gcp/sql/gcloud-sql-cross-db-ownership-chaining-enabled.yaml b/cloud/gcp/sql/gcloud-sql-cross-db-ownership-chaining-enabled.yaml new file mode 100644 index 00000000000..253177181a5 --- /dev/null +++ b/cloud/gcp/sql/gcloud-sql-cross-db-ownership-chaining-enabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-sql-cross-db-ownership-chaining-enabled + +info: + name: Cross DB Ownership Chaining Enabled in SQL Server Database Instances + author: princechaddha + severity: medium + description: | + Ensure that the "cross db ownership chaining" database flag is disabled for your Google Cloud SQL Server database instances. This flag, when enabled, can potentially introduce security risks by allowing cross-database access without explicit permissions. + impact: | + Enabling the "cross db ownership chaining" flag can lead to potential security vulnerabilities by allowing unauthorized access across databases. + remediation: | + Disable the "cross db ownership chaining" flag in your SQL Server database instance configuration to prevent unauthorized cross-database access. + reference: + - https://cloud.google.com/sql/docs/sqlserver/flags + tags: cloud,devops,gcp,gcloud,google-cloud-sql,sqlserver,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter=DATABASE_VERSION:SQLSERVER* --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --project $projectId --format=json | jq -r '.settings.databaseFlags[]? | select(.name=="cross db ownership chaining") | .value // "null"' + + matchers: + - type: word + words: + - 'on' + + extractors: + - type: dsl + dsl: + - '"The cross db ownership chaining flag is enabled for SQL Server instance " + sqlInstance + " in project " + projectId' diff --git a/cloud/gcp/sql/gcloud-sql-database-public-ip-configured.yaml b/cloud/gcp/sql/gcloud-sql-database-public-ip-configured.yaml new file mode 100644 index 00000000000..2a6f0d95f15 --- /dev/null +++ b/cloud/gcp/sql/gcloud-sql-database-public-ip-configured.yaml @@ -0,0 +1,71 @@ +id: gcloud-sql-database-public-ip-configured + +info: + name: Cloud SQL Database Instances with Public IPs + author: princechaddha + severity: medium + description: | + Ensure that your Google Cloud SQL database instances are configured to use private IP addresses instead of public IPs to protect against potential security risks and unauthorized access. + impact: | + Database instances with public IP addresses are exposed to the internet, increasing the risk of unauthorized access and potential attacks. + remediation: | + Configure your Cloud SQL database instances to use private IP addresses to limit exposure to external networks and enhance security. + reference: + - https://cloud.google.com/sql/docs/mysql/configure-private-ip + tags: cloud,devops,gcp,gcloud,google-cloud-sql,networking,security,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --project $projectId --format=json | jq -r '.ipAddresses[]?.type // "null"' + + matchers: + - type: word + words: + - 'PRIMARY' + + extractors: + - type: dsl + dsl: + - '"The SQL instance " + sqlInstance + " in project " + projectId + " is configured with a public IP address and is not set to use only private IPs."' diff --git a/cloud/gcp/sql/gcloud-sql-external-scripts-enabled.yaml b/cloud/gcp/sql/gcloud-sql-external-scripts-enabled.yaml new file mode 100644 index 00000000000..b8b0e409679 --- /dev/null +++ b/cloud/gcp/sql/gcloud-sql-external-scripts-enabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-sql-external-scripts-enabled + +info: + name: External Scripts Enabled in SQL Server Database Instances + author: princechaddha + severity: high + description: | + Ensure that the external scripts enabled database flag is turned off for your Google Cloud SQL Server database instances in order to disable the execution of scripts with certain remote language extensions. + impact: | + Enabling the external scripts enabled flag may expose the database to potential security risks by allowing the execution of external scripts that could exploit vulnerabilities. + remediation: | + Disable the external scripts enabled flag in your SQL Server database instance configuration to enhance security and prevent potential misuse of the feature. + reference: + - https://cloud.google.com/sql/docs/sqlserver/flags + tags: cloud,devops,gcp,gcloud,google-cloud-sql,sqlserver,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter='DATABASE_VERSION:SQLSERVER*' --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --project $projectId --format=json | jq '.settings.databaseFlags[]? | select(.name=="external scripts enabled") | .value' + + matchers: + - type: word + words: + - 'on' + + extractors: + - type: dsl + dsl: + - '"The external scripts enabled flag is enabled for SQL Server instance " + sqlInstance + " in project " + projectId' diff --git a/cloud/gcp/sql/gcloud-sql-ha-not-enabled.yaml b/cloud/gcp/sql/gcloud-sql-ha-not-enabled.yaml new file mode 100644 index 00000000000..1dfac68a1b1 --- /dev/null +++ b/cloud/gcp/sql/gcloud-sql-ha-not-enabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-sql-ha-not-enabled + +info: + name: High Availability Not Enabled for Cloud SQL Database Instances + author: princechaddha + severity: high + description: | + Ensure that all your production and mission-critical Google Cloud SQL database instances are configured for High Availability (HA) and automatic failover support. Configuring HA ensures database reliability and minimizes downtime in the event of an outage. + impact: | + Cloud SQL database instances not configured with High Availability (HA) lack automatic failover support, which can lead to extended downtime and potential data accessibility issues during outages. + remediation: | + Update the configuration of your Google Cloud SQL database instances to use High Availability (REGIONAL) instead of the default ZONAL configuration to enable automatic failover and ensure minimal downtime. + reference: + - https://cloud.google.com/sql/docs/mysql/high-availability + tags: cloud,devops,gcp,gcloud,google-cloud-sql,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --format="value(settings.availabilityType)" + + matchers: + - type: word + words: + - 'ZONAL' + + extractors: + - type: dsl + dsl: + - '"High Availability is not enabled for Cloud SQL instance: " + sqlInstance + " in project: " + projectId' diff --git a/cloud/gcp/sql/gcloud-sql-log-checkpoints-disabled.yaml b/cloud/gcp/sql/gcloud-sql-log-checkpoints-disabled.yaml new file mode 100644 index 00000000000..665b8ea0223 --- /dev/null +++ b/cloud/gcp/sql/gcloud-sql-log-checkpoints-disabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-sql-log-checkpoints-disabled + +info: + name: Log Checkpoints Disabled in PostgreSQL Database Instances + author: princechaddha + severity: medium + description: | + Ensure that the "log_checkpoints" database flag is enabled for your Google Cloud PostgreSQL database instances. The "log_checkpoints" flag allows checkpoints and restart points to be logged and included within the PostgreSQL server log. + impact: | + Without enabling "log_checkpoints", crucial log data related to checkpoints and restart points will not be captured, making it difficult to monitor and troubleshoot PostgreSQL database performance and issues. + remediation: | + Enable the "log_checkpoints" flag for PostgreSQL database instances to ensure logging of checkpoints and restart points for better observability. + reference: + - https://cloud.google.com/sql/docs/postgres/configure-instance-settings + tags: cloud,devops,gcp,gcloud,google-cloud-sql,postgresql,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter='DATABASE_VERSION:POSTGRES*' --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --format=json | jq '.settings.databaseFlags // [] | map(select(.name == "log_checkpoints")) | .[0]?.value' + + matchers: + - type: word + words: + - 'off' + + extractors: + - type: dsl + dsl: + - '"Log Checkpoints flag is disabled in PostgreSQL instance: " + sqlInstance + " in project: " + projectId' diff --git a/cloud/gcp/sql/gcloud-sql-log-connections-disabled.yaml b/cloud/gcp/sql/gcloud-sql-log-connections-disabled.yaml new file mode 100644 index 00000000000..222b4b07abf --- /dev/null +++ b/cloud/gcp/sql/gcloud-sql-log-connections-disabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-sql-log-connections-disabled + +info: + name: Log Connections Disabled for PostgreSQL Database Instances + author: princechaddha + severity: medium + description: | + Ensure that the "log_connections" database flag is enabled for your Google Cloud PostgreSQL database instances. The "log_connections" flag causes each attempted connection to the database instance to be logged, including successful client authentication requests. This flag helps with monitoring and auditing database access. Only PostgreSQL database administrators can change this parameter at session start, and it cannot be changed after the session starts. + impact: | + If "log_connections" is not enabled, you may lose critical information about database connections, impacting monitoring and security auditing capabilities. + remediation: | + Enable the "log_connections" database flag for your PostgreSQL instances in Google Cloud. This can be done by updating the instance settings and applying the change. + reference: + - https://cloud.google.com/sql/docs/postgres/configure-database-flags + tags: cloud,devops,gcp,gcloud,google-cloud-sql,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter='DATABASE_VERSION:POSTGRES*' --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --format="json(settings.databaseFlags)" | jq '.[] | select(.name=="log_connections") | .value' + + matchers: + - type: word + words: + - 'off' + + extractors: + - type: dsl + dsl: + - '"Log Connections flag is disabled for PostgreSQL instance " + sqlInstance + " in project: " + projectId' diff --git a/cloud/gcp/sql/gcloud-sql-log-lock-waits-disabled.yaml b/cloud/gcp/sql/gcloud-sql-log-lock-waits-disabled.yaml new file mode 100644 index 00000000000..7695dfa0324 --- /dev/null +++ b/cloud/gcp/sql/gcloud-sql-log-lock-waits-disabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-sql-log-lock-waits-disabled + +info: + name: Log Lock Waits Flag Disabled for PostgreSQL Database Instances + author: princechaddha + severity: medium + description: | + Ensure that the "log_lock_waits" database flag is enabled for all your Google Cloud PostgreSQL database instances to improve database performance monitoring and troubleshooting. + impact: | + Disabling the "log_lock_waits" flag can lead to reduced visibility into database lock wait events, which may result in difficulty identifying and resolving performance bottlenecks. + remediation: | + Enable the "log_lock_waits" database flag for all PostgreSQL database instances in your Google Cloud environment. This ensures better monitoring and identification of lock wait issues. + reference: + - https://cloud.google.com/sql/docs/postgres/flags + tags: cloud,devops,gcp,gcloud,google-cloud-sql,postgreSQL,azure-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter='DATABASE_VERSION:POSTGRES*' --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --format="json(settings.databaseFlags)" | jq '.[]? | select(.name=="log_lock_waits") | .value' + + matchers: + - type: word + words: + - '"off"' + + extractors: + - type: dsl + dsl: + - '"Log Lock Waits Flag is not enabled for PostgreSQL Database Instance: " + sqlInstance + " in project: " + projectId' diff --git a/cloud/gcp/sql/gcloud-sql-pgaudit-not-enabled.yaml b/cloud/gcp/sql/gcloud-sql-pgaudit-not-enabled.yaml new file mode 100644 index 00000000000..78f4981a54c --- /dev/null +++ b/cloud/gcp/sql/gcloud-sql-pgaudit-not-enabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-sql-pgaudit-not-enabled + +info: + name: pgAudit Flags Not Enabled for PostgreSQL Instances in Cloud SQL + author: princechaddha + severity: medium + description: | + Ensure that the "cloudsql.enable_pgaudit" and "pgaudit.log" database flags are enabled for your Google Cloud PostgreSQL server instances to enable database auditing. These configurations are crucial for compliance with government, financial, and ISO certifications. + impact: | + Without pgAudit and log configurations, critical database activities may go unmonitored, potentially leading to non-compliance with regulatory standards and increasing the risk of security incidents. + remediation: | + Configure your PostgreSQL instances with the "cloudsql.enable_pgaudit" flag set to "on" and the "pgaudit.log" flag set to "all". These settings enable enhanced auditing capabilities. + reference: + - https://cloud.google.com/sql/docs/postgres/flags + tags: cloud,devops,gcp,gcloud,google-cloud-sql,postgresql,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter='DATABASE_VERSION:POSTGRES*' --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --format=json | jq '.settings.databaseFlags[]? | select(.name=="cloudsql.enable_pgaudit") | .value' + + matchers: + - type: word + words: + - 'off' + + extractors: + - type: dsl + dsl: + - '"Cloud SQL instance " + sqlInstance + " in project " + projectId + " has pgAudit flag disabled (cloudsql.enable_pgaudit=off or pgaudit.log!=all)."' diff --git a/cloud/gcp/sql/gcloud-sql-publicly-accessible-instances.yaml b/cloud/gcp/sql/gcloud-sql-publicly-accessible-instances.yaml new file mode 100644 index 00000000000..cdee08cd1c6 --- /dev/null +++ b/cloud/gcp/sql/gcloud-sql-publicly-accessible-instances.yaml @@ -0,0 +1,90 @@ +id: gcloud-sql-publicly-accessible-instances + +info: + name: Publicly Accessible Cloud SQL Database Instances + author: princechaddha + severity: medium + description: | + Ensure that your Google Cloud SQL database instances are configured to accept connections only from trusted networks and IP addresses. Publicly accessible instances may expose sensitive data to unauthorized access. + impact: | + Publicly accessible database instances can lead to unauthorized access, exposing sensitive data and increasing the risk of security breaches. + remediation: | + Configure your Cloud SQL database instances to accept connections only from trusted IP addresses and networks by limiting access to known authorized networks. + reference: + - https://cloud.google.com/sql/docs/mysql/configure-ip + tags: cloud,devops,gcp,gcloud,google-cloud-sql,networking,security,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + code(4) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --project $projectId --format=json | jq -r '.settings.ipConfiguration.ipv4Enabled // "null"' + + matchers: + - type: word + words: + - 'true' + condition: and + + extractors: + - type: dsl + dsl: + - '"The SQL instance " + sqlInstance + " in project " + projectId + " is configured with a public IP address"' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --project $projectId --format=json | jq -r '.settings.ipConfiguration.authorizedNetworks[]?.value // "null"' + + matchers: + - type: word + words: + - '0.0.0.0/0' + condition: and + + extractors: + - type: dsl + dsl: + - '"The SQL instance " + sqlInstance + " in project " + projectId + " allows access from 0.0.0.0/0, making it publicly accessible"' diff --git a/cloud/gcp/sql/gcloud-sql-remote-access-enabled.yaml b/cloud/gcp/sql/gcloud-sql-remote-access-enabled.yaml new file mode 100644 index 00000000000..de301796722 --- /dev/null +++ b/cloud/gcp/sql/gcloud-sql-remote-access-enabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-sql-remote-access-enabled + +info: + name: Remote Access Enabled for SQL Server Database Instances + author: princechaddha + severity: high + description: | + Ensure that the "remote access" database flag is turned off for your Google Cloud SQL Server database instances. This prevents the execution of stored procedures from local or remote servers on which your SQL Server instances are running, improving security and compliance. + impact: | + Enabling the "remote access" flag for SQL Server database instances can lead to security vulnerabilities, as it allows execution of stored procedures from remote servers. This increases the attack surface of the database. + remediation: | + Disable the "remote access" database flag for all SQL Server database instances in Google Cloud Platform. Update the database configuration settings to ensure the flag is turned off. + reference: + - https://cloud.google.com/sql/docs/sqlserver/configure-instance-settings + tags: cloud,devops,gcp,gcloud,google-cloud-sql,sqlserver,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter='DATABASE_VERSION:SQLSERVER*' --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --format=json | jq '.settings.databaseFlags // [] | .[] | select(.name=="remote access") | .value' + + matchers: + - type: word + words: + - 'on' + + extractors: + - type: dsl + dsl: + - '"Remote Access is enabled for SQL instance " + sqlInstance + " in project " + projectId' diff --git a/cloud/gcp/sql/gcloud-sql-skip-show-database-disabled.yaml b/cloud/gcp/sql/gcloud-sql-skip-show-database-disabled.yaml new file mode 100644 index 00000000000..8d01c262344 --- /dev/null +++ b/cloud/gcp/sql/gcloud-sql-skip-show-database-disabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-sql-skip-show-database-disabled + +info: + name: Skip Show Database Flag Not Enabled for MySQL Instances + author: princechaddha + severity: medium + description: | + Ensure that the "skip_show_database" database flag is enabled for your Google Cloud MySQL database instances in order to prevent users from using the SHOW DATABASES statement if they don't have this privilege. + impact: | + If the "skip_show_database" flag is not enabled, unauthorized users may view a list of all databases, leading to potential data exposure and compliance violations. + remediation: | + Enable the "skip_show_database" flag for MySQL database instances in Google Cloud. This can be configured in the database settings under the databaseFlags section or through the gcloud CLI. + reference: + - https://cloud.google.com/sql/docs/mysql/configure-database-flags + tags: cloud,devops,gcp,gcloud,google-cloud-sql,mysql-database,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter='DATABASE_VERSION:MYSQL*' --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --format="json(settings.databaseFlags)" + + matchers: + - type: word + words: + - 'off' + + extractors: + - type: dsl + dsl: + - '"Skip Show Database Flag is not enabled for MySQL instance " + sqlInstance + " in project " + projectId' diff --git a/cloud/gcp/sql/gcloud-sql-ssl-not-enforced.yaml b/cloud/gcp/sql/gcloud-sql-ssl-not-enforced.yaml new file mode 100644 index 00000000000..acd65274b50 --- /dev/null +++ b/cloud/gcp/sql/gcloud-sql-ssl-not-enforced.yaml @@ -0,0 +1,71 @@ +id: gcloud-sql-ssl-not-enforced + +info: + name: SSL/TLS Not Enforced for Cloud SQL Incoming Connections + author: princechaddha + severity: medium + description: | + Enforce all incoming connections to your Cloud SQL database instances to use SSL/TLS only. If the SSL/TLS protocol is not enforced for all Cloud SQL connections, clients without a valid certificate are allowed to connect to the database, leading to potential security vulnerabilities. + impact: | + Without SSL/TLS enforcement, Cloud SQL database connections are vulnerable to eavesdropping, tampering, and impersonation attacks, posing a significant security risk. + remediation: | + Enable SSL/TLS for all incoming connections to your Cloud SQL instances. Update the SSL_MODE configuration to allow only encrypted connections. + reference: + - https://cloud.google.com/sql/docs/mysql/configure-ssl-instance + tags: cloud,devops,gcp,gcloud,google-cloud-sql,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --format="json(settings.ipConfiguration.sslMode)" + + matchers: + - type: word + words: + - 'ALLOW_UNENCRYPTED_AND_ENCRYPTED' + + extractors: + - type: dsl + dsl: + - '"SSL/TLS Not Enforced for incoming connections on Cloud SQL instance " + sqlInstance + " in project " + projectId' diff --git a/cloud/gcp/sql/gcloud-sql-ssl-tls-connections-not-enforced.yaml b/cloud/gcp/sql/gcloud-sql-ssl-tls-connections-not-enforced.yaml new file mode 100644 index 00000000000..f75f7725f3f --- /dev/null +++ b/cloud/gcp/sql/gcloud-sql-ssl-tls-connections-not-enforced.yaml @@ -0,0 +1,71 @@ +id: gcloud-sql-ssl-tls-connections-not-enforced + +info: + name: Allow SSL/TLS Connections Only + author: princechaddha + severity: medium + description: | + Ensure that all incoming connections to your Cloud SQL database instances are encrypted with SSL/TLS to protect against eavesdropping and unauthorized access. The SSL enforcement mode must be set to "ENCRYPTED_ONLY" to enforce secure connections. + impact: | + Allowing unencrypted connections can expose sensitive data to interception and increase the risk of unauthorized access. + remediation: | + Set the SSL enforcement mode to "ENCRYPTED_ONLY" for all Cloud SQL database instances to ensure all incoming connections use SSL/TLS encryption. + reference: + - https://cloud.google.com/sql/docs/mysql/configure-ssl + tags: cloud,devops,gcp,gcloud,google-cloud-sql,networking,security,ssl,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --project $projectId --format="value(settings.ipConfiguration.sslMode)" + + matchers: + - type: word + words: + - 'ALLOW_UNENCRYPTED_AND_ENCRYPTED' + + extractors: + - type: dsl + dsl: + - '"The SQL instance " + sqlInstance + " in project " + projectId + " does not enforce SSL/TLS connections and allows unencrypted access"' diff --git a/cloud/gcp/sql/gcloud-sql-trace-3625-enabled.yaml b/cloud/gcp/sql/gcloud-sql-trace-3625-enabled.yaml new file mode 100644 index 00000000000..86dfcb53ab5 --- /dev/null +++ b/cloud/gcp/sql/gcloud-sql-trace-3625-enabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-sql-trace-3625-enabled + +info: + name: Trace Flag 3625 Enabled in SQL Server Database Instances + author: princechaddha + severity: medium + description: | + Ensure that the 3625 trace flag is turned off for all your Google Cloud SQL Server database instances to follow security best practices. Trace flag 3625 controls the format of certain error messages, which may reveal sensitive information if enabled. + impact: | + Enabling the 3625 trace flag may expose sensitive information through detailed error messages, potentially violating security best practices and compliance requirements. + remediation: | + Disable the 3625 trace flag in your SQL Server database instance configuration to enhance security and protect sensitive information. + reference: + - https://cloud.google.com/sql/docs/sqlserver/flags + tags: cloud,devops,gcp,gcloud,google-cloud-sql,sqlserver,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter='DATABASE_VERSION:SQLSERVER*' --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --project $projectId --format=json | jq '.settings.databaseFlags // [] | map(select(.name=="3625")) | .[].value' + + matchers: + - type: word + words: + - 'on' + + extractors: + - type: dsl + dsl: + - '"The 3625 trace flag is enabled for SQL Server instance " + sqlInstance + " in project " + projectId' diff --git a/cloud/gcp/sql/gcloud-sql-user-options.yaml b/cloud/gcp/sql/gcloud-sql-user-options.yaml new file mode 100644 index 00000000000..7967fe97db6 --- /dev/null +++ b/cloud/gcp/sql/gcloud-sql-user-options.yaml @@ -0,0 +1,70 @@ +id: gcloud-sql-user-options + +info: + name: User Options Flag Enabled in Google Cloud SQL Server Instances + author: princechaddha + severity: medium + description: | + Checks if the "user options" database flag is configured for Google Cloud SQL Server instances, which can define global defaults for all database users. + impact: | + Configuring the "user options" database flag can lead to unintended global defaults for all database users, potentially causing performance issues or undesired behavior. + remediation: | + Disable the "user options" database flag for your Google Cloud SQL Server instances to avoid global defaults for all database users. + reference: + - https://cloud.google.com/sql/docs/sqlserver/configure-database-flags + tags: cloud,devops,gcp,gcloud,google-cloud-sql,sql-database-flags,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sqlInstance of iterate(template.sqlInstances)){ + set("sqlInstance", sqlInstance) + code(3) + }} + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud sql instances list --project $projectId --filter='DATABASE_VERSION:SQLSERVER*' --format="json(name)" + + extractors: + - type: json + name: sqlInstances + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud sql instances describe $sqlInstance --format=json | jq '.settings.databaseFlags // [] | map(select(.name == "user options")) | .[].value' + + matchers: + - type: regex + regex: + - '^(?:100|[1-9][0-9]?)$' + + extractors: + - type: dsl + dsl: + - '"The user options database flag is enabled for the SQL Server instance " + sqlInstance + " in project " + projectId + "."' diff --git a/cloud/gcp/storage/gcloud-bucket-lock-not-configured.yaml b/cloud/gcp/storage/gcloud-bucket-lock-not-configured.yaml new file mode 100644 index 00000000000..32b86862dc2 --- /dev/null +++ b/cloud/gcp/storage/gcloud-bucket-lock-not-configured.yaml @@ -0,0 +1,72 @@ +id: gcloud-bucket-lock-not-configured + +info: + name: Configure Retention Policies with Bucket Lock for Log Buckets + author: princechaddha + severity: medium + description: | + Ensure that all retention policies attached to your Google Cloud log sink buckets are configured with the Bucket Lock feature. This prevents logging data from being overwritten or deleted and ensures compliance with data retention policies by locking the retention configuration. + impact: | + Without the Bucket Lock feature, retention policies can be modified or removed, potentially leading to accidental or unauthorized deletion of critical logging data. + remediation: | + Enable Bucket Lock on your Google Cloud log sink buckets to enforce retention policies and prevent changes to the data retention duration. + reference: + - https://cloud.google.com/storage/docs/bucket-lock + tags: cloud,devops,gcp,gcloud,google-cloud-logging,retention,bucket-lock,security,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let sink of iterate(template.sinks)){ + sink = JSON.parse(sink); + set("bucketName", sink.name) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud logging sinks list --project=$projectId --format="json(name,destination)" + + extractors: + - type: json + name: sinks + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gsutil retention get gs://$bucketName + + matchers: + - type: word + words: + - 'no Retention Policy' + + extractors: + - type: dsl + dsl: + - '"The bucket " + bucketName + " in project " + projectId + " does not have a configured retention policy with Bucket Lock."' diff --git a/cloud/gcp/storage/gcloud-bucket-policies-admin-permissions.yaml b/cloud/gcp/storage/gcloud-bucket-policies-admin-permissions.yaml new file mode 100644 index 00000000000..8856b4210e8 --- /dev/null +++ b/cloud/gcp/storage/gcloud-bucket-policies-admin-permissions.yaml @@ -0,0 +1,75 @@ +id: gcloud-bucket-policies-admin-permissions + +info: + name: Check Bucket Policies with Administrative Permissions + author: princechaddha + severity: high + description: | + Ensure that the IAM policy associated with your Google Cloud Storage buckets does not grant privileged, administrative permissions. This promotes the Principle of Least Privilege (POLP) by providing principals only the minimal access required to perform their tasks. + impact: | + Administrative permissions on Cloud Storage buckets can lead to unauthorized changes, data exposure, or potential misuse, violating security best practices. + remediation: | + Review and update IAM policies for your Google Cloud Storage buckets to remove roles such as roles/owner, roles/editor, or any roles containing "Admin" to adhere to the Principle of Least Privilege. + reference: + - https://cloud.google.com/storage/docs/access-control/iam + tags: cloud,devops,gcp,gcloud,google-cloud-storage,iam,security,polp,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let bucketName of iterate(template.buckets)){ + set("bucketName", bucketName) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud storage buckets list --project $projectId --format="json(name)" + + extractors: + - type: json + name: buckets + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud storage buckets get-iam-policy gs://$bucketName --format="json(bindings)" | jq -r '.bindings[]?.role // "null"' + + matchers: + - type: word + words: + - 'roles/owner' + - 'roles/editor' + - 'roles/storage.admin' + - 'roles/admin' + condition: or + + extractors: + - type: dsl + dsl: + - '"The bucket " + bucketName + " in project " + projectId + " has IAM policies with administrative permissions (e.g., roles/owner, roles/editor, roles/*admin)."' diff --git a/cloud/gcp/storage/gcloud-bucket-website-config-not-defined.yaml b/cloud/gcp/storage/gcloud-bucket-website-config-not-defined.yaml new file mode 100644 index 00000000000..051b936e2f9 --- /dev/null +++ b/cloud/gcp/storage/gcloud-bucket-website-config-not-defined.yaml @@ -0,0 +1,71 @@ +id: gcloud-bucket-website-config-not-defined + +info: + name: Define Index Page Suffix and Error Page for Bucket Website Configuration + author: princechaddha + severity: high + description: | + Ensure that website index (main) page suffix and error (404 not found) page are defined for your Google Cloud Storage buckets with static website configuration. Specifying these configurations ensures proper functionality and user experience for websites hosted on Cloud Storage buckets. + impact: | + Without a defined index page suffix and error page, users may encounter broken functionality or unexpected behavior when accessing the hosted website. + remediation: | + Define an index page suffix (e.g., index.html) and an error page (e.g., 404.html) in the static website configuration for your Cloud Storage buckets. + reference: + - https://cloud.google.com/storage/docs/hosting-static-website + tags: cloud,devops,gcp,gcloud,google-cloud-storage,website-config,static-website,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let bucketName of iterate(template.buckets)){ + set("bucketName", bucketName) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gsutil ls -p $projectId | jq -R . | jq -s . + + extractors: + - type: json + name: buckets + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gsutil web get $bucketName + + matchers: + - type: word + words: + - 'has no website configuration' + + extractors: + - type: dsl + dsl: + - '"The bucket " + bucketName + " in project " + projectId + " does not have a valid static website configuration with both index page suffix and error page defined"' diff --git a/cloud/gcp/storage/gcloud-data-access-audit-logs-not-enabled.yaml b/cloud/gcp/storage/gcloud-data-access-audit-logs-not-enabled.yaml new file mode 100644 index 00000000000..e5e3e8f3cfc --- /dev/null +++ b/cloud/gcp/storage/gcloud-data-access-audit-logs-not-enabled.yaml @@ -0,0 +1,57 @@ +id: gcloud-data-access-audit-logs-not-enabled + +info: + name: Enable Data Access Audit Logs for Cloud Storage + author: princechaddha + severity: medium + description: | + Ensure that Data Access audit logs are enabled for your Google Cloud Storage buckets and objects to track read, write, and admin operations. Data Access audit logs provide insights into resource usage and help ensure security, compliance, and effective troubleshooting. + impact: | + Without Data Access audit logs, tracking operations on storage resources becomes difficult, increasing the risk of undetected unauthorized access or non-compliance with security policies. + remediation: | + Enable Data Access audit logs for the "storage.googleapis.com" service in your project to monitor all read, write, and admin activities on Cloud Storage resources. + reference: + - https://cloud.google.com/logging/docs/audit + tags: cloud,devops,gcp,gcloud,google-cloud-storage,audit-logs,security,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud projects get-iam-policy $projectId --format="json(auditConfigs)" | jq -r '.auditConfigs[]?.auditLogConfigs[]?.logType // "null"' + + matchers: + - type: word + words: + - 'ADMIN_READ' + - 'DATA_READ' + - 'DATA_WRITE' + condition: and + + extractors: + - type: dsl + dsl: + - '"Data Access audit logs are not enabled for the \"storage.googleapis.com\" service in project " + projectId' diff --git a/cloud/gcp/storage/gcloud-insufficient-data-retention-period.yaml b/cloud/gcp/storage/gcloud-insufficient-data-retention-period.yaml new file mode 100644 index 00000000000..bcb998ee18c --- /dev/null +++ b/cloud/gcp/storage/gcloud-insufficient-data-retention-period.yaml @@ -0,0 +1,71 @@ +id: gcloud-insufficient-data-retention-period + +info: + name: Check for Sufficient Data Retention Period for Cloud Storage Buckets + author: princechaddha + severity: medium + description: | + Ensure that the objects stored within your Google Cloud Storage buckets have a sufficient data retention period configured to meet security and compliance requirements. Retention policies prevent the deletion or modification of objects for a specified duration. + impact: | + Insufficient retention periods can lead to data being prematurely deleted, resulting in potential security, compliance, and operational risks. + remediation: | + Configure a sufficient data retention period for your Google Cloud Storage buckets based on your organization's security and compliance policies. + reference: + - https://cloud.google.com/storage/docs/bucket-lock + tags: cloud,devops,gcp,gcloud,google-cloud-storage,retention,security,compliance,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let bucketName of iterate(template.buckets)){ + set("bucketName", bucketName) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gsutil ls -p $projectId | jq -R . | jq -s . + + extractors: + - type: json + name: buckets + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gsutil retention get $bucketName + + matchers: + - type: word + words: + - 'no Retention Policy' + + extractors: + - type: dsl + dsl: + - '"The bucket " + bucketName + " in project " + projectId + " does not have a sufficient retention period configured or the retention policy is unlocked."' diff --git a/cloud/gcp/storage/gcloud-lifecycle-management-not-enabled.yaml b/cloud/gcp/storage/gcloud-lifecycle-management-not-enabled.yaml new file mode 100644 index 00000000000..4f700646e0d --- /dev/null +++ b/cloud/gcp/storage/gcloud-lifecycle-management-not-enabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-lifecycle-management-not-enabled + +info: + name: Enable Lifecycle Management for Cloud Storage Objects + author: princechaddha + severity: medium + description: | + Ensure that your Google Cloud Storage buckets are configured with lifecycle management rules to optimize object management and reduce storage costs. Lifecycle management rules help automate actions such as downgrading or deleting older objects based on user-defined conditions. + impact: | + Without lifecycle management, your storage costs may increase due to older objects occupying space unnecessarily, and object management becomes less efficient. + remediation: | + Enable lifecycle management rules for your Cloud Storage buckets to automate actions like deleting or downgrading storage class of objects based on conditions. + reference: + - https://cloud.google.com/storage/docs/lifecycle + tags: cloud,devops,gcp,gcloud,google-cloud-storage,lifecycle-management,cost-optimization,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let bucketName of iterate(template.buckets)){ + set("bucketName", bucketName) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gsutil ls -p $projectId | jq -R . | jq -s . + + extractors: + - type: json + name: buckets + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gsutil lifecycle get $bucketName + + matchers: + - type: word + words: + - 'no lifecycle configuration' + + extractors: + - type: dsl + dsl: + - '"The bucket " + bucketName + " in project " + projectId + " does not have lifecycle management rules enabled."' diff --git a/cloud/gcp/storage/gcloud-object-encryption-cmk-not-enabled.yaml b/cloud/gcp/storage/gcloud-object-encryption-cmk-not-enabled.yaml new file mode 100644 index 00000000000..d9ad92a69fe --- /dev/null +++ b/cloud/gcp/storage/gcloud-object-encryption-cmk-not-enabled.yaml @@ -0,0 +1,72 @@ +id: gcloud-object-encryption-cmk-not-enabled + +info: + name: Enable Object Encryption with Customer-Managed Keys for Cloud Storage Buckets + author: princechaddha + severity: high + description: | + Ensure that your Google Cloud Storage data is encrypted at rest using Customer-Managed Keys (CMKs) to maintain full control over your data encryption and decryption processes. CMKs can be managed with the Cloud Key Management Service (Cloud KMS). + impact: | + Without CMK encryption, you lose the ability to manage key rotation, encryption policies, and data access, potentially exposing sensitive data to unauthorized access. + remediation: | + Configure your Cloud Storage buckets to use Customer-Managed Keys (CMKs) for encryption to enhance data security and comply with organizational policies. + reference: + - https://cloud.google.com/storage/docs/encryption/customer-managed-keys + tags: cloud,devops,gcp,gcloud,google-cloud-storage,encryption,cmk,security,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let bucketName of iterate(template.buckets)){ + set("bucketName", bucketName) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gsutil ls -p $projectId | jq -R . | jq -s . + + extractors: + - type: json + name: buckets + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gsutil kms encryption $bucketName + + matchers: + - type: word + part: body + words: + - "no default encryption key" + + extractors: + - type: dsl + dsl: + - '"The bucket " + bucketName + " in project " + projectId + " is not encrypted using a Customer-Managed Key (CMK)."' diff --git a/cloud/gcp/storage/gcloud-object-versioning-not-enabled.yaml b/cloud/gcp/storage/gcloud-object-versioning-not-enabled.yaml new file mode 100644 index 00000000000..fda772c2142 --- /dev/null +++ b/cloud/gcp/storage/gcloud-object-versioning-not-enabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-object-versioning-not-enabled + +info: + name: Enable Object Versioning for Cloud Storage Buckets + author: princechaddha + severity: medium + description: | + Ensure that your Cloud Storage buckets are configured with object versioning to protect your object data from being overwritten or accidentally deleted. Object versioning allows multiple variants of an object to be stored in the same bucket, enabling data recovery and restoration. + impact: | + Without object versioning, data loss or accidental overwrites cannot be recovered, leading to potential operational disruptions or compliance issues. + remediation: | + Enable object versioning for your Cloud Storage buckets to preserve object versions and allow for data recovery. + reference: + - https://cloud.google.com/storage/docs/object-versioning + tags: cloud,devops,gcp,gcloud,google-cloud-storage,object-versioning,backup,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let bucketName of iterate(template.buckets)){ + set("bucketName", bucketName) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gsutil ls -p $projectId | jq -R . | jq -s . + + extractors: + - type: json + name: buckets + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gsutil versioning get $bucketName + + matchers: + - type: word + words: + - 'Suspended' + + extractors: + - type: dsl + dsl: + - '"Object versioning is not enabled for the bucket " + bucketName + " in project " + projectId' diff --git a/cloud/gcp/storage/gcloud-public-access-prevention-not-enabled.yaml b/cloud/gcp/storage/gcloud-public-access-prevention-not-enabled.yaml new file mode 100644 index 00000000000..3ff21967eba --- /dev/null +++ b/cloud/gcp/storage/gcloud-public-access-prevention-not-enabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-public-access-prevention-not-enabled + +info: + name: Enforce Public Access Prevention for Cloud Storage Buckets + author: princechaddha + severity: high + description: | + Ensure that the Public Access Prevention feature is enabled for your Google Cloud Storage buckets to restrict public access and protect sensitive data from accidental or malicious exposure. + impact: | + Without Public Access Prevention, sensitive data stored in your Cloud Storage buckets may be publicly accessible, leading to potential data breaches. + remediation: | + Enable the Public Access Prevention feature for your Cloud Storage buckets to restrict public access and secure your data. + reference: + - https://cloud.google.com/storage/docs/public-access-prevention + tags: cloud,devops,gcp,gcloud,google-cloud-storage,security,public-access-prevention,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let bucketName of iterate(template.buckets)){ + set("bucketName", bucketName) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud storage buckets list --project $projectId --format="json(name)" + + extractors: + - type: json + name: buckets + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud storage buckets describe gs://$bucketName --format="json(public_access_prevention)" | jq -r '. // "null"' + + matchers: + - type: word + words: + - 'inherited' + + extractors: + - type: dsl + dsl: + - '"Public Access Prevention is not enabled for the bucket " + bucketName + " in project " + projectId' diff --git a/cloud/gcp/storage/gcloud-publicly-accessible-storage-buckets.yaml b/cloud/gcp/storage/gcloud-publicly-accessible-storage-buckets.yaml new file mode 100644 index 00000000000..cb89c4019dd --- /dev/null +++ b/cloud/gcp/storage/gcloud-publicly-accessible-storage-buckets.yaml @@ -0,0 +1,73 @@ +id: gcloud-publicly-accessible-storage-buckets + +info: + name: Check for Publicly Accessible Cloud Storage Buckets + author: princechaddha + severity: high + description: | + Ensure that the IAM policy associated with your Google Cloud Storage buckets is restricting anonymous and/or public access. The IAM policy should not include bindings for "allUsers" or "allAuthenticatedUsers" to prevent unauthorized access to sensitive data. + impact: | + Publicly accessible Cloud Storage buckets can lead to unauthorized access and potential data breaches, exposing sensitive information to the Internet. + remediation: | + Update the IAM policy of your Google Cloud Storage buckets to remove bindings for "allUsers" and "allAuthenticatedUsers" members, restricting access to authorized users only. + reference: + - https://cloud.google.com/storage/docs/access-control/iam + tags: cloud,devops,gcp,gcloud,google-cloud-storage,iam,security,public-access,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let bucketName of iterate(template.buckets)){ + set("bucketName", bucketName) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gsutil ls -p $projectId | jq -R . | jq -s . + + extractors: + - type: json + name: buckets + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gsutil iam get $bucketName --format=json | jq -r '.bindings[].members[]? // "null"' + + matchers: + - type: word + words: + - 'allUsers' + - 'allAuthenticatedUsers' + condition: or + + extractors: + - type: dsl + dsl: + - '"The bucket " + bucketName + " in project " + projectId + " is publicly accessible because it includes \"allUsers\" or \"allAuthenticatedUsers\" in its IAM policy."' diff --git a/cloud/gcp/storage/gcloud-secure-cors-configuration.yaml b/cloud/gcp/storage/gcloud-secure-cors-configuration.yaml new file mode 100644 index 00000000000..21425007cf8 --- /dev/null +++ b/cloud/gcp/storage/gcloud-secure-cors-configuration.yaml @@ -0,0 +1,71 @@ +id: gcloud-secure-cors-configuration + +info: + name: Secure CORS Configuration for Cloud Storage Buckets + author: princechaddha + severity: medium + description: | + Ensure that Cross-Origin Resource Sharing (CORS) configuration set for your Google Cloud Storage buckets only allows trusted origins to prevent unauthorized data access from web applications. The trusted, authorized origins must be configured according to your organization's policy. + impact: | + Improper CORS configuration can allow unauthorized web applications to access sensitive data stored in your Cloud Storage buckets. + remediation: | + Update the CORS configuration for your Cloud Storage buckets to only allow trusted origins defined by your organization’s policy. + reference: + - https://cloud.google.com/storage/docs/configuring-cors + tags: cloud,devops,gcp,gcloud,google-cloud-storage,cors,security,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let bucketName of iterate(template.buckets)){ + set("bucketName", bucketName) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud storage buckets list --project $projectId --format="json(name)" + + extractors: + - type: json + name: buckets + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud storage buckets describe gs://$bucketName --format="json(cors_config[].origin)" | jq -r '.[]? // "null"' + + matchers: + - type: word + words: + - 'null' + + extractors: + - type: dsl + dsl: + - '"The CORS configuration for the bucket " + bucketName + " in project " + projectId + " is either not set or includes unauthorized origins."' diff --git a/cloud/gcp/storage/gcloud-storage-logs-not-enabled.yaml b/cloud/gcp/storage/gcloud-storage-logs-not-enabled.yaml new file mode 100644 index 00000000000..2b3d755737a --- /dev/null +++ b/cloud/gcp/storage/gcloud-storage-logs-not-enabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-storage-logs-not-enabled + +info: + name: Enable Usage and Storage Logs for Cloud Storage Buckets + author: princechaddha + severity: medium + description: | + Ensure that usage and storage logs are enabled for your Google Cloud Storage buckets to monitor activity, track costs, detect suspicious behavior, and ensure compliance with security and audit requirements. + impact: | + Without usage and storage logs, it is challenging to monitor access patterns, detect anomalies, and ensure compliance with organizational policies and security standards. + remediation: | + Enable usage and storage logs for your Google Cloud Storage buckets to gain visibility into bucket activity and ensure audit compliance. + reference: + - https://cloud.google.com/storage/docs/access-logs + tags: cloud,devops,gcp,gcloud,google-cloud-storage,logging,security,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let bucketName of iterate(template.buckets)){ + set("bucketName", bucketName) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud storage buckets list --project $projectId --format="json(name)" + + extractors: + - type: json + name: buckets + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud storage buckets describe gs://$bucketName --format="json(logging_config)" | jq -r '. // "null"' + + matchers: + - type: word + words: + - 'null' + + extractors: + - type: dsl + dsl: + - '"Usage and storage logs are not enabled for the bucket " + bucketName + " in project " + projectId' diff --git a/cloud/gcp/storage/gcloud-uniform-bucket-level-access-not-enabled.yaml b/cloud/gcp/storage/gcloud-uniform-bucket-level-access-not-enabled.yaml new file mode 100644 index 00000000000..3a5e32f88d5 --- /dev/null +++ b/cloud/gcp/storage/gcloud-uniform-bucket-level-access-not-enabled.yaml @@ -0,0 +1,71 @@ +id: gcloud-uniform-bucket-level-access-not-enabled + +info: + name: Enable Uniform Bucket-Level Access for Cloud Storage Buckets + author: princechaddha + severity: medium + description: | + Ensure that uniform bucket-level access is enabled for all your Google Cloud Storage buckets. This ensures that object access is controlled entirely through bucket-level IAM permissions, providing a consistent and secure way to manage access to bucket data. + impact: | + Without uniform bucket-level access, managing object-level permissions can lead to inconsistent and insecure access control configurations. + remediation: | + Enable uniform bucket-level access for your Google Cloud Storage buckets to manage permissions uniformly and improve security. + reference: + - https://cloud.google.com/storage/docs/uniform-bucket-level-access + tags: cloud,devops,gcp,gcloud,google-cloud-storage,security,access-control,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let bucketName of iterate(template.buckets)){ + set("bucketName", bucketName) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gsutil ls -p $projectId | jq -R . | jq -s . + + extractors: + - type: json + name: buckets + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gsutil uniformbucketlevelaccess get $bucketName + + matchers: + - type: word + words: + - 'Enabled: False' + + extractors: + - type: dsl + dsl: + - '"Uniform bucket-level access is not enabled for the bucket " + bucketName + " in project " + projectId' diff --git a/cloud/gcp/storage/gcloud-vpc-service-controls-not-configured.yaml b/cloud/gcp/storage/gcloud-vpc-service-controls-not-configured.yaml new file mode 100644 index 00000000000..ea6412a7ca6 --- /dev/null +++ b/cloud/gcp/storage/gcloud-vpc-service-controls-not-configured.yaml @@ -0,0 +1,71 @@ +id: gcloud-vpc-service-controls-not-configured + +info: + name: Use VPC Service Controls for Cloud Storage Buckets + author: princechaddha + severity: medium + description: | + Ensure that VPC Service Controls are used to configure a security perimeter around your Google Cloud Storage buckets to prevent data exfiltration and enhance the security posture of your cloud environment. + impact: | + Without VPC Service Controls, sensitive data in your Google Cloud Storage buckets is at a higher risk of unauthorized access and exfiltration. + remediation: | + Configure VPC Service Controls with a security perimeter that includes the Cloud Storage service (storage.googleapis.com) to protect your sensitive data. + reference: + - https://cloud.google.com/vpc-service-controls/docs/overview + tags: cloud,devops,gcp,gcloud,google-cloud-storage,vpc-service-controls,security,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let perimeterName of iterate(template.perimeters)){ + set("perimeterName", perimeterName) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud access-context-manager perimeters list --project $projectId --format="json(name)" + + extractors: + - type: json + name: perimeters + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud access-context-manager perimeters describe $perimeterName --project $projectId --format=json | jq -r '.status.restrictedServices[]? // "null"' + + matchers: + - type: word + words: + - 'storage.googleapis.com' + + extractors: + - type: dsl + dsl: + - '"The VPC Service Perimeter " + perimeterName + " in project " + projectId + " does not include storage.googleapis.com, leaving Cloud Storage buckets unprotected."' diff --git a/cloud/gcp/vertexai/gcloud-vertexai-auto-upgrades.yaml b/cloud/gcp/vertexai/gcloud-vertexai-auto-upgrades.yaml new file mode 100644 index 00000000000..96e1b886447 --- /dev/null +++ b/cloud/gcp/vertexai/gcloud-vertexai-auto-upgrades.yaml @@ -0,0 +1,55 @@ +id: gcloud-vertexai-auto-upgrades + +info: + name: Automatic Upgrades Not Enabled for Vertex AI Notebooks + author: princechaddha + severity: medium + description: | + Ensure that automatic upgrades for Vertex AI Workbench notebook instances are enabled to get the latest features, performance improvements, and security updates without manual intervention. Once auto-upgrades are enabled, Vertex AI Workbench will check, during a recurring time period that you specify, whether your notebook instances can be upgraded, and if so, the service will upgrade your instances. + impact: | + Without automatic upgrades enabled, notebook instances may miss critical security updates, performance improvements, and new features. Manual upgrades require additional operational overhead and can lead to inconsistent environments. + remediation: | + Enable automatic upgrades for Vertex AI notebook instances using the 'gcloud workbench instances update' command with metadata parameter 'notebook-upgrade-schedule'. Example: --metadata 'notebook-upgrade-schedule=3 12 * * SUN' for weekly Sunday upgrades. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/VertexAI/enable-auto-upgrades.html + - https://cloud.google.com/vertex-ai/docs/workbench/user-managed/manage-instance + tags: cloud,devops,gcp,gcloud,vertexai,security,upgrades,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud workbench instances describe tm-vertex-ai-notebook-instance --location=us-central1-a --project=$projectId --format="yaml(gceSetup.metadata.notebook-upgrade-schedule)" + + matchers: + - type: word + words: + - "null" + + extractors: + - type: dsl + dsl: + - '"Project " + projectId + " has Vertex AI notebook instances without automatic upgrades enabled"' \ No newline at end of file diff --git a/cloud/gcp/vertexai/gcloud-vertexai-default-vpc.yaml b/cloud/gcp/vertexai/gcloud-vertexai-default-vpc.yaml new file mode 100644 index 00000000000..8354192b71a --- /dev/null +++ b/cloud/gcp/vertexai/gcloud-vertexai-default-vpc.yaml @@ -0,0 +1,55 @@ +id: gcloud-vertexai-default-vpc + +info: + name: Default VPC Network In Use for Vertex AI Notebooks + author: princechaddha + severity: medium + description: | + Ensure that your Google Cloud Vertex AI notebook instances are not created within the default Virtual Private Cloud (VPC) network. The default VPC comes with predefined, over-permissive firewall rules that are not included in audit logging. While suitable for quick starts, complex production AI applications with multi-tier architectures may require private network segments or customization. + impact: | + The default VPC network comes with predefined, insecure firewall rules that allow broad internal access, SSH, RDP, and ICMP traffic from any source. Additionally, being an auto-mode network, it cannot be used with Cloud VPN or VPC Network Peering features. + remediation: | + Re-create Vertex AI notebook instances in a custom VPC network with properly configured subnets and firewall rules. Use the 'gcloud workbench instances create' command with appropriate network and subnet parameters. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/VertexAI/default-vpc-in-use.html + - https://cloud.google.com/vertex-ai/docs/workbench/user-managed/create-instance + tags: cloud,devops,gcp,gcloud,vertexai,networking,security,vpc,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud workbench instances describe tm-vertex-ai-notebook-instance --location=us-central1-a --project=$projectId --format="value(gceSetup.networkInterfaces[].network)" + + matchers: + - type: word + words: + - "networks/default" + + extractors: + - type: dsl + dsl: + - '"Project " + projectId + " has Vertex AI notebook instances using the default VPC network"' \ No newline at end of file diff --git a/cloud/gcp/vertexai/gcloud-vertexai-external-ip.yaml b/cloud/gcp/vertexai/gcloud-vertexai-external-ip.yaml new file mode 100644 index 00000000000..0f3147401b2 --- /dev/null +++ b/cloud/gcp/vertexai/gcloud-vertexai-external-ip.yaml @@ -0,0 +1,55 @@ +id: gcloud-vertexai-external-ip + +info: + name: External IP Addresses Assigned to Vertex AI Notebooks + author: princechaddha + severity: medium + description: | + Ensure that external IP addresses are not assigned to your Google Cloud Vertex AI notebook instances, in order to help prevent data exfiltration, maintain network isolation, and meet stringent compliance requirements. Vertex AI notebook instances with an assigned external IP address can communicate with the public internet or resources in other VPC networks, which may violate security policies. + impact: | + Assigning external IP addresses to notebook instances exposes them directly to the Internet, bypassing certain security controls. This increases the risk of unauthorized access, potential vulnerabilities, and data exfiltration. + remediation: | + Re-create Vertex AI notebook instances without external IP addresses using the 'gcloud workbench instances create' command with --disable-public-ip flag. Example: gcloud workbench instances create INSTANCE_NAME --disable-public-ip + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/VertexAI/prevent-external-ip-usage.html + - https://cloud.google.com/vertex-ai/docs/workbench/user-managed/manage-instance + tags: cloud,devops,gcp,gcloud,vertexai,security,networking,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud workbench instances describe tm-vertex-ai-notebook-instance --location=us-central1-a --project=$projectId --format="yaml(gceSetup.disablePublicIp)" + + matchers: + - type: word + words: + - "null" + + extractors: + - type: dsl + dsl: + - '"Project " + projectId + " has Vertex AI notebook instances with external IP addresses enabled"' \ No newline at end of file diff --git a/cloud/gcp/vertexai/gcloud-vertexai-idle-shutdown.yaml b/cloud/gcp/vertexai/gcloud-vertexai-idle-shutdown.yaml new file mode 100644 index 00000000000..713ce1268dc --- /dev/null +++ b/cloud/gcp/vertexai/gcloud-vertexai-idle-shutdown.yaml @@ -0,0 +1,55 @@ +id: gcloud-vertexai-idle-shutdown + +info: + name: Idle Shutdown Not Enabled for Vertex AI Notebooks + author: princechaddha + severity: medium + description: | + Ensure that the Idle Shutdown feature is enabled for your Google Cloud Vertex AI notebook instances to optimize costs. Inactive notebook instances continue to incur charges, and Idle Shutdown automatically stops them after a period of inactivity (i.e., no running commands or UI connections), reducing unneeded spending. Vertex AI stops charging for CPUs/GPUs once the notebook instance is shut down. + impact: | + Without idle shutdown enabled, inactive notebook instances continue to run and incur unnecessary charges for compute resources. While disk storage charges may still apply, enabling idle shutdown helps optimize costs by automatically stopping unused instances. + remediation: | + Enable idle shutdown for Vertex AI notebook instances using the 'gcloud workbench instances update' command with metadata parameter 'idle-timeout-seconds'. Example: --metadata 'idle-timeout-seconds=10800' for 3-hour timeout. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/VertexAI/enable-idle-shutdown.html + - https://cloud.google.com/vertex-ai/docs/workbench/user-managed/manage-instance + tags: cloud,devops,gcp,gcloud,vertexai,cost-optimization,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud workbench instances describe tm-vertex-ai-notebook-instance --location=us-central1-a --project=$projectId --format="yaml(gceSetup.metadata.idle-timeout-seconds)" + + matchers: + - type: word + words: + - "null" + + extractors: + - type: dsl + dsl: + - '"Project " + projectId + " has Vertex AI notebook instances without idle shutdown enabled"' \ No newline at end of file diff --git a/cloud/gcp/vertexai/gcloud-vertexai-integrity.yaml b/cloud/gcp/vertexai/gcloud-vertexai-integrity.yaml new file mode 100644 index 00000000000..229ab8c62b5 --- /dev/null +++ b/cloud/gcp/vertexai/gcloud-vertexai-integrity.yaml @@ -0,0 +1,57 @@ +id: gcloud-vertexai-integrity + +info: + name: Integrity Monitoring Not Enabled for Vertex AI Notebooks + author: princechaddha + severity: medium + description: | + Ensure that the Integrity Monitoring feature is enabled for your Google Cloud Vertex AI notebook instances to automatically check and monitor the runtime boot integrity of your shielded notebook instances using Google Cloud Monitoring. The feature requires Virtual Trusted Platform Module (vTPM) and helps ensure that the boot loader on your instances remains untampered. + impact: | + Without integrity monitoring enabled, you cannot verify the boot integrity of your notebook instances. This makes it difficult to detect potential tampering with the boot loader or other security-critical components. + remediation: | + Enable integrity monitoring for Vertex AI notebook instances using the 'gcloud workbench instances update' command with --shielded-integrity-monitoring flag set to true. Note that instances must be stopped before updating this configuration. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/VertexAI/enable-integrity-monitoring.html + - https://cloud.google.com/vertex-ai/docs/workbench/user-managed/manage-instance + tags: cloud,devops,gcp,gcloud,vertexai,security,integrity,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud workbench instances describe tm-vertex-ai-notebook-instance --location=us-central1-a --project=$projectId --format="yaml(gceSetup.shieldedInstanceConfig.enableIntegrityMonitoring)" + + matchers: + - type: word + words: + - "{}" + - "null" + condition: or + + extractors: + - type: dsl + dsl: + - '"Project " + projectId + " has Vertex AI notebook instances without integrity monitoring enabled"' \ No newline at end of file diff --git a/cloud/gcp/vertexai/gcloud-vertexai-monitoring.yaml b/cloud/gcp/vertexai/gcloud-vertexai-monitoring.yaml new file mode 100644 index 00000000000..2dde9c095a7 --- /dev/null +++ b/cloud/gcp/vertexai/gcloud-vertexai-monitoring.yaml @@ -0,0 +1,55 @@ +id: gcloud-vertexai-monitoring + +info: + name: Cloud Monitoring Not Enabled for Vertex AI Notebooks + author: princechaddha + severity: medium + description: | + Ensure that Cloud Monitoring is enabled for your Vertex AI notebook instances in order to gain visibility into their health and performance. Cloud Monitoring reports system and application metrics such as disk, CPU, network, and processes. This allows you to identify issues like resource bottlenecks or errors proactively. To enable the monitoring feature, you must install the Cloud Monitoring agent when you create your notebook instance. + impact: | + Without Cloud Monitoring enabled, you lack visibility into the health and performance of your notebook instances, making it difficult to detect and troubleshoot issues proactively. This can lead to degraded performance or service disruptions. + remediation: | + Re-create Vertex AI notebook instances with Cloud Monitoring enabled by using the 'gcloud workbench instances create' command with metadata parameter 'install-monitoring-agent=true'. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/VertexAI/enable-cloud-monitoring.html + - https://cloud.google.com/vertex-ai/docs/workbench/user-managed/manage-instance + tags: cloud,devops,gcp,gcloud,vertexai,security,monitoring,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud workbench instances describe tm-vertex-ai-notebook-instance --location=us-central1-a --project=$projectId --format="yaml(gceSetup.metadata.install-monitoring-agent)" + + matchers: + - type: word + words: + - "null" + + extractors: + - type: dsl + dsl: + - '"Project " + projectId + " has Vertex AI notebook instances without Cloud Monitoring enabled"' \ No newline at end of file diff --git a/cloud/gcp/vertexai/gcloud-vertexai-root-access.yaml b/cloud/gcp/vertexai/gcloud-vertexai-root-access.yaml new file mode 100644 index 00000000000..77b7bbc7d63 --- /dev/null +++ b/cloud/gcp/vertexai/gcloud-vertexai-root-access.yaml @@ -0,0 +1,55 @@ +id: gcloud-vertexai-root-access + +info: + name: Root Access Not Disabled for Vertex AI Notebooks + author: princechaddha + severity: high + description: | + Ensure that root access to your Google Cloud Vertex AI notebook instances is disabled in order to reduce the risk of accidental or malicious system damage by limiting administrative privileges within the instances. Disabling root access minimizes the risk of unauthorized modifications and helps maintain a more controlled and secure AI environment. + impact: | + Allowing root access to Vertex AI notebook instances increases the risk of unauthorized modifications and potential misuse of superuser privileges. This could lead to system damage, data breaches, or compromise of the AI environment. + remediation: | + Disable root access for Vertex AI notebook instances using the 'gcloud workbench instances update' command with metadata parameter 'notebook-disable-root=true'. Note that instances must be stopped before updating this configuration. + reference: + - https://trendmicro.com/cloudoneconformity/knowledge-base/gcp/VertexAI/disable-root-access.html + - https://cloud.google.com/vertex-ai/docs/workbench/user-managed/manage-instance + tags: cloud,devops,gcp,gcloud,vertexai,security,root-access,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud workbench instances describe tm-vertex-ai-notebook-instance --location=us-central1-a --project=$projectId --format="yaml(gceSetup.metadata.notebook-disable-root)" + + matchers: + - type: word + words: + - "null" + + extractors: + - type: dsl + dsl: + - '"Project " + projectId + " has Vertex AI notebook instances with root access enabled"' \ No newline at end of file diff --git a/cloud/gcp/vertexai/gcloud-vertexai-secure-boot.yaml b/cloud/gcp/vertexai/gcloud-vertexai-secure-boot.yaml new file mode 100644 index 00000000000..06b67a66a58 --- /dev/null +++ b/cloud/gcp/vertexai/gcloud-vertexai-secure-boot.yaml @@ -0,0 +1,55 @@ +id: gcloud-vertexai-secure-boot + +info: + name: Secure Boot Not Enabled for Vertex AI Notebooks + author: princechaddha + severity: medium + description: | + Ensure that the Secure Boot security feature is enabled for your Vertex AI notebook instances in order to protect them against malware and rootkits. Secure Boot helps ensure that the system runs only authentic software by verifying the digital signature of all boot components, and halts the boot process if the signature verification fails. Secure Boot is disabled by default because of the third-party unsigned kernel modules that can't be loaded when the feature is enabled. + impact: | + Without Secure Boot enabled, notebook instances may be vulnerable to boot-level and kernel-level malware, including rootkits. This could allow unauthorized or malicious code to execute during the boot process. + remediation: | + Enable Secure Boot for Vertex AI notebook instances using the 'gcloud workbench instances update' command with --shielded-secure-boot flag set to true. Note that instances must be stopped before updating this configuration. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/VertexAI/enable-secure-boot.html + - https://cloud.google.com/vertex-ai/docs/workbench/user-managed/manage-instance + tags: cloud,devops,gcp,gcloud,vertexai,security,secure-boot,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud workbench instances describe tm-vertex-ai-notebook-instance --location=us-central1-a --project=$projectId --format="yaml(gceSetup.shieldedInstanceConfig.enableSecureBoot)" + + matchers: + - type: word + words: + - "shieldedInstanceConfig: {}" + + extractors: + - type: dsl + dsl: + - '"Project " + projectId + " has Vertex AI notebook instances without Secure Boot enabled"' \ No newline at end of file diff --git a/cloud/gcp/vertexai/gcloud-vertexai-vtpm.yaml b/cloud/gcp/vertexai/gcloud-vertexai-vtpm.yaml new file mode 100644 index 00000000000..a7e1e56aaf6 --- /dev/null +++ b/cloud/gcp/vertexai/gcloud-vertexai-vtpm.yaml @@ -0,0 +1,55 @@ +id: gcloud-vertexai-vtpm + +info: + name: Virtual Trusted Platform Module Not Enabled for Vertex AI Notebooks + author: princechaddha + severity: medium + description: | + Ensure that the Virtual Trusted Platform Module (vTPM) feature is enabled for your Vertex AI notebook instances in order to protect them against persistent and advanced attacks. vTPM safeguards the guest VM's boot process by validating its integrity before and during startup. Additionally, it provides secure generation and protection for encryption keys. + impact: | + Without vTPM enabled, notebook instances lack hardware-based encryption and secure storage for cryptographic keys. This could make them more vulnerable to unauthorized access and tampering with sensitive data. + remediation: | + Enable vTPM for Vertex AI notebook instances using the 'gcloud workbench instances update' command with --shielded-vtpm flag set to true. Note that instances must be stopped before updating this configuration. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/VertexAI/enable-vtpm.html + - https://cloud.google.com/vertex-ai/docs/workbench/user-managed/manage-instance + tags: cloud,devops,gcp,gcloud,vertexai,security,vtpm,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud workbench instances describe tm-vertex-ai-notebook-instance --location=us-central1-a --project=$projectId --format="yaml(gceSetup.shieldedInstanceConfig.enableVtpm)" + + matchers: + - type: word + words: + - "shieldedInstanceConfig: {}" + + extractors: + - type: dsl + dsl: + - '"Project " + projectId + " has Vertex AI notebook instances without Virtual Trusted Platform Module (vTPM) enabled"' \ No newline at end of file diff --git a/cloud/gcp/vpc/gcloud-check-legacy-networks.yaml b/cloud/gcp/vpc/gcloud-check-legacy-networks.yaml new file mode 100644 index 00000000000..94c25c7bae2 --- /dev/null +++ b/cloud/gcp/vpc/gcloud-check-legacy-networks.yaml @@ -0,0 +1,54 @@ +id: gcloud-check-legacy-networks + +info: + name: Check for Legacy Networks + author: princechaddha + severity: medium + description: | + Ensure that your Google Cloud Platform (GCP) projects are not using legacy networks. Legacy networks are no longer recommended for production environments as they do not support advanced networking features. It is strongly advised to use Virtual Private Cloud (VPC) networks instead. + impact: | + Using legacy networks limits access to advanced networking features and can hinder scalability and security. + remediation: | + Migrate your GCP project from legacy networks to Virtual Private Cloud (VPC) networks to utilize the latest networking capabilities. + reference: + - https://cloud.google.com/vpc/docs/vpc + tags: cloud,devops,gcp,gcloud,vpc,networking,security,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute networks list --project $projectId --format="json(name,subnetMode)" + + matchers: + - type: word + words: + - LEGACY + + extractors: + - type: dsl + dsl: + - '"Legacy network found in project " + projectId + ": " + name' diff --git a/cloud/gcp/vpc/gcloud-default-vpc-in-use.yaml b/cloud/gcp/vpc/gcloud-default-vpc-in-use.yaml new file mode 100644 index 00000000000..965bff0b4c5 --- /dev/null +++ b/cloud/gcp/vpc/gcloud-default-vpc-in-use.yaml @@ -0,0 +1,54 @@ +id: gcloud-default-vpc-in-use + +info: + name: Default VPC Network In Use + author: princechaddha + severity: medium + description: | + Ensure that your Google Cloud Platform (GCP) projects are not using the default Virtual Private Cloud (VPC) network. Using the default VPC network does not adhere to security best practices and may not meet specific networking requirements. + impact: | + Using the default VPC network can expose your infrastructure to security risks due to overly permissive rules and configurations. + remediation: | + Delete the default VPC network and create custom VPC networks with tailored configurations to meet your organization's security and networking requirements. + reference: + - https://cloud.google.com/vpc/docs/vpc + tags: cloud,devops,gcp,gcloud,google-cloud-vpc,networking,security,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute networks list --project $projectId --format="json(name)" + + matchers: + - type: word + words: + - 'default' + + extractors: + - type: dsl + dsl: + - '"The default VPC network is in use in project " + projectId' diff --git a/cloud/gcp/vpc/gcloud-dns-logging-not-enabled.yaml b/cloud/gcp/vpc/gcloud-dns-logging-not-enabled.yaml new file mode 100644 index 00000000000..2610361570e --- /dev/null +++ b/cloud/gcp/vpc/gcloud-dns-logging-not-enabled.yaml @@ -0,0 +1,88 @@ +id: gcloud-dns-logging-not-enabled + +info: + name: Enable Cloud DNS Logging for VPC Networks + author: princechaddha + severity: medium + description: | + Ensure that Cloud DNS logging is enabled for all your Virtual Private Cloud (VPC) networks using DNS server policies. Cloud DNS logging records DNS queries resolved by name servers for VPC networks, as well as queries to public DNS zones from external entities. + impact: | + Without Cloud DNS logging, you lose visibility into DNS queries, making it difficult to monitor, troubleshoot, and detect potential security threats or misconfigurations. + remediation: | + Enable Cloud DNS logging for your VPC networks to monitor and analyze DNS query activity for better security and compliance. + reference: + - https://cloud.google.com/dns/docs/policies + tags: cloud,devops,gcp,gcloud,google-cloud-dns,logging,security,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let network of iterate(template.networks)){ + set("networkName", network) + code(3) + for(let dnsPolicy of iterate(template.dnsPolicies)){ + set("dnsPolicy", dnsPolicy.name) + code(4) + } + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute networks list --project $projectId --format="json(name)" + + extractors: + - type: json + name: networks + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud dns policies list --project $projectId --format="json(name)" --filter="networks[].networkUrl:$networkName" + + extractors: + - type: json + name: dnsPolicies + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud dns policies describe $dnsPolicy --project $projectId --format="json(enableLogging)" | jq -r '.enableLogging // "null"' + + matchers: + - type: word + words: + - 'False' + + extractors: + - type: dsl + dsl: + - '"Cloud DNS logging is not enabled for the DNS policy " + dnsPolicy + " in network " + networkName + " in project " + projectId' diff --git a/cloud/gcp/vpc/gcloud-enable-vpc-flow-logs.yaml b/cloud/gcp/vpc/gcloud-enable-vpc-flow-logs.yaml new file mode 100644 index 00000000000..5d8080bab32 --- /dev/null +++ b/cloud/gcp/vpc/gcloud-enable-vpc-flow-logs.yaml @@ -0,0 +1,91 @@ +id: gcloud-enable-vpc-flow-logs + +info: + name: Enable VPC Flow Logs for VPC Subnets + author: princechaddha + severity: medium + description: | + Ensure that VPC Flow Logs is enabled for every subnet created within your production Virtual Private Cloud (VPC) network. Flow Logs capture information about the IP traffic (accepted, rejected, or all traffic) to and from the network interfaces within your VPC subnets. + impact: | + Without VPC Flow Logs, you lose visibility into network traffic within your subnets, making it difficult to monitor, troubleshoot, and enhance the security posture of your network. + remediation: | + Enable VPC Flow Logs for your VPC subnets to gain insights into network traffic and support network security, compliance, and operational monitoring. + reference: + - https://cloud.google.com/vpc/docs/using-flow-logs + tags: cloud,devops,gcp,gcloud,google-cloud-vpc,flow-logs,networking,security,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let network of iterate(template.networks)){ + set("networkName", network) + code(3) + for(let subnet of iterate(template.subnets)){ + subnet = JSON.parse(subnet); + set("subnetName", subnet.name) + set("subnetRegion", subnet.region) + code(4) + } + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute networks list --project $projectId --format="json(name)" + + extractors: + - type: json + name: networks + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute networks subnets list --network=$networkName --project=$projectId --format="json(name,region.basename())" + + extractors: + - type: json + name: subnets + internal: true + json: + - '.[]' + + - engine: + - sh + - bash + source: | + gcloud compute networks subnets describe $subnetName --project=$projectId --format=json --region $subnetRegion | jq '.enableFlowLogs // "null"' + + matchers: + - type: word + words: + - 'false' + - 'null' + + extractors: + - type: dsl + dsl: + - '"The subnet " + subnetName + " of network " + networkName + " in project " + projectId + " does not have VPC Flow Logs enabled"' diff --git a/cloud/gcp/vpc/gcloud-exclude-metadata-from-firewall-logging.yaml b/cloud/gcp/vpc/gcloud-exclude-metadata-from-firewall-logging.yaml new file mode 100644 index 00000000000..7b3b9de38e7 --- /dev/null +++ b/cloud/gcp/vpc/gcloud-exclude-metadata-from-firewall-logging.yaml @@ -0,0 +1,73 @@ +id: gcloud-exclude-metadata-from-firewall-logging + +info: + name: Exclude Metadata from Firewall Logging + author: princechaddha + severity: medium + description: | + Ensure that Virtual Private Cloud (VPC) firewall logging is not configured to include logging metadata to reduce log file size and optimize cloud storage costs. Including metadata in firewall logs can lead to unnecessary storage costs without significant benefits. + impact: | + Including metadata in firewall logging increases log file sizes, leading to higher storage costs and potential inefficiencies in log analysis. + remediation: | + Update the VPC firewall logging configuration to exclude metadata from the logs and reduce storage costs while maintaining logging efficiency. + reference: + - https://cloud.google.com/vpc/docs/using-firewall-rules-logging + tags: cloud,devops,gcp,gcloud,google-cloud-vpc,firewall-logging,security,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let network of iterate(template.networks)){ + set("networkName", network) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute networks list --project $projectId --format="json(name)" + + extractors: + - type: json + name: networks + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute firewall-rules list --filter="network=$networkName" --sort-by="priority" --format="json(name,disabled,logConfig)" + + matchers: + - type: word + words: + - "enable': True" + - "INCLUDE_ALL_METADATA" + condition: and + + extractors: + - type: dsl + dsl: + - '"The firewall rule in network " + networkName + " in project " + projectId + " has logging metadata set to INCLUDE_ALL_METADATA."' diff --git a/cloud/gcp/vpc/gcloud-firewall-rule-logging-not-enabled.yaml b/cloud/gcp/vpc/gcloud-firewall-rule-logging-not-enabled.yaml new file mode 100644 index 00000000000..d6056233805 --- /dev/null +++ b/cloud/gcp/vpc/gcloud-firewall-rule-logging-not-enabled.yaml @@ -0,0 +1,73 @@ +id: gcloud-firewall-rule-logging-not-enabled + +info: + name: Enable Logging for VPC Firewall Rules + author: princechaddha + severity: medium + description: | + Enable Virtual Private Cloud (VPC) firewall rule logging for each firewall rule whose connections you need to log. Firewall rule logging provides valuable insights into the source and destination of traffic, protocols, ports, and actions taken by the rules. + impact: | + Without firewall rule logging, it is difficult to analyze and monitor network traffic, making it challenging to troubleshoot and ensure compliance with security policies. + remediation: | + Enable logging for your VPC firewall rules to capture connection details, including traffic source, destination, and actions taken by the rules. + reference: + - https://cloud.google.com/vpc/docs/using-firewall-rules-logging + tags: cloud,devops,gcp,gcloud,google-cloud-vpc,firewall-logging,security,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let network of iterate(template.networks)){ + set("networkName", network) + code(3) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute networks list --project $projectId --format="json(name)" + + extractors: + - type: json + name: networks + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute firewall-rules list --filter="network=$networkName" --sort-by="priority" --format="json(name,disabled,direction,logConfig)" + + matchers: + - type: word + words: + - '"enable": false' + - '"disabled": false' + condition: and + + extractors: + - type: dsl + dsl: + - '"The firewall rule " + name + " in network " + networkName + " in project " + projectId + " does not have logging enabled."' diff --git a/cloud/gcp/vpc/gcloud-unrestricted-dns-access.yaml b/cloud/gcp/vpc/gcloud-unrestricted-dns-access.yaml new file mode 100644 index 00000000000..4c34db91b2e --- /dev/null +++ b/cloud/gcp/vpc/gcloud-unrestricted-dns-access.yaml @@ -0,0 +1,102 @@ +id: gcloud-unrestricted-dns-access + +info: + name: Check for Unrestricted DNS Access + author: princechaddha + severity: high + description: | + Ensure that Google Cloud VPC network firewall rules do not allow unrestricted access (0.0.0.0/0) on TCP and UDP port 53. Restrict DNS traffic to trusted IP addresses or ranges to reduce the attack surface and enhance security. + impact: | + Allowing unrestricted access to TCP/UDP port 53 exposes DNS servers and associated resources to potential attacks. + remediation: | + Update your VPC firewall rules to allow DNS traffic only from trusted IP addresses or ranges. + reference: + - https://cloud.google.com/vpc/docs/firewalls + tags: cloud,devops,gcp,gcloud,vpc,firewall,dns,security,networking,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let networkName of iterate(template.networks)){ + set("networkName", networkName) + code(3) + set("firewallRules", template.firewallRules) + javascript(1) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute networks list --project $projectId --format="json(name)" + + extractors: + - type: json + name: networks + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute firewall-rules list --filter network=$networkName --sort-by priority --format="json(name,disabled,direction,sourceRanges,allowed[].ports)" + + extractors: + - type: json + name: firewallRules + internal: true + json: + - '.[]' + +javascript: + - code: | + let firewallRules = template.firewallRules; + if (typeof firewallRules === "string") { + firewallRules = JSON.parse(firewallRules); + } + + let insecureRules = []; + for (let rule of firewallRules) { + if ( + rule.disabled === false && + rule.direction === "INGRESS" && + Array.isArray(rule.sourceRanges) && rule.sourceRanges.includes("0.0.0.0/0") && + Array.isArray(rule.allowed) && + rule.allowed.some(allowed => + Array.isArray(allowed.ports) && + (allowed.ports.includes("53")) + ) + ) { + insecureRules.push(rule.name); + } + } + + if (insecureRules.length > 0) { + Export(`The firewall rules in network ${template.networkName} of project ${template.projectId} allow unrestricted DNS access: ${insecureRules.join(", ")}`); + } + + extractors: + - type: dsl + dsl: + - response diff --git a/cloud/gcp/vpc/gcloud-unrestricted-ftp-access.yaml b/cloud/gcp/vpc/gcloud-unrestricted-ftp-access.yaml new file mode 100644 index 00000000000..2e3eba607de --- /dev/null +++ b/cloud/gcp/vpc/gcloud-unrestricted-ftp-access.yaml @@ -0,0 +1,102 @@ +id: gcloud-unrestricted-ftp-access + +info: + name: Check for Unrestricted FTP Access + author: princechaddha + severity: high + description: | + Ensure that Virtual Private Cloud (VPC) firewall rules do not allow unrestricted access (0.0.0.0/0) on TCP ports 20 and 21. Restrict FTP traffic to trusted IP addresses or IP ranges to reduce the attack surface and enhance security. + impact: | + Allowing unrestricted access to TCP ports 20 and 21 exposes FTP servers to potential brute-force or unauthorized access attacks. + remediation: | + Update your VPC firewall rules to allow FTP traffic only from trusted IP addresses or ranges. + reference: + - https://cloud.google.com/vpc/docs/firewalls + tags: cloud,devops,gcp,gcloud,vpc,firewall,ftp,security,networking,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let networkName of iterate(template.networks)){ + set("networkName", networkName) + code(3) + set("firewallRules", template.firewallRules) + javascript(1) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute networks list --project $projectId --format="json(name)" + + extractors: + - type: json + name: networks + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute firewall-rules list --filter network=$networkName --sort-by priority --format="json(name,disabled,direction,sourceRanges,allowed[].ports)" + + extractors: + - type: json + name: firewallRules + internal: true + json: + - '.[]' + +javascript: + - code: | + let firewallRules = template.firewallRules; + if (typeof firewallRules === "string") { + firewallRules = JSON.parse(firewallRules); + } + + let insecureRules = []; + for (let rule of firewallRules) { + if ( + rule.disabled === false && + rule.direction === "INGRESS" && + Array.isArray(rule.sourceRanges) && rule.sourceRanges.includes("0.0.0.0/0") && + Array.isArray(rule.allowed) && + rule.allowed.some(allowed => + Array.isArray(allowed.ports) && + (allowed.ports.includes("20") || allowed.ports.includes("21")) + ) + ) { + insecureRules.push(rule.name); + } + } + + if (insecureRules.length > 0) { + Export(`The firewall rules in network ${template.networkName} of project ${template.projectId} allow unrestricted FTP access: ${insecureRules.join(", ")}`); + } + + extractors: + - type: dsl + dsl: + - response diff --git a/cloud/gcp/vpc/gcloud-unrestricted-icmp-access.yaml b/cloud/gcp/vpc/gcloud-unrestricted-icmp-access.yaml new file mode 100644 index 00000000000..ca188ed6502 --- /dev/null +++ b/cloud/gcp/vpc/gcloud-unrestricted-icmp-access.yaml @@ -0,0 +1,99 @@ +id: gcloud-unrestricted-icmp-access + +info: + name: Check for Unrestricted ICMP Access + author: princechaddha + severity: high + description: | + Ensure that your Google Cloud VPC network firewall rules do not allow unrestricted access (0.0.0.0/0) using ICMP. Restrict ICMP-based access to trusted IP addresses or IP ranges to implement the principle of least privilege (POLP) and reduce the attack surface. + impact: | + Allowing unrestricted ICMP access exposes cloud resources to potential network reconnaissance and exploitation of vulnerabilities. + remediation: | + Update your VPC firewall rules to restrict ICMP-based access to trusted IP addresses or ranges only. + reference: + - https://cloud.google.com/vpc/docs/firewalls + tags: cloud,devops,gcp,gcloud,vpc,firewall,icmp,security,networking,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let networkName of iterate(template.networks)){ + set("networkName", networkName) + code(3) + set("firewallRules", template.firewallRules) + javascript(1) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute networks list --project $projectId --format="json(name)" + + extractors: + - type: json + name: networks + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute firewall-rules list --filter network=$networkName --sort-by priority --format="json(name,disabled,direction,sourceRanges,allowed[].IPProtocol)" + + extractors: + - type: json + name: firewallRules + internal: true + json: + - '.[]' + +javascript: + - code: | + let firewallRules = template.firewallRules; + if (typeof firewallRules === "string") { + firewallRules = JSON.parse(firewallRules); + } + + let insecureRules = []; + for (let rule of firewallRules) { + if ( + rule.disabled === false && + rule.direction === "INGRESS" && + Array.isArray(rule.sourceRanges) && rule.sourceRanges.includes("0.0.0.0/0") && + Array.isArray(rule.allowed) && + rule.allowed.some(allowed => allowed.IPProtocol === "icmp") + ) { + insecureRules.push(rule.name); + } + } + + if (insecureRules.length > 0) { + Export(`The firewall rules in network ${template.networkName} of project ${template.projectId} allow unrestricted ICMP access: ${insecureRules.join(", ")}`); + } + + extractors: + - type: dsl + dsl: + - response diff --git a/cloud/gcp/vpc/gcloud-unrestricted-inbound-uncommon-ports.yaml b/cloud/gcp/vpc/gcloud-unrestricted-inbound-uncommon-ports.yaml new file mode 100644 index 00000000000..a376bdf47c5 --- /dev/null +++ b/cloud/gcp/vpc/gcloud-unrestricted-inbound-uncommon-ports.yaml @@ -0,0 +1,108 @@ +id: gcloud-unrestricted-inbound-uncommon-ports + +info: + name: Check for Unrestricted Inbound Access on Uncommon Ports + author: princechaddha + severity: high + description: | + Ensure that your Virtual Private Cloud (VPC) firewall rules do not allow unrestricted access (0.0.0.0/0) to any uncommon ports to protect against brute force attacks targeting virtual machine instances associated with these firewall rules. Uncommon ports are TCP/UDP ports not included in the common service ports category. + impact: | + Allowing unrestricted access to uncommon ports increases the attack surface and exposes cloud resources to potential brute-force or unauthorized access attacks. + remediation: | + Update your VPC firewall rules to allow traffic only to common ports required for your applications, and restrict access to uncommon ports. + reference: + - https://cloud.google.com/vpc/docs/firewalls + tags: cloud,devops,gcp,gcloud,vpc,firewall,security,networking,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let networkName of iterate(template.networks)){ + set("networkName", networkName) + code(3) + set("firewallRules", template.firewallRules) + javascript(1) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute networks list --project $projectId --format="json(name)" + + extractors: + - type: json + name: networks + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute firewall-rules list --filter network=$networkName --sort-by priority --format="json(name,disabled,direction,sourceRanges,allowed[].ports)" + + extractors: + - type: json + name: firewallRules + internal: true + json: + - '.[]' + +javascript: + - code: | + let firewallRules = template.firewallRules; + if (typeof firewallRules === "string") { + firewallRules = JSON.parse(firewallRules); + } + + const commonPorts = [ + "80", "443", "20", "21", "22", "23", "53", "3389", + "25", "465", "587", "3306", "5432", "1521", "1433", + "135", "137", "138", "139", "445" + ]; + + let insecureRules = []; + for (let rule of firewallRules) { + if ( + rule.disabled === false && + rule.direction === "INGRESS" && + Array.isArray(rule.sourceRanges) && rule.sourceRanges.includes("0.0.0.0/0") && + Array.isArray(rule.allowed) && + rule.allowed.some(allowed => + Array.isArray(allowed.ports) && + allowed.ports.some(port => !commonPorts.includes(port)) + ) + ) { + insecureRules.push(rule.name); + } + } + + if (insecureRules.length > 0) { + Export(`The firewall rules in network ${template.networkName} of project ${template.projectId} allow unrestricted access on uncommon ports: ${insecureRules.join(", ")}`); + } + + extractors: + - type: dsl + dsl: + - response diff --git a/cloud/gcp/vpc/gcloud-unrestricted-mysql-access.yaml b/cloud/gcp/vpc/gcloud-unrestricted-mysql-access.yaml new file mode 100644 index 00000000000..d4b73dc799f --- /dev/null +++ b/cloud/gcp/vpc/gcloud-unrestricted-mysql-access.yaml @@ -0,0 +1,102 @@ +id: gcloud-unrestricted-mysql-access + +info: + name: Check for Unrestricted MySQL Database Access + author: princechaddha + severity: high + description: | + Ensure that Google Cloud VPC network firewall rules do not allow unrestricted access (0.0.0.0/0 on TCP port 3306). Restrict MySQL traffic to trusted IP addresses or IP ranges to reduce the attack surface and enhance security. + impact: | + Allowing unrestricted access to TCP port 3306 exposes MySQL database servers to potential brute-force or unauthorized access attacks. + remediation: | + Update your VPC firewall rules to allow MySQL traffic only from trusted IP addresses or ranges. + reference: + - https://cloud.google.com/vpc/docs/firewalls + tags: cloud,devops,gcp,gcloud,vpc,firewall,security,mysql,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let networkName of iterate(template.networks)){ + set("networkName", networkName) + code(3) + set("firewallRules", template.firewallRules) + javascript(1) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute networks list --project $projectId --format="json(name)" + + extractors: + - type: json + name: networks + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute firewall-rules list --filter network=$networkName --sort-by priority --format="json(name,disabled,direction,sourceRanges,allowed[].ports)" + + extractors: + - type: json + name: firewallRules + internal: true + json: + - '.[]' + +javascript: + - code: | + let firewallRules = template.firewallRules; + if (typeof firewallRules === "string") { + firewallRules = JSON.parse(firewallRules); + } + + let insecureRules = []; + for (let rule of firewallRules) { + if ( + rule.disabled === false && + rule.direction === "INGRESS" && + Array.isArray(rule.sourceRanges) && rule.sourceRanges.includes("0.0.0.0/0") && + Array.isArray(rule.allowed) && + rule.allowed.some(allowed => + Array.isArray(allowed.ports) && + allowed.ports.includes("3306") + ) + ) { + insecureRules.push(rule.name); + } + } + + if (insecureRules.length > 0) { + Export(`The firewall rules in network ${template.networkName} of project ${template.projectId} allow unrestricted MySQL access: ${insecureRules.join(", ")}`); + } + + extractors: + - type: dsl + dsl: + - response diff --git a/cloud/gcp/vpc/gcloud-unrestricted-oracle-db-access.yaml b/cloud/gcp/vpc/gcloud-unrestricted-oracle-db-access.yaml new file mode 100644 index 00000000000..c5a37fffcc9 --- /dev/null +++ b/cloud/gcp/vpc/gcloud-unrestricted-oracle-db-access.yaml @@ -0,0 +1,102 @@ +id: gcloud-unrestricted-oracle-db-access + +info: + name: Check for Unrestricted Oracle Database Access + author: princechaddha + severity: high + description: | + Ensure that Google Cloud VPC network firewall rules do not allow unrestricted access (0.0.0.0/0 on TCP port 1521). Restrict Oracle Database traffic to trusted IP addresses or IP ranges to reduce the attack surface and enhance security. + impact: | + Allowing unrestricted access to TCP port 1521 exposes Oracle Database servers to potential brute-force or unauthorized access attacks. + remediation: | + Update your VPC firewall rules to allow Oracle Database traffic only from trusted IP addresses or ranges. + reference: + - https://cloud.google.com/vpc/docs/firewalls + tags: cloud,devops,gcp,gcloud,vpc,firewall,security,oracle,db,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let networkName of iterate(template.networks)){ + set("networkName", networkName) + code(3) + set("firewallRules", template.firewallRules) + javascript(1) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute networks list --project $projectId --format="json(name)" + + extractors: + - type: json + name: networks + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute firewall-rules list --filter network=$networkName --sort-by priority --format="json(name,disabled,direction,sourceRanges,allowed[].ports)" + + extractors: + - type: json + name: firewallRules + internal: true + json: + - '.[]' + +javascript: + - code: | + let firewallRules = template.firewallRules; + if (typeof firewallRules === "string") { + firewallRules = JSON.parse(firewallRules); + } + + let insecureRules = []; + for (let rule of firewallRules) { + if ( + rule.disabled === false && + rule.direction === "INGRESS" && + Array.isArray(rule.sourceRanges) && rule.sourceRanges.includes("0.0.0.0/0") && + Array.isArray(rule.allowed) && + rule.allowed.some(allowed => + Array.isArray(allowed.ports) && + allowed.ports.includes("1521") + ) + ) { + insecureRules.push(rule.name); + } + } + + if (insecureRules.length > 0) { + Export(`The firewall rules in network ${template.networkName} of project ${template.projectId} allow unrestricted Oracle Database access: ${insecureRules.join(", ")}`); + } + + extractors: + - type: dsl + dsl: + - response diff --git a/cloud/gcp/vpc/gcloud-unrestricted-outbound-access.yaml b/cloud/gcp/vpc/gcloud-unrestricted-outbound-access.yaml new file mode 100644 index 00000000000..f495959a993 --- /dev/null +++ b/cloud/gcp/vpc/gcloud-unrestricted-outbound-access.yaml @@ -0,0 +1,102 @@ +id: gcloud-unrestricted-outbound-access + +info: + name: Check for Unrestricted Outbound Access on All Ports + author: princechaddha + severity: high + description: | + Check your Google Cloud VPC network firewall for any egress rules that allow unrestricted access (0.0.0.0/0) to any TCP/UDP ports. Restrict outbound traffic to only those IP addresses and/or IP ranges that require it in order to implement the principle of least privilege and reduce the attack surface. + impact: | + Allowing unrestricted outbound access on all ports increases the risk of data exfiltration and potential exploitation of cloud resources. + remediation: | + Update your VPC firewall rules to restrict outbound traffic to trusted IP addresses and ports only. + reference: + - https://cloud.google.com/vpc/docs/firewalls + tags: cloud,devops,gcp,gcloud,vpc,firewall,security,networking,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let networkName of iterate(template.networks)){ + set("networkName", networkName) + code(3) + set("firewallRules", template.firewallRules) + javascript(1) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute networks list --project $projectId --format="json(name)" + + extractors: + - type: json + name: networks + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute firewall-rules list --filter network=$networkName --sort-by priority --format="json(name,disabled,direction,destinationRanges,allowed[].ports)" + + extractors: + - type: json + name: firewallRules + internal: true + json: + - '.[]' + +javascript: + - code: | + let firewallRules = template.firewallRules; + if (typeof firewallRules === "string") { + firewallRules = JSON.parse(firewallRules); + } + + let insecureRules = []; + for (let rule of firewallRules) { + if ( + rule.disabled === false && + rule.direction === "EGRESS" && + Array.isArray(rule.destinationRanges) && rule.destinationRanges.includes("0.0.0.0/0") && + Array.isArray(rule.allowed) && + rule.allowed.some(allowed => + Array.isArray(allowed.ports) && + (allowed.ports.includes("0-65535") || allowed.ports.some(port => port.startsWith("tcp:0-") || port.startsWith("udp:0-"))) + ) + ) { + insecureRules.push(rule.name); + } + } + + if (insecureRules.length > 0) { + Export(`The firewall rules in network ${template.networkName} of project ${template.projectId} allow unrestricted outbound access on all ports: ${insecureRules.join(", ")}`); + } + + extractors: + - type: dsl + dsl: + - response diff --git a/cloud/gcp/vpc/gcloud-unrestricted-postgresql-access.yaml b/cloud/gcp/vpc/gcloud-unrestricted-postgresql-access.yaml new file mode 100644 index 00000000000..4b21a27d209 --- /dev/null +++ b/cloud/gcp/vpc/gcloud-unrestricted-postgresql-access.yaml @@ -0,0 +1,102 @@ +id: gcloud-unrestricted-postgresql-access + +info: + name: Check for Unrestricted PostgreSQL Database Access + author: princechaddha + severity: high + description: | + Ensure that Google Cloud VPC network firewall rules do not allow unrestricted access (0.0.0.0/0 on TCP port 5432). Restrict PostgreSQL traffic to trusted IP addresses or IP ranges to implement the Principle of Least Privilege (POLP) and reduce the attack surface. + impact: | + Allowing unrestricted access to TCP port 5432 exposes PostgreSQL database servers to potential brute-force or unauthorized access attacks. + remediation: | + Update your VPC firewall rules to allow PostgreSQL traffic only from trusted IP addresses or ranges. + reference: + - https://cloud.google.com/vpc/docs/firewalls + tags: cloud,devops,gcp,gcloud,vpc,firewall,security,postgresql,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let networkName of iterate(template.networks)){ + set("networkName", networkName) + code(3) + set("firewallRules", template.firewallRules) + javascript(1) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute networks list --project $projectId --format="json(name)" + + extractors: + - type: json + name: networks + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute firewall-rules list --filter network=$networkName --sort-by priority --format="json(name,disabled,direction,sourceRanges,allowed[].ports)" + + extractors: + - type: json + name: firewallRules + internal: true + json: + - '.[]' + +javascript: + - code: | + let firewallRules = template.firewallRules; + if (typeof firewallRules === "string") { + firewallRules = JSON.parse(firewallRules); + } + + let insecureRules = []; + for (let rule of firewallRules) { + if ( + rule.disabled === false && + rule.direction === "INGRESS" && + Array.isArray(rule.sourceRanges) && rule.sourceRanges.includes("0.0.0.0/0") && + Array.isArray(rule.allowed) && + rule.allowed.some(allowed => + Array.isArray(allowed.ports) && + allowed.ports.includes("5432") + ) + ) { + insecureRules.push(rule.name); + } + } + + if (insecureRules.length > 0) { + Export(`The firewall rules in network ${template.networkName} of project ${template.projectId} allow unrestricted PostgreSQL access: ${insecureRules.join(", ")}`); + } + + extractors: + - type: dsl + dsl: + - response diff --git a/cloud/gcp/vpc/gcloud-unrestricted-rdp-access.yaml b/cloud/gcp/vpc/gcloud-unrestricted-rdp-access.yaml new file mode 100644 index 00000000000..325eeff1c63 --- /dev/null +++ b/cloud/gcp/vpc/gcloud-unrestricted-rdp-access.yaml @@ -0,0 +1,102 @@ +id: gcloud-unrestricted-rdp-access + +info: + name: Check for Unrestricted RDP Access + author: princechaddha + severity: critical + description: | + Ensure that Google Cloud VPC firewall rules do not allow unrestricted access (0.0.0.0/0 on TCP port 3389). Restrict RDP traffic to trusted IP addresses or IP ranges to reduce the attack surface and enhance security. + impact: | + Allowing unrestricted access to TCP port 3389 exposes your virtual machines to brute-force or unauthorized access attacks through RDP. + remediation: | + Update your VPC firewall rules to allow RDP traffic only from trusted IP addresses or ranges. + reference: + - https://cloud.google.com/vpc/docs/firewalls + tags: cloud,devops,gcp,gcloud,vpc,firewall,security,rdp,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let networkName of iterate(template.networks)){ + set("networkName", networkName) + code(3) + set("firewallRules", template.firewallRules) + javascript(1) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute networks list --project $projectId --format="json(name)" + + extractors: + - type: json + name: networks + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute firewall-rules list --filter network=$networkName --sort-by priority --format="json(name,disabled,direction,sourceRanges,allowed[].ports)" + + extractors: + - type: json + name: firewallRules + internal: true + json: + - '.[]' + +javascript: + - code: | + let firewallRules = template.firewallRules; + if (typeof firewallRules === "string") { + firewallRules = JSON.parse(firewallRules); + } + + let insecureRules = []; + for (let rule of firewallRules) { + if ( + rule.disabled === false && + rule.direction === "INGRESS" && + Array.isArray(rule.sourceRanges) && rule.sourceRanges.includes("0.0.0.0/0") && + Array.isArray(rule.allowed) && + rule.allowed.some(allowed => + Array.isArray(allowed.ports) && + allowed.ports.includes("3389") + ) + ) { + insecureRules.push(rule.name); + } + } + + if (insecureRules.length > 0) { + Export(`The firewall rules in network ${template.networkName} of project ${template.projectId} allow unrestricted RDP access: ${insecureRules.join(", ")}`); + } + + extractors: + - type: dsl + dsl: + - response diff --git a/cloud/gcp/vpc/gcloud-unrestricted-rpc-access.yaml b/cloud/gcp/vpc/gcloud-unrestricted-rpc-access.yaml new file mode 100644 index 00000000000..632baf5f2f7 --- /dev/null +++ b/cloud/gcp/vpc/gcloud-unrestricted-rpc-access.yaml @@ -0,0 +1,102 @@ +id: gcloud-unrestricted-rpc-access + +info: + name: Check for Unrestricted RPC Access + author: princechaddha + severity: high + description: | + Ensure that Google Cloud VPC network firewall rules do not allow unrestricted access (0.0.0.0/0 on TCP port 135). Restrict access to trusted IP addresses or ranges to reduce the attack surface and protect virtual machine (VM) instances targeted by these firewall rules. + impact: | + Allowing unrestricted access to TCP port 135 exposes resources to potential brute-force or unauthorized access attacks leveraging RPC communications. + remediation: | + Update your VPC firewall rules to allow RPC traffic only from trusted IP addresses or ranges. + reference: + - https://cloud.google.com/vpc/docs/firewalls + tags: cloud,devops,gcp,gcloud,vpc,firewall,security,rpc,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let networkName of iterate(template.networks)){ + set("networkName", networkName) + code(3) + set("firewallRules", template.firewallRules) + javascript(1) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute networks list --project $projectId --format="json(name)" + + extractors: + - type: json + name: networks + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute firewall-rules list --filter network=$networkName --sort-by priority --format="json(name,disabled,direction,sourceRanges,allowed[].ports)" + + extractors: + - type: json + name: firewallRules + internal: true + json: + - '.[]' + +javascript: + - code: | + let firewallRules = template.firewallRules; + if (typeof firewallRules === "string") { + firewallRules = JSON.parse(firewallRules); + } + + let insecureRules = []; + for (let rule of firewallRules) { + if ( + rule.disabled === false && + rule.direction === "INGRESS" && + Array.isArray(rule.sourceRanges) && rule.sourceRanges.includes("0.0.0.0/0") && + Array.isArray(rule.allowed) && + rule.allowed.some(allowed => + Array.isArray(allowed.ports) && + allowed.ports.includes("135") + ) + ) { + insecureRules.push(rule.name); + } + } + + if (insecureRules.length > 0) { + Export(`The firewall rules in network ${template.networkName} of project ${template.projectId} allow unrestricted RPC access: ${insecureRules.join(", ")}`); + } + + extractors: + - type: dsl + dsl: + - response diff --git a/cloud/gcp/vpc/gcloud-unrestricted-smtp-access.yaml b/cloud/gcp/vpc/gcloud-unrestricted-smtp-access.yaml new file mode 100644 index 00000000000..7124a13175e --- /dev/null +++ b/cloud/gcp/vpc/gcloud-unrestricted-smtp-access.yaml @@ -0,0 +1,102 @@ +id: gcloud-unrestricted-smtp-access + +info: + name: Check for Unrestricted SMTP Access + author: princechaddha + severity: high + description: | + Ensure that Google Cloud VPC network firewall rules do not allow unrestricted access (0.0.0.0/0 on TCP port 25). Restrict access to trusted IP addresses or ranges to reduce the risk of security threats for the SMTP server instances associated with these firewall rules. + impact: | + Allowing unrestricted access to TCP port 25 exposes SMTP servers to potential brute-force or unauthorized access attacks. + remediation: | + Update your VPC firewall rules to allow SMTP traffic only from trusted IP addresses or ranges. + reference: + - https://cloud.google.com/vpc/docs/firewalls + tags: cloud,devops,gcp,gcloud,vpc,firewall,security,smtp,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let networkName of iterate(template.networks)){ + set("networkName", networkName) + code(3) + set("firewallRules", template.firewallRules) + javascript(1) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute networks list --project $projectId --format="json(name)" + + extractors: + - type: json + name: networks + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute firewall-rules list --filter network=$networkName --sort-by priority --format="json(name,disabled,direction,sourceRanges,allowed[].ports)" + + extractors: + - type: json + name: firewallRules + internal: true + json: + - '.[]' + +javascript: + - code: | + let firewallRules = template.firewallRules; + if (typeof firewallRules === "string") { + firewallRules = JSON.parse(firewallRules); + } + + let insecureRules = []; + for (let rule of firewallRules) { + if ( + rule.disabled === false && + rule.direction === "INGRESS" && + Array.isArray(rule.sourceRanges) && rule.sourceRanges.includes("0.0.0.0/0") && + Array.isArray(rule.allowed) && + rule.allowed.some(allowed => + Array.isArray(allowed.ports) && + (allowed.ports.includes("25")) + ) + ) { + insecureRules.push(rule.name); + } + } + + if (insecureRules.length > 0) { + Export(`The firewall rules in network ${template.networkName} of project ${template.projectId} allow unrestricted SMTP access: ${insecureRules.join(", ")}`); + } + + extractors: + - type: dsl + dsl: + - response diff --git a/cloud/gcp/vpc/gcloud-unrestricted-sqlserver-access.yaml b/cloud/gcp/vpc/gcloud-unrestricted-sqlserver-access.yaml new file mode 100644 index 00000000000..bbca30a8027 --- /dev/null +++ b/cloud/gcp/vpc/gcloud-unrestricted-sqlserver-access.yaml @@ -0,0 +1,102 @@ +id: gcloud-unrestricted-sqlserver-access + +info: + name: Check for Unrestricted SQL Server Access + author: princechaddha + severity: critical + description: | + Ensure that Google Cloud VPC network firewall rules do not allow unrestricted access (0.0.0.0/0 on TCP port 1433). Restrict access to trusted IP addresses or ranges to implement the Principle of Least Privilege (POLP) and reduce the attack surface. + impact: | + Allowing unrestricted access to TCP port 1433 exposes your resources to potential brute-force or unauthorized access attacks on SQL Server. + remediation: | + Update your VPC firewall rules to allow SQL Server traffic only from trusted IP addresses or ranges. + reference: + - https://cloud.google.com/vpc/docs/firewalls + tags: cloud,devops,gcp,gcloud,vpc,firewall,security,sqlserver,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let networkName of iterate(template.networks)){ + set("networkName", networkName) + code(3) + set("firewallRules", template.firewallRules) + javascript(1) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute networks list --project $projectId --format="json(name)" + + extractors: + - type: json + name: networks + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute firewall-rules list --filter network=$networkName --sort-by priority --format="json(name,disabled,direction,sourceRanges,allowed[].ports)" + + extractors: + - type: json + name: firewallRules + internal: true + json: + - '.[]' + +javascript: + - code: | + let firewallRules = template.firewallRules; + if (typeof firewallRules === "string") { + firewallRules = JSON.parse(firewallRules); + } + + let unrestrictedSQLRules = []; + for (let rule of firewallRules) { + if ( + rule.disabled === false && + rule.direction === "INGRESS" && + Array.isArray(rule.sourceRanges) && rule.sourceRanges.includes("0.0.0.0/0") && + Array.isArray(rule.allowed) && + rule.allowed.some(allowed => + Array.isArray(allowed.ports) && + (allowed.ports.includes("1433")) + ) + ) { + unrestrictedSQLRules.push(rule.name); + } + } + + if (unrestrictedSQLRules.length > 0) { + Export(`The firewall rules in network ${template.networkName} of project ${template.projectId} allow unrestricted SQL Server access: ${unrestrictedSQLRules.join(", ")}`); + } + + extractors: + - type: dsl + dsl: + - response diff --git a/cloud/gcp/vpc/gcloud-unrestricted-ssh-access.yaml b/cloud/gcp/vpc/gcloud-unrestricted-ssh-access.yaml new file mode 100644 index 00000000000..4276913317e --- /dev/null +++ b/cloud/gcp/vpc/gcloud-unrestricted-ssh-access.yaml @@ -0,0 +1,100 @@ +id: gcloud-unrestricted-ssh-access + +info: + name: Check for Unrestricted SSH Access + author: princechaddha + severity: critical + description: | + Ensure that your Google Cloud VPC firewall rules do not allow unrestricted SSH access (0.0.0.0/0 on TCP port 22). Restrict SSH access to trusted IP addresses or ranges to reduce the attack surface and adhere to the principle of least privilege. + impact: | + Allowing unrestricted SSH access exposes your infrastructure to potential brute-force attacks or unauthorized access. + remediation: | + Update your VPC firewall rules to allow SSH traffic only from trusted IP addresses or ranges. + reference: + - https://cloud.google.com/vpc/docs/firewalls + tags: cloud,devops,gcp,gcloud,vpc,firewall,security,ssh,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let networkName of iterate(template.networks)){ + set("networkName", networkName) + code(3) + javascript(1) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute networks list --project $projectId --format="json(name)" + + extractors: + - type: json + name: networks + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute firewall-rules list --filter network=$networkName --sort-by priority --format="json(name,disabled,direction,sourceRanges,allowed[].ports)" + + extractors: + - type: json + name: firewallRules + internal: true + json: + - '.[]' + +javascript: + - code: | + let firewallRules = template.firewallRules; + + if (typeof firewallRules === "string") { + firewallRules = JSON.parse(firewallRules); + } + + let insecureRules = []; + for (let rule of firewallRules) { + if ( + rule.disabled === false && + rule.direction === "INGRESS" && + Array.isArray(rule.sourceRanges) && rule.sourceRanges.includes("0.0.0.0/0") && + Array.isArray(rule.allowed) && rule.allowed.some(allowed => + Array.isArray(allowed.ports) && allowed.ports.includes("22") + ) + ) { + insecureRules.push(rule.name); + } + } + + if (insecureRules.length > 0) { + Export(`The firewall rules in network ${template.networkName} of project ${template.projectId} allow unrestricted SSH access: ${insecureRules.join(", ")}`); + } + + extractors: + - type: dsl + dsl: + - response diff --git a/cloud/gcp/vpc/gcloud-vpc-firewall-port-ranges.yaml b/cloud/gcp/vpc/gcloud-vpc-firewall-port-ranges.yaml new file mode 100644 index 00000000000..9e9aab8b5d7 --- /dev/null +++ b/cloud/gcp/vpc/gcloud-vpc-firewall-port-ranges.yaml @@ -0,0 +1,100 @@ +id: gcloud-vpc-firewall-port-ranges + +info: + name: Check for VPC Firewall Rules with Port Ranges + author: princechaddha + severity: medium + description: | + Ensure that your Google Cloud VPC network firewall rules don't have ranges of ports configured to allow inbound traffic. This protects associated virtual machine instances against Denial-of-Service (DoS) attacks or brute-force attacks. It is recommended to open only specific ports within your firewall rules based on your application requirements. + impact: | + Allowing a range of ports in firewall rules increases the attack surface, exposing cloud resources to potential attacks. + remediation: | + Update your VPC firewall rules to allow only specific ports required for your applications, rather than a range of ports. + reference: + - https://cloud.google.com/vpc/docs/firewalls + tags: cloud,devops,gcp,gcloud,vpc,firewall,security,networking,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + for(let networkName of iterate(template.networks)){ + set("networkName", networkName) + code(3) + set("firewallRules", template.firewallRules) + javascript(1) + } + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute networks list --project $projectId --format="json(name)" + + extractors: + - type: json + name: networks + internal: true + json: + - '.[].name' + + - engine: + - sh + - bash + source: | + gcloud compute firewall-rules list --filter network=$networkName --sort-by priority --format="json(name,disabled,direction,allowed[].ports)" + + extractors: + - type: json + name: firewallRules + internal: true + json: + - '.[]' + +javascript: + - code: | + let firewallRules = template.firewallRules; + if (typeof firewallRules === "string") { + firewallRules = JSON.parse(firewallRules); } + + let insecureRules = []; + for (let rule of firewallRules) { + if ( + rule.disabled === false && + rule.direction === "INGRESS" && + Array.isArray(rule.allowed) && + rule.allowed.some(allowed => + Array.isArray(allowed.ports) && + allowed.ports.some(port => port.includes("0-") || port.includes("80-8080")) + ) + ) { + insecureRules.push(rule.name); + } + } + + if (insecureRules.length > 0) { + Export(`The firewall rules in network ${template.networkName} of project ${template.projectId} allow insecure port ranges for ingress traffic: ${insecureRules.join(", ")}`); + } + + extractors: + - type: dsl + dsl: + - response diff --git a/cloud/gcp/vpc/gcloud-vpc-private-service-connect.yaml b/cloud/gcp/vpc/gcloud-vpc-private-service-connect.yaml new file mode 100644 index 00000000000..e8e23954e06 --- /dev/null +++ b/cloud/gcp/vpc/gcloud-vpc-private-service-connect.yaml @@ -0,0 +1,55 @@ +id: gcloud-vpc-private-service-connect + +info: + name: Private Service Connect Endpoints Not Configured + author: princechaddha + severity: medium + description: | + Ensure that Private Service Connect (PSC) endpoints are configured for your Virtual Private Cloud (VPC) networks. Private Service Connect creates a secure, private tunnel between your VPC network and Google's services (or your own services in another VPC) so traffic never touches the public internet. This enhances security and avoids complexities of managing public connections. + impact: | + Without Private Service Connect endpoints, traffic between your VPC and Google services may traverse the public internet, potentially exposing your services to security risks and performance issues. + remediation: | + Configure Private Service Connect endpoints for your VPC networks using either the Google Cloud Console or gcloud CLI. Use the 'gcloud compute forwarding-rules create' command with appropriate parameters to set up PSC endpoints. + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/VPC/vpc-with-private-service-connect-endpoints.html + - https://cloud.google.com/vpc/docs/private-service-connect + tags: cloud,devops,gcp,gcloud,vpc,networking,security,psc,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute forwarding-rules list --project=$projectId --filter="target~serviceAttachments" --format="json(name)" + + matchers: + - type: word + words: + - "[]" + + extractors: + - type: dsl + dsl: + - '"Project " + projectId + " has no Private Service Connect endpoints configured"' \ No newline at end of file diff --git a/cloud/gcp/vpc/gcloud-vpc-unattached-static-ips.yaml b/cloud/gcp/vpc/gcloud-vpc-unattached-static-ips.yaml new file mode 100644 index 00000000000..30d7d1bd3e1 --- /dev/null +++ b/cloud/gcp/vpc/gcloud-vpc-unattached-static-ips.yaml @@ -0,0 +1,55 @@ +id: gcloud-vpc-unattached-static-ips + +info: + name: Unattached Static External IP Addresses + author: princechaddha + severity: low + description: | + Identify and release any unattached (unused) static external IP addresses from your Google Cloud Platform (GCP) project in order to lower the cost of your cloud bill. A static external IP address is an IP address that is reserved for your GCP project until you decide to release it. Google Cloud considers a static external IP address as in use if it's associated with a virtual machine (VM) instance, whether the VM instance is running or stopped. + impact: | + Google Cloud charges for static IP addresses that are not attached to virtual machines (VM) instances or load balancers. If you reserve a static external IP address and do not assign it to a resource such as a VM instance or a forwarding rule, you will be charged at a higher rate than for static and ephemeral external IP addresses that are in use. + remediation: | + Release unused static external IP addresses using the 'gcloud compute addresses delete' command with the appropriate region and address name parameters. Example: gcloud compute addresses delete ADDRESS_NAME --region=REGION --project=PROJECT_ID + reference: + - https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/VPC/unattached-static-ip-address.html + - https://cloud.google.com/compute/docs/ip-addresses/reserve-static-external-ip-address + tags: cloud,devops,gcp,gcloud,vpc,networking,cost-optimization,gcp-cloud-config + +flow: | + code(1) + for(let projectId of iterate(template.projectIds)){ + set("projectId", projectId) + code(2) + } + +self-contained: true + +code: + - engine: + - sh + - bash + source: | + gcloud projects list --format="json(projectId)" + + extractors: + - type: json + name: projectIds + internal: true + json: + - '.[].projectId' + + - engine: + - sh + - bash + source: | + gcloud compute addresses describe cc-production-instance-static-ip --region=us-central1 --project=$projectId --format="json(name,region,status)" + + matchers: + - type: word + words: + - "RESERVED" + + extractors: + - type: dsl + dsl: + - '"Project " + projectId + " has an unattached static IP address in region us-central1"' \ No newline at end of file