Skip to content

Latest commit

 

History

11 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

paved-org 🛣️

CI License Release

A GCP organization baseline as code: org-wide guardrails, a project factory that vends secure-by-default projects, and a zero-trust workload driving on the paved road — IAP-protected, deployed via a keyless WIF pipeline. Prevention half of CloudCanary.

At a glance: org policies that make insecure states unrepresentable · a project factory vending secure-by-default projects · zero exported keys anywhere (keyless WIF/OIDC end-to-end) · a zero-trust workload (IAP) as living proof · extended into agentic AI: an ai-guardrails module, AI-workload detection in its sister project, and a published MCP trust-boundary threat model (v1.1 — STRIDE × OWASP LLM Top 10 2025, multi-agent extension) with a two-part applied security runbook. Detection half: CloudCanary.

The thesis

Most organizations bolt security onto projects after they exist — a scanner here, a review checklist there, a policy document nobody reads. paved-org makes the organization itself the security boundary. Org policy constraints are enforced at the root and inherited by everything below; the project factory vends projects that are hardened before their first API call. Insecure states aren't forbidden by policy documents — they're unrepresentable in the platform.

Everything here is Terraform, deployed through a GitOps pipeline (plan-on-PR, apply-on-merge) that authenticates to GCP with zero exported service-account keys.

Three acts

Act 1: THE PAVEMENT (org layer)
  GCP Organization
  ├── Org policies (Terraform): the secure-by-default constraint set
  ├── Folder hierarchy: /workloads, /sandbox
  └── Project factory module: vends pre-hardened projects
        (baseline APIs, logging sink, no default network,
         no default-SA editor grant, labels, budget guard)

Act 2: THE KEYLESS ROAD (deployment identity)
  GitHub Actions ──OIDC──> Workload Identity Federation pool
  └── deploys everything with ZERO exported service-account keys
      plan-on-PR · apply-on-merge · state in a versioned GCS bucket

Act 3: THE WORKLOAD (zero trust in action)
  A vended project runs a tiny demo app (Cloud Run)
  └── fronted by Identity-Aware Proxy (IAP — Google's ZTNA,
      BeyondCorp lineage): no VPN, no public ingress,
      every request identity-checked

The paved road — and a workload driving on it.

The guardrails (Act 1)

Seven organization policy constraints, each closing a class of misconfiguration (org/policies.tf, one-line threat model on each):

Constraint What it kills
iam.disableServiceAccountKeyCreation The #1 GCP credential-theft vector: exported keys that never expire
iam.automaticIamGrantsForDefaultServiceAccounts Default service accounts born with project Editor
iam.allowedPolicyMemberDomains IAM grants to identities outside the org's directory
compute.skipDefaultNetworkCreation The permissive default VPC in every new project
compute.vmExternalIpAccess Internet-scannable VMs
storage.uniformBucketLevelAccess Per-object ACL sprawl — the root cause of public-bucket incidents
sql.restrictPublicIp Databases on the public internet

A note on identity governance: modern GCP organizations are born with several of these pre-enforced by Google. paved-org imports those defaults into Terraform state rather than leaving them unmanaged — an unmanaged default is drift waiting to happen, and one of these constraints is tightened beyond Google's default. The full story is in docs/bootstrap.md.

No keys were harmed (Act 2)

The pipeline that enforces iam.disableServiceAccountKeyCreation authenticates without any key itself: GitHub's OIDC issuer vouches for each workflow run, and Workload Identity Federation exchanges that short-lived token for federated credentials. Trust is pinned to exactly one repository via an attribute condition; the deployer service account carries least-privilege org roles (org policy + folder administration — deliberately not organizationAdmin).

A governance layer that violated its own policies would be theater.

Sister repo

paved-org prevents what CloudCanary detects. Run both: prevention for the known, detection for the drift. The key-creation constraint above prevents the exact event CloudCanary's identity-drift canary alerts on.

AI-workload security

Extending the prevention/detection thesis to AI workloads:

  • MCP trust-boundary threat model — five boundaries (B1–B5), STRIDE × OWASP LLM Top 10 (2025), with an IAM lens and a multi-agent (agent ↔ agent) extension (v1.1).
  • MCP security runbook — a two-part applied audit: a managed-connector host and a self-hosted agent gateway, with host hardening, a fail-closed exec-approval gate, and a staging-validated container.
  • modules/ai-guardrails — org-policy guardrails for AI workloads (verified canned constraints), the prevention half of what CloudCanary detects.

Cost & reproducibility

Built end-to-end on GCP free-trial credits. The org layer (policies, folders, WIF, state) is control-plane configuration and costs $0 to keep alive. The workload layer (Act 3) carries the one real cost — a global external HTTPS load balancer for IAP, ~$18/month — so it lives for roughly 48 hours: built, evidenced, then terraform destroyed.

The destroy/apply round trip is documented and repeatable. Reproducibility is the point — the repo's value is the code plus evidence, not a running demo. To rebuild from a bare domain, follow docs/bootstrap.md.

Evidence

Tracked with status in docs/evidence/:

  • ✅ Converged plan: No changes. Your infrastructure matches the configuration.
  • ✅ Plan-on-PR and apply-on-merge: proposals rendered, merges becoming infrastructure — keyless throughout
  • ✅ The platform refusing violations: an SA key request denied by org policy; the default compute SA born with zero privilege
  • ✅ The vending machine: a hardened project created by a pull request
  • ✅ Zero trust, proven both ways: IAP identity challenge and asserted identity on the allow path; 403 for an authenticated-but-unauthorized account
  • ✅ Reproducibility: the paid layer destroyed through the same pipeline that built it

Honest limitations

This is a demo-scale organization, and says so:

  • No multi-environment promotion. One org, one state, one pipeline lane. Production would add dev/nonprod/prod folders with per-environment state and promotion gates.
  • No Security Command Center integration. Production would wire SCC Premium for posture management and threat findings on top of these preventive controls.
  • No VPC Service Controls. Data-exfiltration perimeters are the next layer of a real deployment; nothing here conflicts with adding them.
  • Single-person directory. Group-based IAM (admin groups, breakglass procedures) is stubbed by design; the folder layout leaves room for it.

The full threat model, including accepted risks, is in SECURITY.md.

Repo map

org/                      Act 1 + 2: policies, folders, WIF, org logging — live
modules/project-factory/  Act 1: the vending machine — landing in Act 3
workloads/demo/           Act 3: vended project + Cloud Run + IAP — landing in Act 3
docs/                     architecture, bootstrap guide, evidence
.github/workflows/        plan-on-PR, apply-on-merge, lint

Roadmap

Multi-env promotion · SCC integration · VPC-SC perimeter · group-based IAM & breakglass · budget guard as a factory default · Terraform tests (terraform test) for the factory module.

License

MIT

About

A GCP organization baseline as code: org-wide guardrails, a project factory vending secure-by-default projects, and a zero-trust workload on the paved road — keyless GitOps (WIF/OIDC), Terraform, IAP. Prevention half of CloudCanary.

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages