Using VPC Service Controls

VPC Service Controls is a Google Cloud feature that allows you to set up a secure perimeter to guard against data exfiltration. This page shows how to use VPC Service Controls with Cloud Build private pools to add additional security to your builds.

Limitations

VPC Service Controls protection is available only for builds run in private pools; you cannot use VPC Service Controls with builds run in default pools.

Before you begin

  • To use the command-line examples in this guide, install and configure the Google Cloud CLI.

  • Set up a private connection between your Virtual Private Cloud network and the VPC network where private pools reside. For instructions, see set up your environment to create private pools.

Setting up a private pool in the VPC Service Controls perimeter

To use VPC Service Controls with Cloud Build, you must first create and configure a service perimeter, which is done at the organization level. This setup ensures that VPC Service Controls checks are enforced when using Cloud Build and that developers can only run builds that comply with VPC Service Controls.

Creating a VPC Service Controls perimeter

Identity and Access Management permissions: To set up a service perimeter, you require the Organization Viewer and Access Context Manager Editor roles. For instructions on granting these roles, see Configuring access to Cloud Build resources.

To create a VPC Service Controls perimeter:

Follow the VPC Service Controls Quickstart to:

  1. Create a service perimeter.
  2. Add the project in which you're planning to create the private pool to the perimeter.

  3. Restrict the Cloud Build API.

After setting up your service perimeter, all calls to the Cloud Build API are checked to ensure that the calls originate from within the same perimeter.

Granting the Cloud Build service account access to the VPC Service Controls perimeter

Cloud Build uses the Cloud Build service account or user-specified service accounts to execute builds on your behalf. In the following cases, you must grant the service account access to the VPC Service Controls perimeter, for your builds to access resources within the perimeter:

You don't need to grant the service account access to the VPC Service Controls perimeter if you're using user-specified service accounts to start builds using the Cloud Build API, or the command line.

Perform the following steps to grant the Cloud Build service account access to the VPC Service Controls perimeter:

  1. Note the email address of your Cloud Build service account or user-specified service account. To get the email address of your Cloud Build service account:

    1. Open the IAM page:

      Open the IAM page

    2. Select the project that you added to the service perimeter.

    3. In the permissions table, locate the email address ending with @cloudbuild.gserviceaccount.com and note it down. This is your Cloud Build service account.

  2. Update the ingress policy of the service perimeter to allow the service account to call the Cloud Build APIs. This ingress rule allows the service account to make the CreateBuild API call. For more information about setting VPC Service Controls ingress policies, see Configuring ingress and egress policies and Ingress and egress rules.

    - ingressFrom:
        identities:
        - serviceAccount:SERVICE_ACCOUNT_EMAIL
        sources:
        - accessLevel: '*'
      ingressTo:
        operations:
        - serviceName: 'cloudbuild.googleapis.com'
          methodSelectors:
          - method: '*'
        resources:
        - 'projects/PROJECT_NUMBER'
    
  3. Update the perimeter policy by running the following command replacing variables with appropriate values:

    gcloud beta access-context-manager perimeters update PERIMETER_NAME \
        --set-ingress-policies=INGRESS-FILENAME \
        --policy=POLICY_ID
    

Replace the variables above with the following:

  • SERVICE_ACCOUNT_EMAIL: the email address of your Cloud Build service account or user-specified service account.
  • PROJECT_NUMBER: the project number of the Google Cloud project that you added to the VPC Service Controls perimeter.
  • PERIMETER_NAME: the name of your VPC Service Controls perimeter.
  • INGRESS-FILENAME: the name of your ingress policy file.
  • POLICY_ID: the ID of the access policy.

Optional: Enabling perimeter access for development machines

Because VPC Service Controls checks are enforced for the Cloud Build API, calls to the Cloud Build API fail unless they originate from within the service perimeter. Therefore, to manage builds with the Cloud Build API, the Cloud Build UI in the Google Cloud console, or the Google Cloud CLI, choose one of the following options:

  • Use a machine inside the VPC Service Controls perimeter. For example, you can use a Compute Engine VM or an on-premises machine connected to your VPC network via VPN.

  • Grant developers access to the perimeter. For example, you can create access levels that enable perimeter access based on IP address or user identity. For more information, see Allowing access to protected resources from outside a perimeter.

Setting up organization policy constraints

To ensure that VPC Service Controls checks are enforced correctly and you're restricting builds in a Google Cloud organization to only use the specified private pools, set the constraints/cloudbuild.allowedWorkerPools organization policy constraint. You can apply the organization policy to the entire organization, or to a project or a folder in the organization. For example, your organization policy can specify that:

  • All builds in the organization use the specified private pools.
  • All builds in a folder use the specified private pools.
  • All builds in a project use the specified private pools.

IAM permissions: To manage organization policies, you need the Organization Policy Administrator (roles/orgpolicy.policyAdmin) role. For instructions on granting a role, see Configuring access to Cloud Build resources.

The gcloud resource-manager org-policies allow command sets an organization policy that requires the builds in the organization to only use the specified private pool:

 gcloud resource-manager org-policies allow \
     cloudbuild.allowedWorkerPools \
     projects/PRIVATEPOOL_PROJECT_ID/locations/LOCATION/workerPools/PRIVATEPOOL_ID \
     --organization ORGANIZATION_ID

