Skip to content

🔐 IAM Model

Level: Foundation Solves: Thiết kế và quản lý identity & access management theo chuẩn enterprise security trên GCP

🎯 Mục tiêu (Outcomes)

Sau khi áp dụng kiến thức trong trang này, bạn sẽ có khả năng:

  • Thiết kế IAM Strategy với predefined và custom roles
  • Triển khai Workload Identity cho GKE workloads
  • Cấu hình Service Account Impersonation thay cho SA keys
  • Áp dụng IAM Conditions cho fine-grained access control
  • Implement Least Privilege với IAM Recommender
  • So sánh với AWS IAM model

Khi nào dùng

PatternUse CaseLý do
Workload IdentityGKE pods access GCPNo keys, automatic rotation
SA ImpersonationCross-project accessAudit trail, short-lived
Predefined RolesStandard use casesWell-scoped, maintained
Custom RolesSpecific requirementsExact permissions needed
IAM ConditionsTime-based, resource-basedFine-grained control

Khi nào KHÔNG dùng

PatternVấn đềThay thế
Basic roles (Editor/Owner)Quá broadPredefined roles
Service Account keysKey leak riskWorkload Identity
Default SAsEditor role by defaultUser-managed SAs
Individual user bindingsHard to manageGoogle Groups
allUsers/allAuthenticatedUsersPublic accessSpecific principals

⚠️ Cảnh báo từ Raizo

"Một SA key commit vào GitHub. 30 phút sau, crypto miners đã deploy 50 n8-highmem-96 VMs. $15,000 bill trong 1 ngày. Organization Policy 'Disable SA key creation' là cần thiết."

Core Concepts

GCP IAM Components

┌─────────────────────────────────────────────────────────────────┐
│                    GCP IAM MODEL                                │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  WHO (Principal)          WHAT (Role)         WHERE (Resource)  │
│  ──────────────           ──────────          ────────────────  │
│                                                                 │
│  ┌─────────────┐         ┌─────────────┐     ┌─────────────┐   │
│  │ Google Acct │         │   Viewer    │     │Organization │   │
│  │ Service Acct│   +     │   Editor    │  →  │   Folder    │   │
│  │   Group     │         │   Owner     │     │   Project   │   │
│  │  allUsers   │         │Custom Roles │     │  Resource   │   │
│  └─────────────┘         └─────────────┘     └─────────────┘   │
│                                                                 │
│  IAM Policy = Collection of bindings:                           │
│  { principal + role + resource + (optional) condition }         │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

Principal Types

Principal TypeFormatUse Case
Google Accountuser:email@example.comHuman users
Service AccountserviceAccount:sa@project.iam.gserviceaccount.comApplications
Google Groupgroup:team@example.comTeam access
Cloud Identity Domaindomain:example.comAll domain users
allUsersallUsersPublic access (dangerous!)
allAuthenticatedUsersallAuthenticatedUsersAny Google account

Role Types

Role Hierarchy

