Skip to content

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:

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

architecture

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:

module "scp_management" {
  source = "git::https://github.com/acai-consulting/terraform-aws-acf-scp.git?ref=1.0.5"

  scp_statements     = module.scp_statements.scp_statements
  scp_specifications = local.scp_specifications
  scp_assignments    = local.scp_assignments
  providers = {
    aws = aws.org_mgmt_euc1
  }
}