Skip to content

Commit

Permalink
Added example of regex checking for IAM arns (#144)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
wey-chiang authored Nov 16, 2020
1 parent dce2f08 commit 9341679
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -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)
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 9341679

Please sign in to comment.