Building and Governing AWS Organizations with Terraform at Scale

Managing a growing AWS estate without a coherent multi-account strategy quickly becomes operational overhead. AWS Organizations provides the backbone for multi-account AWS management by centralizing billing, access control, and policy enforcement across all accounts. Service Control Policies are the guardrails that define the maximum permissions available to accounts in your organization. When the entire organizational structure and policy framework lives in Terraform, the definition is versioned, peer-reviewed, and reproducible.

Terraform operates in a way similar to AWS CloudFormation, the AWS native IaC solution. For Organizations workloads, Terraform enables declarative creation of the organization itself, organizational units, member accounts, policy types, and guardrails such as AWS Config rules that are deployed either with AWS CloudFormation or Terraform. The result is a single source of truth for the account hierarchy and the controls that apply to it.

Prerequisites for Terraform Organization Management

Before running any Terraform code against Organizations, the foundational tooling must be in place.

  • Terraform 1.0 or later
  • AWS CLI configured
  • AWS credentials for the management account, the account that will own the organization
  • Root or management account access
  • Understanding of AWS multi-account strategy concepts
  • Understanding of organizational structure for production, staging, development and workload separation

Project structure for a reusable Organizations module typically looks like:

aws-organizations-terraform/ ├── main.tf ├── variables.tf ├── outputs.tf └── terraform.tfvars

This separation keeps provider configuration, resource definitions, and variable inputs clean and enables reuse across environments.

Provider Configuration and Version Constraints

The AWS provider is the execution engine for all Organizations resources.

hcl terraform { required_version = ">= 1.0" required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } }

The provider that uses credentials from the management account is usually configured for a central region.

hcl provider "aws" { region = "us-east-1" }

Alternative examples use eu-central-1 for European deployments.

hcl provider "aws" { region = "eu-central-1" }

Pinning provider versions avoids breaking changes in resource schemas for aws_organizations_organization, aws_organizations_organizational_unit, aws_organizations_account, and aws_organizations_policy.

Creating the AWS Organization

The first step is creating the AWS Organization itself. An empty organization can be defined to bootstrap later resources.

hcl resource "aws_organizations_organization" "organization" { }

A more complete definition enables consolidated billing and service access for security and governance services.

hcl resource "aws_organizations_organization" "main" { aws_service_access_principals = [ "cloudtrail.amazonaws.com", "config.amazonaws.com", "sso.amazonaws.com", "backup.amazonaws.com", "guardduty.amazonaws.com" ] feature_set = "ALL" enabled_policy_types = [ "SERVICE_CONTROL_POLICY", "TAG_POLICY", "BACKUP_POLICY", "AISERVICES_OPT_OPT_OUT_POLICY" ] }

The feature_set = "ALL" enables all Organizations features. Enabled policy types include SERVICECONTROLPOLICY for guardrails, TAGPOLICY for tagging enforcement, BACKUPPOLICY for backup controls, and AISERVICESOPTOUT_POLICY for AI service opt-out.

Resource Key Attribute Purpose
awsorganizationsorganization awsserviceaccess_principals Grants AWS services permission to access the organization
awsorganizationsorganization feature_set Controls available Organizations features
awsorganizationsorganization enabledpolicytypes Activates policy types for SCPs, tag policies, etc.

Organizational Units and Hierarchy

Once the organization exists, the roots and OUs define the account hierarchy.

hcl resource "aws_organizations_organizational_unit" "root" { name = var.organization_name parent_id = aws_organizations_organization.main.roots[0].id }

Environment separation is a common pattern.

hcl resource "aws_organizations_organizational_unit" "environments" { for_each = toset(["Production", "Staging", "Development"]) name = each.key parent_id = aws_organizations_organizational_unit.root.id }

Workload separation adds another dimension.

hcl resource "aws_organizations_organizational_unit" "workloads" { for_each = toset(["Applications", "Data", "Security", "Shared"]) name = each.key parent_id = aws_organizations_organizational_unit.root.id }

Partitioning cloud infrastructure across different AWS accounts is a best-practice that makes achieving the AWS Well Architected pillars significantly easier. A rogue lambda recursively invoking itself in staging would ordinarily exhaust the account's concurrent lambda execution quota and kill production, but if staging and production are separate AWS accounts then they get separate account-level quotas.

Creating Member Accounts with Terraform

Accounts are created under the organization with distinct emails and admin roles.

hcl resource "aws_organizations_account" "users" { name = "acme-corp-users" email = "[email protected]" role_name = "Admin" }

