This is the multi-page printable view of this section.
Click here to print.
Return to the regular view of this page.
Documentation
Welcome to the Org Kickstart documentation. This section covers everything you need to deploy
and manage a governed AWS Organization using Terraform.
In This Section
1 - Overview
What Org Kickstart is and why you’d use it.
What is Org Kickstart?
Org Kickstart is an opinionated Terraform module for bootstrapping and managing AWS Organizations.
It is PrimeHarbor’s alternative to AWS Control Tower — designed to give you the good parts of a
landing zone without the cost, complexity, and lock-in that Control Tower brings.
Deployed into a brand new AWS Management (Payer) account, a single terraform apply can stand up
a fully governed AWS Organization with security services enabled, organizational guardrails in place,
and an account factory ready to provision new accounts.

Why not just use Control Tower?
Control Tower is a massive beast designed to support highly regulated enterprises. For most
organizations, it brings significant drawbacks:
- Expensive: Heavy reliance on AWS Config means costs scale with the number of accounts and regions.
- Inflexible: Modifications require navigating AWS Service Catalog customizations.
- Slow to update: Features like Organization CloudTrail and GuardDuty Delegated Admin lagged behind
AWS best practices for years.
- Complex: You effectively need a PhD in AWS Service Catalog to change anything.
Most organizations deploy Control Tower because their AWS Solutions Architect recommended it, or because
they needed an account factory. Org Kickstart gives you the account factory, the security posture, and
the governance — without the baggage.
What Org Kickstart does
Org Kickstart deploys and manages:
- Security Account — Creates a dedicated security account and delegates GuardDuty, Macie, Inspector, Security Hub, SSO, and CloudFormation StackSets
to a dedicated Security Account. Configures all security services in every default region
across all accounts.
- CloudTrail — Creates a CloudTrail bucket in the Security Account and enables an Organizations
CloudTrail in the Management Account.
- Alternate Contacts — Sets Billing, Operations, and Security contacts for all AWS accounts.
- Organizational Units — Creates four default OUs (Workloads, Governance, Sandbox, Suspended)
plus any custom OUs you define.
- AI Opt-Out Policy — Creates and applies a default AI opt-out policy at the root OU.
- Account Management — Manages AWS accounts and OU placement from Terraform.
- Audit Role — Deploys an Audit Role via CloudFormation StackSet to all accounts, trusting
the Security Account.
- Billing Reports — Creates an S3 bucket for billing data and an Athena-compatible CUR report.
- Organization Services — Enables all important AWS Organization Integrated Services.
- Org Policies — Manages Service Control Policies, Declarative Policies, and Resource Control Policies
with Terraform templating support.
- SSO / Identity Center — Creates an
AdministratorAccess Permission Set, an admin group,
and assigns both to every account.
What is required vs. optional?
Cannot be disabled:
- Security Account
- Four default OUs (Governance, Workloads, Sandbox, Suspended)
- AI Opt-Out Policy
- Core Organization Integrated Services
Can be disabled via variables:
- CloudTrail management:
cloudtrail_bucket_name = null
- SSO management:
disable_sso_management = true
- Audit Role StackSet:
deploy_audit_role = false
- Security services:
security_services object with disable_* flags
- CUR reports:
cur_report_frequency = "NONE"
- Alternate contacts: omit contact blocks from tfvars
Where should I go next?
2 - Getting Started
Prerequisites, bootstrapping, and first deployment.
This section walks you through getting Org Kickstart deployed into a new AWS account.
Prerequisites
Before running Org Kickstart you need:
- Terraform >= 1.0 (< 2.0)
- AWS CLI configured with credentials for the Management (Payer) account
- An S3 bucket for Terraform remote state
- A few manual “artisanal” steps completed in the AWS console (see Bootstrap)
Steps
- Complete the Bootstrap steps in the AWS Console
- Copy
examples/pipeline
to your own private repo — it includes the Makefile, backend config, and directory layout
- Create
your-org.tfvars and your-org.tfbackend for your organization
(see the Reference for all variables; name them to match your env value)
- Initialize Terraform:
make env=your-org tf-init
- Create the Security Account first (required before full apply):
terraform apply -var-file="your-org.tfvars" -target module.security_account
- Deploy everything:
make env=your-org tf-execute
This runs tf-plan followed by tf-apply — saving the plan, applying it, and writing
output-your-org.json to your state bucket.
For subsequent updates, use:
Using with an Existing Organization
If you already have an AWS Organization, see Importing an Existing Org for guidance on
importing existing resources into Terraform state.
Example tfvars
See the Reference page for a full annotated example. The
examples/pipeline
directory in the repository contains a sample private-repo layout with a Makefile, backend config
template, and scripts for CI/CD deployments.
2.1 - Bootstrap a New Account
Manual steps required in the AWS Console before running Terraform.
Before Org Kickstart can be deployed, a few steps must be completed via ClickOps in your new AWS
Management (Payer) account. Terraform cannot perform these actions automatically.
Root Account Tasks
Log into the root user of your new AWS “payer” account and complete the following:
- Add MFA to root
- Enable IAM access to billing
- Go to Organizations and create an Organization
- Go to AWS IAM Identity Center (SSO) and enable it
- Add yourself as a user in Identity Center
- Create a Permission Set named
TempAdministratorAccess (4-hour session recommended)
- Assign the Permission Set to the Payer/Management Account for your user
- Activate trusted access for CloudFormation StackSets — click “Activate trusted access with AWS Organizations to use service-managed permissions” (must be done via console)
Log out of root and never use it again.
Note: As of January 2026, Terraform does not support the aws login capability.
An IAM Identity Center or IAM User must be created to run Terraform.
On Your Machine
- Check email and activate your IAM Identity Center account
- Add MFA to your Identity Center account
- Configure AWS credentials in your environment:
aws configure sso
# or
export AWS_PROFILE=your-sso-profile
You are now ready to deploy Org Kickstart.
Next Steps
- Create your
tfvars file — see the Reference for all variables and a full example
- Run
terraform init and your first apply — see Getting Started
2.2 - Importing an Existing Organization
How to adopt Org Kickstart into an existing AWS Organization.
Org Kickstart can manage an existing AWS Organization. Several resources must be imported into
Terraform state before running terraform apply.
The minimum required imports are the organization, the management account, and the
Security Account (if it already exists). You may also want to import existing accounts,
CloudTrail buckets, billing buckets, and SSO configuration.
Automated Import
The scripts/import_org.sh script generates an import-org.tf file and a TFVars snippet for
your existing accounts.
# From the org-kickstart directory
./scripts/import_org.sh
Review the generated import-org.tf carefully before running Terraform.
Steps
- Run
import_org.sh and review import-org.tf
- Add your CloudTrail or billing bucket to the import file if applicable
- Review SCPs you want to import:
aws organizations list-policies --filter SERVICE_CONTROL_POLICY \
--query 'Policies[].[Id,Name]' --output text
- Iterate with
tf-plan until no unwanted changes appear:
make env=your-org tf-plan
make env=your-org tf-show # review the plan output
- Once satisfied, apply:
make env=your-org tf-apply
- Incrementally enable additional features
Manual Import Examples
Organizational Units
ROOT_OU=$(aws organizations list-roots --query Roots[0].Id --output text)
aws organizations list-organizational-units-for-parent \
--parent-id $ROOT_OU \
--query 'OrganizationalUnits[].[Id,Name]' --output text
import {
to = module.organization.aws_organizations_organizational_unit.TF_VARS_KEY
id = "ou-xxxx-xxxxxxxx"
}
IAM Identity Center (SSO)
To opt out of managing an existing Identity Center, set disable_sso_management = true in your
tfvars. This is recommended for existing orgs with complex SSO configurations.
IDENTITY_STORE_ID=$(aws sso-admin list-instances \
--query Instances[0].IdentityStoreId --output text)
SSO_INSTANCE_ARN=$(aws sso-admin list-instances \
--query Instances[0].InstanceArn --output text)
import {
to = module.organization.aws_identitystore_group.admin_group
id = "$IDENTITY_STORE_ID/$GROUP_ID"
}
import {
to = module.organization.aws_ssoadmin_permission_set.admin_permission_set
id = "$PERMISSION_SET_ARN,$SSO_INSTANCE_ARN"
}
import {
to = module.organization.aws_ssoadmin_managed_policy_attachment.admin_policy_attachments
id = "arn:aws:iam::aws:policy/AdministratorAccess,$PERMISSION_SET_ARN,$SSO_INSTANCE_ARN"
}
CloudTrail
aws cloudtrail list-trails --query Trails[].TrailARN --output text
import {
to = module.organization.aws_s3_bucket.cloudtrail_bucket[0]
id = "YOUR_EXISTING_BUCKET_NAME"
}
import {
to = module.organization.aws_cloudtrail.org_cloudtrail[0]
id = "TRAIL_ARN"
}
Service Control Policies
aws organizations list-policies --filter SERVICE_CONTROL_POLICY \
--query 'Policies[].[Id,Name]' --output text
# Get OUs targeted by a policy
aws organizations list-targets-for-policy --policy-id p-xxxxxx
import {
to = module.organization.module.scp["POLICY_BLOCK_IDENTIFIER_FROM_TFVARS"].aws_organizations_policy.org_policy
id = "p-xxxxxx"
}
Disabling Features for Initial Import
When importing an existing org, you may want to temporarily disable features to prevent
unintended changes on the first apply:
- CloudTrail:
cloudtrail_bucket_name = null
- SSO:
disable_sso_management = true
- Audit Role StackSet:
deploy_audit_role = false
- Security Services: use the
security_services block with disable_* flags
2.3 - Example tfvars
A complete annotated example tfvars file.
The following is a complete example tfvars file showing all major configuration options.
Copy this as a starting point and customize for your organization.
organization = {
organization_name = "my-org"
payer_name = "My Org Management Account"
payer_email = "aws+payer@example.com"
security_account_name = "my-org-security"
security_account_root_email = "aws+security@example.com"
cloudtrail_bucket_name = "my-org-cloudtrail"
cloudtrail_loggroup_name = "CloudTrail/DefaultLogGroup"
billing_data_bucket_name = "my-org-cur"
cur_report_frequency = "DAILY" # DAILY, HOURLY, or MONTHLY
session_duration = "PT8H"
admin_permission_set_name = "AdministratorAccess"
admin_group_name = "AllAdmins"
disable_sso_management = false
deploy_audit_role = true
audit_role_name = "security-audit"
audit_role_stack_set_template_url = "https://s3.amazonaws.com/pht-cloudformation/aws-account-automation/AuditRole-Template.yaml"
declarative_policy_bucket_name = "my-org-account-status"
vpc_flowlogs_bucket_name = "my-org-flowlogs"
macie_bucket_name = "my-org-macie-findings"
# Custom OUs (in addition to the four required OUs)
organization_units = {
"Platform" = {
name = "Platform"
is_child_of_root = true
}
}
# AWS Accounts
accounts = {
dev = {
account_name = "my-org-dev"
account_email = "aws+dev@example.com"
monthly_budget_amount = 500
}
prod = {
account_name = "my-org-prod"
account_email = "aws+prod@example.com"
parent_ou_name = "Workloads"
}
sandbox = {
account_name = "my-org-sandbox"
account_email = "aws+sandbox@example.com"
parent_ou_name = "Sandbox"
}
sso = {
account_name = "my-org-sso"
account_email = "aws+sso@example.com"
parent_ou_name = "Governance"
delegated_admin = ["sso.amazonaws.com"]
}
}
# Alternate contacts applied to all accounts (can be overridden per account)
global_billing_contact = {
name = "Finance Team"
title = "CFO"
email_address = "billing@example.com"
phone_number = "+14041234567"
}
global_security_contact = {
name = "Security Team"
title = "CISO"
email_address = "security@example.com"
phone_number = "+14041234567"
}
global_primary_contact = {
full_name = "IT Operations"
company_name = "My Org, Inc."
address_line_1 = "123 Main Street"
city = "Atlanta"
state_or_region = "GA"
postal_code = "30332"
country_code = "US"
email_address = "aws@example.com"
phone_number = "+14041234567"
}
# Service Control Policies
service_control_policies = {
deny_root = {
policy_name = "DenyRoot"
policy_description = "Denies use of root user"
policy_json_file = "policies/DenyRootSCP.json"
}
security_controls = {
policy_name = "DefaultSecurityControls"
policy_description = "Base security controls for all accounts"
policy_json_file = "policies/SecurityControlsSCP.json.tftpl"
policy_vars = {
audit_role_name = "security-audit"
}
}
}
# Resource Control Policies
resource_control_policies = {
s3_data_perimeter = {
policy_name = "S3DataPerimeter"
policy_description = "Restricts S3 to principals inside the org"
policy_json_file = "policies/RCP_S3DataPerimeter.json.tftpl"
policy_vars = {
org_id = "o-xxxxxxxxxxxx"
}
}
}
# Declarative Policies
declarative_policies = {
deny_public_ami = {
policy_name = "Block_Public_AMIs"
policy_description = "Deny public sharing of all AMIs"
policy_type = "DECLARATIVE_POLICY_EC2"
policy_json_file = "policies/EC2ImageBPA_DCP.json"
policy_targets = ["Workloads", "Governance", "Sandbox"]
}
}
# Security Services
security_services = {
disable_guardduty = false
disable_securityhub = false
disable_macie = false
}
# Billing Alerts
billing_alerts = {
levels = {
level1 = 100
level2 = 500
oh_shit = 1000
}
subscriptions = ["billing-alerts@example.com"]
}
budget_defaults = {
alert_recipients = ["finance@example.com"]
currency = "USD"
warning_percentage = 80
organizational_budget = 1000
}
}
backend_bucket = "my-org-terraform-state-123456789012"
Backend Config File
Create a my-org.tfbackend file alongside your tfvars:
bucket = "my-org-terraform-state-123456789012"
key = "org-kickstart.tfstate"
region = "us-east-1"
Then initialize with:
terraform init -backend-config="my-org.tfbackend"
3 - Examples
Example configurations and pipeline setups.
Pipeline Example
The examples/pipeline
directory in the repository contains a sample layout for a private CI/CD deployment repo.
This shows how to structure your organization-specific configuration files alongside the module.
Sample tfvars
See the Example tfvars page for a full annotated example
configuration file covering all major options.
Policy Library
Ready-to-use policy files are available in the
policies/ directory:
DenyRootSCP.json — Deny root user access
SecurityControlsSCP.json.tftpl — Base security guardrails
DisableRegionsPolicy.json.tftpl — Region restrictions
RCP_S3DataPerimeter.json.tftpl — S3 data perimeter
EC2IMDSv2Enforce_DCP.json — IMDSv2 enforcement
- And more…
Importing an Existing Organization
See Importing an Existing Organization for a step-by-step guide
on adopting Org Kickstart in an existing AWS Organization.
4 - Concepts
Key concepts and architecture behind Org Kickstart.
AWS Organizations Structure
Org Kickstart manages resources in two AWS accounts simultaneously using Terraform’s
multi-provider pattern:
- Management (Payer) Account — Where Terraform runs. Contains the Organization,
OUs, SCPs, RCPs, Declarative Policies, CloudTrail, and SSO/Identity Center.
- Security Account — A dedicated account that is Delegated Administrator for
GuardDuty, Macie, Inspector, Security Hub, CloudFormation StackSets, and optionally SSO.
Required Organizational Units
Four OUs are always created and cannot be disabled:
| OU |
Purpose |
Governance |
Security and payer accounts |
Workloads |
Production workload accounts |
Sandbox |
Development accounts with more freedom |
Suspended |
Accounts pending closure |
Policy Types
AWS Organizations supports three types of preventive controls, all managed by Org Kickstart:
| Type |
Abbreviation |
Scope |
| Service Control Policies |
SCP |
What IAM principals can do |
| Resource Control Policies |
RCP |
What can be done to resources |
| Declarative Policies |
DP |
Baseline configuration of AWS services (EC2 only) |
All three are defined using the same Terraform structure and support .tftpl templating.
Security Services
Org Kickstart enables and configures the following security services across all default
AWS regions and all accounts in the organization:
- GuardDuty — Threat detection. Payer and Security account both run detectors.
- Security Hub — Aggregated security findings. Security Account is delegated admin.
- Inspector — Vulnerability management. Security Account is delegated admin.
- Macie — S3 data security. Security Account is delegated admin.
Audit Role
A cross-account audit role is deployed to every account via CloudFormation StackSets.
The role trusts the Security Account, allowing centralized read access for security
tools and audits without needing IAM users in every account.
Account Factory Pattern
New AWS accounts are defined in the accounts map in tfvars. The account module
handles everything automatically:
- Creates the AWS Organizations account
- Places it in the correct OU
- Assigns SSO access (via Identity Center group and Permission Set)
- Sets billing, operations, and security alternate contacts
- Creates a budget with alert thresholds
- Applies SCPs/RCPs/Declarative Policies inherited from the parent OU
5 - Tasks
How-to guides for common Org Kickstart operations.
This section contains task-oriented guides for common Org Kickstart operations.
Common Tasks
5.1 - Adding a New Account
How to add a new AWS account to your organization.
Adding a new AWS account is the most common operation in Org Kickstart. All account configuration
lives in the accounts map in your tfvars file.
Steps
-
Add an entry to the accounts map in your tfvars file:
accounts = {
# ... existing accounts ...
my_new_account = {
account_name = "my-org-new-account"
account_email = "aws+new-account@example.com"
parent_ou_name = "Workloads"
monthly_budget_amount = 500
}
}
-
Plan and apply:
make env=your-org tf-execute
Or step-by-step to review the plan before applying:
make env=your-org tf-plan
make env=your-org tf-show
make env=your-org tf-apply
Org Kickstart will create the AWS account, place it in the correct OU, assign SSO access,
set alternate contacts, and apply any policies that target the parent OU.
Account Options
| Option |
Description |
account_name |
Display name for the AWS account |
account_email |
Root email address (must be globally unique) |
parent_ou_name |
Place the account in this OU (by name) |
parent_ou_id |
Place the account in this OU (by ID) |
monthly_budget_amount |
Budget alert threshold in USD |
delegated_admin |
List of AWS services to delegate admin for |
close_on_deletion |
Whether to close the account when removed from Terraform |
primary_contact |
Override the global primary contact for this account |
Notes
- The
account_email must be unique across all AWS accounts globally
- New accounts are created by AWS Organizations and may take a few minutes to become available
- The Security Account is managed separately via the
security_account block
5.2 - Creating Policies
How to create and attach SCPs, RCPs, and Declarative Policies.
Org Kickstart manages three types of AWS Organizations policies via the same Terraform pattern:
Service Control Policies (SCPs), Resource Control Policies (RCPs), and
Declarative Policies.
Steps
-
Create a policy JSON file in the policies/ directory of your deployment repo.
For dynamic values, use a .tftpl extension and Terraform template syntax.
// policies/MyPolicy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": "s3:DeleteBucket",
"Resource": "*"
}
]
}
-
Add the policy definition to the appropriate block in your tfvars file:
service_control_policies = {
deny_s3_delete = {
policy_name = "DenyS3BucketDeletion"
policy_description = "Prevent deletion of S3 buckets"
policy_json_file = "policies/MyPolicy.json"
policy_targets = ["Workloads", "Sandbox"]
}
}
-
Plan and apply:
make env=your-org tf-execute
SCPs and RCPs are high-impact changes. Always review the plan before applying:
make env=your-org tf-plan
make env=your-org tf-show
make env=your-org tf-apply
You can also run a security scan of the plan with Checkov before applying:
make env=your-org checkov
Policy Types
| Block |
AWS Type |
service_control_policies |
Service Control Policy (SCP) |
resource_control_policies |
Resource Control Policy (RCP) |
declarative_policies |
Declarative Policy (EC2) |
Declarative Policies also require policy_type = "DECLARATIVE_POLICY_EC2".
Targeting OUs
policy_targets accepts a list of OU names or OU IDs. Use "Root" to target the
organization root:
policy_targets = ["Root"] # all accounts
policy_targets = ["Workloads", "Sandbox"] # by name
policy_targets = ["ou-xxxx-xxxxxxxx"] # by ID
Templated Policies
For policies that need org-specific values, use a .tftpl file:
// policies/AuditRoleProtection.json.tftpl
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Deny",
"Action": ["iam:Delete*"],
"Resource": "arn:aws:iam::*:role/${audit_role_name}"
}]
}
service_control_policies = {
protect_audit_role = {
policy_name = "ProtectAuditRole"
policy_json_file = "policies/AuditRoleProtection.json.tftpl"
policy_vars = {
audit_role_name = "security-audit"
}
}
}
Sample Policies
See the policies/ directory
in the repository for a library of ready-to-use policies. Or check out PrimeHarbor’s respository of Organizational Policies.
6 - Tutorials
End-to-end walkthroughs for common Org Kickstart scenarios.
Step-by-step tutorials for common deployment scenarios.
7 - Reference
Variable reference, policy library, and module documentation.
This section contains low-level reference documentation for Org Kickstart.
In This Section
Source
The complete module documentation is generated from the Terraform source and available in the
ModuleDocs.md file in
the repository.
Policy Library
Sample policies are included in the policies/
directory of the repository:
| File |
Type |
Description |
DenyRootSCP.json |
SCP |
Deny use of root user in all accounts |
SecurityControlsSCP.json.tftpl |
SCP |
Base security controls (requires audit_role_name) |
DisableRegionsPolicy.json.tftpl |
SCP |
Restrict to approved AWS regions |
DenyUnapprovedInstanceTypes.json |
SCP |
Deny non-approved EC2 instance types |
DenyUnapprovedServices.json |
SCP |
Deny unapproved AWS services |
SuspendedAccountsPolicy.json.tftpl |
SCP |
Deny all activity in suspended accounts |
RCP_S3DataPerimeter.json.tftpl |
RCP |
Restrict S3 access to org principals |
EC2ImageBPA_DCP.json |
Declarative |
Block public sharing of AMIs |
EC2SnapshotBPA_DCP.json |
Declarative |
Block public sharing of EBS snapshots |
EC2IMDSv2Enforce_DCP.json |
Declarative |
Enforce IMDSv2 with hop limit of 2 |
Policies with the .tftpl extension support Terraform template variables via policy_vars.
7.1 - Module Documentation
Auto-generated Terraform module reference — inputs, outputs, resources, and sub-modules.
This page is auto-generated from the Terraform source in
[org-kickstart](https://github.com/primeharbor/org-kickstart).
Run `make generate-module-docs` in the `org-kickstart-site/` directory to refresh it.
Requirements
| Name |
Version |
| aws |
>= 5.80.0 |
Providers
Modules
Resources
Outputs
7.2 - Parameter Reference
All Terraform variables for the Org Kickstart module.
All configuration is passed via the organization variable (an object type) and a few
top-level variables. Below are the key configuration parameters.
Top-Level Variables
| Variable |
Type |
Required |
Description |
organization |
object |
Yes |
Main configuration object (see below) |
backend_bucket |
string |
Yes |
S3 bucket name for Terraform state |
Organization Object
Core Identity
| Parameter |
Type |
Required |
Description |
organization_name |
string |
Yes |
Short name for the organization |
payer_name |
string |
Yes |
Display name for the management account |
payer_email |
string |
Yes |
Root email of the management account |
security_account_name |
string |
Yes |
Display name for the security account |
security_account_root_email |
string |
Yes |
Root email for the new security account |
CloudTrail
| Parameter |
Type |
Default |
Description |
cloudtrail_bucket_name |
string |
required |
S3 bucket for CloudTrail logs. Set null to disable |
cloudtrail_loggroup_name |
string |
"CloudTrail/DefaultLogGroup" |
CloudWatch Log Group name |
SSO / Identity Center
| Parameter |
Type |
Default |
Description |
session_duration |
string |
"PT8H" |
ISO 8601 duration for SSO sessions |
admin_permission_set_name |
string |
"AdministratorAccess" |
Name of the admin Permission Set |
admin_group_name |
string |
"AllAdmins" |
Name of the admin Identity Center group |
disable_sso_management |
bool |
false |
Set true to stop Terraform from managing SSO |
Audit Role
| Parameter |
Type |
Default |
Description |
deploy_audit_role |
bool |
true |
Deploy the cross-account audit role StackSet |
audit_role_name |
string |
"security-audit" |
Name of the audit role in each account |
audit_role_stack_set_template_url |
string |
required if deploy |
S3 URL to the CloudFormation template |
Billing
| Parameter |
Type |
Required |
Description |
billing_data_bucket_name |
string |
Yes |
S3 bucket for CUR reports |
cur_report_frequency |
string |
"DAILY" |
DAILY, HOURLY, MONTHLY, or "NONE" to disable |
declarative_policy_bucket_name |
string |
Yes |
S3 bucket for declarative policy documents |
Security Services
Configure which security services to enable/disable:
security_services = {
disable_guardduty = false
disable_securityhub = false
disable_macie = false
}
Organizational Units
Four OUs are always created: Governance, Workloads, Sandbox, Suspended.
Additional OUs can be defined:
organization_units = {
"MyOU" = {
name = "MyOU"
is_child_of_root = true
}
"NestedOU" = {
name = "NestedOU"
parent_id = "MyOU" # use parent OU name for direct children of custom OUs
}
}
Accounts
Each account in the accounts map:
accounts = {
my_account = {
account_name = "my-org-prod" # AWS account display name
account_email = "aws+prod@example.com" # root email (must be unique)
parent_ou_name = "Workloads" # OU name (or use parent_ou_id)
monthly_budget_amount = 1000 # optional, in USD
delegated_admin = ["service.amazonaws.com"] # optional
close_on_deletion = false # optional
# Optional: override primary contact for this account
primary_contact = {
full_name = "Account Owner"
company_name = "My Org"
address_line_1 = "123 Main St"
city = "Atlanta"
state_or_region = "GA"
postal_code = "30332"
country_code = "US"
email_address = "owner@example.com"
phone_number = "+14041234567"
}
}
}
Applied org-wide (overridable per account):
global_billing_contact = {
name = "Name"
title = "CFO"
email_address = "billing@example.com"
phone_number = "+1xxxxxxxxxx"
}
global_security_contact = {
name = "Name"
title = "CISO"
email_address = "security@example.com"
phone_number = "+1xxxxxxxxxx"
}
global_operations_contact = {
name = "Name"
title = "VP Engineering"
email_address = "ops@example.com"
phone_number = "+1xxxxxxxxxx"
}
global_primary_contact = {
full_name = "Name"
company_name = "My Org"
address_line_1 = "123 Main St"
city = "Atlanta"
state_or_region = "GA"
postal_code = "30332"
country_code = "US"
email_address = "aws@example.com"
phone_number = "+1xxxxxxxxxx"
}
Policies
All three policy types follow the same structure:
service_control_policies = {
my_policy = {
policy_name = "MyPolicy"
policy_description = "Description"
policy_json_file = "policies/MyPolicy.json"
policy_targets = ["Workloads", "ou-xxxx-xxxxxxxx"] # OU names or IDs
policy_vars = { # for .tftpl files
variable_name = "value"
}
}
}
The same structure applies to resource_control_policies and declarative_policies
(which also require policy_type = "DECLARATIVE_POLICY_EC2").
Billing Alerts
billing_alerts = {
levels = {
level1 = 100 # USD threshold
level2 = 500
oh_shit = 1000
}
subscriptions = ["email@example.com"]
}
budget_defaults = {
alert_recipients = ["email@example.com"]
currency = "USD"
warning_percentage = 80
organizational_budget = 1000
}
8 - Contribution Guidelines
How to contribute to Org Kickstart
We welcome contributions to both the Terraform module and this documentation site.
All submissions require review via GitHub pull request.
Contributing to the Module
- Fork the org-kickstart repo on GitHub
- Create a feature branch
- Make your changes and test them against a real AWS Organization (see the CLAUDE.md for testing guidance)
- Send a pull request with a clear description of the change and why it’s needed
Testing
When modifying the module:
- Use
make env=your-org tf-plan extensively before applying
- Test in a non-production organization first
- Use targeted applies for risky changes:
terraform apply -var-file="your-org.tfvars" -target <resource>
- Verify SCPs don’t lock out root or prevent remediation
Contributing to the Docs
The documentation source lives in the org-kickstart-site/ directory alongside the module.
Running the Site Locally
Requirements:
- Hugo extended >= 0.155.0
- Node.js (for PostCSS/SCSS processing)
cd org-kickstart-site
make npm # install Node dependencies (first time only)
make test # starts dev server at http://localhost:1319/
Use make test-drafts to also render draft and future-dated content.
Editing Pages
- Fork the org-kickstart-site repo
- Edit files under
org-kickstart-site/content/en/
- Preview locally with
make test
- Submit a pull request
You can also click Edit this page in the top right of any documentation page to
jump directly to the source file on GitHub.
Creating an Issue
Found a bug or want to request a feature? Open an issue on
GitHub.
Useful Resources