Skip to content
Why Pinterest built a custom pipeline to secure infrastructure at scale

Why Pinterest built a custom pipeline to secure infrastructure at scale

6 min read devops

Pinterest engineering reveals its Resource Provisioner Pipeline (RPP), a custom system designed to automate and secure cloud infrastructure provisioning. The pipeline prevents configuration drift and enforces strict security policies across thousands of engineering resources....

Subscribe to listen
audio-thumbnail
Why Pinterest built a custom pipeline to secure infrastructure at scale
0:00
/0
Clinical Summary
Diagnosis

Granting CI/CD pipelines broad execution permissions in multi-repository Terraform architectures creates a massive blast radius, allowing simple copy-paste errors to irrevocably overwrite other teams' production state files.

Prescription
  • Path-to-Workspace Mapping: Maintain a central configuration file that explicitly maps every workspace to an allowed repository, directory path, and team identity.
  • State Backend Validation: Implement pre-flight static analysis to assert that the executing directory strictly matches the S3 backend and KMS keys mapped to that exact workspace.
  • OIDC Role Chaining: Authenticate via GitHub OpenID Connect into a highly restricted central role to perform validation, then hop into a localized, down-scoped IAM team execution role.
Side Effects

Building custom execution orchestration scales poorly, creating a monolithic central registry bottleneck, requiring manual concurrency management, and heavily degrading the developer debugging experience.

Script

Pinterest's Custom Terraform Engine

Pinterest just published a detailed breakdown of their internal Terraform execution engine. They call it the Resource Provisioner Pipeline. You cannot download it. It is not an open-source project. It is a highly specific, proprietary GitHub Actions architecture designed to lock down infrastructure deployments across hundreds of separate workspaces.

The engine itself is custom-built entirely for their scale. But underneath the proprietary code is a masterclass in continuous integration security. Pinterest relies on a specific pattern of OpenID Connect role-chaining and strict backend validation that any engineering team can copy.

The Critical Vulnerability of CI/CD

Picture this. It is a Tuesday afternoon. A product developer needs to spin up a quick test environment for a new service. Their company uses a multi-repo setup for infrastructure. Instead of writing the Terraform from scratch, they copy a module from another team's directory to save time.

They update the resource names, commit the code, and open a pull request. Another engineer on their team gives it a quick approval. But the original developer forgot to change the S3 backend key in the copied code.

The continuous integration pipeline triggers. It has broad permissions to apply Terraform across the cloud environment. It assumes the role, executes the apply, and blindly overwrites the other team's production state file. The test environment spins up, but the production state is irrevocably corrupted.

This is the exact disaster Pinterest built their pipeline to prevent. Granting a CI/CD system broad permissions to execute cloud infrastructure changes creates a massive blast radius. In a distributed, multi-repository architecture, a developer running Terraform from their own repository against another team's workspace is a critical vulnerability.

Enforcing a Cryptographic Path-to-Workspace Mapping

A common reaction is to rely on mandatory pull request approvals and code owners. But required approvals do not eliminate accidents. They just ensure two people signed off on the code. Human rubber-stamping misses copy-paste errors in backend blocks. Code reviews are not a secure system boundary.

To solve this, Pinterest enforces a strict, cryptographic path-to-workspace mapping. The core of this mechanism is their S3 backend validation trick.

The S3 Backend Validation Trick

When a pull request triggers the centralized GitHub Action, the pipeline does not immediately run a Terraform plan. First, it checks out a central source-of-truth configuration file. This file explicitly maps every single workspace to an allowed repository name, a specific directory path, a team name, and an execution role.

Before the pipeline even initializes Terraform, it parses the root module code submitted in the pull request. It runs a validation check to guarantee that the code path strictly references the explicit S3 state backend blocks and KMS keys mapped to that exact workspace in the central registry.

If a developer copies code and alters the backend block to point to workspace two, while executing inside the directory mapped to workspace one, the validation logic catches the discrepancy. The pipeline instantly fails the build. You cannot target a workspace unless your exact repository and file path are explicitly authorized to mutate that specific state file.

Securing the Execution Identity

Validating the state file is only half the equation. The execution identity is the other. Securing a GitHub Actions pipeline requires more than just storing a long-lived AWS credential in a secret variable. Pinterest secures the execution identity using a multi-hop IAM role assumption pattern.

Their GitHub Action workflows use GitHub OpenID Connect to authenticate with AWS. First, the pipeline assumes a highly restricted central identity called the RPP Actions Role. To ensure complete call authenticity, this central role can only be assumed from specific, pre-authorized GitHub workflows. The OIDC token validation enforces this directly at the AWS cloud provider layer based on the subject claims coming from GitHub.

Once the pipeline operates under this central role, it performs the workspace property determination and the strict backend validation. If and only if that validation passes, the pipeline takes a second hop. The central RPP Actions Role assumes a designated, down-scoped team execution role. This localizes the blast radius. By linking specific code paths to specific workspaces and IAM roles, the change is applied with the absolute minimal permissions required for that specific team's infrastructure.

With the localized team role assumed, the deployment process moves forward with fine-grained precision. The workspace initializes and runs basic linting to surface syntax bugs. The pipeline executes a plan and publishes the output directly as a comment on the pull request. If the plan fails, the GitHub check is marked as failed, blocking the merge.

Once the plan is approved, applying the changes requires an explicit comment on the pull request. This intentional step guarantees that code owners are consciously authorizing the mutation. The apply workflow runs through the exact same secure role-chaining process, triggers the apply, and posts the final output back to the thread. The mechanics here are tightly engineered.

Build vs. Buy: The Case for Managed Platforms

Tying the OIDC identity to a central registry, verifying the backend block against the repo path, and then down-scoping the IAM role creates a formidable security boundary. But why build a custom pipeline to do this? Why not just pay for a dedicated infrastructure platform like HCP Terraform, or Spacelift? Those managed platforms solve this exact problem without requiring you to build and maintain a custom execution engine.

If you want a pull request-driven workflow with secure role assumption and strict workspace isolation, Atlantis is a boring, open-source alternative that provides this out of the box.

Building a proprietary GitHub Actions execution engine to orchestrate thousands of Terraform resources is a massive undertaking. Pinterest took this route because they are operating a legacy multi-repo Terraform structure across a huge engineering organization. Enforcing IAM boundaries across entirely autonomous, disconnected repositories requires extreme custom guardrails.

The Heavy Burden of a Custom Architecture

But the operational burden of this architecture is heavy. As teams and workspaces scale, managing that central source-of-truth configuration file becomes a severe bottleneck. It is a monolithic registry of every repository path, workspace, and IAM role in the company. Every time a team needs to spin up a new environment, that central file has to be updated.

Furthermore, tightly coupling every infrastructure deployment to a single set of centralized composite GitHub Actions creates a significant single point of failure. If multiple pull requests trigger plans or applies against the same workspace simultaneously, your custom engine has to handle state locks and race conditions natively. Managed platforms give you queueing and lock management out of the box.

With custom GitHub Actions, you are building that concurrency logic yourself. There is also the developer experience cost. When an apply fails in a strictly locked-down pipeline, product engineers have to debug the infrastructure issue. But because the pipeline enforces strict role-chaining, those engineers often lack the local access required to assume the team IAM role from their own machines. They are stuck trying to debug state issues through pull request comments.

Maintaining this custom framework, the OIDC integrations, and the associated static analysis rules requires a large, dedicated platform engineering team.

The Takeaway: Copy the Pattern, Not the Pipeline

Is this multi-hop IAM role assumption pattern worth the complexity for a fifty-person engineering team, or is it just Pinterest-scale over-engineering? Building the execution engine yourself is over-engineering. For organizations at a normal scale, writing a custom Terraform orchestrator inside GitHub Actions is a massive waste of engineering cycles. You should buy a dedicated Infrastructure as Code continuous integration platform or run Atlantis.

But the specific security pattern is entirely worth adopting. The concept of rigid path-to-workspace mapping is highly effective. You can isolate your state files without writing a custom CI runner. Even if you use an off-the-shelf tool, you can implement a fast pre-flight check in your pipeline. Parse your Terraform configuration, read the backend block, and strictly assert that the directory path executing the code matches the state file it is attempting to alter.

The S3 backend validation trick is a pure architectural win. Tying the physical file path to the allowed execution role eliminates an entire category of cross-environment accidents. Copy the validation logic. Buy the orchestrator.

This is TAKEYOURPILLS.TECH. Go ship something.

References

/