def display_provisioned_ou(org_client, log, deployed_ou, parent_name, indent=0): """ Recursive function to display the deployed AWS Organization structure. """ # query aws for child orgs parent_id = lookup(deployed_ou, 'Name', parent_name, 'Id') child_ou_list = lookup(deployed_ou, 'Name', parent_name, 'Child_OU') child_accounts = lookup(deployed_ou, 'Name', parent_name, 'Accounts') # display parent ou name tab = ' ' log.info(tab * indent + parent_name + ':') # look for policies policy_names = list_policies_in_ou(org_client, parent_id) if len(policy_names) > 0: log.info(tab * indent + tab + 'Policies: ' + ', '.join(policy_names)) # look for accounts account_list = sorted(child_accounts) if len(account_list) > 0: log.info(tab * indent + tab + 'Accounts: ' + ', '.join(account_list)) # look for child OUs if child_ou_list: log.info(tab * indent + tab + 'Child_OU:') indent += 2 for ou_name in child_ou_list: # recurse display_provisioned_ou(org_client, log, deployed_ou, ou_name, indent)
def manage_ou(org_client, args, log, deployed, ou_spec_list, parent_name): """ Recursive function to manage OrganizationalUnits in the AWS Organization. """ for ou_spec in ou_spec_list: # ou exists ou = lookup(deployed['ou'], 'Name', ou_spec['Name']) if ou: # check for child_ou. recurse before other tasks. if 'Child_OU' in ou_spec: manage_ou(org_client, args, log, deployed, ou_spec['Child_OU'], ou_spec['Name']) # check if ou 'absent' if ensure_absent(ou_spec): # error if ou contains anything for key in ['Accounts', 'Policies', 'Child_OU']: if key in ou and ou[key]: msg = ( "Can not delete OU '%s'. deployed '%s' exists." % (ou_spec['Name'], key)) raise RuntimeError(msg) # delete ou log.info("Deleting OU %s" % ou_spec['Name']) if args['--exec']: org_client.delete_organizational_unit( OrganizationalUnitId=ou['Id']) else: manage_policy_attachments(org_client, args, log, deployed['policies'], ou_spec, ou['Id']) manage_account_moves(org_client, args, log, deployed['accounts'], ou_spec, ou['Id']) elif not ensure_absent(ou_spec): # ou does not exist log.info("Creating new OU '%s' under parent '%s'" % (ou_spec['Name'], parent_name)) if args['--exec']: new_ou = org_client.create_organizational_unit( ParentId=lookup(deployed['ou'], 'Name', parent_name, 'Id'), Name=ou_spec['Name'])['OrganizationalUnit'] manage_policy_attachments(org_client, args, log, deployed['policies'], ou_spec, new_ou['Id']) manage_account_moves(org_client, args, log, deployed['accounts'], ou_spec, new_ou['Id']) if ('Child_OU' in ou_spec and isinstance(new_ou, dict) and 'Id' in new_ou): # recurse manage_ou(org_client, args, log, deployed, ou_spec['Child_OU'], new_ou['Name'])
def display_provisioned_accounts(log, deployed_accounts): """ Print report of currently deployed accounts in AWS Organization. """ header = "Provisioned Accounts in Org:" overbar = '_' * len(header) log.info("\n%s\n%s" % (overbar, header)) for a_name in sorted(map(lambda a: a['Name'], deployed_accounts)): a_id = lookup(deployed_accounts, 'Name', a_name, 'Id') a_email = lookup(deployed_accounts, 'Name', a_name, 'Email') spacer = ' ' * (24 - len(a_name)) log.info("%s%s%s\t\t%s" % (a_name, spacer, a_id, a_email))
def display_provisioned_groups(credentials, log, deployed): """ Print report of currently deployed IAM groups in Auth account. List group memebers, attached policies and delegation assume role profiles. """ iam_resource = boto3.resource('iam', **credentials) header = "Provisioned IAM Groups in Auth Account:" overbar = '_' * len(header) log.info("\n\n%s\n%s" % (overbar, header)) for name in sorted(map(lambda g: g['GroupName'], deployed['groups'])): group = iam_resource.Group(name) members = list(group.users.all()) attached_policies = list(group.attached_policies.all()) assume_role_resources = [p.policy_document['Statement'][0]['Resource'] for p in list(group.policies.all()) if p.policy_document['Statement'][0]['Action'] == 'sts:AssumeRole'] log.info("\n%s\t%s" % ('Name:', name)) log.info("%s\t%s" % ('Arn:', group.arn)) if members: log.info("Members:") log.info("\n".join([" %s" % u.name for u in members])) if attached_policies: log.info("Policies:") log.info("\n".join([" %s" % p.arn for p in attached_policies])) if assume_role_resources: log.info("Assume role profiles:") log.info(" Account\tRole ARN") profiles = {} for role_arn in assume_role_resources: account_name = lookup(deployed['accounts'], 'Id', role_arn.split(':')[4], 'Name') profiles[account_name] = role_arn for account_name in sorted(profiles.keys()): log.info(" %s:\t%s" % (account_name, profiles[account_name]))
def manage_delegations(args, log, deployed, auth_spec): """ Create and manage cross account access delegations based on delegation specifications. Manages delegation roles in trusting accounts and group policies in Auth (trusted) account. """ for d_spec in auth_spec['delegations']: if not validate_delegation_spec(args, log, d_spec): log.error("Delegation spec for '%s' invalid" % d_spec['RoleName']) return if d_spec['RoleName'] == auth_spec['org_access_role']: log.error("Refusing to manage delegation '%s'" % d_spec['RoleName']) return # process roles in trusting accounts if d_spec['TrustingAccount'] != 'ALL': for account_name in d_spec['TrustingAccount']: if not lookup(deployed['accounts'], 'Name', account_name): log.error("Can not create delegation role '%s' in account " "'%s'. Account '%s' not found in Org" % (d_spec['RoleName'], account_name, account_name)) for account in deployed['accounts']: credentials = get_assume_role_credentials( account['Id'], auth_spec['org_access_role']) manage_delegation_role(credentials, args, log, deployed, auth_spec, account['Name'], d_spec) # process groups in Auth account set_group_assume_role_policies(args, log, deployed, auth_spec, d_spec)
def place_unmanged_accounts(org_client, args, log, deployed, account_list, dest_parent): """ Move any unmanaged accounts into the default OU. """ for account in account_list: account_id = lookup(deployed['accounts'], 'Name', account, 'Id') dest_parent_id = lookup(deployed['ou'], 'Name', dest_parent, 'Id') source_parent_id = get_parent_id(org_client, account_id) if dest_parent_id and dest_parent_id != source_parent_id: log.info("Moving unmanged account '%s' to default OU '%s'" % (account, dest_parent)) if args['--exec']: org_client.move_account(AccountId=account_id, SourceParentId=source_parent_id, DestinationParentId=dest_parent_id)
def manage_policies(org_client, args, log, deployed_policies, policy_spec): """ Manage Service Control Policies in the AWS Organization. Make updates according to the policy specification ('policy_spec'). Do not touch the default policy. Do not delete an attached policy. """ for p_spec in policy_spec: policy_name = p_spec['Name'] # dont touch default policy if not policy_name == args['default_policy']: policy_id = lookup(deployed_policies, 'Name', policy_name, 'Id') # policy already exists if policy_id: # check if we need to delete policy if ensure_absent(p_spec): log.info("Deleting policy '%s'" % (policy_name)) # dont delete attached policy if org_client.list_targets_for_policy( PolicyId=policy_id)['Targets']: log.error( "Cannot delete policy '%s'. Still attached to OU" % (policy_name)) elif args['--exec']: org_client.delete_policy(PolicyId=policy_id) # check for policy updates elif (p_spec['Description'] != lookup(deployed_policies, 'Id', policy_id, 'Description') or specify_policy_content(p_spec) != get_policy_content( org_client, policy_id)): log.info("Updating policy '%s'" % (policy_name)) if args['--exec']: org_client.update_policy( PolicyId=policy_id, Content=specify_policy_content(p_spec), Description=p_spec['Description'], ) # create new policy elif not ensure_absent(p_spec): log.info("Creating policy '%s'" % (policy_name)) if args['--exec']: org_client.create_policy( Content=specify_policy_content(p_spec), Description=p_spec['Description'], Name=p_spec['Name'], Type='SERVICE_CONTROL_POLICY')
def manage_custom_policy(iam_client, policy_name, args, log, auth_spec): """ Create or update a custom IAM policy in an account based on a policy specification. Returns the policy arn. """ p_spec = lookup(auth_spec['custom_policies'], 'PolicyName', policy_name) if not p_spec: log.error("Custom Policy spec for '%s' not found in auth-spec." % policy_name) log.error("Policy creation failed.") return None if not validate_policy_spec(args, log, p_spec): log.error("Custom Policy spec for '%' invalid." % policy_name) log.error("Policy creation failed.") return None policy_doc = json.dumps(dict( Version='2012-10-17', Statement=p_spec['Statement'])) custom_policies = iam_client.list_policies(Scope='Local')['Policies'] policy = lookup(custom_policies, 'PolicyName', policy_name) if not policy: log.info("Creating custom policy '%s'." % policy_name) if args['--exec']: return iam_client.create_policy( PolicyName=p_spec['PolicyName'], Path=munge_path(auth_spec['default_path'], p_spec), Description=p_spec['Description'], PolicyDocument=policy_doc)['Policy']['Arn'] return None else: current_doc = iam_client.get_policy_version( PolicyArn=policy['Arn'], VersionId=policy['DefaultVersionId'] )['PolicyVersion']['Document'] if json.dumps(current_doc) != policy_doc: log.info("Updating custom policy '%s'." % policy_name) if args['--exec']: iam_client.create_policy_version( PolicyArn=policy['Arn'], PolicyDocument=policy_doc, SetAsDefault=True) return policy['Arn']
def display_provisioned_users(log, deployed): """ Print report of currently deployed IAM users in Auth account. """ header = "Provisioned IAM Users in Auth Account:" overbar = '_' * len(header) log.info("\n%s\n%s\n" % (overbar, header)) for name in sorted([u['UserName'] for u in deployed['users']]): arn = lookup(deployed['users'], 'UserName', name, 'Arn') spacer = ' ' * (12 - len(name)) log.info("%s%s\t%s" % (name, spacer, arn))
def create_accounts(org_client, args, log, deployed_accounts, account_spec): """ Compare deployed_accounts to list of accounts in the accounts spec. Create accounts not found in deployed_accounts. """ for a_spec in account_spec['accounts']: if not lookup(deployed_accounts, 'Name', a_spec['Name'],): # check if it is still being provisioned created_accounts = scan_created_accounts(org_client) if lookup(created_accounts, 'AccountName', a_spec['Name']): log.warn("New account '%s' is not yet available" % a_spec['Name']) break # create a new account log.info("Creating account '%s'" % (a_spec['Name'])) if args['--exec']: new_account = org_client.create_account( AccountName=a_spec['Name'], Email=a_spec['Email']) create_id = new_account['CreateAccountStatus']['Id'] log.info("CreateAccountStatus Id: %s" % (create_id)) # validate creation status counter = 0 maxtries = 5 while counter < maxtries: creation = org_client.describe_create_account_status( CreateAccountRequestId=create_id )['CreateAccountStatus'] if creation['State'] == 'IN_PROGRESS': time.sleep(5) log.info("Account creation in progress for '%s'" % a_spec['Name']) elif creation['State'] == 'SUCCEEDED': log.info("Account creation succeeded") break elif creation['State'] == 'FAILED': log.error("Account creation failed: %s" % creation['FailureReason']) break counter += 1 if counter == maxtries and creation['State'] == 'IN_PROGRESS': log.warn("Account creation still pending. Moving on!")
def manage_group_policies(credentials, args, log, deployed, auth_spec): """ Attach managed policies to groups based on group specification """ iam_client = boto3.client('iam', **credentials) iam_resource = boto3.resource('iam', **credentials) auth_account = lookup(deployed['accounts'], 'Id', auth_spec['auth_account_id'], 'Name') for g_spec in auth_spec['groups']: if ('Policies' in g_spec and g_spec['Policies'] and not ensure_absent(g_spec) and lookup(deployed['groups'], 'GroupName', g_spec['Name'])): group = iam_resource.Group(g_spec['Name']) attached_policies = [p.policy_name for p in list(group.attached_policies.all())] # attach missing policies for policy_name in g_spec['Policies']: if not policy_name in attached_policies: policy_arn = get_policy_arn(iam_client, policy_name, args, log, auth_spec) log.info("Attaching policy '%s' to group '%s' in " "account '%s'." % (policy_name, g_spec['Name'], auth_account)) if args['--exec']: group.attach_policy(PolicyArn=policy_arn) elif lookup(auth_spec['custom_policies'], 'PolicyName', policy_name): policy_arn = get_policy_arn(iam_client, policy_name, args, log, auth_spec) # datach obsolete policies for policy_name in attached_policies: if not policy_name in g_spec['Policies']: policy_arn = get_policy_arn(iam_client, policy_name, args, log, auth_spec) log.info("Detaching policy '%s' from group '%s' in " "account '%s'." % (policy_name, g_spec['Name'], auth_account)) if args['--exec']: group.detach_policy(PolicyArn=policy_arn)
def manage_policy_attachments(org_client, args, log, deployed_policies, ou_spec, ou_id): """ Attach or detach specified Service Control Policy to a deployed OrganizatinalUnit. Do not detach the default policy ever. """ # create lists policies_to_attach and policies_to_detach attached_policy_list = list_policies_in_ou(org_client, ou_id) if 'Policies' in ou_spec and isinstance(ou_spec['Policies'], list): spec_policy_list = ou_spec['Policies'] else: spec_policy_list = [] policies_to_attach = [ p for p in spec_policy_list if p not in attached_policy_list ] policies_to_detach = [ p for p in attached_policy_list if p not in spec_policy_list and p != args['default_policy'] ] # attach policies for policy_name in policies_to_attach: if not lookup(deployed_policies, 'Name', policy_name): raise RuntimeError("spec-file: ou_spec: policy '%s' not defined" % policy_name) if not ensure_absent(ou_spec): log.info("Attaching policy '%s' to OU '%s'" % (policy_name, ou_spec['Name'])) if args['--exec']: org_client.attach_policy(PolicyId=lookup( deployed_policies, 'Name', policy_name, 'Id'), TargetId=ou_id) # detach policies for policy_name in policies_to_detach: log.info("Detaching policy '%s' from OU '%s'" % (policy_name, ou_spec['Name'])) if args['--exec']: org_client.detach_policy(PolicyId=lookup(deployed_policies, 'Name', policy_name, 'Id'), TargetId=ou_id)
def get_policy_arn(iam_client, policy_name, args, log, auth_spec): """ Return the policy arn of the named IAM policy in an account. Checks AWS scope first, then calls manage_custom_policy() for local scope policies. """ aws_policies = iam_client.list_policies(Scope='AWS', MaxItems=500)['Policies'] policy_arn = lookup(aws_policies, 'PolicyName', policy_name, 'Arn') if policy_arn: return policy_arn else: return manage_custom_policy(iam_client, policy_name, args, log, auth_spec)
def manage_group_members(iam_client, args, log, deployed, auth_spec): """ Populate users into groups based on group specification. """ for g_spec in auth_spec['groups']: if (lookup(deployed['groups'], 'GroupName', g_spec['Name']) and not ensure_absent(g_spec)): response = iam_client.get_group( GroupName=g_spec['Name'])['Users'] current_members = [user['UserName'] for user in response if 'UserName' in user] if 'Members' in g_spec and g_spec['Members']: spec_members = g_spec['Members'] else: spec_members = [] add_users = [username for username in spec_members if username not in current_members] remove_users = [username for username in current_members if username not in spec_members] for username in add_users: if lookup(deployed['users'], 'UserName', username): log.info("Adding user '%s' to group '%s'." % (username, g_spec['Name'])) if args['--exec']: iam_client.add_user_to_group( GroupName=g_spec['Name'], UserName=username) else: log.error("User '%s' not found. Can not add user to " "group '%s'" % (username, g_spec['Name'])) for username in remove_users: log.info("Removig user '%s' from group '%s'." % (username, g_spec['Name'])) if args['--exec']: iam_client.remove_user_from_group( GroupName=g_spec['Name'], UserName=username)
def manage_account_moves(org_client, args, log, deployed_accounts, ou_spec, dest_parent_id): """ Alter deployed AWS Organization. Ensure accounts are contained by designated OrganizationalUnits based on OU specification. """ if 'Accounts' in ou_spec and ou_spec['Accounts']: for account in ou_spec['Accounts']: account_id = lookup(deployed_accounts, 'Name', account, 'Id') if not account_id: log.warn("Account '%s' not yet in Org" % account) else: source_parent_id = get_parent_id(org_client, account_id) if dest_parent_id != source_parent_id: log.info("Moving account '%s' to OU '%s'" % (account, ou_spec['Name'])) if args['--exec']: org_client.move_account( AccountId=account_id, SourceParentId=source_parent_id, DestinationParentId=dest_parent_id)
def create_groups(iam_client, args, log, deployed, auth_spec): """ Manage IAM groups based on group specification """ for g_spec in auth_spec['groups']: path = munge_path(auth_spec['default_path'], g_spec) group = lookup(deployed['groups'], 'GroupName', g_spec['Name']) if group: if ensure_absent(g_spec): # check if group has users if iam_client.get_group(GroupName=g_spec['Name'])['Users']: log.error("Group '%s' still has users. " "Can't delete." % g_spec['Name']) # delete group else: log.info("Deleting group '%s'" % g_spec['Name']) if args['--exec']: # delete group policies for policy_name in iam_client.list_group_policies( GroupName=g_spec['Name'])['PolicyNames']: iam_client.delete_group_policy( GroupName=g_spec['Name'], PolicyName=policy_name) iam_client.delete_group(GroupName=g_spec['Name']) elif group['Path'] != path: # update group log.info("Updating path on group '%s'" % g_spec['Name']) if args['--exec']: iam_client.update_group( GroupName=g_spec['Name'], NewPath=path) elif not ensure_absent(g_spec): # create group log.info("Creating group '%s'" % g_spec['Name']) if args['--exec']: response = iam_client.create_group( GroupName=g_spec['Name'], Path=path) log.info(response['Group']['Arn'])
def create_users(iam_client, args, log, deployed, auth_spec): """ Manage IAM users based on user specification """ for u_spec in auth_spec['users']: path = munge_path(auth_spec['default_path'], u_spec) user = lookup(deployed['users'], 'UserName', u_spec['Name']) if user: if ensure_absent(u_spec): log.info("Deleting user '%s'" % u_spec['Name']) if args['--exec']: iam_client.delete_user( UserName=u_spec['Name']) log.info(response['User']['Arn']) elif user['Path'] != path: log.info("Updating path on user '%s'" % u_spec['Name']) if args['--exec']: iam_client.update_user( UserName=u_spec['Name'], NewPath=path) elif not ensure_absent(u_spec): log.info("Creating user '%s'" % u_spec['Name']) if args['--exec']: response = iam_client.create_user( UserName=u_spec['Name'], Path=path) log.info(response['User']['Arn'])
def manage_delegation_role(credentials, args, log, deployed, auth_spec, account_name, d_spec): """ Create and manage a cross account access delegetion role in an account based on delegetion specification. """ iam_client = boto3.client('iam', **credentials) iam_resource = boto3.resource('iam', **credentials) role = iam_resource.Role(d_spec['RoleName']) # check if role should not exist if (account_name not in d_spec['TrustingAccount'] and d_spec['TrustingAccount'] != 'ALL' or ensure_absent(d_spec)): try: role.load() except ClientError as e: if e.response['Error']['Code'] == 'NoSuchEntity': return else: raise e except: raise # delete delegation role log.info("Deleting role '%s' from account '%s'" % (d_spec['RoleName'], account_name)) if args['--exec']: for p in list(role.attached_policies.all()): role.detach_policy(PolicyArn=p.arn) role.delete() return # assemble assume role policy document for delegation role principal = "arn:aws:iam::%s:root" % auth_spec['auth_account_id'] statement = dict( Effect='Allow', Principal=dict(AWS=principal), Action='sts:AssumeRole') mfa = True if 'RequireMFA' in d_spec and d_spec['RequireMFA'] == False: mfa = False if mfa: statement['Condition'] = { 'Bool':{'aws:MultiFactorAuthPresent':'true'}} policy_doc = json.dumps(dict( Version='2012-10-17', Statement=[statement])) # get iam role object. create role if it does not exist (i.e. won't load) try: role.load() except ClientError as e: if e.response['Error']['Code'] == 'NoSuchEntity': log.info("Creating role '%s' in account '%s'" % (d_spec['RoleName'], account_name)) if args['--exec']: iam_client.create_role( Description=d_spec['Description'], Path=munge_path(auth_spec['default_path'], d_spec), RoleName=d_spec['RoleName'], AssumeRolePolicyDocument=policy_doc) if 'Policies' in d_spec and d_spec['Policies']: role.load() for policy_name in d_spec['Policies']: policy_arn = get_policy_arn(iam_client, policy_name, args, log, auth_spec) log.info("Attaching policy '%s' to role '%s' " "in account '%s'" % (policy_name, d_spec['RoleName'], account_name)) if args['--exec'] and policy_arn: role.attach_policy(PolicyArn=policy_arn) return else: return else: raise e except: raise # update delegation role if needed if json.dumps(role.assume_role_policy_document) != policy_doc: log.info("Updating policy document in role '%s' in account '%s'" % (d_spec['RoleName'], account_name)) if args['--exec']: iam_client.update_assume_role_policy( RoleName=role.role_name, PolicyDocument=policy_doc) if role.description != d_spec['Description']: log.info("Updating description in role '%s' in account '%s'" % (d_spec['RoleName'], account_name)) if args['--exec']: iam_client.update_role_description( RoleName=role.role_name, Description=d_spec['Description']) # manage policy attachments attached_policies = [p.policy_name for p in list(role.attached_policies.all())] for policy_name in d_spec['Policies']: # attach missing policies if not policy_name in attached_policies: policy_arn = get_policy_arn(iam_client, policy_name, args, log, auth_spec) log.info("Attaching policy '%s' to role '%s' in account '%s'" % (policy_name, d_spec['RoleName'], account_name)) if args['--exec'] and policy_arn: role.attach_policy(PolicyArn=policy_arn) elif lookup(auth_spec['custom_policies'], 'PolicyName',policy_name): policy_arn = get_policy_arn(iam_client, policy_name, args, log, auth_spec) for policy_name in attached_policies: # datach obsolete policies if not policy_name in d_spec['Policies']: policy_arn = get_policy_arn(iam_client, policy_name, args, log, auth_spec) log.info("Detaching policy '%s' from role '%s' in account '%s'" % (policy_name, d_spec['RoleName'], account_name)) if args['--exec'] and policy_arn: role.detach_policy(PolicyArn=policy_arn)
def set_group_assume_role_policies(args, log, deployed, auth_spec, d_spec): """ Assign and manage assume role trust policies on IAM groups in Auth account. """ credentials = get_assume_role_credentials( auth_spec['auth_account_id'], auth_spec['org_access_role']) iam_resource = boto3.resource('iam', **credentials) group = iam_resource.Group(d_spec['TrustedGroup']) auth_account = lookup(deployed['accounts'], 'Id', auth_spec['auth_account_id'], 'Name') try: group.load() except ClientError as e: if e.response['Error']['Code'] == 'NoSuchEntity': log.error("Group '%s' not found in account '%s'" % (d_spec['TrustedGroup'], auth_account)) log.error("Can not create group assume role policy for " "delegation '%s'" % d_spec['RoleName']) return else: raise e except: raise # make list of existing group policies which match this role name group_policies_for_role = [p.policy_name for p in list(group.policies.all()) if d_spec['RoleName'] in p.policy_name.split('-')] # test if delegation should be deleted if ensure_absent(d_spec): for policy_name in group_policies_for_role: log.info("Deleting assume role group policy '%s' from group '%s' " "in account '%s'" % (policy_name, d_spec['TrustedGroup'], auth_account)) if args['--exec']: group.Policy(policy_name).delete() return if d_spec['TrustingAccount'] == 'ALL': trusting_accounts = [a['Name'] for a in deployed['accounts']] else: trusting_accounts = d_spec['TrustingAccount'] # keep track of managed group policies as we process them managed_policies = [] for account in trusting_accounts: account_id = lookup(deployed['accounts'], 'Name', account, 'Id') policy_name = "%s-%s" % (account, d_spec['RoleName']) managed_policies.append(policy_name) # assemble assume role policy document statement = dict( Effect='Allow', Action='sts:AssumeRole', Resource="arn:aws:iam::%s:role%s%s" % ( account_id, munge_path(auth_spec['default_path'], d_spec), d_spec['RoleName'])) policy_doc = json.dumps(dict( Version='2012-10-17', Statement=[statement])) # create or update group policy if not policy_name in group_policies_for_role: log.info("Creating assume role policy '%s' for group '%s' in " "account '%s'." % (policy_name, d_spec['TrustedGroup'], auth_account)) if args['--exec']: group.create_policy( PolicyName=policy_name, PolicyDocument=policy_doc) elif json.dumps(group.Policy(policy_name).policy_document) != policy_doc: log.info("Updating assume role policy '%s' for group '%s' in " "account '%s'." % (policy_name, d_spec['TrustedGroup'], auth_account)) if args['--exec']: group.Policy(policy_name).put(PolicyDocument=policy_doc) # purge any policies for this role that are no longer being managed for policy_name in group_policies_for_role: if policy_name not in managed_policies: log.info("Deleting obsolete policy '%s' from group '%s' in " "account '%s'." % (policy_name, d_spec['TrustedGroup'], auth_account)) if args['--exec']: group.Policy(policy_name).delete()