# GCP VPC Service Controls: — Why a Leaked Key Still Cannot Steal Your Data

Source: https://ai.techclick.in/blog_gcp_vpc_service_controls
Markdown: https://ai.techclick.in/blog_gcp_vpc_service_controls.md
Publisher: Techclick Infosec Pvt Ltd

GCP VPC Service Controls for L1/L2 engineers and the Professional Cloud Security Engineer exam: how a service perimeter stops data exfiltration even with a valid key, ingress/egress rules, access levels, dry-run mode and reading violation logs.

GCP VPC Service Controls: — Why a Leaked Key Still Cannot Steal Your Data student learning map
                     A visual study map for GCP VPC Service Controls: — Why a Leaked Key Still Cannot Steal Your Data showing learning path, evidence, traps, and practice sequence.

                     TECHCLICK STUDY MAP
                     GCP VPC Service Controls: — Why a Leaked Key Still...
                     GCP · learn the flow, prove with evidence, avoid unsafe shortcuts

   1. Start
   🎯 By the end you will be able to

   2. Understand
   Pick where you want to start

   3. Prove
   ① The exfiltration gap IAM cannot...

   4. Practice
   ② How a perimeter works — ingress,...

                     How to use this page
                     First build the mental model, then connect the concept to a realistic production decision. Finish by testing yourself.
                     Techclick Infosec Pvt Ltd | ai.techclick.in | Training Contact: WhatsApp +91 92772 29456

             Content-specific feature visual for this lesson: use it as the 60-second map before reading the full detail.

             Most engineers think…

             Most engineers think Google Cloud IAM is the whole story for data security — "if I lock down the roles tightly, nobody can take my data." So they treat a leaked key as just a permissions problem.

             Wrong — and it's the gap that causes real breaches. IAM answers  WHO can call an API , but a  valid  credential used by the wrong person from the wrong place still passes that check.  VPC Service Controls  answers a different question —  WHERE the data may go  — by drawing a  service perimeter  around managed services like BigQuery and Cloud Storage. Inside the wall data moves freely; crossing the wall is denied by default, regardless of IAM. So a leaked key that  could  read the dataset still  cannot  copy it out. IAM and VPC-SC are two different walls, and you need both.

## ① The exfiltration gap IAM cannot close

 Picture Sneha, an L2 cloud-security engineer at  Flipkart . A data analyst on her team has  roles/bigquery.dataViewer  on a dataset called  customer_pii . The analyst downloads a  service-account key  to test a script, and the key file ends up committed to a public GitHub repo. Within hours a scanner bot has it. The attacker now holds a credential that, as far as  IAM  is concerned, is allowed to read that dataset.

 Here is the uncomfortable part. IAM's job is to answer one question:  can this principal perform this action on this resource?  The stolen key  is  that principal, and the principal  does  have  bigquery.dataViewer . So when the attacker runs  bq query  and then exports the results to a BigQuery dataset in their own personal project, IAM raises no objection — the role check passes. The data walks out the front door with a valid badge. IAM never asked the one question that matters here:  should this data be allowed to leave the company at all?

 This is the  data exfiltration  gap, and it is not theoretical. Google's own product page is blunt that VPC Service Controls exists to  minimise data exfiltration risks from services like Cloud Storage and BigQuery  — precisely because tight IAM alone does not stop a valid credential from copying data outward. The same gap opens whether the threat is an external attacker with a stolen key or a careless insider with legitimate access who simply copies a dataset to the wrong place.

 👉 So far: IAM checks WHO, not WHERE — so a valid (or stolen) credential can still exfiltrate data. Next: the second wall that closes the gap.

 The fix is a second, independent wall.  VPC Service Controls  (VPC-SC) lets you draw a  service perimeter  around a set of projects and the  restricted services  they use. Inside the perimeter, data flows freely. Crossing the perimeter — reading data out to a project that isn't inside, or copying a dataset to one — is  denied by default , and crucially this happens  independently of IAM . The leaked key still has the role; the perimeter still says no.

  Figure 1 — Two walls — IAM and the perimeter

 A two-layer security picture for Google Cloud. The first gate is Identity and Access Management, which checks whether the caller has permission. The second layer is a VPC Service Controls service perimeter, a wall drawn around a set of projects and their managed services such as BigQuery and Cloud Storage. Inside the wall the prod data project holds a BigQuery dataset and a Cloud Storage bucket. A leaked service-account key passes the IAM check from the attacker's laptop on the public internet, but the perimeter blocks the call because the request crosses the boundary. Red marks the untrusted attacker, blue marks the trusted inspected interior, amber marks the perimeter policy decision, green marks the allowed in-perimeter path.

 Two walls: IAM checks WHO — the perimeter checks WHERE the data may go
  Attacker laptop  public internet 203.0.113.45  holds a leaked SA key (.json)  IAM says: roles/bigquery.dataViewer ✓
  Gate 1 — IAM  WHO can call this API?
  Service perimeter — accProd (the wall)
  project prod-data-9f2a
  BigQuery dataset  customer_pii
  Cloud Storage bucket  gs://gcp-acc-statements
  Restricted services  bigquery.googleapis.com  storage.googleapis.com  data may move freely INSIDE,  never crosses OUT by default

