Create a sample IaC validation report


This tutorial describes how you can verify that your infrastructure as code (IaC) doesn't violate your organization policies or Security Health Analytics detectors.

Objectives

  • Create a security posture.
  • Deploy the posture on a project.
  • Check an example Terraform file for violations.
  • Fix the violations in the Terraform file, and check the file again to verify the fix.

Before you begin

Set up permissions

  1. Make sure that you have the following role or roles on the organization: Project Creator and Security Posture Admin

    Check for the roles

    1. In the Google Cloud console, go to the IAM page.

      Go to IAM
    2. Select the organization.
    3. In the Principal column, find the row that has your email address.

      If your email address isn't in that column, then you do not have any roles.

    4. In the Role column for the row with your email address, check whether the list of roles includes the required roles.

    Grant the roles

    1. In the Google Cloud console, go to the IAM page.

      Go to IAM
    2. Select the organization.
    3. Click Grant access.
    4. In the New principals field, enter your email address.
    5. In the Select a role list, select a role.
    6. To grant additional roles, click Add another role and add each additional role.
    7. Click Save.

Set up Cloud Shell

  1. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  2. Find your organization ID:
    gcloud organizations list

Prepare the environment

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. Install the Google Cloud CLI.
  3. To initialize the gcloud CLI, run the following command:

    gcloud init
  4. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  5. Make sure that billing is enabled for your Google Cloud project.

  6. Enable the Security posture service and Security Command Center management APIs:

    gcloud services enable securityposture.googleapis.com  securitycentermanagement.googleapis.com
  7. Set up authentication:

    1. Create the service account:

      gcloud iam service-accounts create SERVICE_ACCOUNT_NAME

      Replace SERVICE_ACCOUNT_NAME with a name for the service account.

    2. Grant the roles/securityposture.reportCreator IAM role to the service account:

      gcloud projects add-iam-policy-binding PROJECT_ID --member="serviceAccount:SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com" --role=roles/securityposture.reportCreator

      Replace the following:

      • SERVICE_ACCOUNT_NAME: the name of the service account
      • PROJECT_ID: the project ID where you created the service account
    3. Generate the key file:

      gcloud iam service-accounts keys create FILE_NAME.json --iam-account=SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com

      Replace the following:

      • FILE_NAME: a name for the key file
      • SERVICE_ACCOUNT_NAME: the name of the service account
      • PROJECT_ID: the project ID where you created the service account
  8. Install the Google Cloud CLI.
  9. To initialize the gcloud CLI, run the following command:

    gcloud init
  10. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  11. Make sure that billing is enabled for your Google Cloud project.

  12. Enable the Security posture service and Security Command Center management APIs:

    gcloud services enable securityposture.googleapis.com  securitycentermanagement.googleapis.com
  13. Set up authentication:

    1. Create the service account:

      gcloud iam service-accounts create SERVICE_ACCOUNT_NAME

      Replace SERVICE_ACCOUNT_NAME with a name for the service account.

    2. Grant the roles/securityposture.reportCreator IAM role to the service account:

      gcloud projects add-iam-policy-binding PROJECT_ID --member="serviceAccount:SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com" --role=roles/securityposture.reportCreator

      Replace the following:

      • SERVICE_ACCOUNT_NAME: the name of the service account
      • PROJECT_ID: the project ID where you created the service account
    3. Generate the key file:

      gcloud iam service-accounts keys create FILE_NAME.json --iam-account=SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com

      Replace the following:

      • FILE_NAME: a name for the key file
      • SERVICE_ACCOUNT_NAME: the name of the service account
      • PROJECT_ID: the project ID where you created the service account
  14. Copy the project ID:
    gcloud projects describe PROJECT_ID
  15. Initialize Terraform:
    terraform init

Create and deploy a posture

  1. In Cloud Shell, launch the Cloud Shell Editor. To launch the editor, click Code Editor Button Open Editor on the toolbar of the Cloud Shell window.

  2. Create a YAML file named example-standard.yaml.

  3. Paste the following code into your file:

    name: organizations/ORGANIZATION_ID/locations/global/postures/example-standard
    state: ACTIVE
    policySets:
    - policies:
    - constraint:
        orgPolicyConstraintCustom:
          customConstraint:
            actionType: ALLOW
            condition: "resource.initialNodeCount == 3"
            description: Set initial node count to be exactly 3.
            displayName: fixedNodeCount
            methodTypes:
            - CREATE
            name: organizations/ORGANIZATION_ID/customConstraints/custom.fixedNodeCount
            resourceTypes:
            - container.googleapis.com/NodePool
          policyRules:
          - enforce: true
      policyId: fixedNodeCount
    - constraint:
        securityHealthAnalyticsCustomModule:
          config:
            customOutput: {}
            description: Set MTU for a network to be exactly 1000.
            predicate:
              expression: "!(resource.mtu == 1000)"
            recommendation: Only create networks whose MTU is 1000.
            resourceSelector:
              resourceTypes:
              - compute.googleapis.com/Network
            severity: HIGH
          displayName: fixedMTU
          moduleEnablementState: ENABLED
      policyId: fixedMTU
    - constraint:
        securityHealthAnalyticsModule:
          moduleEnablementState: ENABLED
          moduleName: BUCKET_POLICY_ONLY_DISABLED
      policyId: bucket_policy_only_disabled
    - constraint:
        securityHealthAnalyticsModule:
          moduleEnablementState: ENABLED
          moduleName: BUCKET_LOGGING_DISABLED
      policyId: bucket_logging_disabled
    policySetId: policySet1
    

    Replace ORGANIZATION_ID with your organization ID.

  4. In Cloud Shell, create the posture:

    gcloud scc postures create organizations/ORGANIZATION_ID/locations/global/postures/example-standard --posture-from-file=example-standard.yaml
    
  5. Copy the posture revision ID that the command generates.

  6. Deploy the posture to your project:

    gcloud scc posture-deployments create organizations/ORGANIZATION_ID/locations/global/postureDeployments/example-standard \
    --posture-name=organizations/ORGANIZATION_ID/locations/global/postures/example-standard \
    --posture-revision-id="POSTURE_REVISION_ID" \
    --target-resource=projects/PROJECT_ID
    

    Replace the following:

    • ORGANIZATION_ID: your organization ID.
    • POSTURE REVISION_ID: your posture revision ID that you copied.
    • PROJECT_ID: your project ID.

Create the Terraform file and validate

  1. In Cloud Shell, launch the Cloud Shell Editor.

  2. Create a Terraform file named main.tf.

  3. Paste the following code into your file:

    terraform {
      required_providers {
        google = {
          source  = "hashicorp/google"
        }
      }
    }
    
    provider "google" {
      region  = "us-central1"
      zone    = "us-central1-c"
    }
    
    resource "google_compute_network" "example_network"{
      name                            = "example-network-1"
      delete_default_routes_on_create = false
      auto_create_subnetworks         = false
      routing_mode                    = "REGIONAL"
      mtu                             = 100
      project                         = "PROJECT_ID"
    }
    
    resource "google_container_node_pool" "example_node_pool" {
      name               = "example-node-pool-1"
      cluster            = "example-cluster-1"
      project            = "PROJECT_ID"
      initial_node_count = 2
    
      node_config {
        preemptible  = true
        machine_type = "e2-medium"
      }
    }
    
    resource "google_storage_bucket" "example_bucket" {
      name          = "example-bucket-1"
      location      = "EU"
      force_destroy = true
    
      project = "PROJECT_ID"
    
      uniform_bucket_level_access = false
    }
    

    Replace PROJECT_ID with the project ID of the project that you created.

  4. In Cloud Shell, create the Terraform plan file and convert it to JSON format:

    terraform plan -out main.plan
    terraform show -json main.plan > mainplan.json
    
  5. Create the IaC validation report for mainplan.json:

    gcloud scc iac-validation-reports create organizations/ORGANIZATION_ID/locations/global --tf-plan-file=mainplan.json
    

    This command returns an IaC validation report that describes the following violations:

    • The mtu for example_network isn't 1000.
    • The initial_node_count for example_node_pool isn't 3.
    • The example_bucket doesn't have uniform bucket level access enabled.
    • The example_bucket doesn't have logging enabled.

Resolve violations

  1. In Cloud Shell, launch the Cloud Shell Editor.

  2. Update the main.tf file with the following changes:

    terraform {
      required_providers {
        google = {
          source  = "hashicorp/google"
        }
      }
    }
    
    provider "google" {
      region  = "us-central1"
      zone    = "us-central1-c"
    }
    
    resource "google_compute_network" "example_network"{
      name                            = "example-network-1"
      delete_default_routes_on_create = false
      auto_create_subnetworks         = false
      routing_mode                    = "REGIONAL"
      mtu                             = 1000
      project                         = "PROJECT_ID"
    }
    
    resource "google_container_node_pool" "example_node_pool" {
      name               = "example-node-pool-1"
      cluster            = "example-cluster-1"
      project            = "PROJECT_ID"
      initial_node_count = 3
    
      node_config {
        preemptible  = true
        machine_type = "e2-medium"
      }
    }
    
    resource "google_storage_bucket" "example_bucket" {
      name          = "example-bucket-1"
      location      = "EU"
      force_destroy = true
    
      project = "PROJECT_ID"
      uniform_bucket_level_access = true
    
      logging {
        log_bucket   = "my-unique-logging-bucket" // Create a separate bucket for logs
        log_object_prefix = "tf-logs/"             // Optional prefix for better structure
      }
    }
    

    Replace PROJECT_ID with the project ID of the project that you created.

  3. In Cloud Shell, create the Terraform plan file and convert it to JSON format:

    terraform plan -out main.plan
    terraform show -json main.plan > mainplan.json
    
  4. Recreate the IaC validation report for mainplan.json:

    gcloud scc iac-validation-reports create organizations/ORGANIZATION_ID/locations/global --tf-plan-file=mainplan.json
    

Clean up

To avoid incurring charges to your Google Cloud account for the resources used in this tutorial, either delete the project that contains the resources, or keep the project and delete the individual resources.

Delete the project

    Delete a Google Cloud project:

    gcloud projects delete PROJECT_ID

What's next