From 93416795398525af829d254f342554942c6ed907 Mon Sep 17 00:00:00 2001 From: Weyland <71197790+wey-chiang@users.noreply.github.com> Date: Mon, 16 Nov 2020 17:43:30 -0500 Subject: [PATCH] Added example of regex checking for IAM arns (#144) * Added example of regex checking for IAM arns * Fixed line formatting * Fixed lint issues * Bugfix: role patterns * Fix: Removed 2 lines - unnecessary return * Added test case for role pattern * Changed test case so it reaches the intended condition * Fixed tests --- ...m_entity_created_without_cloudformation.py | 41 ++++++++++++------ ..._entity_created_without_cloudformation.yml | 43 +++++++++++++++++++ 2 files changed, 71 insertions(+), 13 deletions(-) diff --git a/aws_cloudtrail_rules/aws_iam_entity_created_without_cloudformation.py b/aws_cloudtrail_rules/aws_iam_entity_created_without_cloudformation.py index ca602b1b8..5ef4d2af3 100644 --- a/aws_cloudtrail_rules/aws_iam_entity_created_without_cloudformation.py +++ b/aws_cloudtrail_rules/aws_iam_entity_created_without_cloudformation.py @@ -1,30 +1,45 @@ +import re + # The role dedicated for IAM administration IAM_ADMIN_ROLES = { - 'arn:aws:iam::123456789012:role/IdentityCFNServiceRole', + "arn:aws:iam::123456789012:role/IdentityCFNServiceRole", } +# The role patterns dedicated for IAM Service Roles +IAM_ADMIN_ROLE_PATTERNS = {"arn:aws:iam::[0-9]+:role/IdentityCFNServiceRole"} + # API calls that are indicative of IAM entity creation IAM_ENTITY_CREATION_EVENTS = { - 'BatchCreateUser', - 'CreateGroup', - 'CreateInstanceProfile', - 'CreatePolicy', - 'CreatePolicyVersion', - 'CreateRole', - 'CreateServiceLinkedRole', - 'CreateUser', + "BatchCreateUser", + "CreateGroup", + "CreateInstanceProfile", + "CreatePolicy", + "CreatePolicyVersion", + "CreateRole", + "CreateServiceLinkedRole", + "CreateUser", } def rule(event): # Check if this event is in scope - if event['eventName'] not in IAM_ENTITY_CREATION_EVENTS: + if event["eventName"] not in IAM_ENTITY_CREATION_EVENTS: return False # All IAM changes MUST go through CloudFormation - if event['userIdentity'].get('invokedBy') != 'cloudformation.amazonaws.com': + if event["userIdentity"].get("invokedBy") != "cloudformation.amazonaws.com": return True # Only approved IAM Roles can make IAM Changes - return event['userIdentity']['sessionContext']['sessionIssuer'][ - 'arn'] not in IAM_ADMIN_ROLES + for admin_role_pattern in IAM_ADMIN_ROLE_PATTERNS: + # Check if the arn matches any role patterns, returns False (whitelisting it) if there is a match + if (len( + re.findall( + admin_role_pattern, + event["userIdentity"]["sessionContext"]["sessionIssuer"] + ["arn"], + )) > 0): + return False + + return (event["userIdentity"]["sessionContext"]["sessionIssuer"]["arn"] + not in IAM_ADMIN_ROLES) diff --git a/aws_cloudtrail_rules/aws_iam_entity_created_without_cloudformation.yml b/aws_cloudtrail_rules/aws_iam_entity_created_without_cloudformation.yml index 2086c1304..7a771bf17 100644 --- a/aws_cloudtrail_rules/aws_iam_entity_created_without_cloudformation.yml +++ b/aws_cloudtrail_rules/aws_iam_entity_created_without_cloudformation.yml @@ -106,6 +106,49 @@ Tests: "eventType": "AwsApiCall", "recipientAccountId": "123456789012" } + - + Name: IAM Entity Created Manually With Approved Role Pattern + ExpectedResult: false + Log: + { + "eventVersion": "1.05", + "userIdentity": { + "type": "AssumedRole", + "principalId": "1111:tester", + "arn": "arn:aws:sts::123456789012:assumed-role/tester", + "accountId": "123456789012", + "accessKeyId": "1", + "invokedBy": "cloudformation.amazonaws.com", + "sessionContext": { + "attributes": { + "mfaAuthenticated": "true", + "creationDate": "2019-01-01T00:00:00Z" + }, + "sessionIssuer": { + "type": "Role", + "principalId": "1111", + "arn": "arn:aws:iam::210987654321:role/IdentityCFNServiceRole", + "accountId": "123456789012", + "userName": "tester" + } + } + }, + "eventTime": "2019-01-01T00:00:00Z", + "eventSource": "iam.amazonaws.com", + "eventName": "CreateUser", + "awsRegion": "us-east-1", + "sourceIPAddress": "111.111.111.111", + "userAgent": "console.amazonaws.com", + "requestParameters": { + "userName": "user", + "path": "/" + }, + "responseElements": null, + "requestID": "1", + "eventID": "1", + "eventType": "AwsApiCall", + "recipientAccountId": "123456789012" + } - Name: IAM Entity Created Manually ExpectedResult: true