hcl resource "aws_organizations_account" "staging" { name = "acme-corp-staging" email = "[email protected]" role_name = "Admin" }

hcl resource "aws_organizations_account" "production" { name = "acme-corp-production" email = "[email protected]" role_name = "Admin" }

Note that there's a different email for each account. The users account can be used only for user management while staging and production are used for application infrastructure, therefore environment separation is achieved at the AWS account level.

A typical reference implementation also creates IAM groups and roles for developers, and provisions an S3 bucket and DynamoDB table for the Terraform backend.

Service Control Policies as Guardrails

Service Control Policies define the maximum permissions available to accounts in your organization. Managing all of this through Terraform means the entire policy framework lives in version control.

hcl resource "aws_organizations_policy" "deny_root" { name = "DenyRootAccess" }

SCPs can be attached to OUs to enforce least privilege, deny actions, require encryption, or block risky services. Because SCPs are evaluated before IAM, they provide an organization-wide safety net that cannot be overridden by member account administrators.

Policy Type Example Use Case
SERVICECONTROLPOLICY Deny root user access, block wildcard IAM
TAG_POLICY Require CostCenter and Environment tags
BACKUP_POLICY Enforce backup plans for critical resources
AISERVICESOPTOUT_POLICY Opt out of generative AI services

AWS Config and Centralized Compliance with Organizations

AWS Config provides configuration, compliance, and auditing features that are required for governing resources and providing security posture assessment at scale. With support for AWS Organizations, AWS Config makes it possible to manage the organization centrally, with rules deployed either with AWS CloudFormation or Terraform.

Architecture when deployed via Terraform:

  • AWS Config and the configuration recorder and delivery channel must be run in the delegated administrator and member accounts.
  • The administrator account aggregates its findings through AWS Organizations.
  • In secondary/member accounts, Config is collecting data on resources in the environment, and making a determination of compliant or non-compliant based on the AWS Config rules.

Terraform can create the organization with service access principals for config.amazonaws.com and cloudtrail.amazonaws.com, enabling organization-wide configuration recording and centralized logging.

A centralized CloudTrail example for organization trails:

hcl resource "aws_cloudtrail" "org_trail" { name = aws_s3_bucket.cloudtrail.id include_global_service_events = true is_organization_trail = true enable_logging = true event_selector { read_write_type = "All" include_management_events = true } tags = { Environment = "Organization" ManagedBy = "Terraform" } }

AWS CloudFormation also provides resources and properties for deploying organization AWS Config rules, allowing hybrid IaC environments.

Managing Organizations End-to-End with Terraform

Infrastructure-as-code tools help streamline and systematize configuration of AWS Organizations. Configuring the baseline organization can be done in only a few minutes, and from there adding new accounts can be done with only a few lines of code if set up right.

The downside of running with multiple AWS accounts is that they can be complicated to set up and manage. AWS Organizations is intimidating the first time you open it up, and it’s easy to make mistakes the first time you go to set up an account hierarchy. Terraform codifies the hierarchy and guardrails.

Typical steps covered in a comprehensive guide:
- Create an organization from scratch
- Set up organizational units
- Create accounts
- Write effective SCPs
- Enable AWS Config delegated administrator
- Deploy organization-wide CloudTrail

When setting up a new organization on AWS, you have to create quite a few resources before you can develop any application infrastructure. Thankfully these resources, just like almost any other resources, can be created and managed with Terraform.

Conclusion

AWS Organizations is the backbone of multi-account AWS management and Terraform is the control plane that makes that backbone reproducible. By defining the organization, OUs, member accounts, service access principals, policy types, SCPs, and centralized AWS Config in code, teams gain version control, peer review, and automated drift detection for their governance model.

The pattern scales from a three-account users/staging/production setup to enterprise hierarchies with dozens of OUs, workload-specific SCPs, and delegated administrators for Security, Config, and Backup. The key is to codify the management account provider, enable the required policy types, attach SCPs at the OU level, and delegate AWS Config and CloudTrail to a central administrator account. This setup provides a comprehensive foundation for deploying AWS Organizations using Terraform and enables guardrails at scale across the entire estate.

Sources

  1. AWS Organizations, AWS Config, and Terraform
  2. Create organizations and scps in terraform
  3. AWS Organizations Terraform
  4. Setting up an AWS organization from scratch with Terraform
  5. Managing your AWS organization in Terraform

Related Posts