ACAI ACF Module: terraform-aws-acf-scp
Overview
AWS Organization Service Control Policies (SCPs) enable you to manage permissions across your AWS Organization by both granting permissions and establishing guardrails that restrict the actions of IAM users and roles. Essentially, the maximum permissions available to IAM users and roles in an AWS account are determined by the SCPs attached to the root, its Organizational Units (OUs), and the individual AWS accounts.
For more details, see:
- AWS Organizations SCPs Overview
- IAM Policy Evaluation Logic
- Policy evaluation for requests within a single account
For a permission to be allowed for a specific account, there must be an explicit Allow statement at every level from the root through each OU in the direct path to the account [1].
Deny SCPs applied to an Organization Unit (OU) will be applied to the accounts of the OU and will be inherited to all lower level OUs and accounts [2].
Information
- The SCP size is limited to 5,120 characters.
- A maximum of 5 SCPs can be assigned to an Organization Unit (OU).
- SCPs will not be applied to the Organization Management Account (Root).
Solution
GitHub Repository | Terraform Registry
Terraform module to provision and assign Service Control Policies (SCPs) to Organization Units or AWS accounts. For SCP statements have a look at this repository: terraform-aws-acf-scp-statements
Features
- Provisions SCPs based on specified statements.
- Supports the use of wildcards in OU-Paths.
Must have Python3 and boto3 installed at the worker.
Usage
Consider an AWS Organization with the following OU structure:
/root
/root/CoreAccounts
/root/CoreAccounts/Connectivity
/root/CoreAccounts/Management
/root/CoreAccounts/Security
/root/SandboxAccounts
/root/WorkloadAccounts
/root/WorkloadAccounts/BusinessUnit_1
/root/WorkloadAccounts/BusinessUnit_1/CICD
/root/WorkloadAccounts/BusinessUnit_1/NonProd
/root/WorkloadAccounts/BusinessUnit_1/Prod
/root/WorkloadAccounts/BusinessUnit_2
/root/WorkloadAccounts/BusinessUnit_2/CICD
/root/WorkloadAccounts/BusinessUnit_2/NonProd
/root/WorkloadAccounts/BusinessUnit_2/Prod
/root/WorkloadAccounts/BusinessUnit_3
/root/WorkloadAccounts/BusinessUnit_3/CICD
/root/WorkloadAccounts/BusinessUnit_3/NonProd
/root/WorkloadAccounts/BusinessUnit_3/Prod
Specifying SCP Statements
The module expects SCP specifications as a map.
Each specification contains a policy_name and a list of statement_ids that correspond to entries in your SCP statements map.
For example, you can pull in SCP statements from the following repository:
For sample SCP statements have a look at this repository: terraform-aws-acf-scp-statements
module "scp_statements" {
source = "git::https://github.com/acai-consulting/terraform-aws-acf-scp-statements.git?ref=1.0.0"
}
locals {
scp_specifications = {
"top_level" = {
policy_name = "top_level"
statement_ids = [
"deny_root_user"
]
}
"core_accounts" = {
policy_name = "core_accounts"
statement_ids = [
"deny_iam_users"
]
}
"core_account_non_connectivity" = {
policy_name = "core_account_non_connectivity"
statement_ids = [
"deny_vpc"
]
}
"workload" = {
policy_name = "workload"
statement_ids = [
"deny_vpc",
"protect_security_resources",
]
}
"workload_class1" = {
policy_name = "workload_class1"
statement_ids = [
"allow_services1",
]
}
"workload_class2" = {
policy_name = "workload_class2"
statement_ids = [
"allow_services2",
]
}
"workload_prod" = {
policy_name = "workload_prod"
statement_ids = [
"deny_regions_prod",
"deny_iam_users",
]
}
"workload_non_prod" = {
policy_name = "workload_non_prod"
statement_ids = [
"deny_regions_nonprod",
]
}
"deny_vpc" = {
policy_name = "deny_vpc"
statement_ids = [
"deny_vpc",
]
}
}
Specifying SCP Assignments
SCPs can be assigned at both the OU and account levels.
The ou_assignments map pairs OU paths (which are case-sensitive) with lists of SCP policy names.
Information
The OU-Names are case-sensitive.
scp_assignments = {
ou_assignments = {
"/root" = ["top_level"]
"/root/CoreAccounts" = ["core_accounts"]
"/root/CoreAccounts/Management" = ["deny_vpc"]
"/root/SandboxAccounts" = []
"/root/WorkloadAccounts" = ["workload"]
"/root/WorkloadAccounts/BusinessUnit_1" = ["workload_class1"]
"/root/WorkloadAccounts/BusinessUnit_2" = ["workload_class1"]
"/root/WorkloadAccounts/BusinessUnit_3" = ["workload_class2"]
"/root/WorkloadAccounts/*/Prod" = ["workload_prod"]
"/root/WorkloadAccounts/*/NonProd" = ["workload_non_prod"]
}
account_assignments = {
"590183833356" = ["deny_vpc"] # core_logging
}
}
}
Deploy SCP Assignments
Once you’ve defined your SCP statements, specifications, and assignments, deploy the ACF module as shown below: