VPC Service Controls is a Google Cloud feature that lets you 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.
-
Cloud Build Pub/Sub triggers are not supported when VPC Service Controls is used.
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:
- Create a service perimeter.
Add the project in which you're planning to create the private pool to the perimeter.
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 service account access to the VPC Service Controls perimeter
In the following cases, you must grant the legacy Cloud Build or Compute Engine service account access to the VPC Service Controls perimeter for your builds to access resources within the perimeter:
If you're using the legacy Cloud Build or Compute Engine service account to start builds using a build trigger, Cloud Build API, or the command line.
If you're using user-specified service accounts to start builds using a build trigger.
You don't need to grant the legacy Cloud Build or Compute Engine 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 legacy Cloud Build or Compute Engine service account access to the VPC Service Controls perimeter:
Note the email address of the legacy service account:
Open the IAM page:
Select the project that you added to the service perimeter.
In the permissions table, locate the email address corresponding the legacy Cloud Build service account.
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'
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 the 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 Run 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
Open the Worker Pool page in the Google Cloud console:
Select the project where you want to create the private pool.
In the Worker pool page, click Create.
In the Create private pool side panel:
Enter a name for your private pool.
Select the region in which you want the private pool to be created.
Select the Compute Engine machine type you want to use for your private pool.
Enter the project number of the Google Cloud project where you created your VPC network.
Enter the name of your VPC network.
Uncheck Assign external IPs.
Click Create.
gcloud
Create a private pool config file in the YAML or the JSON format, and set the
egressOption
flag toNO_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 formatprojects/NETWORK_PROJECT_ID/global/networks/NETWORK_NAME
, whereNETWORK_PROJECT_ID
is the project ID of the Google Cloud project that holds your VPC network andNETWORK_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 specify0
, Cloud Build uses the default value of 100.egressOption
is the flag to enable VPC Service Controls perimeter for your private pool. Set this toNO_PUBLIC_EGRESS
to create your private pool within the VPC Service Controls perimeter.
Run the following
gcloud
command, wherePRIVATEPOOL_ID
is a unique identifier for your private pool,PRIVATEPOOL_CONFIG_FILE
is the name of your private pool config file, andREGION
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:
In your private pool config file, make sure that the
egressOption
field is set toNO_PUBLIC_EGRESS
.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:
- Choose to store your build logs in Cloud Logging by setting
loggingMode
toCLOUD_LOGGING_ONLY
. - In your private project, create a Cloud Storage logs bucket to store your build logs. For instructions on doing this, see Storing build logs in a user-created bucket.
- Disable build logs by setting
loggingMode
toNONE
.
Running builds
Run your build using the instructions at Running builds in a private pool.
What's next
- Learn how to run builds in private pools.
- Learn how to configure commonly used networking use cases.