Use the Conformity Knowledge Base AI to help improve your Cloud Posture

Cross-Account Access Lacks External ID and MFA

Trend Cloud One™ – Conformity is a continuous assurance tool that provides peace of mind for your cloud infrastructure, delivering over 1000 automated best practice checks.

Risk Level: Medium (should be achieved)
Rule ID: IAM-050

Ensure that Amazon IAM roles used to establish a trusted relationship between your AWS cloud account and a third-party entity (also known as cross-account access roles) are using Multi-Factor Authentication (MFA) or external IDs to secure the access to your resources and to prevent "confused deputy" attacks. The MFA/external ID adds an extra layer of security on top of role's temporary security credentials and facilitates external third-party accounts to access your AWS resources in a secure way.

This rule can help you with the following compliance standards:

  • APRA
  • MAS
  • NIST4

For further details on compliance standards supported by Conformity, see here.

This rule can help you work with the AWS Well-Architected Framework.

This rule resolution is part of the Conformity Security & Compliance tool for AWS.

Security

Increase the security of your cross-account IAM role by requiring either an optional external ID (similar to a password) or an MFA device to secure further the access to your AWS cloud resources and prevent "confused deputy" attacks. This is highly recommended if you don't own or have administrative access to the AWS account that can assume this IAM role. To assume this cross-account role, users must be available in the trusted account and provide the external ID or the unique passcode generated by the MFA device configured.


Audit

To determine if the Amazon IAM roles that provide cross-account access to your AWS resources use either MFA or external IDs, perform the following operations:

Using AWS Console

01 Sign in to the AWS Management Console.

02 Navigate to Amazon IAM console at https://console.aws.amazon.com/iam/.

03 In the navigation panel, under Access management, choose Roles.

04 Click on the name of the Amazon IAM role that you want to examine.

05 Select the Trust relationships tab and verify the following configuration information:

  1. Check the Trusted entities list to determine if the selected role allows cross-account access. If one or more AWS accounts are listed as trusted entities, these accounts can assume the role, therefore the selected Amazon IAM role provides cross-account access to other AWS accounts. If the Trusted entities lists AWS services instead of AWS accounts as identity providers, the selected IAM role does not provide cross-account access and the Audit process ends here.
  2. Check the Conditions section to determine the conditions that define how and when trusted entities can assume the selected IAM role. The cross-account IAM role lacks MFA-based protection and external ID support if the following conditions are met:
    • The conditions listed in the Conditions section don't include the aws:MultiFactorAuthPresent key (representing Multi-Factor Authentication protection) or sts:ExternalId key (representing external ID-based access).
    • The conditions listed in the Conditions section include aws:MultiFactorAuthPresent key or sts:ExternalId key but the aws:MultiFactorAuthPresent key value is set to false or the sts:ExternalId key does not have a value.

06 Repeat steps no. 4 and 5 for each IAM role available within your AWS cloud account.

Using AWS CLI

01 Run list-users command (OSX/Linux/UNIX) with custom query filters to list the names of all IAM users available within your AWS account:

aws iam list-users
  --output table
  --query 'Users[*].UserName'

02 The command output should return a table with the requested IAM user identifiers:

---------------------------
|        ListUsers        |
+-------------------------+
|  cc-cross-account-role  |
|  cc-rds-manager-role    |
+-------------------------+

03 Run get-role command (OSX/Linux/UNIX) using the name of the IAM role that you want to examine as the identifier parameter and custom filtering to describe the policy that grants an AWS entity the permission to assume the selected role:

aws iam get-role
  --role-name cc-cross-account-role
  --query 'Role.AssumeRolePolicyDocument'

04 The command output should return the trust relationship policy configured for the selected IAM role:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:root"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

