Introduction
VPC Service Controls (VPC SC) is Google Cloud's answer to the API-level data exfiltration problem. While IAM answers "who can call this API," VPC SC answers "from which network context can this API be called for these specific resources." It wraps managed services such as Cloud Storage, BigQuery, Pub/Sub, Cloud KMS, and AI Platform inside a logical boundary called a service perimeter. Any request that crosses the perimeter without an explicit ingress or egress rule is denied at the API front end, regardless of how strong the caller's IAM grant is.
For the PCNE exam, VPC Service Controls appears in almost every "hybrid + sensitive data + private connectivity" scenario. You will see questions that combine the restricted VIP (199.36.153.4/30), Private Google Access for on-premises, Cloud DNS forwarding zones, dry-run vs enforced perimeters, and ingress rules with Access Levels. Mastering the rule semantics, the perimeter bridge model, and the troubleshooting log fields is the difference between two and four correct answers on perimeter questions.
VPC SC is enforced at the Google API front door, not inside your VPC. Even a request from a global external IP can be allowed if the perimeter's ingress rules permit it via an Access Level, and a request from inside your VPC can be denied if the source project is outside the perimeter. Always reason about VPC SC at the API layer, not the network layer.
Service Perimeter Concept
What a perimeter actually contains
A service perimeter is created at the Organization scope via Access Context Manager. Each perimeter declares three lists: the resources it protects (project numbers, and increasingly VPC networks), the restricted services whose API surface is wrapped by the perimeter, and the VPC accessible services (the subset of restricted services that VMs inside the perimeter are allowed to call). A typical perimeter looks like accessPolicies/<policyId>/servicePerimeters/<name> and is referenced by gcloud as gcloud access-context-manager perimeters describe <name>.
Resources are projects, not networks
For most services, the unit of protection is a project number such as projects/1234567890. When a request hits storage.googleapis.com, VPC SC looks at the destination bucket's project and asks whether that project is inside a perimeter. If yes, the request must originate from inside the same perimeter or be allowed by an ingress rule. Adding a project to a perimeter does not require any code change in your application—the enforcement is transparent at the API layer.
Restricted services list
Not all Google APIs are VPC SC aware. The restricted services field enumerates exactly which APIs are blocked at the perimeter, for example storage.googleapis.com, bigquery.googleapis.com, pubsub.googleapis.com, cloudkms.googleapis.com, aiplatform.googleapis.com. The full supported list is published at cloud.google.com and is the only place you should trust—services move between "supported," "beta," and "GA" frequently. Services that are not supported (some Marketplace APIs, certain admin APIs) cannot be protected by VPC SC and need other controls such as Organization Policy.
A service perimeter is an Organization-scoped logical boundary that wraps a list of project numbers and a list of restricted service APIs, denying any cross-boundary call unless an ingress or egress rule, perimeter bridge, or Access Level explicitly permits it.
Ingress Rules
Anatomy of an ingress rule
An ingress rule lets a caller outside the perimeter reach resources inside the perimeter. Every ingress rule has two halves. The ingressFrom block declares the source: identities (a list of user:, serviceAccount:, or group: principals), identityType (one of ANY_IDENTITY, ANY_USER_ACCOUNT, ANY_SERVICE_ACCOUNT), and sources which is either an accessLevel reference such as accessPolicies/123/accessLevels/corp_ip or a resource such as projects/9876543210. The ingressTo block declares the destination: operations (a per-service list of method selectors like storage.googleapis.com with methodSelectors filtering to google.storage.objects.get) and resources (which specific projects inside the perimeter are reachable, or * for all).
A concrete example
A common pattern is "allow our CI/CD service account from our corporate IP range to read from a build artifact bucket." That becomes one ingress rule with ingressFrom.identities = ["serviceAccount:[email protected]"], ingressFrom.sources.accessLevel = corp_ip, ingressTo.operations listing storage.googleapis.com / google.storage.objects.get and google.storage.objects.list, and ingressTo.resources = ["projects/1234567890"]. Without the access level the rule denies; without the operation selector the rule denies; the combination of both is what permits the call.
Why ingress rules replaced "access levels on a perimeter"
Older VPC SC perimeters supported only a flat accessLevels list which applied to the entire perimeter. Modern perimeters use fine-grained ingress rules that scope by identity, source, target operation, and target resource—giving you per-API and per-project precision. Always model new perimeters with ingress rules rather than the legacy global access level list, and never assume that a single Access Level grants access to all services inside a perimeter.
When you draft ingress rules, write them in plain English first—"who, from where, to do what, on which resource"—and then map each clause to identities, sources, operations, and resources. Most denied requests trace back to a missing clause in one of those four fields.
Egress Rules
Going the other direction
Egress rules let a caller inside the perimeter reach resources outside the perimeter. The structure mirrors ingress: egressFrom lists the calling identities and identity types, while egressTo lists externalResources, operations, or resources outside the perimeter. A typical use case is a Dataflow worker running inside a protected analytics project that needs to read a publicly shared dataset in another organization's BigQuery project.
External resources and Service Directory
The egressTo.externalResources field is the only way to express "this on-premises endpoint reached via Private Service Connect" or "this third-party endpoint registered in Service Directory." For Service Directory–backed PSC endpoints, you list the endpoint as //servicedirectory.googleapis.com/projects/.../endpoints/... in the egress rule, which is required when traffic egresses from a VPC inside the perimeter to a private endpoint hosted outside the perimeter. Without this, calls to your own PSC endpoint can be denied with a NO_MATCHING_ACCESS_LEVEL violation.
Egress + restricted VIP combine to lock outbound
Egress rules block exfiltration paths such as a compromised VM in your perimeter uploading data to an attacker-owned Cloud Storage bucket in a different organization. Combined with the restricted VIP (covered below) and a Cloud DNS response policy that resolves *.googleapis.com to the restricted VIP, the only way a VM inside the perimeter can reach Google APIs is via the restricted path, where the perimeter is enforced. There is no "back door" through the public VIP.
Egress rules are not symmetric with ingress rules and they do not automatically create the reverse path. If project A inside perimeter P needs to call BigQuery in project B inside perimeter Q, you need an egress rule from P and an ingress rule on Q. Both sides must agree, or use a perimeter bridge.
Perimeter Bridges
Bidirectional and symmetric by design
A perimeter bridge is a special perimeter type that contains two or more existing perimeters and lets resources in those member perimeters call each other freely for the restricted services. Bridges are bidirectional (traffic flows both ways) and symmetric (all members of the bridge can talk to all other members—you cannot make A talk to B but block B from talking to A using a bridge alone). If you need asymmetric flow, use ingress/egress rules instead.
The 10-perimeter cap
A single project can be a member of at most 10 perimeter bridges. This is a hard quota and often catches teams that scale by adding "one bridge per cross-team integration." The exam likes to test this number, and it likes to combine it with "you have 12 teams, each needs to share data with each other—what do you do." The answer is usually "consolidate into a regular perimeter with ingress/egress rules" rather than "create N bridges."
When to bridge vs when to use ingress/egress
Bridges are best when two perimeters need broad, symmetric collaboration—for example, a "data engineering" perimeter and a "data analytics" perimeter where most projects on each side need to call BigQuery and Cloud Storage on the other side. Ingress/egress rules are better when only specific identities or specific operations need to cross—for example, a single CI service account that needs to write build artifacts. Bridges trade granularity for simplicity; rules trade simplicity for granularity.
A perimeter bridge does not extend the protected resource set of its members. It only allows cross-perimeter communication. Putting projects A and B into a bridge does not protect them—each must still be a resource of a regular perimeter. Bridge-only "protection" is a common misconfiguration that leaves projects exposed.
Dry-Run Mode
Spec vs status
Every service perimeter has two states: the enforced configuration (called status in the API) and the dry-run configuration (called spec). You declare both in the same perimeter resource. The enforced status actually denies traffic; the dry-run spec only logs what would have been denied without actually blocking the call. This dual state is what lets you safely roll out perimeter changes in production.
The dry-run rollout playbook
The recommended sequence is: (1) create the perimeter with only a spec block and useExplicitDryRunSpec=true; (2) leave it in dry-run for at least one full business cycle, often 1–2 weeks; (3) collect all vpcServiceControlsUniqueId log entries with metadata.dryRun=true and convert each unique denied call into an explicit ingress or egress rule; (4) once the dry-run log is clean, promote spec to status with gcloud access-context-manager perimeters dry-run enforce. Skipping dry-run is one of the top reasons production outages are blamed on VPC SC.
Enforce vs replace
dry-run enforce copies the spec into status, while dry-run drop discards the spec. You can also dry-run update to iterate on the spec without touching the enforced state. The exam loves the distinction between "I want to test a new perimeter rule without breaking prod" (use spec) and "I want to roll back to my previous configuration" (use dry-run drop if you have not yet enforced, or update status directly if you have).
Dry-run mode = spec block + useExplicitDryRunSpec=true. Enforced mode = status block. Logs from dry-run have metadata.dryRun=true. Promote with gcloud access-context-manager perimeters dry-run enforce. Use a 1–2 week soak before enforcing in production.
Restricted VIP
The 199.36.153.4/30 range
The restricted virtual IP is a Google-managed address range, 199.36.153.4/30, that exposes only VPC SC–aware (restricted) services. The companion private VIP is 199.36.153.8/30 and exposes all Google APIs without VPC SC enforcement; the restricted VIP is the one you want for any traffic that should be subject to perimeter rules. Both ranges are reachable from inside Google's network and from on-premises networks via Cloud Interconnect or Cloud VPN when Private Google Access for on-premises is configured.
Cloud DNS configuration
To force traffic to the restricted VIP, create a Cloud DNS private zone for googleapis.com containing a CNAME *.googleapis.com → restricted.googleapis.com. and an A record for restricted.googleapis.com. → the four addresses 199.36.153.4, 199.36.153.5, 199.36.153.6, 199.36.153.7. The same pattern can be set up as a Cloud DNS response policy for VPCs that need to override the default public resolution. For on-premises, configure your on-prem DNS to forward googleapis.com queries to Cloud DNS via an inbound forwarder.
Why this matters for VPC SC
If a VM inside a protected project resolves storage.googleapis.com to the public VIP, the call still goes to a VPC SC–protected backend, but the network path is via the internet which may break your egress firewall posture. By forcing the restricted VIP, you keep all Google API traffic on Google's backbone, ensure VPC SC enforcement is consistent, and can implement a default-deny egress firewall to 0.0.0.0/0 while still allowing API access. The combination "restricted VIP + perimeter + default-deny egress" is the canonical secure data analytics pattern.
The restricted VIP is the GCP-side requirement for Private Google Access for on-premises with VPC SC. Without it, on-prem traffic to Google APIs goes to public endpoints that may or may not be reachable from your on-prem network, and the perimeter rules can produce confusing "Policy Denied" logs.
Access Levels and Access Context Manager
What an Access Level represents
An Access Level, defined in Access Context Manager (ACM), is a named reusable condition that evaluates request attributes such as source IP CIDR, principal identity, device policy (verified by Endpoint Verification), required signal types, region, and time of day. A BasicLevel is an AND/OR combination of attribute conditions; a CustomLevel is a CEL expression that has access to fields such as origin.ip, origin.region_code, device.is_corp_owned, and levels.
Wiring Access Levels into ingress rules
Inside an ingress rule, ingressFrom.sources.accessLevel = accessPolicies/<id>/accessLevels/<name> references an Access Level. The ingress rule then evaluates as "request matches if the calling identity is in identities and the request attributes satisfy the Access Level and the destination matches operations and resources." Access Levels can also be referenced from IAM Conditions for context-aware access on individual resources, but inside VPC SC they only matter when referenced from ingress rules.
Common Access Level patterns
Three patterns appear repeatedly: (1) corporate IP access levels that list your office and VPN CIDRs to allow administrative access from known networks; (2) device-trust access levels that require device.is_corp_owned=true and device.encryption_status=ENCRYPTED for laptops that pass Endpoint Verification; (3) region access levels that allow requests only from approved countries to satisfy data residency policies. Combining all three in one CustomLevel CEL expression is common for sensitive datasets.
Troubleshooting Policy Denied Logs
Where the logs live
VPC SC denials are written to Cloud Logging as policy_denied audit log entries. The relevant filter is protoPayload.@type="type.googleapis.com/google.cloud.audit.AuditLog" AND protoPayload.metadata.@type="type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata". Each entry carries a vpcServiceControlsUniqueId field which is the single most useful identifier in the system—you give that ID to Google Cloud Support and they can trace the denial across services without you sharing project numbers or IAM details.
Reading the violationReason
The audit metadata's violationReason enumerates the cause. Common values: NO_MATCHING_ACCESS_LEVEL (the caller did not match any ingress rule's Access Level), RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER (cross-perimeter call without an egress/ingress pair or bridge), NETWORK_NOT_IN_SAME_SERVICE_PERIMETER (a VPC outside the perimeter is being used), SERVICE_NOT_ALLOWED_FROM_VPC (the called service is not in VPC accessible services), and METHOD_NOT_ALLOWED_FROM_OUTSIDE (the ingress rule allows the service but not the specific method). Knowing these strings is exam-testable because the question often quotes a log line.
The dry-run debugging loop
In dry-run mode the same fields appear but metadata.dryRun=true and the call is not actually blocked. The standard workflow is: filter logs by metadata.dryRun=true AND severity=WARNING, group by (servicePerimeterName, violationReason, principalEmail, resource), and for each cluster decide whether to add an ingress rule, an egress rule, or fix the caller. The Troubleshooter tool in Cloud Console (Security → VPC Service Controls → Troubleshooter) takes a vpcServiceControlsUniqueId and pretty-prints the same data with suggested remediations.
vpcServiceControlsUniqueId is the single thread that connects a user-facing API error, the Cloud Logging entry, the Troubleshooter UI, and a Google Support case. Always have users capture and report this ID when a request is denied unexpectedly.
VPC Accessible Services
Restricting which services VMs can call
Inside a perimeter, a VM's IAM grant alone does not determine which Google APIs it can reach. The perimeter's vpcAccessibleServices block can restrict the subset of restricted services that VPC traffic (from inside the perimeter) is allowed to call. Setting enableRestriction=true with allowedServices=["storage.googleapis.com","bigquery.googleapis.com"] means a VM inside the perimeter cannot call pubsub.googleapis.com even if it has Pub/Sub IAM access, because the API call from that VPC is dropped by VPC SC.
Defense in depth
vpcAccessibleServices is the inverse of ingress rules. Ingress restricts what comes in; VPC accessible services restricts what goes out from VPC sources. Combined they give you a "you cannot reach what you do not need" posture: external attackers cannot reach a service through a stolen credential, and a compromised internal VM cannot pivot to a service that was never in scope for that workload. This is what makes VPC SC genuinely a defense-in-depth control rather than just an access list.
Common Architectures with VPC SC
Analytics perimeter with on-prem ingestion
A typical analytics deployment uses one perimeter wrapping the BigQuery project, the Cloud Storage staging project, and the Dataflow runner project. On-premises ingestion uses Private Google Access for on-prem + restricted VIP. An ingress rule allows the on-prem ETL service account from a corporate IP Access Level to write into the staging bucket and to run Dataflow jobs. An egress rule allows the Dataflow worker service account to read from an approved external pretrained model bucket.
Hub-and-spoke with shared services
When a hub VPC offers shared services (DNS, security scanning, logging) and spoke VPCs run business workloads, each spoke project lives in its own perimeter or shares a regular perimeter. Cross-perimeter calls to the hub (for example, calling a Cloud Function that scans uploaded files) use a perimeter bridge between hub and each spoke, or individual ingress rules on the hub perimeter referencing the spoke project numbers.
白話文解釋(Plain English Explanation)
Analogy 1: The Sealed Datacenter
Imagine your company runs a top-secret research datacenter. IAM is the ID badge that opens the door. But once you are inside, an employee could still smuggle a hard drive out in their pocket. VPC Service Controls is the metal detector and X-ray scanner at every exit: even an employee with a valid badge cannot carry a file out unless an explicit "permitted to remove" form (an egress rule) has been signed for that exact file and that exact destination. The metal detector does not care about the badge—it cares about what is leaving the building.
Analogy 2: The Embassy Visa System
Each service perimeter is a country with sealed borders. A regular perimeter is the home country. Ingress rules are visas: who from outside (which identities, from which IP) is allowed to enter, for which purpose (operations), and which cities they can visit (resources). Egress rules are export permits: who inside is allowed to go abroad, to which destinations, with which goods. A perimeter bridge is a Schengen-style open border between two specific countries. The restricted VIP is the only official airport—all international travel must go through it so that the visa stamps actually happen.
Analogy 3: The Bank Vault with Dual Control
The status state is the live vault: a wrong move actually locks customers out. The spec state (dry-run) is the architectural blueprint pinned to the wall: it shows what the new vault rules would do, and the security guard records every "would have been denied" event in a notebook (vpcServiceControlsUniqueId), but the actual vault still uses the old rules. Only when the blueprint has been reviewed for a week and every denied event is either expected or explained does the bank physically rebuild the vault to match the blueprint (dry-run enforce).
Exam Tips and Traps
- Trap: Thinking IAM is enough. IAM stops unauthorized access; VPC SC stops authorized users from exfiltrating data through Google APIs.
- Trap: Assuming a perimeter bridge protects projects. Bridges only allow cross-perimeter calls; protection still comes from a regular perimeter.
- Tip: When the question mentions "preventing data exfiltration," "restricting which networks can call BigQuery," or "on-premises access to Cloud Storage with Private Google Access," VPC SC is almost always the answer.
- Tip: When a question quotes a log line with
violationReason: NO_MATCHING_ACCESS_LEVEL, the fix is to add or update an Access Level referenced by an ingress rule—not to change IAM. - Memorize: Restricted VIP
199.36.153.4/30. Private VIP199.36.153.8/30. Bridge cap of 10 per project. Dry-run =spec. Enforced =status.
FAQ
Q1 — Can I put projects from different organizations into the same perimeter?
No. A service perimeter is scoped to a single Organization and references projects by their project number within that Organization. Cross-organization data sharing must use ingress rules on each side or use shared external paths such as Analytics Hub.
Q2 — Does VPC SC cost extra?
There is no per-API surcharge. The operational cost comes from designing perimeters, writing ingress/egress rules, running a meaningful dry-run period, and configuring Cloud DNS and the restricted VIP across hybrid networks.
Q3 — How long should I keep a perimeter in dry-run mode before enforcing?
At least one full business cycle, typically 1–2 weeks. The goal is to catch monthly batch jobs, weekend backups, and any rare admin tooling. Promote with gcloud access-context-manager perimeters dry-run enforce only after the dry-run log is clean.
Q4 — Can VPC SC protect Cloud Run, Cloud Functions, or App Engine?
Cloud Run, Cloud Functions 2nd gen, and several serverless services are supported as restricted services. Check the official supported services list at cloud.google.com because new services are added frequently and beta-status entries should not be relied on for production.
Q5 — What happens if I add a project to a perimeter while a workload is running?
New API calls are immediately evaluated against the perimeter, so any in-flight or new request that does not satisfy ingress/egress rules will be denied with policy_denied. Always change perimeter membership during a maintenance window or after a dry-run validation.
Q6 — How is VPC SC different from Organization Policy constraints like storage.publicAccessPrevention?
Organization Policy constrains how a resource is configured (e.g., a bucket cannot be made public). VPC SC constrains how the API can be called (e.g., even a private bucket cannot be read by a caller outside the perimeter). The two are complementary and most secure deployments use both.
Q7 — Can I use VPC SC to restrict access by country?
Yes, indirectly. Create an Access Level in Access Context Manager with a regions condition listing approved country codes, then reference that Access Level from an ingress rule's sources.accessLevel. The region is derived from the caller's source IP geolocation.