◆ NexGenCloud Inc.
🛠 Scenario
NexGenCloud is migrating their analytics platform from on-prem to GCP. You're the Platform Engineer setting up the IAM foundation. The CISO requires: least privilege, auditability, and data exfiltration protection.
📚 Pre-Requisites (Do Beforehand)
- GCP Org — must have Organization node (not free trial)
- Billing Account linked to the org
- Org Admin role (
roles/resourcemanager.organizationAdmin) - IAM Security Reviewer role for audits
- Cloud Identity / Google Workspace domain verified
🎯 What You'll Build
- SOP 1 Org Hierarchy + Folder structure
- SOP 2 Custom IAM Roles (least privilege)
- SOP 3 IAM Conditions (time/IP/resource)
- SOP 4 Service Accounts + Workload Identity Fed
- SOP 5 Deny Policies (break-glass prevention)
- SOP 6 VPC Service Controls perimeter
- SOP 7 Policy Analyzer + Audit Logging
- SOP 8 Project Factory Pattern
⚠ Prerequisites
- GCP Organization node must exist — check at IAM & Admin / Settings
- You need
roles/resourcemanager.organizationAdminorroles/resourcemanager.folderAdmin - Decide naming convention beforehand:
nexgen-{env}-{purpose}
👉 Portal Steps
nexgencloud.comnexgen-dev — Development workloads
nexgen-staging — Pre-production validation
nexgen-prod — Production workloads
nexgen-dev/ → platform, data-science, apisnexgen-prod/ → platform, data-science, apis
nexgen-shared-networking (under nexgen-common)nexgen-dev-platform-gke (under nexgen-dev/platform)nexgen-dev-ds-pipelines (under nexgen-dev/data-science)
✅ Verification
You should see this tree in Resource Manager:
⚠ Key Tip for Interview: Hierarchy matters because Org Policies and IAM roles inherit downward. Setting a policy at nexgen-prod folder applies to all projects inside it. Use this for policy isolation between environments.
⚠ Prerequisites
- Need
roles/iam.roleAdminat Organization level - Know exactly which permissions are needed (start broad, then narrow)
- Use IAM & Admin / Roles to reference existing roles
👉 Portal Steps — Create nexgenSecurityViewer
NexGen Security ViewerID:
nexgenSecurityViewer (auto-generated)Description: Read-only access to security configurations, IAM, and audit logs
Role launch stage: General Availability
Add Permissions:
iam.roles.get, iam.roles.listiam.serviceAccounts.getIamPolicyresourcemanager.projects.getIamPolicylogging.logEntries.list, logging.logs.listorgpolicy.policies.list, orgpolicy.policy.getasset.assets.list* (Cloud Asset Inventory)
👉 Portal Steps — Create nexgenNetworkAdmin
NexGen Network AdminID:
nexgenNetworkAdminPermissions:
compute.networks.create, compute.networks.update, compute.networks.deletecompute.subnetworks.* (full control)compute.firewalls.create, .update, .deletecompute.routes.*dns.managedZones.*compute.interconnects.* (if on-prem)
🎯 Assign SecurityViewer
- Go to IAM & Admin / IAM / Organization node
- Click + ADD → Add security team group:
security@nexgencloud.com - Select role: Custom → NexGen Security Viewer
- Click SAVE. Inherits to all child folders/projects.
🎯 Assign NetworkAdmin
- Go to IAM & Admin / IAM at nexgen-common folder
- Add
network-team@nexgencloud.comwith NexGen Network Admin - Scoped to shared-infra folder only — not dev/prod
✅ Verification
Go to IAM & Admin / Roles → Filter by "nexgen". You'll see both custom roles with permission counts. Assign a test user and verify they can only read IAM policies but cannot modify.
⚠ Interview Tip: Say: "Custom roles reduce blast radius. Instead of giving roles/editor (3000+ perms), we give exactly the perms needed. Audit with Policy Analyzer to find over-permissioned principals."
⚠ Prerequisites
- Custom role from SOP 2 (or any existing role)
- Resource Manager tags created (optional but recommended)
- Understand CEL (Common Expression Language) syntax
👉 Scenario A — Time-Based Condition
"Developers can deploy to staging only during business hours (9AM-5PM Mon-Fri)."
Business hours onlyCondition type:
Time → TemporalExpression (CEL):
bindings[].condition in the policy JSON.👉 Scenario B — Resource Tag Condition
"Only allow changes to resources tagged environment=prod if coming from the on-prem NAT IP."
environment → Values: dev, staging, prod, sharedScope: Organization (so all projects can use it)
environment=prod✅ Verification
Use IAM & Admin / Policy Analyzer → query a principal to see their effective access with conditions applied. The condition status shows granted or not granted based on context.
⚠ Prerequisites
- GKE cluster with Workload Identity enabled (
--workload-pool=PROJECT.svc.id.goog) - GitHub repo with OIDC provider configured (or Azure DevOps)
- Permissions:
iam.serviceAccountAdmin,iam.workloadIdentityPoolAdmin
👉 Part A — Create & Bind GCP Service Account
gke-microservice-saID:
gke-microservice-saDescription: Service account for GKE microservices to read GCS and write logs
Roles (grant least privilege):
roles/storage.objectViewer (read GCS)roles/logging.logWriter (write logs)roles/monitoring.metricWriter (custom metrics)
👉 Part B — Workload Identity Federation (GitHub Actions)
github-poolID:
github-pool
github-providerIssuer URL:
https://token.actions.githubusercontent.comAudience:
https://github.com/NexGenCloudAttribute mapping:
gke-microservice-sa.👉 Part C — K8s Workload Identity
✅ Verification (Deploy a Pod)
No keys needed! Workload Identity exchanges K8s SA token for GCP SA token automatically.
⚠ Prerequisites
- Need
roles/iam.denyAdminat Organization level (separate from regular IAM admin) - Understand that deny always overrides allow
- Test in a dev folder first (dry-run mindset)
👉 Deny Policy 1 — Prevent Public GCS Buckets
nexgencloud.com) to apply globally.deny-public-gcsDenial conditions: (leave blank to apply to all)
Principals: ALL (apply to everyone)
Permissions: search and add:
principalSet:group:security-admins@nexgencloud.com — this allows break-glass access.
👉 Deny Policy 2 — Block Service Account Key Creation
deny-sa-key-creation-prodPrincipals: ALL
Permissions:
✅ Verification
Try to make a GCS bucket public: Cloud Storage / Bucket / Permissions / + Add principal / allUsers / Storage Object Viewer. You'll see “Policy denied by org policy” error.
Check deny policy logs: Logging / Logs Explorer → query: protoPayload.metadata.denyPolicyName
⚠ Prerequisites
- Identify which projects to protect (prod projects with GCS, BQ, Bigtable)
- Identify on-prem IP ranges and SA that need ingress/egress access
- Permissions:
accesscontextmanager.policyAdmin - Org ID — needed for the access policy name
👉 Portal Steps
nexgen-prod-perimeterType: Regular (standard) vs Bridge (for peering across perimeters)
nexgen-prod-platform-gkenexgen-prod-ds-pipelinesnexgen-prod-apisnexgen-prod-data-lake
IP Subnet → 203.0.113.0/24 (on-prem)Identity:
serviceAccount:etl-sa@nexgen-prod-data-lake.iam.gserviceaccount.comServices: Cloud Storage, BigQuery
EXTERNAL → specify monitoring projectIdentity:
serviceAccount:monitoring-sa@nexgen-common.iam...Services: Cloud Monitoring, Cloud Logging
⚠ Critical: Always start in DRY RUN. A misconfigured perimeter can break all prod access. Monitor for 24-48 hours before enforcing.
✅ Verification
From a VM outside the perimeter: gsutil ls gs://nexgen-prod-bucket should fail with 403 VPC Service Controls.
From inside (VM in prod project or on-prem with ingress): should succeed.
⚠ Prerequisites
- Access to query:
roles/iam.roleViewer+roles/cloudasset.viewer - Cloud Asset API enabled in at least one project
👉 Part A — Use Policy Analyzer
dev-team@nexgencloud.comScope:
nexgencloud.com (Organization)Click ANALYZE
👉 Part B — Set Up Audit Logs for IAM Changes
IAM:IAM → check Admin Read + Data Access
iam-audit-sinkInclusion filter:
nexgen-audit-logs for querying with SQL.
✅ Verification
After making an IAM change, run this in Logging / Logs Explorer:
You'll see who changed what policy, when, and the diff.
⚠ Prerequisites
- Be comfortable with Terraform
- Shared VPC host project already deployed
- Service account for Terraform with
roles/resourcemanager.projectCreator+ billing permissions
👉 Portal Steps — Create the Pattern Manually (First Time)
nexgen-dev-backend-v2Parent:
nexgen-dev/apis folderBilling account: Link to org billing
compute.googleapis.com
container.googleapis.com
cloudresourcemanager.googleapis.com
iam.googleapis.com
logging.googleapis.com
monitoring.googleapis.com
dev-backend-subnet).dev-team@nexgencloud.com → roles/container.developer (can deploy to GKE)ci-cd-sa@nexgen-common.iam.gserviceaccount.com → roles/container.developermonitoring-sa@nexgen-common.iam.gserviceaccount.com → roles/monitoring.metricWriter
nexgen-prod-perimeter.👉 Automate with Terraform (The Real Way)
✅ Verification
After Terraform apply, go to Resource Manager and confirm the new project exists in the correct folder with APIs enabled. Check IAM to verify baseline roles are applied.