Replace the placeholder values in the above commands with the following:

  • PRIVATEPOOL_ID: the ID of the private pool to run builds.

  • PRIVATEPOOL_PROJECT_ID: the ID of the Google Cloud project that contains the private pool.

  • LOCATION: the region that contains the private pool.

  • ORGANIZATION_ID: the ID of the Organization where you're running builds.

The command supports under: and is prefixes.

To set organization policy that requires all builds in the organization to use any private pool under that organization:

 gcloud resource-manager org-policies allow \
     cloudbuild.allowedWorkerPools under:organizations/ORGANIZATION_ID \
     --organization ORGANIZATION_ID

Where, ORGANIZATION_ID is the ID of the organization that contains the private pools.

To set an organization policy that requires all builds in the projects under a folder to use any private pool in the specified project:

 gcloud resource-manager org-policies allow \
     cloudbuild.allowedWorkerPools under:projects/PROJECT_ID \
     --folder FOLDER_ID

Where PROJECT_ID is the ID of the project that contains the private pools and FOLDER_ID contains the projects where you're running the builds.

To set an organization policy that requires all builds in a project to use any private pool in the specified project:

 gcloud resource-manager org-policies allow \
     cloudbuild.allowedWorkerPools under:projects/PRIVATEPOOL_PROJECT_ID \
     --project BUILD_PROJECT_ID

Where PRIVATEPOOL_PROJECT_ID is the ID of the project that contains the private pools and BUILD_PROJECT_ID is the ID of the project where you're running the builds.

Keep the following considerations in mind when enforcing the constraints/cloudbuild.allowedWorkerPools organization policy constraint:

  • If you apply this organization policy constraint to a Google Cloud project, ensure that all builds in the project use the private pool; builds attempting to use the default shared pool will fail.

  • If your Google Cloud organization contains services such as App Engine or Cloud Functions that implicitly use Cloud Build, enforcing this the organization policy constraint may cause these services to not work as expected.

Creating a private pool in the service perimeter

Console

  1. Open the Worker Pool page in the Google Cloud console:

    Open the Cloud Build worker pool page

  2. Select the project where you want to create the private pool.

  3. In the Worker pool page, click Create.

  4. In the Create private pool side panel:

    1. Enter a name for your private pool.

    2. Select the region in which you want the private pool to be created.

    3. Select the Compute Engine machine type you want to use for your private pool.

    4. Enter the project number of the Google Cloud project where you created your VPC network.

    5. Enter the name of your VPC network.

    6. Uncheck Assign external IPs.

    7. Click Create.

gcloud

  1. Create a private pool config file in the YAML or the JSON format, and set the egressOption flag to NO_PUBLIC_EGRESS:

    privatePoolV1Config:
      networkConfig:
        egressOption: NO_PUBLIC_EGRESS
        peeredNetwork: PEERED_NETWORK
      workerConfig:
        diskSizeGb: 'PRIVATE_POOL_DISK_SIZE'
        machineType: PRIVATE_POOL_MACHINE_TYPE
    

    Where:

    • PEERED_NETWORK is the network resource URL of the network that is peered to the service provider network. PEERED_NETWORK must be of the format projects/NETWORK_PROJECT_ID/global/networks/NETWORK_NAME, where NETWORK_PROJECT_ID is the project ID of the Google Cloud project that holds your VPC network and NETWORK_NAME is the name of your VPC network.
    • PRIVATE_POOL_MACHINE_TYPE is the Compute Engine machine type for private pool instance. For supported machine types, see Private pool config file schema.
    • PRIVATE_POOL_DISK_SIZE is disk size for private pool instance in GB. Specify a value greater than or equal to 100 and less than or equal to 1000. If you specify 0, Cloud Build uses the default value of 100.
    • egressOption is the flag to enable VPC Service Controls perimeter for your private pool. Set this to NO_PUBLIC_EGRESS to create your private pool within the VPC Service Controls perimeter.
  2. Run the following gcloud command, where PRIVATEPOOL_ID is a unique identifier for your private pool, PRIVATEPOOL_CONFIG_FILE is the name of your private pool config file, and REGION is the region where you want to create your private pool:

    gcloud builds worker-pools create PRIVATEPOOL_ID --config-from-file PRIVATEPOOL_CONFIG_FILE --region REGION
    

Optional: Enabling public internet calls on the VPC network

Make sure your VPC network is configured to allow network connectivity to where your repository is hosted (e.g. github.com) with the following settings:

  1. In your private pool config file, make sure that the egressOption field is set to NO_PUBLIC_EGRESS.

  2. The VPC network that your private pool runs on is defined as a PeeredNetwork. To allow calls to your repository host, ensure that this VPC network allows public egress to your repository host. For information on doing this, see routes and firewall rules.

Running builds in a private pool within the service perimeter

Builds run within the service perimeter don't have access to the public internet, because of which you'll need to perform a few actions before running a build.

Pushing built images and artifacts

If your builds push images and artifacts to Container Registry (Deprecated), Artifact Registry, or Cloud Storage that are in a different Google Cloud project, make sure to add that project to the same service perimeter as the project from which your builds originate.

Creating a logs bucket

Build run within the service perimeter will not have permissions to store build logs in the default Cloud Storage logs bucket. Choose one of the following options:

Running builds

Run your build using the instructions at Running builds in a private pool.

What's next