aws re:invent 2016: how to automate policy validation (sec311)
TRANSCRIPT
© 2016, Amazon Web Services, Inc. or its Affiliates. All rights reserved.
Brigid Johnson, AWS Identity and Access Management
November 29, 2016
SEC311
How to Automate
Policy Validation
Which entities can call powerful actions?
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.
Policy Review
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.
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
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.
Policy Validation Scenarios
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.
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
Tools for Validation
Manual Option #1Use the IAM console to validate access
Manual Option #2Use the IAM policy simulator to validate access
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.
Simulate Principal Policy
Inputspolicy-source-arn
policy-input-list(optional)
action-names
resource-arns(default *)
resource-policy(optional)
resource-owner(optional)
caller-arn(default sourceARN)
context-entries(optional)
resource-handling-
option(optional)
OutputsEvaluationResults (list)
EvalActionName
EvalResourceName
EvalDecision
MatchedStatements(list)
EvalDecision:
• allowed
• explicitDeny
• implicitDeny
Simulate Principal Policy
aws iam simulate-principal-policy --policy-source-arnarn: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
Simulate Principal Policy
Here is the output from our command.
Oh Bother!
Simulate Custom Policy
Inputspolicy-input-list
action-names
resource-arns(default *)
resource-policy(optional)
resource-owner(optional)
caller-arn(default sourceARN)
context-entries(optional)
resource-handling-
option(optional)
OutputsEvaluationResults (list)
EvalActionName
EvalResourceName
EvalDecision
MatchedStatements(list)
Quick Recap
• Policy refresher
• Scenarios
• Policy simulator APIs
So how do we automate?
How do we get this list?
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.
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.
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
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
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
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.
SNS Notification
New Compliance Change Record:
----------------------------
{ "awsAccountId": "028103658970",
"configRuleName": "powerful_actions_policy_validation_pre",
"resourceType": "AWS::IAM::User",
"resourceId": "AIDAJEWF7IMZXWB7AVHX2",
"awsRegion": "us-east-1",
...
"complianceType": "NON_COMPLIANT",
"resultRecordedTime": "2016-11-21T20:32:39.821Z",
"configRuleInvokedTime": "2016-11-21T20:29:20.684Z",
"annotation": "Entity: arn:aws:iam:028103658970::user/Casey is NON_COMPLIANT for validation of powerful actions access.",
"resultToken": null
},
"oldEvaluationResult": "COMPLIANT",
...
}
You’ve
Got Mail!
Lambda Function
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
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
Lambda FunctionValidate Powerful Actions
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
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
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
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
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
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
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
Lambda Role Policy
{ "Version": "2012-10-17","Statement": [
{ "Sid": "AllowLambdaSimulateAccess","Effect": "Allow","Action": [
"config:GetResourceConfigHistory","config:PutEvaluations","config:StartConfigRulesEvaluation","iam:GetPolicy","iam:GetPolicyVersion","iam:SimulateCustomPolicy","iam:SimulatePrincipalPolicy","iam:ListEntitiesforPolicy","iam:GetGroup","logs:*","s3:GetBucketPolicy"],
"Resource": ["*"]}]}
Lambda FunctionValidate Critical Resources
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
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
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
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
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
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
Lambda FunctionValidate Restricted EC2 Regions
Restricted Regions Policy
{"Version": "2012-10-17","Statement": [{
"Sid": "THISALLOWSEC2ReadandRuninRegion","Effect": "Allow","Action": ["ec2:Describe*",
"ec2:RunInstances"],"Resource": "*","Condition": {
"StringEquals": {"ec2:Region": ["us-west-1", "us-west-2"]
}}},{
"Effect": "Allow","Action": ["iam:PassRole"],"Resource": "arn:aws:iam::028103658970:role/app-mobile-ec2-role"
},{
"Effect": "Allow","Action": ["iam:List*"],"Resource": "*"
}]}
Context keys
and values
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
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
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
Let’s Recap
• Check multiple powerful actions
• Check actions on specific critical resources
• Check actions with context keys and values
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
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
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
Thank you!
Remember to complete
your evaluations!