Sitemap

Running Terraform in AWS GovCloud for FedRAMP High: A Practical In-Boundary Pipeline

6 min readJul 11, 2025
Press enter or click to view image in full size
Photo by Josh Olalde on Unsplash

Infrastructure as Code (IaC) has revolutionized the way we build and maintain cloud infrastructure, and Terraform has emerged a leader. In commercial environments, managing Terraform with Terraform Cloud, GitHub Actions, or Atlantis is straightforward. These platforms offer convenient features like a web UI, state management, drift detection, and team-based workflows.

But if you’re working on FedRAMP High-authorized systems in AWS GovCloud, you already know the landscape is very different. SaaS-based Terraform management tools aren’t compliant. External CI/CD runners are out. And all tooling must be hosted entirely in-boundary using FedRAMP-authorized services.

So what do you do when you need a safe, auditable, and automated way to apply Terraform in GovCloud?

This blog post outlines a secure, fully in-boundary pattern for running Terraform using:

  • GitLab for source control
  • AWS CodePipeline for orchestration
  • AWS CodeBuild for Terraform execution
  • Amazon S3 (with native state locking) as the backend

This solution lets you keep the flexibility and speed of Terraform automation without sacrificing compliance or security.

The Problem: No SaaS in a FedRAMP High World

SaaS tools such as Terraform Cloud offer convenient features: execution logs, drift detection, state locking, variable management, RBAC, and more. But the convenience comes with a caveat: these tools are not FedRAMP High authorized, nor are they hosted in GovCloud. This makes them unsuitable for workloads that must remain strictly in-boundary.

FedRAMP High imposes stringent controls around data sovereignty, user access, logging, and network boundaries. For government agencies and contractors, this often means:

  • No internet-based execution services (Terraform Cloud, GitHub Actions, etc.)
  • All tools and pipelines must reside within AWS GovCloud or another FedRAMP-authorized environment
  • Logs, artifacts, and state must be stored within compliant systems

So how do you automate Terraform deployments in GovCloud while meeting these requirements?

The Solution:

To maintain full boundary compliance while still enjoying the benefits of automated Terraform workflows, you can architect a solution using self-hosted GitLab, AWS CodePipeline, AWS CodeBuild, and S3.

High-Level Architecture

Here’s what a compliant, fully in-boundary setup looks like:

  1. Self-Hosted GitLab in GovCloud:
  • Stores Terraform code in repositories
  • Triggers pipelines using webhook events
  • Provides merge request workflows and audit logs
  • Able to be run in a fully FIPS-compliant manner

2. AWS CodePipeline:

  • Manages pipeline orchestration
  • Pulls Terraform code from GitLab via CodeCommit or artifact store
  • Invokes CodeBuild jobs to plan/apply Terraform

3. AWS CodeBuild:

  • Executes terraform init, plan, apply
  • Uses IAM roles for secure access to AWS APIs
  • Stores state files securely in S3 with state locking via DynamoDB

4. Artifact & State Storage:

  • S3 bucket for Terraform state and concurrency control (private, encrypted, access-logged)
  • S3 or CodePipeline artifacts for pipeline inputs/outputs

Step-by-Step Implementation

Let’s walk through each layer of the implementation.

1. GitLab: Hosting the Terraform Code

Your GitLab instance must be hosted in GovCloud. Configure it with:

  • Internal runners for CI if needed (optional in this setup)
  • Merge request protections
  • Webhooks to notify downstream services of new commits (optional for polling-based pipeline triggers)

2. Terraform Backend Configuration

Use a backend configuration that stores state securely in GovCloud:

terraform {
backend "s3" {
bucket = "govcloud-tf-state"
key = "envs/prod/main.tfstate"
region = "us-gov-east-1"
lock_table = "s3" # No need for DynamoDB
encrypt = true
}
}

This enables locking directly via the S3 API. Make sure the bucket:

  • Has bucket versioning enabled
  • Has encryption enforced (SSE-KMS with a customer-managed CMK)
  • Has access logs and IAM policies that restrict access
  • Is private and not publicly accessible
  • Optionally includes replication for DR

The new lock_table = "s3" setting tells Terraform to use the new S3-native locking capability, so no DynamoDB is needed.

⚠️ Note: As of this writing, ensure you’re using Terraform 1.8 or later for full support of this feature.

3. CodePipeline: Orchestrating the Workflow

Create a CodePipeline with the following stages:

  • Source Stage: Pulls code directly from GitLab using an AWS CodeStar connection, which securely links your GovCloud pipeline to your GitLab repository.
  • Build Stage: Invokes a CodeBuild project that runs Terraform commands (init, plan, and apply).

Using AWS CodeStar Connections with GitLab

AWS recently added support for GitLab (self-managed and GitLab.com) as a source in CodePipeline via CodeStar Connections, allowing you to trigger pipeline executions directly from GitLab events like commits or merges — all without needing a mirror in CodeCommit.

To use this:

  1. Create a CodeStar connection to GitLab (via IAM and AWS Developer Tools).
  2. Authorize the connection in the AWS console or via the AWS CLI.
  3. Reference the connection in your CodePipeline source configuration.

Example CodePipeline configuration:

