AnalysisType: rule
Filename: aws_iam_entity_created_without_cloudformation.py
RuleID: "AWS.CloudTrail.IAMEntityCreatedWithoutCloudFormation"
DisplayName: "IAM Entity Created Without CloudFormation"
Enabled: false
LogTypes:
- AWS.CloudTrail
Reports:
MITRE ATT&CK:
- TA0003:T1136
Tags:
- AWS
- Configuration Required
- Identity and Access Management
- Persistence:Create Account
Severity: Medium
Description: >
An IAM Entity (Group, Policy, Role, or User) was created manually. IAM entities should be created in code to ensure that permissions are tracked and managed correctly.
Runbook: >
Verify whether IAM entity needs to exist. If so, re-create it in an appropriate CloudFormation, Terraform, or other template. Delete the original manually created entity.
Reference: https://blog.awsfundamentals.com/aws-iam-roles-with-aws-cloudformation
SummaryAttributes:
- userAgent
- sourceIpAddress
- recipientAccountId
- p_any_aws_arns
Tests:
- Name: IAM Entity Created Automatically
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::123456789012: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 With Approved Role
ExpectedResult: true
Log:
{
"eventVersion": "1.05",
"userIdentity":
{
"type": "AssumedRole",
"principalId": "1111:tester",
"arn": "arn:aws:sts::123456789012:assumed-role/tester",
"accountId": "123456789012",
"accessKeyId": "1",
"sessionContext":
{
"attributes":
{
"mfaAuthenticated": "true",
"creationDate": "2019-01-01T00:00:00Z",
},
"sessionIssuer":
{
"type": "Role",
"principalId": "1111",
"arn": "arn:aws:iam::123456789012: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 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
Log:
{
"eventVersion": "1.05",
"userIdentity":
{
"type": "AssumedRole",
"principalId": "1111:tester",
"arn": "arn:aws:sts::123456789012:assumed-role/tester",
"accountId": "123456789012",
"accessKeyId": "1",
"sessionContext":
{
"attributes":
{
"mfaAuthenticated": "true",
"creationDate": "2019-01-01T00:00:00Z",
},
"sessionIssuer":
{
"type": "Role",
"principalId": "1111",
"arn": "arn:aws:iam::123456789012:role/OtherRole",
"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: Non IAM Entity Creation Event
ExpectedResult: false
Log:
{
"eventVersion": "1.05",
"userIdentity":
{
"type": "AssumedRole",
"principalId": "1111:tester",
"arn": "arn:aws:sts::123456789012:assumed-role/tester",
"accountId": "123456789012",
"accessKeyId": "1",
"sessionContext":
{
"attributes":
{
"mfaAuthenticated": "true",
"creationDate": "2019-01-01T00:00:00Z",
},
"sessionIssuer":
{
"type": "Role",
"principalId": "1111",
"arn": "arn:aws:iam::123456789012:role/OtherRole",
"accountId": "123456789012",
"userName": "tester",
},
},
},
"eventTime": "2019-01-01T00:00:00Z",
"eventSource": "iam.amazonaws.com",
"eventName": "NotCreateUser",
"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: Error Manually Creating IAM Entity
ExpectedResult: false
Log:
{
"eventVersion": "1.05",
"errorCode": "EntityAlreadyExists",
"userIdentity":
{
"type": "AssumedRole",
"principalId": "1111:tester",
"arn": "arn:aws:sts::123456789012:assumed-role/tester",
"accountId": "123456789012",
"accessKeyId": "1",
"sessionContext":
{
"attributes":
{
"mfaAuthenticated": "true",
"creationDate": "2019-01-01T00:00:00Z",
},
"sessionIssuer":
{
"type": "Role",
"principalId": "1111",
"arn": "arn:aws:iam::123456789012:role/OtherRole",
"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",
}
# ------ paired body: aws_iam_entity_created_without_cloudformation.py ------
import re
from panther_aws_helpers import aws_cloudtrail_success, aws_rule_context
# The role dedicated for IAM administration
IAM_ADMIN_ROLES = {
"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",
}
def rule(event):
# Check if this event is in scope
if (
not aws_cloudtrail_success(event)
or event.get("eventName") not in IAM_ENTITY_CREATION_EVENTS
):
return False
# All IAM changes MUST go through CloudFormation
if event.deep_get("userIdentity", "invokedBy") != "cloudformation.amazonaws.com":
return True
# Only approved IAM Roles can make IAM Changes
for admin_role_pattern in IAM_ADMIN_ROLE_PATTERNS:
# Check if the arn matches any role patterns, return False if there is a match
if (
len(
re.findall(
admin_role_pattern,
event.deep_get("userIdentity", "sessionContext", "sessionIssuer", "arn"),
)
)
> 0
):
return False
return (
event.deep_get("userIdentity", "sessionContext", "sessionIssuer", "arn")
not in IAM_ADMIN_ROLES
)
def alert_context(event):
return aws_rule_context(event)