Managing permissions across a growing number of identities and resources can be time-consuming and complex. Testing, validating, and understanding permissions before and after policy changes are deployed is critical to ensuring that your users and systems have the appropriate level of access. This session walks through the tools that are available to test, validate, and understand the permissions in your account. We demonstrate how to use these tools and how to automate them to continually validate the permissions in your accounts. The tools demonstrated in this session help you answer common questions such as:
Which users and roles have access to perform powerful actions?
Which users and roles have access to critical resources such as Amazon S3 buckets?
Who is able to launch instances in a specific region?
3. What to Expect from the Session
• Know why and when to validate policies
• Learn the tools available for policy validation
• Explore three common scenarios for policy validation
• See demonstrations using AWS Config, AWS Lambda,
and Amazon SNS to validate policy changes.
5. Policy Overview
Policies specify what AWS service actions users and systems are
allowed to perform on which resources.
Example: Amazon S3 Read-Only
Example of an IAM user/group/role access policy
{
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:Get*", "s3:List*"],
"Resource": "*"
}
]
}
JSON-formatted documents
Contain a statement (permissions)
which specify:
What actions a principal can perform
Which resources can be accessed
Note: Access is denied by default.
6. Identity-based policies
Attached to an IAM user, group,
or role.
Types of Policies for Access Control
Resource-based policies
Attached to a resource to specify
who has access to the resource.
Amazon S3 buckets
Amazon Glacier vaults
Amazon SNS topics
Amazon SQS queues
AWS KMS keys
7. Policy Structure
Principal: Entity allowed or denied access to a resource.
Required for resource-based, but not IAM policies.
Policies contain one ore more statement. Each statement is the
following elements.
Action: Service and actions.
Resource: Object(s) the actions can be performed on.
Conditions: Conditions for when the statement is in effect.
9. Why Validate?
There are some powerful actions in AWS
IAM:Put(User, Group, Role)Policy – Updates an inline policy.
S3:PutBucketPolicy – Updates S3 bucket policy.
KMS:Decrypt – Decrypts KMS ciphertext.
Ensure access to critical resources is limited
S3 bucket with sensitive information.
EC2 instance that runs a service critical to your business.
10. Permission Scenarios to Validate
Determine the IAM entities that are allowed to:
#1 Call powerful actions
#2 Access a critical resource
#3 Launch EC2 instances in restricted regions
14. APIs For Automation
Two APIs available for programmatic policy validation
IAM:SimulatePrincipalPolicy: Simulate the set of IAM policies attached to an
IAM user, group, or role to determine the policies' effective permissions for a
list of API actions and AWS resources.
IAM:SimulateCustomPolicy: Simulate a set of IAM policies and optionally a
resource policy that is not attached to an IAM entity to determine the policies’
effective permissions for a list of API actions and AWS resources.
16. Simulate Principal Policy
aws iam simulate-principal-policy
--policy-source-arn
arn:aws:iam::112233445566:user/Casey
--action-names
"iam:putuserpolicy"
Let’s see what it looks like on the command line
IAM User ARN
Powerful action
21. AWS Services to Help us Automate
AWS Lambda AWS Config Rules Amazon SNS
Run policy validation to
determine if a user, group,
role, or policy is
compliant. This can be
scheduled or triggered by
a change.
Use AWS Config rules to
trigger validation
functions when an IAM
entity changes.
Notify when Lambda
policy validation
function finds an
invalid permission.
22. Two Solutions for Validation
Periodic Audit
Scheduled validation on
users, groups, and roles to
audit permissions.
Configuration Change
Run validation when a
change on an IAM resource
has been made.
23. Solution Architecture
AWS Lambda
AWS Config Rules
Amazon SNS
Run policy validation
on resources to check
if they are compliant.
Trigger Lambda
function when a user,
group, role, or policy
changes.
Alert when compliant
status changes based
on Lambda validation.
1
2
3
24. Solution Architecture
AWS Config
Trigger Lambda
function when a user,
group, role, or policy
changes or set a
schedule to audit
resources.
Three types of AWS Config rules to support our
scenarios. These rules use AWS Lambda functions
that you create to determine if IAM resources are
complaint or not.
1) Validate Powerful Actions
2) Validate Critical Resources
3) Validate Restricted Regions for EC2
25. Solution Architecture
AWS Lambda
Run policy validation
on resources to check
if they are compliant.
Three types of Lambda functions for each AWS
Config rule. These functions use IAM policy
simulator APIs to validate permissions.
1) Validate Powerful Actions
2) Validate Critical Resources
3) Validate Restricted Regions for EC2
26. Solution Architecture
Amazon SNS
Alert when compliant
status changes based
on permission
validation.
1 SNS topic to report when an IAM resource
changes status. Customers can subscribe to SNS
topics to receive near real-time notifications.
29. Core Elements of the Lambda Function
Inputs
1. IAM resource.
2. Related
resources.
3. Resource
policies.
Validation
Simulate
permissions of
related entities.
Outputs
1. IAM resource
information
2. COMPLIANT or
NOT_COMPLIANT
30. Lambda Function Evaluation Logic
Send
Result
Simulate
Principal
Send
Result
For Each
User
Simulate
Policy
Send
Result
For Each
Attached
Entity
Simulate
Principal
User or
Role
Group
Managed
Policy
32. Inputs
# Resource types this function can evaluate
APPLICABLE_RESOURCES = ["AWS::IAM::User",
"AWS::IAM::Group","AWS::IAM::Role","AWS::IAM::Policy"]
# Actions that we will simulate to determine compliance
POWERFUL_ACTIONS = ['iam:putrolepolicy', 's3:putbucketpolicy']
def evaluate_compliance(configuration_item, result_token):
resource_name = configuration_item["resourceName"]
resource_arn = configuration_item["ARN"]
timestamp = configuration_item["configurationItemCaptureTime"]
resource_type = configuration_item["resourceType"]
resource_id = configuration_item["resourceId"]
Define list of
actions
Information
for
simulation
33. Simulate - Principal
def simulate_principal_policy(iam, resource_arn):
# Call IAM to simulate the policy on restricted actions.
response = iam.simulate_principal_policy(PolicySourceArn=resource_arn,
ActionNames=POWERFUL_ACTIONS,
ResourceArns=['*'])
results = response['EvaluationResults']
allows_powerful_action = False
# Determine if any restricted actions are allowed.
for actions in results:
eval_decision = actions['EvalDecision']
if(eval_decision == 'allowed'):
action_name = actions['EvalActionName']
print "Restricted action " + action_name + " granted “ + resource_arn
allows_powerful_action = True
# If any restricted actions were allowed, consider the resource non-compliant.
if(allows_powerful_action):
return "NON_COMPLIANT"
return "COMPLIANT"
Run
simulation
Evaluate
result
Determine
compliance
34. Simulate - Policy
def simulate_managed_policy(iam, policy_arn):
# Retrieve the policy.
get_policy_response = iam.get_policy(PolicyArn=policy_arn)
default_version = get_policy_response["Policy"]["DefaultVersionId"]
get_policy_version_response = iam.get_policy_version(
PolicyArn=policy_arn,
VersionId=default_version)
policy_document = json.dumps(
get_policy_version_response["PolicyVersion"]["Document"])
Get policy for
simulation
35. Simulate – Policy Continued
# Simulate the policy
simulation_response = iam.simulate_custom_policy(
PolicyInputList=[policy_document],
ActionNames=POWERFUL_ACTIONS,
ResourceArns=["*"])
results = simulation_response['EvaluationResults']
allows_powerful_action = False
# Determine if any restricted actions are allowed.
for actions in results:
evalDecision = actions['EvalDecision']
if(evalDecision == 'allowed'):
actionName = actions['EvalActionName']
print "Restricted action " + actionName + " granted to " + policy_arn
allows_powerful_action = True
# If any restricted actions were allowed, consider the resource non-compliant.
if(allows_powerful_action):
return "NON_COMPLIANT"
return "COMPLIANT"
Run
simulation
Evaluate
result
Determine
compliance
36. Sent Result to AWS Config
def record_results(config, compliance_result, result_token, resource_type,
resource_id, resource_arn, timestamp):
# Call Config to record the results of our evaluation.
annotation = "Entity: " + resource_arn + " is " + compliance_result + " for
validation of powerful actions access."
config.put_evaluations(
Evaluations=[
{
"ComplianceResourceType": resource_type,
"ComplianceResourceId": resource_id,
"ComplianceType": compliance_result,
"Annotation": annotation,
"OrderingTimestamp": timestamp
},
],
ResultToken=result_token
)
Pro Tip: You
can put
evaluations
for any
resource
37. Support Functions
get_users_for_group: gets a list of all users in a group
simulate_group: simulates group and each user in it
evaluate_compliance: coordinates evaluation of entities
38. Demo
Use Case: Validate which users, groups, roles, and policies
have access to invoke powerful actions.
1. Create a role for the Lambda function
2. Create the Lambda function
3. Create a AWS Config rule
4. Run and test
41. Inputs
# Resource types this function can evaluate
APPLICABLE_RESOURCES = ["AWS::IAM::User",
"AWS::IAM::Group","AWS::IAM::Role","AWS::IAM::Policy"]
# Actions non-compliant on a specific resource
ACTIONS = ['s3:GetObject']
# The critical bucket
BUCKET_ARN = "arn:aws:s3:::aws-reinvent-session-311-hr/*"
BUCKET_NAME = "aws-reinvent-session-311-hr"
def evaluate_compliance(configuration_item, result_token):
resource_name = configuration_item["resourceName"]
resource_arn = configuration_item["ARN"]
timestamp = configuration_item["configurationItemCaptureTime"]
resource_type = configuration_item["resourceType"]
resource_id = configuration_item["resourceId"]
Define list of
actions
Define critical
resource
42. Simulate - Principal
def simulate_principal_policy(iam, resource_arn):
# Get the resource-based policy
bucket_policy=get_bucket_policy()
# Call IAM to simulate the policy on critical resources.
if(bucket_policy is not None and resource_type == "AWS::IAM::User"):
response = iam.simulate_principal_policy(
PolicySourceArn=resource_arn,
ActionNames=ACTIONS,
ResourceArns=[BUCKET_ARN],
ResourcePolicy=bucket_policy)
else:
response =
iam.simulate_principal_policy(PolicySourceArn=resource_arn,
ActionNames=ACTIONS,ResourceArns=[BUCKET_ARN])
results = response['EvaluationResults']
allows_critical_resource = False
Get the
bucket policy
Simulate with
bucket policy
Simulate
without
bucket policy
43. Simulate - Policy
def simulate_managed_policy(iam, policy_arn):
# Retrieve the policy.
get_policy_response = iam.get_policy(PolicyArn=policy_arn)
default_version = get_policy_response["Policy"]["DefaultVersionId"]
get_policy_version_response = iam.get_policy_version(
PolicyArn=policy_arn,
VersionId=default_version)
policy_document = json.dumps(
get_policy_version_response["PolicyVersion"]["Document"])
Get policy for
simulation
44. Simulate – Policy Continued
# Simulate the policy
simulation_response =
iam.simulate_custom_policy(PolicyInputList=[policy_document],
ActionNames=ACTIONS,
ResourceArns=[BUCKET_ARN])
results = simulation_response['EvaluationResults']
allows_critical_resource = False
# Determine if any action is allowed on the critical resource.
for actions in results:
evalDecision = actions['EvalDecision']
if(evalDecision == 'allowed'):
actionName = actions['EvalActionName']
print “Access to " + BUCKET_ARN + " allowed by " + policy_arn
allows_critical_resource = True
# If any access to critical resources are allowed then non-compliant.
if(allows_critical_resource):
return "NON_COMPLIANT"
return "COMPLIANT"
Run
simulation
45. Support Functions
get_users_for_group: gets a list of all users in a group
simulate_group: simulates group and each user in it
evaluate_compliance: coordinates evaluation of entities
New!
get_bucket_policy: gets the bucket policy for a bucket
46. Demo
Use Case: Validate which users, groups, roles, and policies
have access to critical resources
1. Create the Lambda function
2. Create a AWS Config rule
3. Run and test
49. Inputs
# Resource types this function can evaluate
APPLICABLE_RESOURCES = ["AWS::IAM::User",
"AWS::IAM::Group","AWS::IAM::Role","AWS::IAM::Policy"]
# Actions that we will simulate to determine compliance
ACTIONS = ['ec2:RunInstances']
# Condion keys and values we consider non-compliant
CONTEXT_KEY_NAME = "ec2:Region"
CONTEXT_KEY_VALUES = ["us-east-1", "us-east-2"]
def evaluate_compliance(configuration_item, result_token):
resource_name = configuration_item["resourceName"]
resource_arn = configuration_item["ARN"]
timestamp = configuration_item["configurationItemCaptureTime"]
resource_type = configuration_item["resourceType"]
resource_id = configuration_item["resourceId"]
Define list of
actions
Define
conditions
50. Simulate - Principal
allows_restricted_regions = False
for contextValue in CONTEXT_KEY_VALUES:
# Call IAM to simulate the policy on restricted actions.
context = {'ContextKeyName': CONTEXT_KEY_NAME, 'ContextKeyValues':
[contextValue], 'ContextKeyType': 'string'}
response = iam.simulate_principal_policy(PolicySourceArn=resource_arn,
ActionNames=ACTIONS,ResourceArns=['*'],ContextEntries=[context])
results = response['EvaluationResults']
# Determine if the simulation allowed action in restricted region.
for actions in results:
eval_decision = actions['EvalDecision']
if(eval_decision == 'allowed'):
action_name = actions['EvalActionName']
print "Restricted " + action_name + " granted to " + resource_arn
allows_restricted_regions = True
# If any restricted regions were allowed, consider the resource non-compliant.
if(allows_restricted_regions):
return "NON_COMPLIANT"
return "COMPLIANT"
Set the
context
Simulate
51. Simulate – Policy Continued
allows_restricted_regions = False
for contextValue in CONTEXT_KEY_VALUES:
# Simulate the policy
context = {'ContextKeyName': CONTEXT_KEY_NAME, 'ContextKeyValues':
[contextValue], 'ContextKeyType': 'string'}
simulation_response = iam.simulate_custom_policy(
PolicyInputList=[policy_document],
ActionNames=ACTIONS,ResourceArns=['*'],ContextEntries=[context])
results = simulation_response['EvaluationResults']
# Determine if the simulation allowed action in restricted region.
for actions in results:
evalDecision = actions['EvalDecision']
if(evalDecision == 'allowed'):
actionName = actions['EvalActionName']
print "Restricted " + actionName + " granted to " + policy_arn
allows_restricted_regions = True
# If any restricted regions were allowed, consider the resource non-compliant.
if(allows_restricted_regions):
return "NON_COMPLIANT"
return "COMPLIANT"
Set the
context
Simulate
52. Let’s Recap
• Check multiple powerful actions
• Check actions on specific critical resources
• Check actions with context keys and values
53. What else is possible
• Use AWS Config to run recurring permission validation
every 24 hours.
• Invoke a reactive action to non-compliant IAM entities
using your Lambda function.
• Include a whitelist of entities that are allowed these
permissions.
• Parse your policies.
What Else?
Stop by the Security Booth to discuss your ideas
54. Additional Resources
AWS Config Documentation
- Supported Resources, Configuration Items, and
Relationships
- API on ConfigurationItem
AWS DevOps Blog
How to Centrally Manage AWS Config Rules across Multiple
AWS Accounts
55. Get the Code
Lambda functions available in this location:
Bucket Link:
https://s3.amazonaws.com/awsiammedia/public/sample/SE
C311automatingpolicyvalidation/
Powerful Actions:
iam-policy-validate-powerfulActions.py
Critical Resources:
iam-policy-validate-criticalResources.py
Restricted Regions:
iam-policy-validate-restrictedRegions.py