fbpx

Automate quality for IAM Access Analyzer cross-account access findings upon IAM roles

In this website post, we demonstrate how exactly to automatically resolve AWS Identity and Access Management (IAM) Access Analyzer findings generated in reaction to unintended cross-account access for IAM roles. The answer automates the resolution by giving an answer to the Amazon EventBridge event generated by IAM Access Analyzer for every active finding.

You should use identity-based policies and resource-based policies to granularly control usage of a particular resource and how it really is used by you over the entire AWS Cloud environment. You should make sure that policies you create stick to your organization’s requirements on data/resource access and security guidelines. IAM Access Analyzer is really a feature you could enable to continuously monitor policies for changes, and generate detailed findings linked to access from external entities to your AWS resources.

 

Once you enable Access Analyzer, an analyzer is established by you for the entire organization or your account. The account or organization you select is recognized as the zone of trust for the analyzer. The zone of trust determines which kind of access is known as trusted by Access Analyzer. Access Analyzer monitors all supported resources to recognize policies that grant cross-account or public access from beyond your zone of trust, and generates findings. In this article, we will concentrate on an IAM Access Analyzer finding that’s generated when an IAM role is granted usage of an external AWS principal that’s outside your zone of trust. To solve the finding, we shall show you how exactly to automatically block such unintended access with the addition of explicit deny statement to the IAM role trust policy.

Prerequisites

To make sure that the answer only prevents unintended cross account access for IAM roles, we recommend you to do the next inside your AWS environment before deploying the perfect solution is described in your blog post:

Note: This solution adds an explicit deny in the IAM role trust policy to block the unintended access, which overrides any existing allow actions. We advise that you carefully evaluate that may be the resolution action you intend to apply.

Solution overview

To show this solution, we shall take a scenario what your location is asked to grant usage of an external AWS account. To be able to grant access, an IAM is established by you role named Audit_CrossAccountRole on your own AWS account 123456789012. You grant permission to assume the role Audit_CrossAccountRole to an AWS principal named Alice in AWS account 999988887777, that is out-side of one’s AWS Organizations. The next is an exemplory case of the trust policy for the IAM role Audit_CrossAccountRole:


     

“Version”: “2012-10-17”,
“Statement”: [

  "Effect": "Allow",
  "Principal": 
    "AWS": "arn:aws:iam::999988887777:user/Alice"
  ,
  "Action": "sts:AssumeRole",
  "Condition": 

]

        Assuming the main arn:aws:iam::999988887777:user/Alice had not been archived in Access Analyzer previously, you see a dynamic finding in Access Analyzer as shown in Figure 1.

 

Figure 1: Sample IAM Access Analyzer finding in AWS Console

Figure 1: Sample IAM Access Analyzer finding in AWS Console

Typically, you’ll review this determine and finding whether this access is supposed or not. If the access is unintended, it is possible to block access to the main 999988887777/Alice with the addition of an explicit deny to the IAM role trust policy, and follow-up with IAM role owner to learn if there is grounds to permit this cross-account access. If the access is supposed, you’ll be able to create an archive rule which will archive the suppress and finding such findings in future.

We shall walk through the answer to automate this resolution process in the rest of this post.

Solution walkthrough

Access Analyzer sends an event to Amazon EventBridge for each active finding. This solution configures a meeting rule in EventBridge to complement a dynamic finding, and triggers an answer AWS Lambda function. The Lambda function checks that the resource enter the finding can be an IAM role, and adds a deny statement to the associated IAM role trust policy as an answer. The Lambda function sends a contact through &lt also;a href=”https://aws.amazon.com/sns” target=”_blank” rel=”noopener noreferrer”>Amazon Simple Notification Service (Amazon SNS) to the e-mail address configured in the perfect solution is. The average person or group who receives the e-mail can review the automatic resolution and the IAM role then. They are able to decide either to eliminate the role for unintended access then, or even to delete the deny statement from the IAM trust policy and create an archive rule in Access Analyzer to suppress such findings in future.

Figure 2: Automated resolution accompanied by human review

Figure 2: Automated resolution accompanied by human review