05 Based on the policy document returned at the previous step, verify the following configuration information:

  1. Check the policy document returned by the get-role command output to determine if the IAM role allows cross-account access. If one or more AWS accounts are listed as trusted entities, i.e. "Principal": { "AWS": "arn:aws:iam::<aws-account-id>:root" }, as shown in the example above, the configured AWS account(s) can assume the role, therefore the selected Amazon IAM role provides cross-account access to other AWS accounts. If the policy document lists AWS cloud services as identity providers, i.e. "Principal": { "Service": "ec2.amazonaws.com" }, the selected IAM role does not provide cross-account access and the Audit process ends here.
  2. Check the "Condition" element to determine the conditions that define how and when trusted entities can assume the selected IAM role. If the policy document returned at the previous step does not have any "Condition" elements, as shown in the example above, the Audit process ends here. If there are "Condition" elements defined, check the elements value(s) for MFA and external ID support. The cross-account IAM role lacks MFA-based protection and external ID support if the following conditions are met:
    • The conditions listed for the "Condition" element don't include the aws:MultiFactorAuthPresent key (Multi-Factor Authentication protection) or the sts:ExternalId key (external ID support).
    • The conditions listed for the "Condition" element include aws:MultiFactorAuthPresent key or sts:ExternalId key but the aws:MultiFactorAuthPresent key value is set to false (i.e. "Condition": { "Bool": { "aws:MultiFactorAuthPresent": "false" } }) or sts:ExternalId key does not have any values (i.e. "Condition": { "StringEquals": { "sts:ExternalId": "" } }).

06 Repeat steps no. 3 – 5 for each IAM role available in your AWS cloud account.

Remediation / Resolution

To update the trust relationship policies defined for your Amazon IAM cross-account roles in order to enable Multi-Factor Authentication (MFA) and/or external ID support for secure access, perform the following operations:

Using AWS CloudFormation

01 CloudFormation template (JSON). Replace <external_id> with your own passphrase:

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "Enable MFA and External ID Support for Cross-Account IAM Role",
  "Resources": {
    "CrossAccountIAMRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "RoleName": "cc-cross-account-role",
        "Description": "Full Access to Amazon EC2",
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "AWS": "arn:aws:iam::123456789012:root"
              },
              "Condition": {
                 "Bool": {
                    "aws:MultiFactorAuthPresent": "true"
                 },
                 "StringEquals": {
                    "sts:ExternalId": "<external_id>"
                 }
              },
              "Action": [
                "sts:AssumeRole"
              ]
            }
          ]
        },
        "ManagedPolicyArns": [
          "arn:aws:iam::aws:policy/AmazonEC2FullAccess"
        ],
        "Path": "/"
      }
    }
  }
}

02 CloudFormation template (YAML). Replace <external_id> with your own passphrase:

AWSTemplateFormatVersion: '2010-09-09'
Description: Enable MFA and External ID Support for Cross-Account IAM Role
Resources:
  CrossAccountIAMRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: cc-cross-account-role
      Description: Full Access to Amazon EC2
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              AWS: arn:aws:iam::123456789012:root
            Condition:
              Bool:
                aws:MultiFactorAuthPresent: 'true'
              StringEquals:
                sts:ExternalId: "<external_id>"
            Action:
              - sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonEC2FullAccess
      Path: /

Using Terraform (AWS Provider)

01 Terraform configuration file (.tf). Replace <external_id> with your own passphrase:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.27"
    }
  }

  required_version = ">= 0.14.9"
}

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

resource "aws_iam_role" "iam-role" {
  name = "cc-cross-account-role"
  path = "/"
  managed_policy_arns = [ "arn:aws:iam::aws:policy/AmazonEC2FullAccess" ]

  assume_role_policy = <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "AWS": "arn:aws:iam::123456789012:root"
          },
          "Condition": {
             "Bool": {
                "aws:MultiFactorAuthPresent": "true"
             },
             "StringEquals": {
                "sts:ExternalId": "<external_id>"
             }
          },
          "Action": [
            "sts:AssumeRole"
          ]
        }
    ]
}
EOF
}

Using AWS Console

01 Sign in to the AWS Management Console.

02 Navigate to Amazon IAM console at https://console.aws.amazon.com/iam/.

03 In the navigation panel, under Access management, choose Roles.

04 Click on the name of the cross-account IAM role that you want to reconfigure.

05 Select the Trust relationships tab and choose Edit trust relationship.

06 On the Edit Trust Relationship page, add one of the following blocks to the existing policy:

  1. To enable Multi-Factor Authentication (MFA) and force the IAM users in the trusted account(s) to provide the passcode generated by the MFA device upon accessing your AWS cloud resources, add the following Condition element block: "Condition": { "Bool": { "aws:MultiFactorAuthPresent": "true" } to the trust relationship policy. Once updated, the policy document configured for the selected IAM role should look like this:
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": "sts:AssumeRole",
                "Effect": "Allow",
                "Condition": {
                    "Bool": {
                        "aws:MultiFactorAuthPresent": "true"
                    }
                },
                "Principal": {
                    "AWS": "arn:aws:iam::123456789012:root"
                }
            }
        ]
    }
    
  2. To enable external ID support in order to force the users within the trusted AWS accounts to provide the required ID (passphrase) upon accessing your AWS cloud resources, add the following "Condition" element block: "Condition": { "StringEquals": { "sts:ExternalId": "<external_id>" } to the trust relationship policy, then replace <external_id> with your own passphrase. Once updated, the policy document configured for the selected IAM role, should look like this:
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": "sts:AssumeRole",
                "Effect": "Allow",
                "Condition": {
                    "StringEquals": {
                        "sts:ExternalId": "<external_id>"
                    }
                },
                "Principal": {
                    "AWS": "arn:aws:iam::123456789012:root"
                }
            }
        ]
    }
    
  3. (Optional) To enable both MFA protection and external ID support for the selected cross-account IAM role, add the following "Condition" element block: "Condition": { "Bool": { "aws:MultiFactorAuthPresent": "true" }, "StringEquals": { "sts:ExternalId": "<external_id>" } }, to the trust relationship policy. Once updated, the policy document defined for the selected role should look like this:
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": "sts:AssumeRole",
                "Effect": "Allow",
                "Condition": {
                    "Bool": {
                        "aws:MultiFactorAuthPresent": "true"
                    },
                    "StringEquals": {
                        "sts:ExternalId": "<external_id>"
                    }
                },
                "Principal": {
                    "AWS": "arn:aws:iam::123456789012:root"
                }
            }
        ]
    }
    
  4. Choose Update Trust Policy to apply the configuration changes.

07 Repeat steps no. 4 – 6 to enable MFA and/or external ID support for other cross-account IAM roles, available within your AWS cloud account.

Using AWS CLI

01 Redefine the trust relationship policy for the selected cross-account IAM role, to enable MFA/external ID support and save the policy document to a JSON file named cc-cross-account-role-trust-policy.json. Based on the feature that you want to enable, add one of the following element blocks to the existing policy:

  1. To enable Multi-Factor Authentication (MFA) and force that the users in the trusted AWS accounts to provide the passcode generated by the MFA device upon accessing your AWS cloud resources, add the following "Condition" element block: "Condition": { "Bool": { "aws:MultiFactorAuthPresent": "true" }. Once redefined, the trust policy document for the selected IAM role should look like this:
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": "sts:AssumeRole",
                "Effect": "Allow",
                "Condition": {
                    "Bool": {
                        "aws:MultiFactorAuthPresent": "true"
                    }
                },
                "Principal": {
                    "AWS": "arn:aws:iam::123456789012:root"
                }
            }
        ]
    }
    
  2. To enable external ID support in order to ensure that the IAM users within the trusted AWS accounts provide the required ID (passphrase) upon accessing your AWS cloud resources, add the following "Condition" element block: "Condition": { "StringEquals": { "sts:ExternalId": "<external_id>" }, then replace <external_id> with your own passphrase. Once redefined, the trust policy document for the selected IAM role should look like this:
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": "sts:AssumeRole",
                "Effect": "Allow",
                "Condition": {
                    "StringEquals": {
                        "sts:ExternalId": "<external_id>"
                    }
                },
                "Principal": {
                    "AWS": "arn:aws:iam::123456789012:root"
                }
            }
        ]
    }
    
  3. (Optional) To enable both MFA protection and external ID support for the selected cross-account IAM role, add the following "Condition" element block: "Condition": { "Bool": { "aws:MultiFactorAuthPresent": "true" }, "StringEquals": { "sts:ExternalId": "<external_id>" } }, to the trust relationship policy. Once updated, the policy document defined for the selected role should look like this:
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": "sts:AssumeRole",
                "Effect": "Allow",
                "Condition": {
                    "Bool": {
                        "aws:MultiFactorAuthPresent": "true"
                    },
                    "StringEquals": {
                        "sts:ExternalId": "<external_id>"
                    }
                },
                "Principal": {
                    "AWS": "arn:aws:iam::123456789012:root"
                }
            }
        ]
    }
    

02 Run update-assume-role-policy command (OSX/Linux/UNIX) to apply the trust relationship policy defined at the previous step (i.e. cc-cross-account-role-trust-policy.json) for the selected cross-account IAM role (if successful, the command does not produce an output):

aws iam update-assume-role-policy
  --role-name cc-cross-account-role
  --policy-document file://cc-cross-account-role-trust-policy.json

03 Repeat steps no. 1 and 2 to enable MFA and/or external ID support for other cross-account IAM roles, available in your AWS cloud account.

References

Publication date Feb 13, 2018