Skip to content

Terraform module used to configure the feature and structure of an AWS organization

License

Notifications You must be signed in to change notification settings

appvia/terraform-aws-organization

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

60 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Github Actions

Terraform AWS Organization Module

Description

The purpose of this module is to create an AWS organization with a tree of organizational units and accounts. The module also provides the capability to enable AWS services, policy types, and delegation of services to other AWS accounts.

Organizational Units

You can defined your organizational units in the organization input variable. The organization input variable is an object with a list of units and accounts. Each unit can have a list of sub-units. The organization input variable defaults to an object with an empty list of units and accounts. An example is provided below

organization = {
  units = [
    {
      name = "Infrastucture",
      key  = "infrastructure",
    },
    {
      name = "Workloads",
      key  = "workloads",
      units = [
        {
          name = "Development",
          key  = "workloads/development",
        },
        {
          name = "Production",
          key  = "workloads/production",
        },
      ]
    },
    {
      name = "Sandbox",
      key  = "sandbox",
    }
  ]

Organizational Features

The enable_aws_services input variable is a list of AWS services to enable for the organization. The enable_policy_types input variable is a list of policy types to enable for the organization. The enable_delegation input variable provides the capability to delegate the management of a service to another AWS account. An example is provided below

enable_aws_services = [
  "access-analyzer.amazonaws.com",
  "account.amazonaws.com",
  "cloudtrail.amazonaws.com",
  "compute-optimizer.amazonaws.com",
  "config-multiaccountsetup.amazonaws.com",
  "config.amazonaws.com",
  "controltower.amazonaws.com",
  "cost-optimization-hub.bcm.amazonaws.com",
  "guardduty.amazonaws.com",
  "ram.amazonaws.com",
  "securityhub.amazonaws.com",
  "servicequotas.amazonaws.com",
  "sso.amazonaws.com",
  "tagpolicies.tag.amazonaws.com"
]

enable_policy_types = [
  "AISERVICES_OPT_OUT_POLICY",
  "BACKUP_POLICY",
  "SERVICE_CONTROL_POLICY",
  "TAG_POLICY"
]

enable_delegation = {
  organizations = {
    account_name = "Audit"
  }
  securityhub = {
    account_name = "Audit"
  }
  guardduty = {
    account_name = "Audit"
  }
  ipam = {
    account_name = "Network"
  }
  macie = {
    account_name = "Audit"
  }
  inspection = {
    account_name = "Audit"
  }
}

Service Control Policies

You can attach service control policies (SCPs) to the organization's root or to specific organizational units. The service_control_policies input variable is a map of SCPs to apply to the organization's root. The map key is the name of the SCP and the value is an object with the following attributes:

  • description - A description for the SCP
  • content - The content of the SCP
  • key - If we created the organizational unit, this is the key to attach the policy to
  • target_id - If the organizational unit already exists, this is the target ID to attach the policy to

An example where is have created the organizational units below

organization = {
  units = [
    {
      name = "Infrastucture",
      key  = "infrastructure",
    },
    {
      name = "Workloads",
      key  = "workloads",
      units = [
        {
          name = "Production",
          key  = "workloads/production",
        },
      ]
    }
  ]
}

## Checkout the basic example for more details
service_control_policies = {
  "DenyAll" = {
    description = "Deny all actions"
    content     = file("${path.module}/policies/deny-all.json")
    key         = "infrastructure"
  }
  "DenyProduction" = {
    description = "Deny all actions in the infrastructure unit"
    content     = file("${path.module}/policies/deny-infrastructure.json")
    key         = "infrastructure/production"
  }
}

Alternatively if the organizational unit already exists, you can attach the SCP to the target ID. An example is provided below

service_control_policies = {
  "DenyAll" = {
    description = "Deny all actions"
    content     = file("${path.module}/policies/deny-all.json")
    target_id   = "ou-123456789012"
  }
}

Backup Policies

Backup policies can be attached to the organization's root or to specific organizational units. The backup_policies input variable is a map of backup policies to apply to the organization's root. The map key is the name of the backup policy and the value is an object with the following attributes:

  • description - A description for the backup policy
  • content - The content of the backup policy
  • key - If we created the organizational unit, this is the key to attach the policy to
  • target_id - If the organizational unit already exists, this is the target ID to attach the policy to

An example where is have created the organizational units below

organization = {
  units = [
    {
      name = "Infrastucture",
      key  = "infrastructure",
    }
  ]
}

backup_policies = {
  "BackupAll" = {
    description = "Backup all resources"
    content     = file("${path.module}/policies/backup-all.json")
    key         = "infrastructure"
    # target_id   = "ou-123456789012" # If the organizational unit already exists
  }
}

Service Quotas

Service quotas can be applied to the organization. The service_quotas input variable is a collection of service quotas to apply to the organization. The collection is a list of objects with the following attributes:

  • service_code - The service code of the service quota
  • quota_code - The quota code of the service quota
  • value - The value of the service quota

An example is provided below

service_quotas = [
  {
    service_code = "ec2"
    quota_code   = "L-1216C47A"
    value        = 100
  }
]

Since AWS Service Quotas are not regional and only accessible from us-east-1, a aws.us-east-1 provider must be defined and passed to the module. This is required regardless of whether you define any service quotas, as providers cannot be optional.

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

module "organization" {
  providers = {
    aws           = aws
    aws.us-east-1 = aws.us-east-1
  }
}

Update Documentation

The terraform-docs utility is used to generate this README. Follow the below steps to update:

  1. Make changes to the .terraform-docs.yml file
  2. Fetch the terraform-docs binary (https://terraform-docs.io/user-guide/installation/)
  3. Run terraform-docs markdown table --output-file ${PWD}/README.md --output-mode inject .

Providers

Name Version
aws >= 5.0.0
aws.us-east-1 >= 5.0.0

Inputs

Name Description Type Default Required
tags A map of tags to resources provisioned by this module. map(string) n/a yes
backup_policies A map of backup policies to apply to the organization's root.
map(object({
description = string
# A description for the backup policy
content = string
# The content of the backup policy
key = optional(string)
# If we created the organizational unit, this is the key to attach the policy to
target_id = optional(string)
# If the organizational unit already exists, this is the target ID to attach the policy to
}))
{} no
enable_aws_services A list of AWS services to enable for the organization. list(string)
[
"access-analyzer.amazonaws.com",
"account.amazonaws.com",
"cloudtrail.amazonaws.com",
"compute-optimizer.amazonaws.com",
"config-multiaccountsetup.amazonaws.com",
"config.amazonaws.com",
"controltower.amazonaws.com",
"cost-optimization-hub.bcm.amazonaws.com",
"guardduty.amazonaws.com",
"ram.amazonaws.com",
"securityhub.amazonaws.com",
"servicequotas.amazonaws.com",
"sso.amazonaws.com",
"tagpolicies.tag.amazonaws.com"
]
no
enable_delegation Provides at the capability to delegate the management of a service to another AWS account.
object({
access_analyzer = optional(object({
account_name = string
# The name of the account to delegate the management of Access Analyzer to
}), null)
guardduty = optional(object({
account_name = string
# The name of the account to delegate the management of GuardDuty to
}), null)
inspection = optional(object({
account_name = string
# The name of the account to delegate the management of Inspector to
}), null)
ipam = optional(object({
account_name = string
# The name of the account to delegate the management of IPAM to
}), null)
macie = optional(object({
account_name = string
# The name of the account to delegate the management of Macie to
}), null)
organizations = optional(object({
account_name = string
# The name of the account to delegate the management of Organizations to
}), null)
securityhub = optional(object({
account_name = string
# The name of the account to delegate the management of Security Hub to
}), null)
stacksets = optional(object({
account_name = string
# The name of the account to delegate the management of StackSets to
}), null)
})
{
"access_analyzer": null,
"guardduty": null,
"inspection": null,
"ipam": null,
"macie": null,
"organizations": null,
"securityhub": null,
"stacksets": null
}
no
enable_policy_types A list of policy types to enable for the organization. list(string)
[
"AISERVICES_OPT_OUT_POLICY",
"BACKUP_POLICY",
"RESOURCE_CONTROL_POLICY",
"SERVICE_CONTROL_POLICY",
"TAG_POLICY"
]
no
organization The organization with the tree of organizational units and accounts to construct. Defaults to an object with an empty list of units and accounts
object({
units = optional(list(object({
name = string,
key = string,
units = optional(list(object({
name = string,
key = string,
units = optional(list(object({
name = string,
key = string,
units = optional(list(object({
name = string,
key = string,
units = optional(list(object({
name = string,
key = string,
})), [])
})), [])
})), [])
})), [])
})), [])
})
{} no
service_control_policies A map of service control policies (SCPs) to apply to the organization's root.
map(object({
description = string
# A description for the service control policy
content = string
# The content of the service control policy
key = optional(string)
# If we created the organizational unit, this is the key to attach the policy to
target_id = optional(string)
# If the organizational unit already exists, this is the target ID to attach the policy to
}))
{} no
service_quotas A collection of service quotas to apply to the organization.
list(object({
service_code = string
# The service code of the service quota
quota_code = string
# The quota code of the service quota
value = number
# The value of the service quota
}))
[] no
tagging_policies A map of tagging policies to apply to the organization's root.
map(object({
description = string
# A description for the tagging policy
content = string
# The content of the tagging policy
key = optional(string)
# If we created the organizational unit, this is the key to attach the policy to
target_id = optional(string)
# If the organizational unit already exists, this is the target ID to attach the policy to
}))
{} no

Outputs

Name Description
master_account_email The email address of the master account provided by AWS
master_account_id The ARN of the master account provided by AWS
organization_arn The ARN of the organization provided by AWS
organization_id The ID of the organization provided by AWS
organizational_units The organizational units created in the organization

About

Terraform module used to configure the feature and structure of an AWS organization

Topics

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •