DCE IAM Policies

Understanding Principal Policies

When an AWS account is added to the DCE account pool, an IAM role and policy are created within the account. This role is assumed by end-users when accessing their leased account.

The principal user’s IAM role is returned as principalRoleArn when creating a new account via the DCE API. For example:

{
  "id": "123456789012",
  "adminRoleArn": "arn:aws:iam::123456789012:role/OrganizationAccountAccessRole",
  "principalRoleArn": "arn:aws:iam::123456789012:role/DCEPrincipal"
}

By default, the DCEPrincipal role has near-administrative access to their leased account, with a few exceptions:

  • Users may not create AWS support tickets
    • e.g., we don’t want users increasing service limits
  • Users may not modify resources required by DCE to manage the child account
    • e.g. users cannot modify the IAM Trust Relationship which allows DCE master to assume into the child account’s IAM roles
  • Users are limited to a set of configured regions
  • Users are limited to AWS services which DCE knows how to destroy.
    • This is to prevent orphan resources in accounts after reset.

Principal Role Security

By default, principal users may elevate their own IAM access. For example, users may create a new IAM role with an attached AdministrativeAccess policy, assign the role to an EC2 instance, and then SSH into the instance as an admin user.

The best way to block this backdoor access to IAM policy elevation is through a Service Control Policy, or SCP. An SCP is an organization-level policy which allows administrators to control access to all IAM roles and users within the organizations.

See DCE Service Control Policies

DCE Service Control Policies (SCP)

Implementing DCE in an AWS Organization provides the ability to use SCPs, which can be helpful for ensuring the resilience of DCE internal resources. The following SCP is an example policy that contains two statements for protecting your DCE accounts:

  • DenyChangesToAdminPrincipalRoleAndPolicy is designed to prevent anyone other than the AdminRole from modifying the roles and policies used by DCE.
  • DenyUnsupportedServices is designed to allow access only to services that are supported by AWS Nuke
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DenyChangesToAdminPrincipalRoleAndPolicy",
            "Effect": "Deny",
            "NotAction": [
                "iam:GetContextKeysForPrincipalPolicy",
                "iam:GetRole",
                "iam:GetRolePolicy",
                "iam:ListAttachedRolePolicies",
                "iam:ListInstanceProfilesForRole",
                "iam:ListRolePolicies",
                "iam:ListRoleTags",
                "iam:DeactivateMFADevice",
                "iam:CreateSAMLProvider",
                "iam:UpdateAccountPasswordPolicy",
                "iam:DeleteVirtualMFADevice",
                "iam:EnableMFADevice",
                "iam:CreateAccountAlias",
                "iam:DeleteAccountAlias",
                "iam:UpdateSAMLProvider",
                "iam:DeleteSAMLProvider"
            ],
            "Resource": [
                "arn:aws:iam::*:role/AdminRole",
                "arn:aws:iam::*:role/DCEPrincipal*",
                "arn:aws:iam::*:policy/DCEPrincipal*"
            ],
            "Condition": {
                "StringNotLike": {
                    "aws:PrincipalARN": "arn:aws:iam::*:role/AdminRole"
                }
            }
        },
        {
            "Sid": "DenyUnsupportedServices",
            "Effect": "Deny",
            "NotAction": [
                "acm:*",
                "acm-pca:*",
                "apigateway:*",
                "application-autoscaling:*",
                "appstream:*",
                "athena:*",
                "autoscaling:*",
                "aws-portal:*",
                "backup:*",
                "batch:*",
                "budgets:*",
                "cloud9:*",
                "clouddirectory:*",
                "cloudformation:*",
                "cloudfront:*",
                "cloudhsm:*",
                "cloudsearch:*",
                "cloudtrail:*",
                "cloudwatch:*",
                "codebuild:*",
                "codecommit:*",
                "codedeploy:*",
                "codepipeline:*",
                "codestar:*",
                "cognito-identity:*",
                "cognito-idp:*",
                "cognito-sync:*",
                "comprehend:*",
                "config:*",
                "datapipeline:*",
                "dax:*",
                "devicefarm:*",
                "dms:*",
                "ds:*",
                "dynamodb:*",
                "ec2:*",
                "ecr:*",
                "ecs:*",
                "eks:*",
                "elasticache:*",
                "elasticbeanstalk:*",
                "elasticfilesystem:*",
                "elasticloadbalancing:*",
                "elasticmapreduce:*",
                "elastictranscoder:*",
                "es:*",
                "events:*",
                "execute-api:*",
                "firehose:*",
                "fsx:*",
                "globalaccelerator:*",
                "glue:*",
                "iam:*",
                "imagebuilder:*",
                "iot:*",
                "iotanalytics:*",
                "kafka:*",
                "kinesis:*",
                "kinesisanalytics:*",
                "kinesisvideo:*",
                "kms:*",
                "lakeformation:*",
                "lambda:*",
                "lex:*",
                "lightsail:*",
                "logs:*",
                "machinelearning:*",
                "mediaconvert:*",
                "medialive:*",
                "mediapackage:*",
                "mediastore:*",
                "mediatailor:*",
                "mobilehub:*",
                "mq:*",
                "neptune-db:*",
                "opsworks:*",
                "opsworks-cm:*",
                "rds:*",
                "redshift:*",
                "rekognition:*",
                "resource-groups:*",
                "robomaker:*",
                "route53:*",
                "s3:*",
                "sagemaker:*",
                "sdb:*",
                "secretsmanager:*",
                "servicecatalog:*",
                "servicediscovery:*",
                "servicequotas:*",
                "ses:*",
                "sns:*",
                "sqs:*",
                "ssm:*",
                "states:*",
                "storagegateway:*",
                "sts:*",
                "tag:*",
                "transfer:*",
                "waf:*",
                "wafv2:*",
                "waf-regional:*",
                "worklink:*",
                "workspaces:*"
            ],
            "Resource": "*"
        }
    ]
}

Customizing the Principal IAM Policy

Customize the IAM Policies for DCE Principals via Terraform variables.

See Configuring Terraform Variables.

Variable Default Description
principal_policy See principal_policy.tmpl File location for a IAM principal policy template
allowed_regions all AWS regions AWS regions which the principal is allowed to access

The file specified in principal_policy is rendered using golang templates, and accepts the following arguments:

Argument Description
PrincipalPolicyArn ARN of the principal IAM policy
PrincipalRoleArn ARN of the principal IAM role
AdminRoleArn ARN of the admin access role within the account
PrincipalIAMDenyTags Populated from the principal_iam_deny_tags Terraform variable. By default, these are used to deny access to AWS resources with AppName=DCE tags
Regions AWS Regions, populated from the allowed_regions Terraform variable