TTechclick ⚡ XP 0% All lessons
GCP · Network · VPC Service ControlsInteractive · L1 / L2 / L3

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

A developer at your company leaks a service-account key with BigQuery Data Viewer on a dataset full of customer PII. With only IAM, that key can copy the whole dataset to a personal project from a laptop anywhere on the internet. VPC Service Controls draws a wall around the data so the export is blocked at the boundary — valid credential or not. This lesson builds that wall.

📅 2026-06-11 · ⏱ 13 min · 3 live demos · 4 infographics · 🏷 10-Q assessment + AI Tutor inline

⚡ Quick Answer

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.

🎯 By the end you will be able to

Read as:

Pick where you want to start

1

The exfiltration gap

Why IAM alone lets a leaked key steal data.

2

How a perimeter works

Ingress, egress, access levels — what crosses the wall.

3

Building it safely

Dry-run first, then rules and private connectivity.

4

Operating VPC-SC

Violation logs, breakages and a worked block.

🧠 Warm-up — 3 questions, no score

Just notice which ones make you pause. We answer all three inside the lesson.

1. A user has BigQuery Data Viewer on a PII dataset and leaks their key. With ONLY IAM, can that key export the dataset to a personal project?

Answered in The exfiltration gap.

2. You want to find out what a new perimeter would break BEFORE it blocks anyone. Which mode do you use first?

Answered in Building it safely.

3. A VM inside a perimeter must reach BigQuery without a public IP and without leaving Google's network. What makes that possible?

Answered in How a perimeter works.

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
IAM only checks WHO is calling; the VPC Service Controls perimeter is a second wall that stops data leaving even when the credential is valid 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 laptoppublic internet 203.0.113.45holds a leaked SA key (.json)IAM says: roles/bigquery.dataViewer ✓ Gate 1 — IAMWHO can call this API? Service perimeter — accProd (the wall) project prod-data-9f2a BigQuery datasetcustomer_pii Cloud Storage bucketgs://gcp-acc-statements Restricted servicesbigquery.googleapis.comstorage.googleapis.comdata 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 / attackertrusted / insidepolicy / decisionkey insightallowed
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?

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.

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
A request crossing the perimeter is denied by default; only a matching ingress or egress rule, or an access level, lets it through 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 arrivesto bigquery.googleapis.com 1 · IAM checkcaller has the role? → continue 2 · Same perimeter as the resource?caller project + resource project both insideyes → 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 callthe 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 checkleaked-sa@prod calls bq copy → IAM sees role bigquery.dataViewer → passes
② Perimeter checkis dst attacker-side-proj inside perimeter accProd? → NO
③ Egress evalinside → outside = egress; any egress rule allows this identity → resource? → none
④ Deny + logrequest denied; violation RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER written to audit log
Press Play to step through the healthy path. Then press Break it.
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?

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.

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.

🖥️ 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
VPC Service Controls on one card — the perimeter, ingress/egress, access levels, restricted VIP, the dry-run ladder and the first commands you type 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 perimeterwall around projects + restrictedservices (BigQuery, GCS, Pub/Sub…)free comms inside, deny acrossindependent of IAM Ingress vs egressingress = outside → inegress = inside → outside projectboth denied unless a rule allowsfrom {identity} → to {resource/op} Access levelscontext conditions in AccessContext ManagerIP range · region · device · identitylayer onto ingress rules Restricted VIPrestricted.googleapis.com→ 199.36.153.4/30Private Google Access keepstraffic off the public internet Dry-run ladder1 · dry-run, no rules → watch logs2 · add ingress/egress for breaks3 · 0 violations for 2–4 weeks4 · enforce — never enforce-first Bridge vs rulesbridge = 2 perimeters shareprojects bidirectionallyGoogle prefers ingress/egressrules = finer-grained Top violation codesNO_MATCHING_ACCESS_LEVELRESOURCES_NOT_IN_SAME_…PERIMETERNETWORK_NOT_IN_SAME_…SERVICE_NOT_ALLOWED_FROM_VPC Read the violationsLogs Explorer, filter on:VpcServiceControlAuditMetadatamatch the unique id from the"prohibited by org policy" error First commandsgcloud access-context-manager perimeters dry-run create perimeters dry-run enforcegcloud 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?

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.

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?"

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
Without a perimeter a leaked key copies a BigQuery dataset to a personal project; with the perimeter the same copy is blocked as an egress violation 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 key203.0.113.45 prod customer_piiBigQuery dataset personal projectattacker-side-proj bq cp prod:customer_pii \ attacker-side-proj:loot ✗ data exfiltrated — IAM allowed it AFTER — perimeter enforced leaked SA key203.0.113.45 prod customer_piiinside accProd personal projectOUTSIDE perimeter violationReason:RESOURCES_NOT_IN_SAME_SERVICE_PERIMETER ✓ blocked at the boundary — data stays leak / blocked attemptpolicy decisionsafe / 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 privilegeNext: 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.

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.

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?

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?

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?

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?

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?

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?

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.
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.

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.

📖 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

  1. 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
  2. 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
  3. 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
  4. 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
  5. 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
  6. 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
  7. 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.