Figure 2 shows the next steps of the resolution solution.

  1. Access Analyzer scans generates and resources findings in line with the zone of trust and the archive rules configuration. The following can be an exemplory case of an Access Analyzer active finding event delivered to Amazon EventBridge:
     
    "version": "0",
    "id": "22222222-dcba-4444-dcba-333333333333",
    "detail-type": "Access Analyzer Finding",
    "source": "aws.access-analyzer",
    "account": "123456789012",
    "time": "2020-05-13T03:14:33Z",
    "region": "us-east-1",
    "resources": [
        "arn:aws:access-analyzer:us-east-1: 123456789012:analyzer/AccessAnalyzer"
    ],
    "detail": 
        "version": "1.0",
        "id": "a5018210-97c4-46c4-9456-0295898377b6",
        "status": "ACTIVE",
        "resourceType": "AWS::IAM::Role",
        "resource": "arn:aws:iam::123456789012:role/ Audit_CrossAccountRole",
        "createdAt": "2020-05-13T03:14:32Z",
        "analyzedAt": "2020-05-13T03:14:32Z",
        "updatedAt": "2020-05-13T03:14:32Z",
        "accountId": "123456789012",
        "region": "us-east-1",
        "principal": 
            "AWS": "aws:arn:iam::999988887777:user/Alice"
        ,
        "action": [
            "sts:AssumeRole"
        ],
        "condition": ,
        "isDeleted": false,
        "isPublic": false
     
  2. EventBridge receives a meeting for the Access Analyzer finding, and triggers the AWS Lambda function in line with the event rule configuration. The next is an exemplory case of the EventBridge event pattern to complement active Access Analyzer findings:
         
    

    “source”: [
    “aws.access-analyzer”
    ],
    “detail-type”: [
    “Access Analyzer Finding”
    ],
    “detail”:
    “status”: [ “ACTIVE” ],
    “resourceType”: [ “AWS::IAM:Role” ]

     
  3. The Lambda function processes the function when ResourceType is add up to AWS::IAM::Role , as shown in the next example Python code:
         ResourceType = event['detail']['resourceType']
    

    ResourceType = “”.join(ResourceType.split())
    if ResourceType == ‘AWS::IAM::Role’ :

Then, the Lambda function adds an explicit deny statement in the trust policy of the IAM role where in fact the Sid of the brand new statement references the Access Analyzer finding ID.

     def disable_iam_access(                                                            ,                                                             ,                                                             ):
    try:
        ext_arn = ext_arn.strip()
        policy = 
            "Sid":                                                             ,
            "Effect": "Deny",
            "Principal": 
                "AWS":                                                             ,
            "Action": "sts:AssumeRole"
    response = iam.get_role(RoleName=                                                            )
    current_policy = response['Role']['AssumeRolePolicyDocument']
    current_policy = current_policy['Statement'].append(policy)
    new_policy = json.dumps(response['Role']['AssumeRolePolicyDocument'])
    logger.debug(new_policy)
    response = iam.update_assume_role_policy(
        PolicyDocument=new_policy,
        RoleName=                                                            )
    logger.info(response)
except Exception as e:
    logger.error(e)
    logger.error('Unable to update IAM Policy')
 

As result, the IAM role trust policy appears like the next example:

     
    "Version": "2012-10-17",
    "Statement": [

            "Effect": "Allow",
            "Principal": 
    "AWS": "arn:aws:iam::999988887777:user/Alice"
            ,
            "Action": "sts:AssumeRole",
        ,

            "Sid": "22222222-dcba-4444-dcba-333333333333",
            "Effect": "Deny",
            "Principal": 
    "AWS": "arn:aws:iam::999988887777:user/Alice"
            ,
            "Action": "sts:AssumeRole"

    ]

 

Note : After Access Analyzer adds the deny statement, on another scan, Access Analyzer finds the resource is not any shared beyond your zone of trust longer. Access Analyzer changes the status of the finding to Resolved and the finding appears in the Resolved findings  table.

  • The Lambda function sends a notification to an SNS topic that sends a contact to the configured email (which should function as business proprietor or security team) subscribed to the SNS topic. The e-mail notifies them a specific IAM role has been blocked from the cross-account access. The next is an exemplory case of the SNS code for the notification.
         def send_notifications(sns_topic,principal, resource_arn, finding_id):
    sns_client = boto3.client("sns")
    message = "The IAM Role resource  allows access to the main . Trust policy for the role has been updated to deny the external access. Please review the IAM Role and its own trust policy. If this access is supposed, update the IAM Role trust policy to eliminate a statement with SID matching with the finding id  and mark the finding as archived or create an archive rule. If this access isn't intended delete the IAM Role.". format(
        resource_arn, principal)
    subject = "Access Analyzer finding  was automatically resolved ".format(finding_id)
    snsResponse = sns_client.publish(
        TopicArn=sns_topic,
        Message=message,
        Subject=subject
    )
     

    Figure 3 shows a good example of the e-mail notification.

    Figure 3: Sample resolution email generated by the solution

    Figure 3: Sample resolution email generated by the answer

  • The security team or business proprietor who receives the e-mail reviews the role and does among the following steps:
    • If you discover that the IAM role with cross-account access is supposed then:Take away the deny statement added in the trust policy through AWS CLI or AWS Management Console . As stated above, the Access is added by the perfect solution is Analyzer finding ID as Sid for the deny statement. The next command shows removing the deny statement for role_name through AWS CLI utilizing the finding id obtainable in the email notification.
           POLICY_DOCUMENT=          aws iam get-role --role-name '' --query "Role.AssumeRolePolicyDocument.Version: Version, Statement: Statement[?Sid!='']"      

      aws iam update-assume-role-policy –role-name ‘ ‘ –policy-document “$POLICY_DOCUMENT”