{
"stages": [
{
"name": "Source",
"actions": [
{
"name": "GitLabSource",
"actionTypeId": {
"category": "Source",
"owner": "AWS",
"provider": "CodeStarSourceConnection",
"version": "1"
},
"outputArtifacts": [
{
"name": "SourceOutput"
}
],
"configuration": {
"ConnectionArn": "arn:aws:codestar-connections:us-gov-east-1:123456789012:connection/abcd1234-5678-90ef-ghij-klmnopqrstuv",
"FullRepositoryId": "my-org/terraform-infra",
"BranchName": "main"
},
"runOrder": 1
}
]
},
{
"name": "Plan",
"actions": [
{
"name": "TerraformPlan",
"actionTypeId": {
"category": "Build",
"owner": "AWS",
"provider": "CodeBuild",
"version": "1"
},
"inputArtifacts": [
{
"name": "SourceOutput"
}
],
"outputArtifacts": [
{
"name": "PlanOutput"
}
],
"configuration": {
"ProjectName": "terraform-plan-codebuild"
},
"runOrder": 1
}
]
},
{
"name": "Approve",
"actions": [
{
"name": "ManualApproval",
"actionTypeId": {
"category": "Approval",
"owner": "AWS",
"provider": "Manual",
"version": "1"
},
"runOrder": 1
}
]
},
{
"name": "Apply",
"actions": [
{
"name": "TerraformApply",
"actionTypeId": {
"category": "Build",
"owner": "AWS",
"provider": "CodeBuild",
"version": "1"
},
"inputArtifacts": [
{
"name": "SourceOutput"
},
{
"name": "PlanOutput"
}
],
"configuration": {
"ProjectName": "terraform-apply-codebuild"
},
"runOrder": 1
}
]
}
]
}

⚠️You must use us-gov-east-1 region to create your CodeStar connection since it’s not available in us-gov-west-1.

This method allows you to trigger pipelines directly from GitLab and keeps the source control fully in-boundary and auditable.

The terraform-plan-codebuild project should:

  • Run terraform init and terraform plan -out=tfplan
  • Upload tfplan as an artifact for review

The terraform-apply-codebuild project should:

  • Download tfplan
  • Run terraform apply tfplan

The manual approval action allows for human review of the plan before applying any infrastructure changes.

4. CodeBuild: Executing Terraform

Define a buildspec.yml for the plan stage. This job runs terraform init and terraform plan, then packages the plan output (tfplan) as a CodePipeline artifact so it can be used in the Apply stage. Specify the appropriate TF version for the Terraform code you have written.

version: 0.2

phases:
install:
commands:
- echo "Installing Terraform..."
- curl -o terraform.zip https://releases.hashicorp.com/terraform/1.8.0/terraform_1.8.0_linux_amd64.zip
- unzip terraform.zip -d /usr/local/bin
- terraform version

pre_build:
commands:
- echo "Initializing Terraform..."
- terraform init

build:
commands:
- echo "Running terraform plan..."
- terraform plan -out=tfplan

artifacts:
files:
- tfplan

This job assumes the plan artifact (tfplan) has been reviewed and approved. It performs terraform apply on the approved plan.

version: 0.2

phases:
install:
commands:
- echo "Installing Terraform..."
- curl -o terraform.zip https://releases.hashicorp.com/terraform/1.8.0/terraform_1.8.0_linux_amd64.zip
- unzip terraform.zip -d /usr/local/bin
- terraform version

pre_build:
commands:
- echo "Initializing Terraform..."
- terraform init

build:
commands:
- echo "Applying terraform plan..."
- terraform apply -auto-approve tfplan

Use IAM roles for CodeBuild that grant least-privilege access to:

  • S3 for state and locking
  • AWS services your Terraform code is provisioning

Make sure the roles and logs follow FedRAMP access control guidelines (MFA for humans, scoped session tokens for machines, centralized audit logging, etc.).

Security and Compliance Considerations

To meet FedRAMP High, your Terraform automation setup should address:

  • Access Controls: Use IAM roles, groups, and SCPs to enforce RBAC
  • Auditability: Store CloudTrail logs, CodeBuild logs, and GitLab MR history in a secure, central log aggregator
  • Boundary Enforcement: No internet access to Terraform Cloud, GitHub Actions, or any outbound pipelines
  • Encryption: Use CMKs to encrypt all at-rest and in-transit data
  • Pipeline Approvals: Use CodePipeline’s manual approval actions or custom Lambda integrations

Optional Enhancements

Here are ways you can take this baseline architecture further:

  • Environment Separation: Use one pipeline per environment (dev, test, prod) with different backends and roles
  • Custom Terraform Modules: Host private modules in S3 or GitLab, not the Terraform Registry
  • Secrets Management: Use AWS Secrets Manager or Parameter Store (not hard-coded vars)
  • Guardrails: Integrate tools like Checkov or Conftest in CodeBuild for policy-as-code enforcement
  • SNS Notifications: Integrate approvals and status updates into secure chat channels

Conclusion

While SaaS tools like Terraform Cloud make IaC easier in commercial environments, they simply aren’t viable in high-side, compliance-heavy contexts like FedRAMP High in AWS GovCloud. With a thoughtful architecture using GitLab, CodePipeline, and CodeBuild, you can implement a secure, fully in-boundary Terraform automation framework that satisfies compliance requirements without sacrificing velocity.

By leaning on native AWS tools and infrastructure that is already FedRAMP-authorized, you remove risk from your supply chain while still maintaining a modern DevSecOps workflow.

--

--

Don Spidell
Don Spidell

Written by Don Spidell

Cloud Architect Lead at Allocore (formerly Summit Technology Group). Long-time AWS user highlighting interesting use cases and solutions built on AWS.

No responses yet