┌─────────────────────────────────────────────────────────────────┐
│                    GCP ROLE TYPES                               │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  BASIC ROLES (Legacy - Avoid in Enterprise)                     │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │ • roles/viewer    - Read-only access                    │    │
│  │ • roles/editor    - Read + Write (NO IAM, NO Billing)   │    │
│  │ • roles/owner     - Full control including IAM          │    │
│  │                                                         │    │
│  │ ⚠️ TOO BROAD - Use predefined or custom roles instead   │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                 │
│  PREDEFINED ROLES (Recommended)                                 │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │ • roles/compute.instanceAdmin.v1                        │    │
│  │ • roles/storage.objectViewer                            │    │
│  │ • roles/bigquery.dataEditor                             │    │
│  │ • roles/cloudsql.client                                 │    │
│  │                                                         │    │
│  │ ✅ Scoped to specific services and actions              │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                 │
│  CUSTOM ROLES (When predefined don't fit)                       │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │ • Define exact permissions needed                       │    │
│  │ • Can be org-level or project-level                     │    │
│  │ • Requires maintenance as APIs evolve                   │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

Custom Role Example

yaml
title: "Application Deployer"
description: "Deploy applications to Cloud Run"
stage: GA
includedPermissions:
  - run.services.get
  - run.services.list
  - run.services.create
  - run.services.update
  - run.revisions.get
  - run.revisions.list
  - artifactregistry.repositories.downloadArtifacts

⚠️ Custom Role Maintenance

Custom roles require ongoing maintenance. When GCP adds new permissions to services, custom roles don't automatically include them. Review quarterly.

Service Accounts

Service Account Types

┌─────────────────────────────────────────────────────────────────┐
│                SERVICE ACCOUNT TYPES                            │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  DEFAULT SERVICE ACCOUNTS (Avoid)                               │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │ • Compute Engine default SA                             │    │
│  │   {project-number}-compute@developer.gserviceaccount.com│    │
│  │ • App Engine default SA                                 │    │
│  │   {project-id}@appspot.gserviceaccount.com              │    │
│  │                                                         │    │
│  │ ⚠️ Has Editor role by default - TOO PERMISSIVE          │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                 │
│  USER-MANAGED SERVICE ACCOUNTS (Recommended)                    │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │ • Create dedicated SA per application/workload          │    │
│  │ • Grant minimum required permissions                    │    │
│  │ • Use meaningful names: {app}-{env}@{project}.iam...    │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                 │
│  GOOGLE-MANAGED SERVICE ACCOUNTS                                │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │ • Created by GCP services automatically                 │    │
│  │ • Example: Cloud Build, Dataflow service agents         │    │
│  │ • Don't modify unless necessary                         │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

Service Account Best Practices

Workload Identity

GKE Workload Identity

┌─────────────────────────────────────────────────────────────────┐
│                 WORKLOAD IDENTITY                               │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │                    GKE Cluster                          │    │
│  │  ┌─────────────────────────────────────────────────┐    │    │
│  │  │              Kubernetes Namespace               │    │    │
│  │  │  ┌─────────────────────────────────────────┐    │    │    │
│  │  │  │           Pod                           │    │    │    │
│  │  │  │  ┌─────────────────────────────────┐    │    │    │    │
│  │  │  │  │  K8s Service Account            │    │    │    │    │
│  │  │  │  │  (my-app-ksa)                   │    │    │    │    │
│  │  │  │  └──────────────┬──────────────────┘    │    │    │    │
│  │  │  └─────────────────┼───────────────────────┘    │    │    │
│  │  └────────────────────┼────────────────────────────┘    │    │
│  └───────────────────────┼─────────────────────────────────┘    │
│                          │                                      │
│                          │ Workload Identity binding             │
│                          ▼                                      │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │              GCP Service Account                        │    │
│  │              (my-app-gsa@project.iam...)                │    │
│  │                         │                               │    │
│  │                         ▼                               │    │
│  │              ┌─────────────────────┐                    │    │
│  │              │   GCP Resources     │                    │    │
│  │              │   (BigQuery, GCS)   │                    │    │
│  │              └─────────────────────┘                    │    │
│  └─────────────────────────────────────────────────────────┘    │
│                                                                 │
│  NO SERVICE ACCOUNT KEYS NEEDED!                                │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

Workload Identity Setup

bash
# 1. Enable Workload Identity on cluster
gcloud container clusters update CLUSTER_NAME \
  --workload-pool=PROJECT_ID.svc.id.goog

# 2. Create GCP Service Account
gcloud iam service-accounts create my-app-gsa \
  --display-name="My App Service Account"

# 3. Grant permissions to GCP SA
gcloud projects add-iam-policy-binding PROJECT_ID \
  --member="serviceAccount:my-app-gsa@PROJECT_ID.iam.gserviceaccount.com" \
  --role="roles/bigquery.dataViewer"

# 4. Allow K8s SA to impersonate GCP SA
gcloud iam service-accounts add-iam-policy-binding \
  my-app-gsa@PROJECT_ID.iam.gserviceaccount.com \
  --role="roles/iam.workloadIdentityUser" \
  --member="serviceAccount:PROJECT_ID.svc.id.goog[NAMESPACE/KSA_NAME]"

# 5. Annotate K8s Service Account
kubectl annotate serviceaccount KSA_NAME \
  --namespace NAMESPACE \
  iam.gke.io/gcp-service-account=my-app-gsa@PROJECT_ID.iam.gserviceaccount.com

IAM Conditions

Conditional Access

json
{
  "bindings": [
    {
      "role": "roles/storage.objectViewer",
      "members": ["user:developer@example.com"],
      "condition": {
        "title": "Business hours only",
        "description": "Access only during business hours",
        "expression": "request.time.getHours('Asia/Ho_Chi_Minh') >= 9 && request.time.getHours('Asia/Ho_Chi_Minh') <= 18"
      }
    }
  ]
}

Common Condition Patterns

yaml
# Time-based access
expression: |
  request.time.getHours("Asia/Ho_Chi_Minh") >= 9 &&
  request.time.getHours("Asia/Ho_Chi_Minh") <= 18 &&
  request.time.getDayOfWeek("Asia/Ho_Chi_Minh") >= 1 &&
  request.time.getDayOfWeek("Asia/Ho_Chi_Minh") <= 5

# Resource name prefix
expression: |
  resource.name.startsWith("projects/_/buckets/prod-")

# Tag-based access
expression: |
  resource.matchTag("env", "production")

# Temporary access (expires)
expression: |
  request.time < timestamp("2024-12-31T23:59:59Z")

Service Account Impersonation

Impersonation Chain

┌─────────────────────────────────────────────────────────────────┐
│            SERVICE ACCOUNT IMPERSONATION                        │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  User/SA A                                                      │
│      │                                                          │
│      │ Has: roles/iam.serviceAccountTokenCreator                │
│      │ On: SA B                                                 │
│      ▼                                                          │
│  Service Account B                                              │
│      │                                                          │
│      │ Has: roles/storage.admin                                 │
│      │ On: GCS Bucket                                           │
│      ▼                                                          │
│  GCS Bucket                                                     │
│                                                                 │
│  Command:                                                       │
│  gcloud storage ls gs://bucket \                                │
│    --impersonate-service-account=sa-b@project.iam...            │
│                                                                 │
│  ✅ No SA keys needed                                           │
│  ✅ Audit trail shows impersonation                             │
│  ✅ Short-lived credentials                                     │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

GCP vs AWS IAM Comparison

ConceptGCPAWS
IdentityGoogle Account, Service AccountIAM User, IAM Role
GroupsGoogle Groups (external)IAM Groups (internal)
RolesPredefined + CustomManaged + Customer
Policy AttachmentBinding at resource levelAttach to identity
Temporary CredentialsImpersonation, Workload IdentityAssumeRole, STS
Cross-AccountCross-project IAMCross-account roles
ConditionsCEL expressionsIAM Conditions

Best Practices Checklist

  • [ ] No basic roles (viewer/editor/owner) in production
  • [ ] Service accounts per workload, not shared
  • [ ] Workload Identity for GKE workloads
  • [ ] No service account keys (use impersonation)
  • [ ] Groups for human access, not individual bindings
  • [ ] IAM conditions for sensitive resources
  • [ ] Regular access reviews with IAM Recommender
  • [ ] Audit logs enabled for IAM changes

⚖️ Trade-offs

Trade-off 1: Predefined vs Custom Roles

Khía cạnhPredefined RolesCustom Roles
MaintenanceGoogle maintainsYou maintain
GranularityFixedExact permissions
UpdatesAutomaticManual review
AuditStandardCustom audit

Khuyến nghị: Predefined là default. Custom chỉ khi predefined quá broad hoặc too restrictive.


Trade-off 2: SA Keys vs Workload Identity

Khía cạnhSA KeysWorkload Identity
SetupSimpleComplex
SecurityKey leak riskNo keys
RotationManualAutomatic
PortabilityAny environmentGCP only

Trade-off 3: Granular vs Simple IAM

ApproachGranularityManageability
Role per resourceVery fineComplex
Role per projectMediumBalanced
Role per folderCoarseSimple

🚨 Failure Modes

Failure Mode 1: Service Account Key Leak

🔥 Incident thực tế

Developer commit SA key vào public repo. Bot detect trong 10 phút. Attackers spin up GPU VMs cho crypto mining. $50K bill before detection.

Cách phát hiệnCách phòng tránh
Unusual API activityDisable SA key creation (org policy)
Cost spikeUse Workload Identity
GitHub secret scanningPre-commit hooks
Security Command CenterShort-lived tokens only

Failure Mode 2: Over-Privileged Service Account

Cách phát hiệnCách phòng tránh
IAM Recommender alertsStart with minimal permissions
Unused permissionsRegular access reviews
Editor role on default SARemove Editor from default SAs

Failure Mode 3: IAM Policy Conflicts

Cách phát hiỆnCách phòng tránh
Access denied unexpectedlyTest in sandbox
Policy troubleshooter errorsDocument inheritance
Conflicting conditionsUse policy analyzer

🔐 Security Baseline

IAM Security Requirements

RequirementImplementationVerification
No SA keysOrg policy enforcedSecurity Command Center
No basic rolesPolicy analyzerIAM Recommender
Workload IdentityGKE configurationCluster audit
IAM audit logsCloud LoggingLog sink verified
Groups for humansGoogle GroupsUser binding audit

Service Account Security

yaml
# Minimum SA permissions pattern
resources:
  - type: "iam.googleapis.com/ServiceAccount"
    properties:
      name: "my-app-sa"
    bindings:
      - role: "roles/iam.serviceAccountUser"
        members:
          - "serviceAccount:deployer@project.iam.gserviceaccount.com"
      - role: "roles/iam.workloadIdentityUser"
        members:
          - "serviceAccount:project.svc.id.goog[namespace/ksa]"

📊 Ops Readiness

Metrics cần Monitoring

MetricSourceAlert Threshold
SA key creationAudit LogsAny
Unused permissionsIAM Recommender> 10% unused
Basic role usagePolicy AnalyzerAny in prod
allUsers bindingsSecurity Command CenterAny
Failed auth attemptsAudit LogsSpike

Runbook Entry Points

Tình huốngRunbook
SA key leakrunbook/sa-key-rotation.md
Over-privileged SA detectedrunbook/iam-remediation.md
Access denied investigationrunbook/iam-troubleshooting.md
IPolicyCrossover violationrunbook/iam-recommender-review.md
Workload Identity setuprunbook/workload-identity-setup.md

Design Review Checklist

Identity

  • [ ] No SA keys in use
  • [ ] Workload Identity for GKE
  • [ ] SA impersonation configured
  • [ ] Groups cho human access

Authorization

  • [ ] No basic roles
  • [ ] Predefined roles preferred
  • [ ] Custom roles documented
  • [ ] IAM conditions where needed

Audit

  • [ ] IAM audit logs enabled
  • [ ] Regular recommender review
  • [ ] Access reviews scheduled
  • [ ] Policy analyzer runs

Operations

  • [ ] SA inventory maintained
  • [ ] Permission documentation
  • [ ] Runbooks available
  • [ ] Training completed

📎 Liên kết