Further, it is possible to create an archive rule with criteria such as for example AWS Account ID, resource type, and principal, to archive new findings that match the criteria automatically.

  • If you discover that the IAM role provides unintentional cross-account access you then might delete the IAM role. Also, you need to investigate who created the IAM role by checking relevant AWS CloudTrail events like iam:createRole , to enable you to arrange for preventive actions.

Solution deployment

It is possible to deploy the solution through the use of either the AWS Management Console or the  AWS Cloud Development Kit (AWS CDK) .

To deploy the answer utilizing the AWS Management Console

  • In your AWS account, launch the template by choosing the Launch Stack  button, which creates the stack the in us-east-1 Region.
    Select the Launch Stack button to launch the template
  • On the Quick create stack page, for  Stack name , enter a distinctive stack name because of this account; for instance, iam-accessanalyzer-findings-resolution , as shown in Figure 4.

    Figure 4: Deploy the solution using CloudFormation template

    Figure 4: Deploy the perfect solution is using CloudFormation template

  • For NotificationEmail , enter the e-mail address to get notifications for just about any resolution actions taken by the answer.
  • Choose Create stack .

Additionally, you’ll find the most recent code on the aws-iam-permissions-guardrails GitHub repository , where you are able to donate to the sample code also. The next procedure shows how exactly to deploy the solution utilizing the AWS Cloud Development Kit (AWS CDK) .

To deploy the perfect solution is utilizing the AWS CDK

  • Deploy the answer to your account utilizing the following commands:
         git clone git@github.com:aws-samples/aws-iam-permissions-guardrails.git
    cd aws-iam-permissions-guardrails/access-analyzer/iam-role-findings-resolution/ 
    cdk bootstrap
    cdk deploy --parameters NotificationEmail=                                                       
         

After deployment, you need to confirm the AWS Amazon SNS email subscription to obtain the notifications from the perfect solution is.

To confirm the e-mail address for notifications

  • Check your email choose&nbsp and inbox; Confirm subscription  in the e-mail from Amazon SNS.
  • Amazon SNS opens your online browser and displays a subscription confirmation together with your subscription ID.

To test the answer

Create an IAM role with a trust policy with another AWS account as principal that’s neither section of archive rule nor inside your zone of trust. Also, because of this test, usually do not attach any permission policies to the IAM role. You shall receive a contact notification after a short while, like the one shown in Figure 3 previously.

As a next thing, review the resolution action as described in step 5 in the perfect solution is walkthrough section above.

Tidy up

In the event that you launched the answer in the AWS Management Console utilizing the Launch Stack button, it is possible to delete the stack by navigating to CloudFormation console , selecting the precise stack by its name, and clicking the Delete button.

In the event that you deployed the perfect solution is using AWS CDK, it is possible to perform the cleanup utilizing the following CDK command from the neighborhood directory where in fact the solution was cloned from GitHub.

     cdk destroy
     

Cost estimate

Deploying the answer won’t incur any costs alone, but there’s a cost from the AWS Lambda execution and Amazon SNS notifications through email, once the findings generated by IAM Access Analyzer match the EventBridge event rule and the notifications are sent. AWS Lambda and Amazon SNS have perpetual free tier and you’ll be charged only once the usage goes beyond the free tier usage every month.

Summary

In this website post, you’re showed by us how exactly to automate the resolution of unintended cross-account IAM roles using IAM Access Analyzer. As a resolution, a deny was added by this solution statement in to the IAM role’s trust policy.

It is possible to expand the solution to solve Access Analyzer findings for Amazon KMS and S3, by modifying the associated resource policies. You can even include capabilities like automating the rollback of the resolution if the role is supposed, or introducing an approval workflow to solve the finding to match to your organization’s process requirements. Also, IAM Access Analyzer allows you to&nbsp now; preview and validate public and cross-account access before deploying permissions changes.

When you have feedback concerning this post, submit comments in the Comments section below. When you have questions concerning this post, take up a new thread on the AWS IAM forum .

Want more AWS Security how-to content, news, and show announcements? Follow us on Twitter .