def get_sqs_queue_policies( session: botocore.session.Session, account_id: str, region_allow_list: Optional[List[str]] = None, region_deny_list: Optional[List[str]] = None) -> List[Policy]: """Using a botocore Session object, return a list of Policy objects representing the queue policies of each SQS queue in this account. The region allow/deny lists are mutually-exclusive (i.e. at least one of which has the value None) lists of allowed/denied regions to pull data from. """ result = [] # Iterate through all regions of SQS where possible for sqs_region in get_regions_to_search(session, 'sqs', region_allow_list, region_deny_list): try: # Grab the queue names queue_urls = [] sqsclient = session.create_client('sqs', region_name=sqs_region) response = sqsclient.list_queues() if 'QueueUrls' in response: queue_urls.extend(response['QueueUrls']) else: continue # Grab the queue policies for queue_url in queue_urls: queue_name = queue_url.split('/')[-1] sqs_policy_response = sqsclient.get_queue_attributes( QueueUrl=queue_url, AttributeNames=['Policy']) if 'Policy' in sqs_policy_response: sqs_policy_doc = json.loads(sqs_policy_response['Policy']) result.append( Policy( 'arn:aws:sqs:{}:{}:{}'.format( sqs_region, account_id, queue_name), queue_name, json.loads(sqs_policy_doc))) logger.info('Caching policy for {}'.format( 'arn:aws:sqs:{}:{}:{}'.format(sqs_region, account_id, queue_name))) else: result.append( Policy( 'arn:aws:sqs:{}:{}:{}'.format( sqs_region, account_id, queue_name), queue_name, { "Statement": [], "Version": "2012-10-17" })) logger.info( 'Queue {} does not have a bucket policy, adding a "stub" policy instead.' .format(queue_name)) except botocore.exceptions.ClientError as ex: logger.info( 'Unable to search SQS in region {} for queues. The region may be disabled, or the current principal may not be authorized to access the service. Continuing.' .format(sqs_region)) logger.debug('Exception was: {}'.format(ex)) return result
def get_s3_bucket_policies(session: botocore.session.Session) -> List[Policy]: """Using a botocore Session object, return a list of Policy objects representing the bucket policies of each S3 bucket in this account. """ result = [] s3client = session.create_client('s3') buckets = [x['Name'] for x in s3client.list_buckets()['Buckets']] for bucket in buckets: bucket_arn = 'arn:aws:s3:::{}'.format( bucket) # TODO: allow different partition try: bucket_policy = json.loads( s3client.get_bucket_policy(Bucket=bucket)['Policy']) result.append(Policy(bucket_arn, bucket, bucket_policy)) logger.info('Caching policy for {}'.format(bucket_arn)) except botocore.exceptions.ClientError as ex: if 'NoSuchBucketPolicy' in str(ex): logger.info( 'Bucket {} does not have a bucket policy, adding a "stub" policy instead.' .format(bucket)) result.append( Policy(bucket_arn, bucket, { "Statement": [], "Version": "2012-10-17" })) else: logger.info( 'Unable to retrieve bucket policy for {}. You should add this manually. Continuing.' .format(bucket)) logger.debug('Exception was: {}'.format(ex)) return result
def build_playground_graph() -> Graph: """Constructs and returns a Graph objects with many nodes, edges, groups, and policies""" common_iam_prefix = 'arn:aws:iam::000000000000:' # policies to use and add admin_policy = Policy('arn:aws:iam::aws:policy/AdministratorAccess', 'AdministratorAccess', _get_admin_policy()) ec2_for_ssm_policy = Policy('arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM', 'AmazonEC2RoleforSSM', _get_ec2_for_ssm_policy()) s3_full_access_policy = Policy('arn:aws:iam::aws:policy/AmazonS3FullAccess', 'AmazonS3FullAccess', _get_s3_full_access_policy()) jump_policy = Policy('arn:aws:iam::000000000000:policy/JumpPolicy', 'JumpPolicy', _get_jump_policy()) policies = [admin_policy, ec2_for_ssm_policy, s3_full_access_policy, jump_policy] # IAM role trust docs to be used ec2_trusted_policy_doc = _make_trust_document({'Service': 'ec2.amazonaws.com'}) root_trusted_policy_doc = _make_trust_document({'AWS': 'arn:aws:iam::000000000000:root'}) alt_root_trusted_policy_doc = _make_trust_document({'AWS': '000000000000'}) other_acct_trusted_policy_doc = _make_trust_document({'AWS': '999999999999'}) # nodes to add nodes = [] # Regular admin user nodes.append(Node(common_iam_prefix + 'user/admin', 'AIDA00000000000000000', [admin_policy], [], None, None, 1, True, True)) # Regular ec2 role nodes.append(Node(common_iam_prefix + 'role/ec2_ssm_role', 'AIDA00000000000000001', [ec2_for_ssm_policy], [], ec2_trusted_policy_doc, common_iam_prefix + 'instance-profile/ec2_ssm_role', 0, False, False)) # ec2 role with admin nodes.append(Node(common_iam_prefix + 'role/ec2_admin_role', 'AIDA00000000000000002', [ec2_for_ssm_policy], [], ec2_trusted_policy_doc, common_iam_prefix + 'instance-profile/ec2_admin_role', 0, False, True)) # assumable role with s3 access nodes.append(Node(common_iam_prefix + 'role/s3_access_role', 'AIDA00000000000000003', [s3_full_access_policy], [], root_trusted_policy_doc, None, 0, False, False)) # second assumable role with s3 access with alternative trust policy nodes.append(Node(common_iam_prefix + 'role/s3_access_role_alt', 'AIDA00000000000000004', [s3_full_access_policy], [], alt_root_trusted_policy_doc, None, 0, False, False)) # externally assumable role with s3 access nodes.append(Node(common_iam_prefix + 'role/external_s3_access_role', 'AIDA00000000000000005', [s3_full_access_policy], [], other_acct_trusted_policy_doc, None, 0, False, False)) # jump user with access to sts:AssumeRole nodes.append(Node(common_iam_prefix + 'user/jumpuser', 'AIDA00000000000000006', [jump_policy], [], None, None, 1, True, False)) # user with S3 access, path in user's ARN nodes.append(Node(common_iam_prefix + 'user/somepath/some_other_jumpuser', 'AIDA00000000000000007', [jump_policy], [], None, None, 1, True, False)) # role with S3 access, path in role's ARN nodes.append(Node(common_iam_prefix + 'role/somepath/somerole', 'AIDA00000000000000008', [s3_full_access_policy], [], alt_root_trusted_policy_doc, None, 0, False, False)) # edges to add edges = obtain_edges(None, checker_map.keys(), nodes, sys.stdout, True) return Graph(nodes, edges, policies, [], _get_default_metadata())
def _get_scps_for_target(target_id: str) -> List[Policy]: """This method takes an ID for a target (root, OU, or account), then composes and returns a list of Policy objects for that target.""" scps_result = [] policy_name_arn_list = [] list_policies_paginator = orgsclient.get_paginator( 'list_policies_for_target') for lpp_page in list_policies_paginator.paginate( TargetId=target_id, Filter='SERVICE_CONTROL_POLICY'): for policy in lpp_page['Policies']: policy_name_arn_list.append((policy['Name'], policy['Arn'])) for name_arn_pair in policy_name_arn_list: policy_name, policy_arn = name_arn_pair desc_policy_resp = orgsclient.describe_policy( PolicyId=policy_arn.split('/')[-1]) scps_result.append( Policy(policy_arn, policy_name, json.loads(desc_policy_resp['Policy']['Content']))) logger.debug('SCPs of {}: {}'.format(target_id, [x.arn for x in scps_result])) scp_list.extend(scps_result) return scps_result
def test_admin_verified_for_group_member(self): admin_policy = Policy( 'arn:aws:iam::000000000000:group/admins', 'inline_admin', { 'Version': '2012-10-17', 'Statement': [{ 'Effect': 'Allow', 'Action': '*', 'Resource': '*' }] }) admin_group = Group('arn:aws:iam::000000000000:group/admins', [admin_policy]) not_admin_group = Group('arn:aws:iam::000000000000:group/losers', []) new_node_1 = Node('arn:aws:iam::000000000000:user/node_1', 'id1', [], [admin_group], None, None, 1, False, False, None, False, None) new_node_2 = Node('arn:aws:iam::000000000000:user/node_2', 'id2', [], [not_admin_group], None, None, 1, False, False, None, False, None) update_admin_status([new_node_1, new_node_2]) self.assertTrue(new_node_1.is_admin, 'Member of admin group should be marked as an admin') self.assertFalse( new_node_2.is_admin, 'Member of non-admin group should not be marked as an admin')
def build_graph_with_one_admin() -> Graph: """Constructs and returns a Graph object with one node that is an admin""" admin_user_arn = 'arn:aws:iam::000000000000:user/admin' policy = Policy(admin_user_arn, 'InlineAdminPolicy', _get_admin_policy()) node = Node(admin_user_arn, 'AIDA00000000000000000', [policy], [], None, None, 1, True, True, None, False, None) return Graph([node], [], [policy], [], _get_default_metadata())
def _build_user_with_policy(policy_dict, policy_name='single_user_policy', user_name='asdf', number='0') -> Node: """Helper function: builds an IAM User with a given input policy.""" policy = Policy('arn:aws:iam::000000000000:policy/{}'.format(policy_name), policy_name, policy_dict) result = Node('arn:aws:iam::000000000000:user/{}'.format(user_name), 'AIDA0000000000000000{}'.format(number), [policy], [], None, None, 1, True, False, None, False, None) return result
def test_admin_verified_by_inline_policies(self): admin_policy = Policy( 'arn:aws:iam::000000000000:user/user_1', 'inline_admin', { 'Version': '2012-10-17', 'Statement': [{ 'Effect': 'Allow', 'Action': '*', 'Resource': '*' }] }) not_admin_policy = Policy( 'arn:aws:iam::000000000000:user/user_2', 'inline_not_admin', { 'Version': '2012-10-17', 'Statement': [{ 'Effect': 'Allow', 'Action': '*', 'Resource': '*' }, { 'Effect': 'Deny', 'Action': '*', 'Resource': '*' }] }) new_node_1 = Node('arn:aws:iam::000000000000:user/user_1', 'id1', [admin_policy], [], None, None, 1, False, False, None, False, None) new_node_2 = Node('arn:aws:iam::000000000000:user/user_2', 'id2', [not_admin_policy], [], None, None, 1, False, False, None, False, None) update_admin_status([new_node_1, new_node_2]) self.assertTrue(new_node_1.is_admin, 'User with admin policy should be marked as an admin') self.assertFalse( new_node_2.is_admin, 'User with non-admin policy should not be marked as an admin')
def get_sns_topic_policies( session: botocore.session.Session, region_allow_list: Optional[List[str]] = None, region_deny_list: Optional[List[str]] = None, client_args_map: Optional[dict] = None) -> List[Policy]: """Using a botocore Session object, return a list of Policy objects representing the topic policies of each SNS topic in this account. The region allow/deny lists are mutually-exclusive (i.e. at least one of which has the value None) lists of allowed/denied regions to pull data from. """ result = [] snsargs = client_args_map.get('sns', {}) # Iterate through all regions of SNS where possible for sns_region in get_regions_to_search(session, 'sns', region_allow_list, region_deny_list): try: # Grab the topics topics = [] snsclient = session.create_client('sns', region_name=sns_region, **snsargs) sns_paginator = snsclient.get_paginator('list_topics') for page in sns_paginator.paginate(): topics.extend([x['TopicArn'] for x in page['Topics']]) # Grab the topic policies for topic in topics: policy_str = snsclient.get_topic_attributes( TopicArn=topic)['Attributes']['Policy'] result.append( Policy( topic, topic.split(':') [-1], # SNS Topic ARN Format: arn:<partition>:sns:<region>:<account>:<Topic Name> json.loads(policy_str))) logger.info('Caching policy for {}'.format(topic)) except botocore.exceptions.ClientError as ex: logger.info( 'Unable to search SNS in region {} for topic policies. The region may be disabled, or the current principal may not be authorized to access the service. Continuing.' .format(sns_region)) logger.debug('Exception was: {}'.format(ex)) continue return result
def get_kms_key_policies( session: botocore.session.Session, region_allow_list: Optional[List[str]] = None, region_deny_list: Optional[List[str]] = None, client_args_map: Optional[dict] = None) -> List[Policy]: """Using a botocore Session object, return a list of Policy objects representing the key policies of each KMS key in this account. The region allow/deny lists are mutually-exclusive (i.e. at least one of which has the value None) lists of allowed/denied regions to pull data from. """ result = [] kmsargs = client_args_map.get('kms', {}) # Iterate through all regions of KMS where possible for kms_region in get_regions_to_search(session, 'kms', region_allow_list, region_deny_list): try: # Grab the keys cmks = [] kmsclient = session.create_client('kms', region_name=kms_region, **kmsargs) kms_paginator = kmsclient.get_paginator('list_keys') for page in kms_paginator.paginate(): cmks.extend([x['KeyArn'] for x in page['Keys']]) # Grab the key policies for cmk in cmks: policy_str = kmsclient.get_key_policy( KeyId=cmk, PolicyName='default')['Policy'] result.append( Policy( cmk, cmk.split('/') [-1], # CMK ARN Format: arn:<partition>:kms:<region>:<account>:key/<Key ID> json.loads(policy_str))) logger.info('Caching policy for {}'.format(cmk)) except botocore.exceptions.ClientError as ex: logger.info( 'Unable to search KMS in region {} for key policies. The region may be disabled, or the current principal may not be authorized to access the service. Continuing.' .format(kms_region)) logger.debug('Exception was: {}'.format(ex)) continue return result
def test_permissions_boundary_no_resource_policy(self): """In the case of no resource policy, the effective permissions are the "intersection" of the caller's identity policies + the boundary policy. Both the user's identity policies + boundary policy must permit the API call. A matching deny statement in either set will deny the whole call. """ boundary = Policy( 'arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess', 'AmazonS3ReadOnlyAccess', { "Version": "2012-10-17", "Statement": [ { "Action": [ "s3:Get*", "s3:List*" ], "Resource": "*", "Effect": "Allow" } ] } ) iam_user_1 = _build_user_with_policy( { 'Version': '2012-10-17', 'Statement': [{ 'Effect': 'Allow', 'Action': '*', 'Resource': '*' }] }, 'admin_policy', 'asdf1', '1' ) iam_user_1.permissions_boundary = boundary self.assertTrue( local_check_authorization(iam_user_1, 's3:GetObject', 'arn:aws:s3:::bucket/object', {}) ) self.assertFalse( local_check_authorization(iam_user_1, 's3:PutObject', 'arn:aws:s3:::bucket/object', {}) )
def get_policies_and_fill_out(iamclient, nodes: List[Node], groups: List[Group], output: io.StringIO = os.devnull, debug=False) -> List[Policy]: """Using an IAM.Client object, return a list of Policy objects. Adds references to each passed Node and Group object where applicable. Writes high-level progress information to parameter output """ result = [] # navigate through nodes and add policy objects if they do not already exist in result output.write("Obtaining policies used by all IAM users and roles\n") for node in nodes: node_name_components = arns.get_resource(node.arn).split('/') node_type, node_name = node_name_components[0], node_name_components[ -1] dprint(debug, 'Grabbing inline policies for {}'.format(node.arn)) # get inline policies if node_type == 'user': inline_policy_arns = iamclient.list_user_policies( UserName=node_name) # get each inline policy, append it to node's policies and result list for policy_name in inline_policy_arns['PolicyNames']: dprint(debug, ' Grabbing inline policy: {}'.format(policy_name)) inline_policy = iamclient.get_user_policy( UserName=node_name, PolicyName=policy_name) policy_object = Policy( arn=node.arn, name=policy_name, policy_doc=inline_policy['PolicyDocument']) node.attached_policies.append(policy_object) result.append(policy_object) elif node_type == 'role': inline_policy_arns = iamclient.list_role_policies( RoleName=node_name) # get each inline policy, append it to the node's policies and result list # in hindsight, it's possible this could be folded with the above code, assuming the API doesn't change for policy_name in inline_policy_arns['PolicyNames']: dprint(debug, ' Grabbing inline policy: {}'.format(policy_name)) inline_policy = iamclient.get_role_policy( RoleName=node_name, PolicyName=policy_name) policy_object = Policy( arn=node.arn, name=policy_name, policy_doc=inline_policy['PolicyDocument']) node.attached_policies.append(policy_object) result.append(policy_object) # get attached policies for users and roles if node_type == 'user': attached_policies = iamclient.list_attached_user_policies( UserName=node_name) else: # node_type == 'role': attached_policies = iamclient.list_attached_role_policies( RoleName=node_name) for attached_policy in attached_policies['AttachedPolicies']: policy_arn = attached_policy['PolicyArn'] dprint(debug, ' Grabbing managed policy: {}'.format(policy_arn)) # reduce API calls, search existing policies for matching arns policy_object = _get_policy_by_arn(policy_arn, result) if policy_object is None: # Gotta retrieve the policy's current default version dprint(debug, ' Policy cache miss, calling API') policy_response = iamclient.get_policy(PolicyArn=policy_arn) dprint( debug, ' Policy version: {}'.format( policy_response['Policy']['DefaultVersionId'])) policy_version_response = iamclient.get_policy_version( PolicyArn=policy_arn, VersionId=policy_response['Policy']['DefaultVersionId']) policy_object = Policy( arn=policy_arn, name=policy_response['Policy']['PolicyName'], policy_doc=policy_version_response['PolicyVersion'] ['Document']) result.append(policy_object) node.attached_policies.append(policy_object) output.write("Obtaining policies used by IAM groups\n") for group in groups: group_name = arns.get_resource(group.arn).split( '/', 1)[-1] # split by slashes and take the final item dprint(debug, 'Getting policies for: {}'.format(group.arn)) # get inline policies inline_policies = iamclient.list_group_policies(GroupName=group_name) for policy_name in inline_policies['PolicyNames']: dprint(debug, ' Grabbing inline policy: {}'.format(policy_name)) inline_policy = iamclient.get_group_policy(GroupName=group_name, PolicyName=policy_name) policy_object = Policy(arn=group.arn, name=policy_name, policy_doc=inline_policy['PolicyDocument']) group.attached_policies.append(policy_object) result.append(policy_object) # get attached policies attached_policies = iamclient.list_attached_group_policies( GroupName=group_name) for attached_policy in attached_policies['AttachedPolicies']: policy_arn = attached_policy['PolicyArn'] dprint(debug, ' Grabbing managed policy: {}'.format(policy_arn)) # check cached policies first policy_object = _get_policy_by_arn(policy_arn, result) if policy_object is None: dprint(debug, ' Policy cache miss, calling API') policy_response = iamclient.get_policy(PolicyArn=policy_arn) dprint( debug, ' Policy version: {}'.format( policy_response['Policy']['DefaultVersionId'])) policy_version_response = iamclient.get_policy_version( PolicyArn=policy_arn, VersionId=policy_response['Policy']['DefaultVersionId']) policy_object = Policy( arn=policy_arn, name=policy_response['Policy']['PolicyName'], policy_doc=policy_version_response['PolicyVersion'] ['Document']) result.append(policy_object) group.attached_policies.append(policy_object) return result
def get_nodes_groups_and_policies(iamclient) -> dict: """Using an IAM.Client object, return a dictionary containing nodes, groups, and policies to be added to a Graph object. Admin status for the nodes are not updated. Writes high-level information on progress to the output stream. """ logger.info('Obtaining IAM Users/Roles/Groups/Policies in the account.') result_paginator = iamclient.get_paginator( 'get_account_authorization_details') user_results = [] group_results = [] role_results = [] policy_results = [] for page in result_paginator.paginate(): user_results += page['UserDetailList'] group_results += page['GroupDetailList'] role_results += page['RoleDetailList'] policy_results += page['Policies'] logger.info( 'Sorting users, roles, groups, policies, and their relationships.') # this is the result we return: dictionary with nodes/groups/users all filled out result = {'nodes': [], 'groups': [], 'policies': []} for p in policy_results: # go through each policy and update policy_results doc = [ x['Document'] for x in p['PolicyVersionList'] if x['IsDefaultVersion'] ][0] result['policies'].append(Policy(p['Arn'], p['PolicyName'], doc)) for g in group_results: # go through all inline policies and update policy_results group_policies = [] if 'GroupPolicyList' in g: # have to key-check these for p in g['GroupPolicyList']: group_policies.append( Policy( g['Arn'], # inline policies get the same Arn as their principal p['PolicyName'], p['PolicyDocument'])) result[ 'policies'] += group_policies # this is just adding the inline policies for the group for p in g['AttachedManagedPolicies']: group_policies.append( _get_policy_by_arn_or_raise(p['PolicyArn'], result['policies'])) result['groups'].append(Group(g['Arn'], group_policies)) for u in user_results: # go through all inline policies and update policy_results user_policies = [] if 'UserPolicyList' in u: # have to key-check these for p in u['UserPolicyList']: user_policies.append( Policy( u['Arn'], # inline policies inherit the Arn of their principal for the purposes of tracking p['PolicyName'], p['PolicyDocument'])) result['policies'] += user_policies for p in u['AttachedManagedPolicies']: user_policies.append( _get_policy_by_arn_or_raise(p['PolicyArn'], result['policies'])) if 'PermissionsBoundary' in u: boundary_policy = _get_policy_by_arn_or_raise( u['PermissionsBoundary']['PermissionsBoundaryArn'], result['policies']) else: boundary_policy = None group_list = [] for group_name in u['GroupList']: for group in result['groups']: if arns.get_resource(group.arn).split('/')[-1] == group_name: group_list.append(group) break _tags = {} if 'Tags' in u: for tag in u['Tags']: _tags[tag['Key']] = tag['Value'] # still need to figure out access keys result['nodes'].append( Node(u['Arn'], u['UserId'], user_policies, group_list, None, None, 0, 'PasswordLastUsed' in u, False, boundary_policy, False, _tags)) for r in role_results: # go through all inline policies and update policy_results role_policies = [] for p in r['RolePolicyList']: role_policies.append( Policy( r['Arn'], # inline policies inherit the Arn of their principal for the purposes of tracking p['PolicyName'], p['PolicyDocument'])) result['policies'] += role_policies for p in r['AttachedManagedPolicies']: role_policies.append( _get_policy_by_arn_or_raise(p['PolicyArn'], result['policies'])) _tags = {} if 'Tags' in r: for tag in r['Tags']: _tags[tag['Key']] = tag['Value'] result['nodes'].append( Node(r['Arn'], r['RoleId'], role_policies, None, r['AssumeRolePolicyDocument'], [x['Arn'] for x in r['InstanceProfileList']], 0, False, False, None, False, _tags)) logger.info("Obtaining Access Keys data for IAM users") for node in result['nodes']: if arns.get_resource(node.arn).startswith('user/'): # Grab access-key count and update node user_name = arns.get_resource(node.arn)[5:] if '/' in user_name: user_name = user_name.split('/')[-1] access_keys_data = iamclient.list_access_keys(UserName=user_name) node.access_keys = len(access_keys_data['AccessKeyMetadata']) # logger.debug('Access Key Count for {}: {}'.format(user_name, len(access_keys_data['AccessKeyMetadata']))) logger.info('Gathering MFA virtual device information') mfa_paginator = iamclient.get_paginator('list_virtual_mfa_devices') for page in mfa_paginator.paginate(AssignmentStatus='Assigned'): for device in page['VirtualMFADevices']: user_arn = device['User']['Arn'] logger.debug('Found virtual MFA device for {}'.format(user_arn)) for node in result['nodes']: if node.arn == user_arn: node.has_mfa = True break logger.info('Gathering MFA physical device information') for node in result['nodes']: node_resource_name = arns.get_resource(node.arn) if node_resource_name.startswith('user/'): user_name = node_resource_name.split('/')[-1] mfa_devices_response = iamclient.list_mfa_devices( UserName=user_name) if len(mfa_devices_response['MFADevices']) > 0: node.has_mfa = True return result
def get_secrets_manager_policies( session: botocore.session.Session, region_allow_list: Optional[List[str]] = None, region_deny_list: Optional[List[str]] = None) -> List[Policy]: """Using a botocore Session object, return a list of Policy objects representing the resource policies of the secrets in AWS Secrets Manager. The region allow/deny lists are mutually-exclusive (i.e. at least one of which has the value None) lists of allowed/denied regions to pull data from. """ result = [] # Iterate through all regions of Secrets Manager where possible for sm_region in get_regions_to_search(session, 'secretsmanager', region_allow_list, region_deny_list): try: # Grab the ARNs of the secrets in this region secret_arns = [] smclient = session.create_client('secretsmanager', region_name=sm_region) list_secrets_paginator = smclient.get_paginator('list_secrets') for page in list_secrets_paginator.paginate(): if 'SecretList' in page: for entry in page['SecretList']: if 'PrimaryRegion' in entry and entry[ 'PrimaryRegion'] != sm_region: continue # skip things we're supposed to find in other regions secret_arns.append(entry['ARN']) # Grab resource policies for each secret for secret_arn in secret_arns: sm_response = smclient.get_resource_policy(SecretId=secret_arn) # verify that it is in the response and not None/empty if 'ResourcePolicy' in sm_response and sm_response[ 'ResourcePolicy']: sm_policy_doc = json.loads(sm_response['ResourcePolicy']) result.append( Policy(secret_arn, sm_response['Name'], sm_policy_doc)) logger.info( 'Storing the resource policy for secret {}'.format( secret_arn)) else: result.append( Policy(secret_arn, sm_response['Name'], { "Statement": [], "Version": "2012-10-17" })) logger.info( 'Secret {} does not have a resource policy, inserting a "stub" policy instead' .format(secret_arn)) except botocore.exceptions.ClientError as ex: logger.info( 'Unable to search Secrets Manager in region {} for secrets. The region may be disabled, or ' 'the current principal may not be authorized to access the service. ' 'Continuing.'.format(sm_region)) logger.debug('Exception was: {}'.format(ex)) return result
def test_permissions_boundary_with_resource_policy(self): boundary_1 = Policy( 'arn:aws:iam::aws:policy/AssumeJumpRole', 'AssumeJumpRole', { "Version": "2012-10-17", "Statement": [ { "Action": "sts:AssumeRole", "Resource": "arn:aws:iam::000000000000:role/JumpRole", "Effect": "Allow" } ] } ) iam_user_1 = _build_user_with_policy( { 'Version': '2012-10-17', 'Statement': [{ 'Effect': 'Allow', 'Action': '*', 'Resource': '*' }] }, 'admin_policy', 'asdf1', '1' ) iam_user_1.permissions_boundary = boundary_1 boundary_2 = Policy( 'arn:aws:iam::aws:policy/EmptyPolicy', 'EmptyPolicy', { "Version": "2012-10-17", "Statement": [] } ) iam_user_2 = _build_user_with_policy( { 'Version': '2012-10-17', 'Statement': [] }, 'admin_policy', 'asdf2', '2' ) iam_user_2.permissions_boundary = boundary_2 trust_doc = { 'Version': '2012-10-17', 'Statement': [{ 'Effect': 'Allow', 'Principal': { 'AWS': [ 'arn:aws:iam::000000000000:user/asdf2', 'arn:aws:iam::000000000000:root' ] }, 'Action': 'sts:AssumeRole' }] } self.assertTrue( local_check_authorization_full( iam_user_1, 'sts:AssumeRole', 'arn:aws:iam::000000000000:role/JumpRole', {}, trust_doc, '000000000000' ) ) self.assertTrue( local_check_authorization_full( iam_user_2, 'sts:AssumeRole', 'arn:aws:iam::000000000000:role/JumpRole', {}, trust_doc, '000000000000' ) )