Securing cloud infrastructure traditionally relies on Identity and Access Management (IAM). If a user has the Storage Object Admin role, they can access a Google Cloud Storage (GCS) bucket. However, IAM evaluates who is making the request, but not where the request is coming from or how the data is being moved. If an authenticated developer downloads a highly confidential database backup from a corporate GCS bucket and uploads it to their personal GCS bucket in a different project, IAM allows it. This is a massive data exfiltration risk.
Google Cloud solves this with VPC Service Controls (VPC-SC). VPC-SC draws an invisible, cryptographic perimeter around your GCP projects. Even if a user has full IAM permissions, if they attempt to move data outside the perimeter, the API request is denied.
However, enterprise environments are rarely isolated. What happens when an application inside Perimeter A legitimately needs to query a BigQuery dataset inside Perimeter B? The solution is a VPC-SC Perimeter Bridge.
Understanding VPC-SC Architecture
A VPC-SC Perimeter operates at the Google API layer, not the network layer. It intercepts calls to services like storage.googleapis.com or bigquery.googleapis.com.
If you place Project 1 inside a perimeter, a Compute Engine VM in Project 1 can write to a GCS bucket in Project 1. But if that VM tries to write to a GCS bucket in Project 2 (which is outside the perimeter), VPC-SC intercepts the API call and blocks it, preventing exfiltration.
A Perimeter Bridge allows two distinctly isolated perimeters to communicate securely without merging them into a single massive, insecure perimeter.
Step 1: Creating the Independent Perimeters
To demonstrate a bridge, we must first establish the perimeters. We assume you have a Google Cloud Organization and two projects: finance-project and analytics-project.
Using the gcloud CLI, create the Finance Perimeter protecting the Cloud Storage API:
gcloud access-context-manager perimeters create finance_perimeter \
--title="Finance Data Perimeter" \
--resources="projects/finance-project" \
--restricted-services="storage.googleapis.com" \
--policy=YOUR_ACCESS_POLICY_ID
Create the Analytics Perimeter protecting the BigQuery API:
gcloud access-context-manager perimeters create analytics_perimeter \
--title="Analytics Data Perimeter" \
--resources="projects/analytics-project" \
--restricted-services="bigquery.googleapis.com" \
--policy=YOUR_ACCESS_POLICY_ID
At this point, if a data pipeline running in analytics-project attempts to read a CSV file from a bucket in finance-project to load into BigQuery, the request will be blocked by VPC-SC with a REJECTED_BY_VPC_SERVICE_CONTROLS error.
Step 2: Designing the Perimeter Bridge
To allow the analytics pipeline to read the finance data, we create a Perimeter Bridge. A bridge essentially instructs the Google API control plane to treat both projects as if they were in the same perimeter, but only for the specific projects explicitly named in the bridge.
Create the bridge linking the two projects:
gcloud access-context-manager perimeters create finance_analytics_bridge \
--title="Bridge: Finance to Analytics" \
--perimeter-type=bridge \
--resources="projects/finance-project,projects/analytics-project" \
--policy=YOUR_ACCESS_POLICY_ID
Once the bridge is active, the data pipeline in the Analytics project can successfully call the GCS API in the Finance project.
Step 3: Enforcing Ingress and Egress Rules (Modern Approach)
While Perimeter Bridges are powerful, they are bi-directional. A bridge means the Analytics project can read Finance data, but it also means the Finance project can write to the Analytics project. In strict Zero Trust environments, this bi-directional trust is often too broad.
Google Cloud recently introduced Ingress and Egress Rules as a more granular alternative (and eventual successor) to Perimeter Bridges. Instead of bridging the perimeters entirely, you define directional API rules.
To allow the Analytics project to read GCS from the Finance project (without allowing Finance to touch BigQuery), you configure an Ingress rule on the Finance perimeter.
Create a YAML file named ingress.yaml:
- ingressFrom:
identityType: ANY_IDENTITY
sources:
- resource: projects/analytics-project
ingressTo:
operations:
- serviceName: storage.googleapis.com
methodSelectors:
- method: "google.storage.objects.get"
resources:
- projects/finance-project
Apply the Ingress rule to the Finance perimeter:
gcloud access-context-manager perimeters update finance_perimeter \
--set-ingress-policies=ingress.yaml \
--policy=YOUR_ACCESS_POLICY_ID
This approach establishes a surgical, one-way conduit. The Analytics pipeline can execute the objects.get method against the Finance bucket, but absolutely no other API calls are permitted across the boundary.
Step 4: Troubleshooting VPC-SC Denials
When VPC-SC blocks an API call, diagnosing the failure can be complex, as the error surfaces in the application layer (often as a generic 403 Forbidden). To identify exfiltration blocks, you must query Cloud Logging.
In the Logs Explorer, run the following query:
logName="projects/YOUR_PROJECT_ID/logs/cloudaudit.googleapis.com%2Fpolicy"
protoPayload.metadata.@type="type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata"
The resulting logs will explicitly state the violationReason (e.g., RESOURCES_NOT_IN_SAME_PERIMETER), the blocked API method, and the identity that attempted the call, allowing you to correctly adjust your Perimeter Bridges or Ingress rules.
Conclusion
Google Cloud VPC Service Controls provide the ultimate defense against data exfiltration, rendering compromised IAM credentials useless outside the defined boundary. By mastering Perimeter Bridges and granular Ingress/Egress rules, cloud architects can construct highly secure, interconnected data lakes that facilitate complex analytics without sacrificing rigorous data residency and exfiltration protections.