- valid key → call ✕ DENIED Key insight: IAM said yes, the perimeter said no — the data never left untrusted / attacker trusted / inside policy / decision key insight allowed Look at the two gates: IAM (amber, top) passes the leaked key because the role is valid. The perimeter wall (amber dashes around the prod project) is the second check — and it denies the cross-boundary call, so the data never leaves. Daily-life analogy — the bank locker room vs the locker key Your locker key is IAM — it proves you may open locker number 42. But the locker room of a bank has a second rule that has nothing to do with your key: no locker leaves the building . Even a thief who steals your key can open the locker, but he cannot carry the locker out the front door — the room itself won't allow it. VPC Service Controls is that room. IAM decides who can open the box; the perimeter decides that the box's contents can't be walked out of the building. ### The gap, in one tap each Tap each card — this is the exact reasoning an interviewer wants when they ask "why isn't IAM enough?" 🔑 IAM = WHO tap to flip IAM checks if a principal has the role. A stolen key is still that principal with that role. So: the role check passes. 📤 Export is allowed tap to flip With dataViewer you can query AND export results to another project. So: the data can leave with a valid badge. 🌍 From anywhere tap to flip A leaked key works from any IP on the planet — laptop, VPS, attacker box. So: location is invisible to IAM. 🧱 VPC-SC = WHERE tap to flip The perimeter asks if data may cross the boundary, not who you are. So: the export is blocked regardless of IAM. Quick check · Q1 of 10 Rahul at TCS argues: "We give every analyst exactly the minimum IAM role, so we can't be breached by a leaked key." Where does that reasoning fail? a) A minimum role like bigquery.dataViewer still permits reading and exporting the data out to another project, which IAM allows from anywhere b) Minimum roles are impossible to configure in GCP c) IAM automatically blocks all exports between projects d) Leaked keys stop working after 24 hours by default Correct: a. Even the minimum read role lets the principal query and export data; IAM checks the role, not the destination or the caller's location, so a leaked key exfiltrates fine. IAM does NOT auto-block cross-project exports (that's exactly the gap), minimum roles are very configurable, and SA keys are long-lived — they don't expire in 24 hours. You need a perimeter. Pause & Predict Predict: if VPC-SC blocks data from crossing the perimeter "regardless of IAM", does that mean you can now be sloppy with IAM roles? Type your guess. Reveal answer Answer: No — they guard different things and you need both. VPC-SC stops data leaving the perimeter, but inside the perimeter IAM still decides who can touch what. A perimeter won't stop an over-privileged insider from reading or deleting data they shouldn't have access to in the first place — it only stops that data being moved outside. Tight IAM (least privilege) + a perimeter (anti-exfiltration) are complementary layers, not substitutes. ## ② How a perimeter works — ingress, egress & access levels A service perimeter is just two lists plus a default rule. The first list is the projects (and optionally VPC networks) that sit inside the wall. The second is the restricted services — the Google-managed APIs you're protecting, named by their API hostname like bigquery.googleapis.com or storage.googleapis.com . The default rule is the whole point: requests that cross the boundary are denied , while requests that stay inside flow freely. Everything else in VPC-SC is about carving precise exceptions to that default deny. Two words name the two directions of crossing. Ingress is a call coming in from outside the perimeter to a protected resource (an on-prem CI runner calling your bucket). Egress is the reverse — something inside reaching out to a project outside the perimeter (copying a dataset to a personal project). Both are blocked by default. To allow a specific, legitimate crossing you write an ingress rule or an egress rule that names exactly which identity may do which operation on which resource . On top of ingress sits the context-aware layer: access levels . An access level is a named condition built in Access Context Manager — for example "the request must come from the corporate IP range 203.0.113.0/24 , from a managed device, in India." You then attach that access level to an ingress rule, so even a valid identity is only let in when the context matches . IP range, geolocation, device posture and identity all become conditions on the wall. 👉 So far: a perimeter = inside-projects + restricted-services + default-deny; ingress/egress rules and access levels are the controlled exceptions. Next: watch one blocked request get evaluated. Figure 2 — How a boundary-crossing request is decided The decision flow for one API request reaching a restricted service inside a VPC Service Controls perimeter. First the request must pass IAM. Then the perimeter checks: is the caller already inside the same perimeter? If yes, allow. If the call is coming in from outside, it is ingress and must match an ingress rule or a granted access level such as a corporate IP range or trusted identity. If a resource inside the perimeter is reaching out to a project outside, it is egress and must match an egress rule. If nothing matches, the request is denied with the error Request is prohibited by organization's policy and a violation is logged. Amber marks the policy checks, green marks allow, red marks the default deny. Crossing the boundary: deny by default, allow only on a matching rule API request arrives to bigquery.googleapis.com 1 · IAM check caller has the role? → continue 2 · Same perimeter as the resource? caller project + resource project both inside yes → ALLOW (free comms inside) 3a · Ingress (from OUTSIDE → in) matches an ingress rule OR an access level? (corp IP 203.0.113.0/24, trusted identity, device) 3b · Egress (inside → OUTSIDE project) matches an egress rule? (egressFrom identity → egressTo resource/op) match → ALLOW the call the only ways across the wall no match → DENY (default) "Request is prohibited by organization's policy" + violation logged Trace the request: pass IAM (1), then the perimeter asks 'same perimeter?' (2). If not, it's ingress (3a) or egress (3b) and needs a matching rule/access level — otherwise it hits the red default deny at the bottom. ### ▶ Watch a leaked-key export hit the wall The attacker holds the leaked key and runs a BigQuery copy of customer_pii to their personal project. Follow the request as the perimeter evaluates it. Press Play for the healthy path, then Break it to see the failure. ① IAM check leaked-sa@prod calls bq copy → IAM sees role bigquery.dataViewer → passes ▼ ② Perimeter check is dst attacker-side-proj inside perimeter accProd ? → NO ▼ ③ Egress eval inside → outside = egress ; any egress rule allows this identity → resource? → none ▼ ④ Deny + log request denied; violation RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER written to audit log Press Play to step through the healthy path. Then press Break it . ▶ Play Next ▶ ⚠ Break it ↺ Reset gcloud — define an access level (corporate IP) in Access Context Manager # conditions.yaml - ipSubnetworks: - 203.0.113.0/24 gcloud access-context-manager levels create corp_in \ --title="Corp India network" \ --basic-level-spec=conditions.yaml \ --policy=accessPolicies/418972419283 Expected output Create request issued for: [corp_in] Waiting for operation [...] to complete...done. Created level [accessPolicies/418972419283/accessLevels/corp_in]. Common mistake — "I added the IAM binding but the on-prem job still gets denied" Symptom: a CI runner at Infosys has the right IAM role on the bucket, but every call returns Request is prohibited by organization's policy . Cause: the runner is outside the perimeter, so this is an ingress crossing — and IAM permissions alone don't satisfy a perimeter. Fix: add an ingress rule (or an access level for the runner's IP) that permits that identity to call the restricted service from outside. The perimeter is a separate gate; granting the role doesn't open it. Quick check · Q2 of 10 Aditya at Wipro sees a Cloud Function INSIDE the perimeter failing to write to a Pub/Sub topic in a DIFFERENT project that is OUTSIDE the perimeter. What kind of crossing is this, and what fixes it cleanly? a) Ingress — add an access level for the function b) Neither — it's purely an IAM problem, add a role c) Egress — add an egress rule allowing that identity to reach the outside resource/operation d) It cannot be fixed; cross-project calls are always blocked Correct: c. A resource inside the perimeter reaching out to a project outside it is egress, so the clean fix is an egress rule (egressFrom identity → egressTo the resource and operation). It isn't ingress (that's outside→in), it isn't only IAM (the perimeter is a separate gate), and cross-perimeter calls are absolutely allowable — that's what egress rules are for. Pause & Predict Predict: you attach an access level requiring 'corporate IP 203.0.113.0/24' to your ingress rule. An admin connects from a café on public Wi-Fi with a perfectly valid identity and full IAM rights. What happens? Type your guess. Reveal answer Answer: They're denied — and that's the feature working. The access level is a condition layered on top of identity: even a fully-authorised admin is only let in when the context matches (here, the corporate IP). From café Wi-Fi the source IP doesn't match 203.0.113.0/24, so the ingress check fails and the request is blocked. This is exactly how VPC-SC neutralises a stolen credential used from an unexpected place. ## ③ Building it safely — dry-run first, then rules & private connectivity Here is the rule that separates a calm rollout from a Sev-1 outage: never enforce a perimeter first. A new perimeter denies by default, so flipping straight to enforced mode will silently break every legitimate workflow you forgot about — backups, CI/CD, analytics jobs, partner integrations. Instead you start in dry-run mode , which logs exactly what would be denied while letting everything through. The official ladder is four rungs. (1) Create the perimeter in dry-run with your restricted services but no ingress/egress rules. (2) Let traffic run for a couple of weeks and collect the violation logs — each one is a real workflow that crosses the boundary. (3) For every legitimate violation, add a precise ingress or egress rule (or an access level) until the dry-run logs go quiet. (4) Only when you see zero unexpected violations do you enforce . Google's guidance is to plan on roughly 2–4 weeks of dry-run analysis before flipping the switch. Google Cloud Console → Security → VPC Service Controls → New perimeter . Note the Enforcement mode toggle — leave it on Dry run for the first few weeks. (Recreated for clarity — your console matches this.)"> 🖥️ This is the screen you'll use — Google Cloud Console → Security → VPC Service Controls → New perimeter . Note the Enforcement mode toggle — leave it on Dry run for the first few weeks. (Recreated for clarity — your console matches this.) console.cloud.google.com · Security · VPC Service Controls 1 Title accProd-data-perimeter 2 Perimeter type Regular 3 Enforcement mode Dry run ◉ · Enforced ○ Projects (to protect) prod-data-9f2a, analytics-3c11 4 Restricted services bigquery.googleapis.com, storage.googleapis.com Access levels corp_in (203.0.113.0/24) Ingress / Egress rules Add an ingress rule · Add an egress rule Create perimeter gcloud — create the perimeter in DRY-RUN mode (no rules yet, just watch) gcloud access-context-manager perimeters dry-run create accProd \ --perimeter-title="accProd-data-perimeter" \ --perimeter-type=regular \ --perimeter-resources=projects/839271046512,projects/771203998145 \ --perimeter-restricted-services=bigquery.googleapis.com,storage.googleapis.com \ --policy=418972419283 Expected output Create dry-run spec request issued for: [accProd] Waiting for operation [accessPolicies/418972419283/...] to complete...done. Created dry-run spec for Service Perimeter [accProd]. 👉 So far: dry-run → collect violations → add rules → enforce, over 2–4 weeks. Next: the plumbing that keeps the traffic inside Google's network in the first place. A perimeter is only as good as the path traffic takes. If a VM inside the perimeter reaches BigQuery over a normal public Google API endpoint, that traffic technically rides the internet — which weakens the boundary. The fix is Private Google Access pointed at the restricted VIP . You route *.googleapis.com to restricted.googleapis.com , which resolves to 199.36.153.4/30 — a range that is not announced to the internet — so calls to your restricted services stay on Google's internal network and honour the perimeter. Figure 3 — VPC-SC on one card — the cheat-sheet A nine-tile cheat sheet. Tiles cover the perimeter definition, the two crossing types ingress and egress, access levels, the restricted VIP and private connectivity, the dry-run rollout ladder, perimeter bridges versus rules, the top violation reason codes, the audit-log filter, and the first gcloud commands. Each tile has a one-line role. VPC Service Controls — your one-glance card Service perimeter wall around projects + restricted services (BigQuery, GCS, Pub/Sub…) free comms inside, deny across independent of IAM Ingress vs egress ingress = outside → in egress = inside → outside project both denied unless a rule allows from {identity} → to {resource/op} Access levels context conditions in Access Context Manager IP range · region · device · identity layer onto ingress rules Restricted VIP restricted.googleapis.com → 199.36.153.4/30 Private Google Access keeps traffic off the public internet Dry-run ladder 1 · dry-run, no rules → watch logs 2 · add ingress/egress for breaks 3 · 0 violations for 2–4 weeks 4 · enforce — never enforce-first Bridge vs rules bridge = 2 perimeters share projects bidirectionally Google prefers ingress/egress rules = finer-grained Top violation codes NO_MATCHING_ACCESS_LEVEL RESOURCES_NOT_IN_SAME_…PERIMETER NETWORK_NOT_IN_SAME_… SERVICE_NOT_ALLOWED_FROM_VPC Read the violations Logs Explorer, filter on: VpcServiceControlAuditMetadata match the unique id from the "prohibited by org policy" error First commands gcloud access-context-manager perimeters dry-run create perimeters dry-run enforce gcloud logging read … Your one-card map: the perimeter, ingress vs egress, access levels, the restricted VIP, the dry-run ladder, bridges vs rules, the top violation codes, the audit-log filter, and the first commands. Keep it open in your first weeks. One more building block for bigger orgs: the perimeter bridge . When two separate perimeters genuinely need to share data — say a central shared-data perimeter and a analytics perimeter — a bridge lets their projects talk both ways. Google's own guidance, though, is to prefer ingress/egress rules over bridges wherever you can, because rules are far more granular: a bridge opens broad bidirectional access, while a rule names one identity, one resource and one operation. Prove the perimeter actually protects before you trust it Don't assume — test it. From a VM or identity outside the perimeter, try a read or copy of a protected resource and confirm you get Request is prohibited by organization's policy . Then from inside the perimeter confirm the same call succeeds. If the outside call succeeds when it shouldn't, your perimeter is in dry-run (logging only) — check the Enforcement mode , because dry-run never actually denies. Quick check · Q3 of 10 Priya at PhonePe is asked to roll out VPC-SC across the prod org with zero downtime. Which rollout order is correct? a) Enforce immediately, then add ingress/egress rules as tickets come in b) Create the perimeter, enforce, then enable dry-run to double-check c) Skip dry-run; add every possible ingress/egress rule up front, then enforce blind d) Dry-run with no rules → read violation logs → add ingress/egress rules → enforce only when violations are clean Correct: d. Dry-run first surfaces every real breakage as a logged violation without denying anyone; you then write precise rules until the logs are clean, and only then enforce. Enforcing first causes the very outage you're trying to avoid; dry-run after enforce is backwards; and you can't guess every rule up front — the violation logs are how you discover what's actually needed. Pause & Predict Predict: a team enables a perimeter in dry-run, sees zero violations for two days, and enforces. The next morning the nightly Dataflow export to a partner bucket fails. Why did dry-run not warn them? Type your guess. Reveal answer Answer: Because dry-run only logs the workflows that actually RAN during the observation window — and a nightly job that runs once a day may not have executed (or its boundary-crossing path may not have triggered) in those two days. The lesson is to run dry-run long enough to capture every periodic workflow: nightly, weekly, month-end. Google suggests 2–4 weeks precisely so cron jobs, backups and month-end reports all get a chance to show up as violations before you enforce. ## ④ Operating VPC-SC — violation logs, breakages & a worked block Once the perimeter is live, most of your day-to-day is reading violations. When a request is blocked, the caller sees a short, deliberately vague error — Request is prohibited by organization's policy — plus a vpcServiceControlsUniqueIdentifier . That identifier is your key. You take it to Logs Explorer and find the matching audit entry, which carries the full story: the caller, the resource, the service, and the all-important violationReason . The violation reasons are a small, learnable set. NO_MATCHING_ACCESS_LEVEL means the caller's IP, device or identity matched no ingress rule or access level (a client from outside the perimeter). RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER means one request touched resources in two different perimeters (the classic cross-project copy/export). NETWORK_NOT_IN_SAME_SERVICE_PERIMETER means the calling VPC network isn't inside the perimeter, and SERVICE_NOT_ALLOWED_FROM_VPC means the VPC config disallowed that service. Learn these four and you can triage almost any VPC-SC denial. gcloud logging — pull the VPC-SC violations from the audit log gcloud logging read ' protoPayload.metadata."@type"="type.googleapis.com/google.cloud.audit.VpcServiceControlAuditMetadata" AND protoPayload.metadata.violationReason="RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER" ' --project=prod-data-9f2a --limit=3 --format="value(protoPayload.metadata.violationReason, protoPayload.requestMetadata.callerIp, resource.labels.service)" Expected output RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER 203.0.113.45 bigquery.googleapis.com RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER 203.0.113.45 bigquery.googleapis.com NETWORK_NOT_IN_SAME_SERVICE_PERIMETER 10.20.4.7 storage.googleapis.com Three breakages cause most of the tickets, and none of them are bugs — they're the perimeter doing its job. CI/CD pipelines (Terraform, Cloud Build) run from outside the perimeter, so they hit ingress denials until you add a rule for the build identity — engineers on the Google issue trackers routinely report Terraform plans dying with vpcServiceControlsUniqueIdentifier errors mid-deploy. Cross-project analytics that read a dataset in another perimeter throw RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER . And public datasets — a query joining bigquery-public-data — can break because that public project sits outside your perimeter, needing an egress rule. 👉 So far: read the violation, match the unique id, learn the four reason codes, expect the three classic breakages. Next: a full worked block of a BigQuery export, then the cheat-card recap. Karthik at ICICI faces this Karthik, an L2 analyst, gets paged: a data scientist's nightly job that copies the curated 'customer_360' BigQuery dataset to a sandbox project for ML training started failing at 2 a.m. with 'Request is prohibited by organization's policy'. Nothing in IAM changed. Likely cause The sandbox project is OUTSIDE the prod perimeter that was enforced yesterday. The copy is therefore an egress crossing (inside → outside), and there's no egress rule permitting the data scientist's service account to copy to that project — so the default deny blocks it. IAM is fine; the perimeter is new. Diagnosis Karthik takes the vpcServiceControlsUniqueIdentifier from the error, opens Logs Explorer, and filters on the VpcServiceControlAuditMetadata type. The entry shows violationReason RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER and the sandbox project as the destination — confirming it's an egress block, not an IAM issue. Cloud Console → Logging → Logs Explorer → filter protoPayload.metadata."@type"="...VpcServiceControlAuditMetadata" → read violationReason Fix Decide the policy: either bring the sandbox project INTO the perimeter (if it should be trusted), or add a tightly-scoped egress rule (egressFrom = that one service account; egressTo = the sandbox project, bigquery.googleapis.com, the copy operation). Karthik chose the egress rule so only that identity, that destination and that operation are allowed. Verify Re-run the nightly copy → it succeeds; re-pull the audit log → no new RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER violation for that identity, and an unrelated outside caller is still denied. egress-policy.yaml — the worked fix: allow ONE identity to copy to ONE outside project - egressFrom: identities: - serviceAccount:ml-trainer@prod-data-9f2a.iam.gserviceaccount.com egressTo: resources: - projects/552038174490 # the sandbox project operations: - serviceName: bigquery.googleapis.com methodSelectors: - method: "google.cloud.bigquery.v2.TableService.InsertTable" # apply it to the perimeter's dry-run config first, then enforce # gcloud access-context-manager perimeters dry-run update accProd \ # --set-egress-policies=egress-policy.yaml --policy=418972419283 Expected output Update dry-run spec request issued for: [accProd] Waiting for operation [accessPolicies/418972419283/...] to complete...done. Updated dry-run spec for Service Perimeter [accProd]. Common mistake — over-broad egress rule that quietly re-opens the hole Symptom: the ticket is fixed, but a reviewer flags that your egress rule used identityType: ANY_IDENTITY and resources: '*' to make the error go away fast. That re-opens the exact exfiltration path you built the perimeter to close — now any identity can egress to any project. Fix: scope egress (and ingress) rules to the single identity, the single destination resource, and the specific method. A perimeter with wildcard rules is a perimeter in name only. Quick check · Q4 of 10 An interviewer asks Meera: "A query joining your protected dataset with bigquery-public-data suddenly fails after you enforce a perimeter. Why, and what's the right fix?" a) The public dataset's project is outside the perimeter, so the join is an egress crossing — add a scoped egress rule (or access to that public project) b) Public datasets are always blocked by GCP and cannot be queried c) The query failed because IAM removed the dataViewer role automatically d) You must disable the perimeter entirely to use any public data Correct: a. bigquery-public-data lives in a Google-owned project outside your perimeter, so reaching it is egress and the default deny blocks it until you add a scoped egress rule. Public datasets aren't universally blocked, IAM roles aren't auto-removed by VPC-SC, and you never disable the whole perimeter for one query — you write a narrow exception. Figure 4 — Before/after — the leaked key meets the wall A before-and-after of the same attack. On the left, without VPC Service Controls, an attacker holding a leaked service-account key runs a bq copy of the customer_pii dataset to a personal Google Cloud project, and the data leaves successfully because IAM alone allows it. On the right, with the perimeter enforced, the identical bq copy is blocked because the destination project is outside the perimeter, returning an egress violation reason RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER, and the data stays inside. Red marks the leak, green marks the blocked-and-safe outcome. Same leaked key, same command — the perimeter is the difference BEFORE — no perimeter leaked SA key 203.0.113.45 prod customer_pii BigQuery dataset personal project attacker-side-proj bq cp prod:customer_pii \ attacker-side-proj:loot ✗ data exfiltrated — IAM allowed it AFTER — perimeter enforced leaked SA key 203.0.113.45 prod customer_pii inside accProd personal project OUTSIDE perimeter ✕ violationReason: RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER ✓ blocked at the boundary — data stays leak / blocked attempt policy decision safe / data retained Left (red): no perimeter, so the leaked key's bq copy to a personal project succeeds and PII leaks. Right (green): with the perimeter enforced, the identical copy is an egress violation and is blocked — the data stays. Step back to the picture you should be able to draw cold. IAM gates WHO can call an API; VPC-SC gates WHERE the data may go. The perimeter wraps your projects + restricted services with a default-deny; ingress/egress rules and access levels are the narrow, named exceptions; Private Google Access + the restricted VIP keep the traffic on Google's network; and the dry-run ladder (watch → add rules → enforce) is how you roll it out without an outage. Read the violationReason , scope every rule tightly, and you have anti-exfiltration that holds even when a credential leaks. Daily-life analogy — the society gate-pass register A housing-society gate has two checks. The guard's resident list is IAM — it confirms you live in flat B-402. But the gate-pass register for moving furniture out is VPC-SC — even a genuine resident can't carry a sofa out the gate without a signed move-out pass naming exactly what's leaving. The dry-run phase is the society first logging every item that goes out for a month (without stopping anyone) so they learn the normal pattern, then switching the rule on. IAM = do you belong here; VPC-SC = may this thing leave. Pairs with: Google Cloud IAM least privilege Next: Security Command Center — one view of every risk Pause & Predict Predict: for the Professional Cloud Security Engineer exam, in ONE sentence, what is VPC Service Controls' role — and what is it NOT? Type your guess. Reveal answer Answer: It IS a context-and-perimeter control that prevents data exfiltration from managed services even when IAM would allow the call — a default-deny anti-exfiltration boundary layered on top of IAM. It is NOT a replacement for IAM, NOT a port/protocol packet firewall, and NOT about encryption-at-rest (that's CMEK). The exam tests this IAM-gates-WHO vs VPC-SC-gates-WHERE distinction directly, usually via a leaked-key or cross-project-copy scenario. ### 🤖 Ask the AI Tutor Tap any question — instant, scoped to this lesson. No login, no waiting. If IAM is locked down tight, do I really still need VPC Service Controls? What exactly is the difference between an ingress rule and an egress rule? Why does everyone insist on dry-run mode first? What is the restricted VIP and why does it matter for a perimeter? A request got blocked — how do I actually debug it? How much of the Professional Cloud Security Engineer exam does this cover? Pre-curated from GCP docs + community Q&A, scoped to this lesson. For a live prod issue, paste your export into chat.techclick.in. ## 📝 Wrap-up assessment — six more You've answered 4 inline. Six left. 70% (7 of 10) marks the lesson complete on your profile. Tap Submit all answers at the end. Q5 · Remember What does a VPC Service Controls service perimeter do by default to a request that crosses its boundary? a) Allows it if the caller has any IAM role b) Routes it through Cloud NAT for inspection c) Denies it — cross-perimeter communication is blocked unless an ingress/egress rule or access level allows it d) Encrypts it with a customer-managed key Correct: c. A perimeter permits free communication inside but blocks boundary crossings by default; you open precise paths with ingress/egress rules or access levels. It is not satisfied by IAM alone, it is not a NAT/inspection device, and it is unrelated to at-rest encryption (CMEK). Q6 · Apply A service account inside your perimeter must write to a Pub/Sub topic in a partner project that is OUTSIDE the perimeter. What do you add to allow exactly this, and nothing more? a) An access level for the whole organization b) An egress rule: egressFrom that one identity, egressTo the partner project + the specific Pub/Sub operation c) A project-wide Owner IAM binding for the service account d) A perimeter bridge between every project in the org Correct: b. Inside→outside is egress, so a scoped egress rule naming the one identity, the one destination resource and the specific operation is the least-privilege fix. An org-wide access level or a bridge is far too broad, and Owner is an IAM change that still wouldn't satisfy the perimeter's egress gate. Q7 · Apply You're rolling out a new perimeter on a production org and must avoid breaking running jobs. What is the correct first step? a) Create the perimeter in dry-run mode with restricted services and watch the violation logs, before adding rules or enforcing b) Enforce it immediately and fix breakages from incoming tickets c) Delete all service-account keys first d) Enable enforced mode but disable audit logging to reduce noise Correct: a. Dry-run logs what would be denied without denying, so you discover breakages safely first, then add rules, then enforce. Enforcing first causes outages, deleting keys doesn't roll out a perimeter, and disabling audit logging would blind you to the very violations you need to read. Q8 · Analyze A nightly BigQuery copy from a protected dataset to a sandbox project failed at 2 a.m. with 'Request is prohibited by organization's policy', and nothing in IAM changed. The perimeter was enforced yesterday. Most likely root cause? a) The service account lost its dataViewer role overnight b) BigQuery had a regional outage c) The sandbox project is outside the perimeter, so the copy is an egress crossing with no matching egress rule — a RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER violation d) The restricted VIP changed its IP range Correct: c. The copy goes from inside the perimeter to a project outside it, which is egress; with no egress rule it's denied as RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER. IAM is unchanged (so no lost role), it's a policy denial not a regional outage, and the restricted VIP range is fixed at 199.36.153.4/30. The egress/perimeter cause is the only one that fits. Q9 · Analyze An on-prem CI runner with the correct IAM role on a protected bucket keeps getting denied by the perimeter. The audit log shows violationReason NO_MATCHING_ACCESS_LEVEL. What is happening and what's the fix? a) The runner is outside the perimeter (an ingress crossing) and matches no ingress rule/access level — add an ingress rule or an access level for its IP range b) The bucket is corrupted; recreate it c) IAM is misconfigured; grant Owner to the runner d) VPC-SC is incompatible with Cloud Storage; remove storage from restricted services Correct: a. NO_MATCHING_ACCESS_LEVEL means an outside caller (ingress) matched no ingress rule or access level — the IAM role alone doesn't satisfy the perimeter. The fix is an ingress rule/access level for the runner's identity or IP. The bucket isn't corrupt, Owner won't open the perimeter gate, and Cloud Storage is fully supported by VPC-SC. Q10 · Evaluate Two ways to summarise VPC-SC to a hiring manager: (A) "it's a firewall that blocks bad IPs from reaching GCP"; (B) "it's a perimeter around managed services that denies data crossing the boundary by default — regardless of IAM — so a leaked key can't exfiltrate data." Which is stronger and why? a) A — it's simpler and firewalls are what people know b) B — it names the real mechanism (a default-deny anti-exfiltration perimeter independent of IAM) instead of mislabelling it as an IP firewall c) A — VPC-SC really is just an IP allowlist d) Identical — both describe the same control Correct: b. B is accurate: VPC-SC is a service perimeter that gates WHERE data may go, independent of IAM, stopping exfiltration even by a valid credential. A is wrong — VPC-SC is not a packet/IP firewall (though access levels can use IP as one condition); calling it an IP allowlist misses the entire anti-exfiltration point the exam and the job test. Submit all answers Try again Lesson complete — saved to your profile. Almost! You need 70% (7 of 10) — re-read the path that tripped you up and tap "Try again". ### 🧠 In your own words Type one line: In one line, why can VPC Service Controls block a leaked service-account key that IAM happily lets through? Then compare to the expert version. Compare with expert answer Expert version: Because IAM only checks whether the principal has the role (WHO), while VPC-SC adds an independent perimeter that denies the data crossing the boundary by default (WHERE) — so the valid-but-stolen key passes IAM yet the export is blocked at the wall. ### 🗣 Teach a friend Best way to lock it in — explain it in one line to a teammate. Tap to generate a paste-ready summary. Generate my one-liner 📩 Quiz me on this in 7 days. Opt in and we'll email 3 micro-questions on VPC Service Controls at Day 1, Day 7 and Day 30 — spaced repetition is how this sticks. Un-tick any time. ### 📖 Glossary VPC Service Controls (VPC-SC) A GCP control that draws a perimeter around managed services so data cannot leave it, independent of IAM. Service perimeter A security boundary around a set of projects and restricted services; free comms inside, deny across by default. Restricted services The Google-managed APIs you protect inside a perimeter, named by hostname (e.g. bigquery.googleapis.com). Ingress An API call from OUTSIDE the perimeter to a resource INSIDE it; denied unless an ingress rule or access level allows it. Egress A client/resource INSIDE the perimeter reaching a resource OUTSIDE it; denied unless an egress rule allows it. Access level A named condition in Access Context Manager (IP range, region, device, identity) attached to ingress rules. Access Context Manager The GCP service that defines access levels and holds the access policy under which perimeters live. Dry-run mode A perimeter config that logs violations as if enforced but does not deny — used to find breakages before enforcing. Restricted VIP restricted.googleapis.com → 199.36.153.4/30, a not-internet-announced range for VPC-SC-aware API access. Private Google Access Lets VMs without external IPs reach Google APIs over Google's internal network, paired with the restricted VIP. Perimeter bridge Lets projects in two perimeters communicate bidirectionally; Google prefers granular ingress/egress rules instead. violationReason The audit-log field naming why a request was denied — e.g. RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER, NO_MATCHING_ACCESS_LEVEL. #### 📚 Sources Google Cloud — "Overview of VPC Service Controls" (service perimeter definition: a security boundary that blocks cross-perimeter communication by default; restricted services; access levels; perimeter bridge; data-exfiltration mitigation for Cloud Storage and BigQuery). cloud.google.com/vpc-service-controls/docs/overview

- Google Cloud — "Dry run mode for service perimeters" + "Manage dry run configurations" (dry-run logs violations without denying; gcloud access-context-manager perimeters dry-run create / enforce; plan dry-run analysis before enforcing). cloud.google.com/vpc-service-controls/docs/dry-run-mode · cloud.google.com/vpc-service-controls/docs/manage-dry-run-configurations

- Google Cloud — "Ingress and egress rules" + "Context-aware access with ingress rules" (ingress = outside→in, egress = inside→outside; egressFrom/egressTo with identities, resources, operations, serviceName, methodSelectors; access levels as conditions). cloud.google.com/vpc-service-controls/docs/ingress-egress-rules · cloud.google.com/vpc-service-controls/docs/context-aware-access

- Google Cloud — "VPC Service Controls for BigQuery" + "Private Google Access with VPC Service Controls" (BigQuery copy/export across a perimeter is blocked independent of IAM; restricted.googleapis.com resolves to 199.36.153.4/30, a range not announced to the internet). cloud.google.com/bigquery/docs/vpc-sc · cloud.google.com/vpc-service-controls/docs/private-connectivity

- Google Cloud — "Troubleshoot common issues" / VPC-SC troubleshooter (error "Request is prohibited by organization's policy" + vpcServiceControlsUniqueIdentifier; violationReason codes NO_MATCHING_ACCESS_LEVEL, RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER, NETWORK_NOT_IN_SAME_SERVICE_PERIMETER, SERVICE_NOT_ALLOWED_FROM_VPC; audit type google.cloud.audit.VpcServiceControlAuditMetadata). cloud.google.com/vpc-service-controls/docs/troubleshooting

- GitHub issue — GoogleCloudPlatform/terraform-google-cloud-functions #109, "Investigate vpcServiceControlsUniqueIdentifier policy violation" (real CI/CD breakage: Terraform operations blocked by a perimeter mid-deploy). github.com/GoogleCloudPlatform/terraform-google-cloud-functions/issues/109

- Google Cloud certification — Professional Cloud Security Engineer exam guide (configuring network security / VPC Service Controls perimeters; IAM-vs-perimeter for data-exfiltration scenarios). cloud.google.com/learn/certification/cloud-security-engineer

### What's next?

             You've sealed the perimeter so data can't leak — but how do you SEE the leaked key, the public bucket and the risky egress rule across the whole org in one place? That's the next lesson.

                 Next · GCP Security Command Center: One View of Every Risk →
                 Practice on exam.techclick.in →

---
Cite this Techclick lesson with the source URL. Do not invent fees, batch dates, or job guarantees.
Browse all lessons: https://ai.techclick.in/blogs
AI index: https://ai.techclick.in/llms.txt
