Organization Policies & Supply Chain Security
Tại sao quan trọng
Bạn đã learn Cloud Build, Artifact Registry, và deployments. Nhưng ở organization level, bạn cần lock down toàn bộ CI/CD pipeline.
Scenario: Một team member có thể:
# Connect Cloud Build to arbitrary GitHub repo?
# (ngoài org's control)
# Push images without vulnerability scanning?
# Deploy directly without approval?Nếu không có organization policies, answers có thể "yes" — mở rộng supply chain risk.
Organization policies (từ Chương 33) apply enforcement across projects: không cho phép builds kết nối to unauthorized external systems, enforce security practices, ensure compliance.
allowedIntegrations Policy
Policy Overview
compute.skipDefaultNetworkCreation là tổng quát. Cho CI/CD, critical policy là allowedIntegrations.
Organization Policy: Cloud Build > allowedIntegrations
Controls: Which external systems Cloud Build triggers có thể connect to
Default: All allowed (unrestricted)
Secure: Only allow specific integrations (Cloud Source Repos, approved GitHub orgs)Cloud Build Integration Points
Cloud Build có thể trigger từ / connect to:
- Cloud Source Repositories (internal, controlled by Google)
- GitHub (external, managed by third party)
- GitLab (external)
- Bitbucket (external)
- Manual webhook (arbitrary external systems)
Risk per integration:
Cloud Source Repos: ✓ Low risk (Google-managed, inside GCP)
GitHub Public Repos: ⚠ Medium risk
- Repo visibility may change
- Collaborators may add malicious code
GitHub Private Repos: ⚠ Medium risk (same as public)
GitLab: ⚠ Medium risk (third-party, less control)
Bitbucket: ⚠ Medium risk
Webhooks: ✗ High risk (arbitrary external trigger)
- Attacker can trigger builds
- Builds execute with full permissionsSetting allowedIntegrations Policy
# org-policy.yaml (at organization level)
constraint: compute.allowedIntegrations
listPolicy:
allowedValues:
- "cloudsourcerepos.googleapis.com"
- "github.com:myorg" # Only this GitHub orgDeployment:
# Apply policy to organization
gcloud resource-manager org-policies set-policy org-policy.yaml \
--project=my-projectPolicy Evaluation
After policy applied:
Scenario 1: Try to connect Cloud Build to myorg/myrepo on GitHub
├─ Policy checks: "github.com:myorg" ✓ in allowedIntegrations
└─ ALLOWED
Scenario 2: Try to connect to externalorg/externalrepo on GitHub
├─ Policy checks: "github.com:externalorg" ✗ NOT in allowedIntegrations
└─ DENIED
Scenario 3: Try to create webhook trigger
├─ Policy checks: webhooks not in allowedIntegrations
└─ DENIEDIdentity Verification for External Integrations
Nếu bạn allow GitHub integrations, organization still needs to verify:
Question: "Is commit từ legitimate GitHub account, or forked repo?"Solution: Branch protection + required status checks
# GitHub repository settings
# Branch: main
# - Require status checks before merging
# - Dismiss stale pull request approvals
# - Require code reviews from code owners
# - Require branches to be up to dateCloud Build level:
# cloudbuild.yaml — log who triggered build
steps:
- name: 'gcr.io/cloud-builders/git'
args: ['log', '-1', '--format=%an <%ae>']
# Output: "John Doe <john@example.com>" — verify against allowed committersService Account Policies
Beyond allowedIntegrations, lock down service accounts used:
# Constraint: iam.serviceAccountUser
# Effect: Only specific service accounts có thể be used for builds
constraints:
- serviceaccount: "cloud-build@my-project.iam.gserviceaccount.com"
roles:
- roles/container.developer # Can deploy to GKE
- roles/artifactregistry.writerSupply Chain Security Audit Trail
Để maintain audit trail:
# Log tất cả Cloud Build activities
gcloud logging read "resource.type=cloudbuild" \
--limit=100 \
--format=jsonKey logs to audit:
- Build triggers modified: Who changed trigger configuration?
- Service account roles changed: New permissions granted?
- Deployments initiated: Who triggered deployment?
- Builds that failed: Which builds failed, and why?
Example query:
# Find all builds triggered from external repos
gcloud logging read "resource.type=cloudbuild AND sourceRepo != 'cloud-source-repositories'" \
--format=json | jq '.[] | {timestamp, sourceRepoUrl, buildId, result}'Real-World: Hardened CI/CD Organization Policy
Scenario
- Organization: MyCorp
- Security requirement: All deployments must be auditable, no unauthorized external triggers
- Integrations: Only internal Cloud Source Repos + approved GitHub org
Policy Setup
1. Organization-level constraints:
# org-policies.yaml
constraints:
- name: "compute.allowedIntegrations"
listPolicy:
allowedValues:
- "cloudsourcerepos.googleapis.com" # Internal
- "github.com:mycorp" # Only mycorp org
- name: "iam.disableServiceAccountCreation"
# Prevent creation of uncontrolled service accounts
denyRule:
deny: []
allowRule:
allow: []2. Cloud Build service account with least privilege:
# Create dedicated service accounts
gcloud iam service-accounts create cloud-build-ci \
--display-name="Cloud Build CI Service Account"
# Grant only necessary permissions
gcloud projects add-iam-policy-binding my-project \
--member=serviceAccount:cloud-build-ci@my-project.iam.gserviceaccount.com \
--role=roles/artifactregistry.writer
gcloud projects add-iam-policy-binding my-project \
--member=serviceAccount:cloud-build-ci@my-project.iam.gserviceaccount.com \
--role=roles/container.developer
# Explicitly DENY dangerous roles
gcloud projects add-iam-policy-binding my-project \
--member=serviceAccount:cloud-build-ci@my-project.iam.gserviceaccount.com \
--role=roles/editor \
--condition='resource.name != projects/my-project'3. Build trigger configuration:
gcloud builds triggers create github \
--repo-owner=mycorp \
--repo-name=myapp \
--branch-pattern="^main$" \
--build-config=cloudbuild.yaml \
--service-account=cloud-build-ci@my-project.iam.gserviceaccount.com4. Audit logging:
# Enable Cloud Audit Logs
gcloud logging write audit-log '
{
"event": "cloudbuild-deployment",
"triggeredBy": "github.com:mycorp/myapp",
"timestamp": "'$(date -u +'%Y-%m-%dT%H:%M:%SZ')'",
"buildId": "'${BUILD_ID}'"
}' --severity=INFO
# Query audit trail
gcloud logging read "logName=projects/my-project/logs/audit-log" \
--format=json --limit=50Supply Chain Security Checklist
Before marking CI/CD as production-ready:
✓ Trigger sources validated
└─ allowedIntegrations policy enforced
└─ GitHub branch protection enabled
└─ Cloud Source Repos used for sensitive code
✓ Build provenance enabled
└─ requestedVerifyOption: VERIFIED ở cloudbuild.yaml
✓ Service account least privilege
└─ Custom service accounts per build step
└─ No default service account usage
└─ Minimum IAM roles granted
✓ Artifact scanning enabled
└─ Vulnerability scanning active
└─ SBOM generated
└─ No deployment of CRITICAL vulnerabilities
✓ Deployment gates implemented
└─ Cloud Deploy approval gates
└─ Binary Authorization enabled
└─ Canary deployments for prod
✓ Audit trail enabled
└─ Cloud Audit Logs capturing all CI/CD events
└─ Retention policy set (e.g., 1 year)
└─ Monitoring alerts for suspicious activity
✓ Organization policies enforced
└─ allowedIntegrations configured
└─ Service account creation restricted
└─ Dangerous roles denied at org levelCommon Misconfigurations
Misconfiguration 1: No allowedIntegrations Policy
Risk: Teams connect builds to random external GitHub repos
Mitigation: Enforce policy org-wide
gcloud resource-manager org-policies set-policy org-policy.yaml \
--project=ORG_ID \
--update-enforced-policyMisconfiguration 2: Default Service Account Used
# cloudbuild.yaml — BAD
steps:
- name: 'gcr.io/cloud-builders/docker'
args: ['push', '...']
# Uses default service account (too permissive)Fix: Use explicit custom service account
steps:
- name: 'gcr.io/cloud-builders/docker'
serviceAccount: 'projects/PROJECT/serviceAccounts/pusher@PROJECT.iam.gserviceaccount.com'
args: ['push', '...']Misconfiguration 3: No Approval Gates for Prod
# Deploy automatically to production
gcloud deploy delivery-pipelines create app-pipeline \
--config=deploy.yaml
# Missing: requireApproval: true for prod stageFix:
serialPipeline:
stages:
- targetId: prod
deployParameters:
- requireApproval: true # Explicit gate