def test_compare_version_policies_default_set(self): """ Testing that a policy without Version is only considered identical when default_version="2008-10-17" """ self.assertFalse(compare_policies(self.version_policy_missing, self.version_policy_missing, default_version="2012-10-17")) self.assertTrue(compare_policies(self.version_policy_old, self.version_policy_missing, default_version="2012-10-17")) self.assertFalse(compare_policies(self.version_policy_old, self.version_policy_missing, default_version="2008-10-17")) self.assertFalse(compare_policies(self.version_policy_new, self.version_policy_missing, default_version="2012-10-17")) self.assertTrue(compare_policies(self.version_policy_new, self.version_policy_missing, default_version="2008-10-17"))
def update_sqs_queue(module, client, queue_url): check_mode = module.check_mode changed = False existing_attributes = client.get_queue_attributes( QueueUrl=queue_url, AttributeNames=['All'], aws_retry=True)['Attributes'] new_attributes = snake_dict_to_camel_dict(module.params, capitalize_first=True) attributes_to_set = dict() # Boto3 SQS deals with policies as strings, we want to deal with them as # dicts if module.params.get('policy') is not None: policy = module.params.get('policy') current_value = existing_attributes.get('Policy', '{}') current_policy = json.loads(current_value) if compare_policies(current_policy, policy): attributes_to_set['Policy'] = json.dumps(policy) changed = True if module.params.get('redrive_policy') is not None: policy = module.params.get('redrive_policy') current_value = existing_attributes.get('RedrivePolicy', '{}') current_policy = json.loads(current_value) if compare_policies(current_policy, policy): attributes_to_set['RedrivePolicy'] = json.dumps(policy) changed = True for attribute, value in existing_attributes.items(): # We handle these as a special case because they're IAM policies if attribute in ['Policy', 'RedrivePolicy']: continue if attribute not in new_attributes.keys(): continue if new_attributes.get(attribute) is None: continue new_value = new_attributes[attribute] if isinstance(new_value, bool): new_value = str(new_value).lower() value = str(value).lower() if str(new_value) == str(value): continue # Boto3 expects strings attributes_to_set[attribute] = str(new_value) changed = True if changed and not check_mode: client.set_queue_attributes(QueueUrl=queue_url, Attributes=attributes_to_set, aws_retry=True) return changed, existing_attributes.get('queue_arn')
def test_compare_version_policies_defaults_old(self): """ Testing that a policy without Version is considered identical to one with the 'old' Version (by default) """ self.assertFalse( compare_policies(self.version_policy_old, self.version_policy_missing)) self.assertTrue( compare_policies(self.version_policy_new, self.version_policy_missing))
def test_compare_version_policies_default_disabled(self): """ Testing that a policy without Version not considered identical when default_version=None """ self.assertFalse( compare_policies(self.version_policy_missing, self.version_policy_missing, default_version=None)) self.assertTrue( compare_policies(self.version_policy_old, self.version_policy_missing, default_version=None)) self.assertTrue( compare_policies(self.version_policy_new, self.version_policy_missing, default_version=None))
def test_compare_large_policies_without_differences(self): """ Testing two larger policies which are identical except for: * The statements are in different orders * The contents of the statements are also in different orders * The second contains a list of length one for the Principal whereas in the first it is a string """ self.assertFalse(compare_policies(self.larger_policy_one, self.larger_policy_two))
def test_compare_small_policies_without_differences(self): """ Testing two small policies which are identical except for: * The contents of the statement are in different orders * The second policy contains a list of length one whereas in the first it is a string """ self.assertFalse( compare_policies(self.small_policy_one, self.small_policy_two))
def _set_topic_attrs(self): changed = False try: topic_attributes = self.connection.get_topic_attributes( TopicArn=self.topic_arn)['Attributes'] except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: self.module.fail_json_aws( e, msg="Couldn't get topic attributes for topic %s" % self.topic_arn) if self.display_name and self.display_name != topic_attributes[ 'DisplayName']: changed = True self.attributes_set.append('display_name') if not self.check_mode: try: self.connection.set_topic_attributes( TopicArn=self.topic_arn, AttributeName='DisplayName', AttributeValue=self.display_name) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: self.module.fail_json_aws(e, msg="Couldn't set display name") if self.policy and compare_policies( self.policy, json.loads(topic_attributes['Policy'])): changed = True self.attributes_set.append('policy') if not self.check_mode: try: self.connection.set_topic_attributes( TopicArn=self.topic_arn, AttributeName='Policy', AttributeValue=json.dumps(self.policy)) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: self.module.fail_json_aws(e, msg="Couldn't set topic policy") if self.delivery_policy and ( 'DeliveryPolicy' not in topic_attributes or compare_delivery_policies( self.delivery_policy, json.loads(topic_attributes['DeliveryPolicy']))): changed = True self.attributes_set.append('delivery_policy') if not self.check_mode: try: self.connection.set_topic_attributes( TopicArn=self.topic_arn, AttributeName='DeliveryPolicy', AttributeValue=json.dumps(self.delivery_policy)) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: self.module.fail_json_aws( e, msg="Couldn't set topic delivery policy") return changed
def create_or_update_bucket_cors(connection, module): name = module.params.get("name") rules = module.params.get("rules", []) changed = False try: current_camel_rules = connection.get_bucket_cors( Bucket=name)['CORSRules'] except ClientError: current_camel_rules = [] new_camel_rules = snake_dict_to_camel_dict(rules, capitalize_first=True) # compare_policies() takes two dicts and makes them hashable for comparison if compare_policies(new_camel_rules, current_camel_rules): changed = True if changed: try: cors = connection.put_bucket_cors( Bucket=name, CORSConfiguration={'CORSRules': new_camel_rules}) except (BotoCoreError, ClientError) as e: module.fail_json_aws( e, msg="Unable to update CORS for bucket {0}".format(name)) module.exit_json(changed=changed, name=name, rules=rules)
def update_policy(connection, module, key, policy): if policy is None: return False try: new_policy = json.loads(policy) except ValueError as e: module.fail_json_aws(e, msg="Unable to parse new policy as JSON") key_id = key['key_arn'] try: keyret = connection.get_key_policy(KeyId=key_id, PolicyName='default') original_policy = json.loads(keyret['Policy']) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError): # If we can't fetch the current policy assume we're making a change # Could occur if we have PutKeyPolicy without GetKeyPolicy original_policy = {} if not compare_policies(original_policy, new_policy): return False if not module.check_mode: try: connection.put_key_policy(KeyId=key_id, PolicyName='default', Policy=policy) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Unable to update key policy") return True
def test_compare_wildcard_policies_without_differences(self): """ Testing two small wildcard policies which are identical except for: * Principal: "*" vs Principal: ["AWS": "*"] """ self.assertFalse( compare_policies(self.wildcard_policy_one, self.wildcard_policy_two))
def main(): argument_spec = dict(name=dict(required=True, type='str'), role_arn=dict(required=True, type='str'), artifact_store=dict(required=True, type='dict'), stages=dict(required=True, type='list', elements='dict'), version=dict(type='int'), state=dict(choices=['present', 'absent'], default='present')) module = AnsibleAWSModule(argument_spec=argument_spec) client_conn = module.client('codepipeline') state = module.params.get('state') changed = False # Determine if the CodePipeline exists found_code_pipeline = describe_pipeline(client=client_conn, name=module.params['name'], version=module.params['version'], module=module) pipeline_result = {} if state == 'present': if 'pipeline' in found_code_pipeline: pipeline_dict = copy.deepcopy(found_code_pipeline['pipeline']) # Update dictionary with provided module params: pipeline_dict['roleArn'] = module.params['role_arn'] pipeline_dict['artifactStore'] = module.params['artifact_store'] pipeline_dict['stages'] = module.params['stages'] if module.params['version'] is not None: pipeline_dict['version'] = module.params['version'] pipeline_result = update_pipeline(client=client_conn, pipeline_dict=pipeline_dict, module=module) if compare_policies(found_code_pipeline['pipeline'], pipeline_result['pipeline']): changed = True else: pipeline_result = create_pipeline( client=client_conn, name=module.params['name'], role_arn=module.params['role_arn'], artifact_store=module.params['artifact_store'], stages=module.params['stages'], version=module.params['version'], module=module) changed = True elif state == 'absent': if found_code_pipeline: pipeline_result = delete_pipeline(client=client_conn, name=module.params['name'], module=module) changed = True module.exit_json(changed=changed, **camel_dict_to_snake_dict(pipeline_result))
def get_or_create_policy_version(module, iam, policy, policy_document): try: versions = iam.list_policy_versions(PolicyArn=policy['Arn'])['Versions'] except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Couldn't list policy versions") for v in versions: try: document = iam.get_policy_version(PolicyArn=policy['Arn'], VersionId=v['VersionId'])['PolicyVersion']['Document'] except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Couldn't get policy version {0}".format(v['VersionId'])) # If the current policy matches the existing one if not compare_policies(document, json.loads(to_native(policy_document))): return v, False # No existing version so create one # There is a service limit (typically 5) of policy versions. # # Rather than assume that it is 5, we'll try to create the policy # and if that doesn't work, delete the oldest non default policy version # and try again. try: version = iam.create_policy_version(PolicyArn=policy['Arn'], PolicyDocument=policy_document)['PolicyVersion'] return version, True except botocore.exceptions.ClientError as e: if e.response['Error']['Code'] == 'LimitExceeded': delete_oldest_non_default_version(module, iam, policy) try: version = iam.create_policy_version(PolicyArn=policy['Arn'], PolicyDocument=policy_document)['PolicyVersion'] return version, True except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as second_e: e = second_e # Handle both when the exception isn't LimitExceeded or # the second attempt still failed module.fail_json_aws(e, msg="Couldn't create policy version")
def create(self): matching_policies = [] policy_doc = self.get_policy_text() policy_match = False for pol in self.list(): if not compare_policies(self.get(pol), policy_doc): matching_policies.append(pol) policy_match = True if (self.policy_name not in matching_policies) and not (self.skip_duplicates and policy_match): self.put(policy_doc)
def find_missing(self, update, current_condition): missing = [] for desired in update['Updates']: found = False desired_condition = desired[self.conditiontuple] current_conditions = current_condition[self.conditiontuples] for condition in current_conditions: if not compare_policies(condition, desired_condition): found = True if not found: missing.append(desired) return missing
def get_or_create_policy_version(policy, policy_document): try: versions = client.list_policy_versions(PolicyArn=policy['Arn'])['Versions'] except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Couldn't list policy versions") for v in versions: try: document = client.get_policy_version(PolicyArn=policy['Arn'], VersionId=v['VersionId'])['PolicyVersion']['Document'] except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Couldn't get policy version {0}".format(v['VersionId'])) if module.check_mode and compare_policies(document, json.loads(to_native(policy_document))): return v, True # If the current policy matches the existing one if not compare_policies(document, json.loads(to_native(policy_document))): return v, False # No existing version so create one # There is a service limit (typically 5) of policy versions. # # Rather than assume that it is 5, we'll try to create the policy # and if that doesn't work, delete the oldest non default policy version # and try again. try: version = client.create_policy_version(PolicyArn=policy['Arn'], PolicyDocument=policy_document)['PolicyVersion'] return version, True except is_boto3_error_code('LimitExceeded'): delete_oldest_non_default_version(policy) try: version = client.create_policy_version(PolicyArn=policy['Arn'], PolicyDocument=policy_document)['PolicyVersion'] return version, True except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as second_e: module.fail_json_aws(second_e, msg="Couldn't create policy version") except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except module.fail_json_aws(e, msg="Couldn't create policy version")
def wait_policy_is_applied(module, s3_client, bucket_name, expected_policy, should_fail=True): for dummy in range(0, 12): try: current_policy = get_bucket_policy(s3_client, bucket_name) except (ClientError, BotoCoreError) as e: module.fail_json_aws(e, msg="Failed to get bucket policy") if compare_policies(current_policy, expected_policy): time.sleep(5) else: return current_policy if should_fail: module.fail_json(msg="Bucket policy failed to apply in the expected time", requested_policy=expected_policy, live_policy=current_policy) else: return None
def create_or_update_identity_policy(connection, module): identity = module.params.get('identity') policy_name = module.params.get('policy_name') required_policy = module.params.get('policy') required_policy_dict = json.loads(required_policy) changed = False policy = get_identity_policy(connection, module, identity, policy_name) policy_dict = json.loads(policy) if policy else None if compare_policies(policy_dict, required_policy_dict): changed = True try: if not module.check_mode: connection.put_identity_policy(Identity=identity, PolicyName=policy_name, Policy=required_policy, aws_retry=True) except (BotoCoreError, ClientError) as e: module.fail_json_aws( e, msg='Failed to put identity policy {policy}'.format( policy=policy_name)) # Load the list of applied policies to include in the response. # In principle we should be able to just return the response, but given # eventual consistency behaviours in AWS it's plausible that we could # end up with a list that doesn't contain the policy we just added. # So out of paranoia check for this case and if we're missing the policy # just make sure it's present. # # As a nice side benefit this also means the return is correct in check mode try: policies_present = connection.list_identity_policies( Identity=identity, aws_retry=True)['PolicyNames'] except (BotoCoreError, ClientError) as e: module.fail_json_aws(e, msg='Failed to list identity policies') if policy_name is not None and policy_name not in policies_present: policies_present = list(policies_present) policies_present.append(policy_name) module.exit_json( changed=changed, policies=policies_present, )
def create_or_update_bucket(s3_client, module, location): policy = module.params.get("policy") name = module.params.get("name") requester_pays = module.params.get("requester_pays") tags = module.params.get("tags") purge_tags = module.params.get("purge_tags") versioning = module.params.get("versioning") encryption = module.params.get("encryption") encryption_key_id = module.params.get("encryption_key_id") changed = False result = {} try: bucket_is_present = bucket_exists(s3_client, name) except EndpointConnectionError as e: module.fail_json_aws(e, msg="Invalid endpoint provided: %s" % to_text(e)) except (BotoCoreError, ClientError) as e: module.fail_json_aws(e, msg="Failed to check bucket presence") if not bucket_is_present: try: bucket_changed = create_bucket(s3_client, name, location) s3_client.get_waiter('bucket_exists').wait(Bucket=name) changed = changed or bucket_changed except WaiterError as e: module.fail_json_aws(e, msg='An error occurred waiting for the bucket to become available') except (BotoCoreError, ClientError) as e: module.fail_json_aws(e, msg="Failed while creating bucket") # Versioning try: versioning_status = get_bucket_versioning(s3_client, name) except BotoCoreError as exp: module.fail_json_aws(exp, msg="Failed to get bucket versioning") except ClientError as exp: if exp.response['Error']['Code'] != 'NotImplemented' or versioning is not None: module.fail_json_aws(exp, msg="Failed to get bucket versioning") else: if versioning is not None: required_versioning = None if versioning and versioning_status.get('Status') != "Enabled": required_versioning = 'Enabled' elif not versioning and versioning_status.get('Status') == "Enabled": required_versioning = 'Suspended' if required_versioning: try: put_bucket_versioning(s3_client, name, required_versioning) changed = True except (BotoCoreError, ClientError) as e: module.fail_json_aws(e, msg="Failed to update bucket versioning") versioning_status = wait_versioning_is_applied(module, s3_client, name, required_versioning) # This output format is there to ensure compatibility with previous versions of the module result['versioning'] = { 'Versioning': versioning_status.get('Status', 'Disabled'), 'MfaDelete': versioning_status.get('MFADelete', 'Disabled'), } # Requester pays try: requester_pays_status = get_bucket_request_payment(s3_client, name) except BotoCoreError as exp: module.fail_json_aws(exp, msg="Failed to get bucket request payment") except ClientError as exp: if exp.response['Error']['Code'] not in ('NotImplemented', 'XNotImplemented') or requester_pays: module.fail_json_aws(exp, msg="Failed to get bucket request payment") else: if requester_pays: payer = 'Requester' if requester_pays else 'BucketOwner' if requester_pays_status != payer: put_bucket_request_payment(s3_client, name, payer) requester_pays_status = wait_payer_is_applied(module, s3_client, name, payer, should_fail=False) if requester_pays_status is None: # We have seen that it happens quite a lot of times that the put request was not taken into # account, so we retry one more time put_bucket_request_payment(s3_client, name, payer) requester_pays_status = wait_payer_is_applied(module, s3_client, name, payer, should_fail=True) changed = True result['requester_pays'] = requester_pays # Policy try: current_policy = get_bucket_policy(s3_client, name) except BotoCoreError as exp: module.fail_json_aws(exp, msg="Failed to get bucket policy") except ClientError as exp: if exp.response['Error']['Code'] != 'NotImplemented' or policy is not None: module.fail_json_aws(exp, msg="Failed to get bucket policy") else: if policy is not None: if isinstance(policy, string_types): policy = json.loads(policy) if not policy and current_policy: try: delete_bucket_policy(s3_client, name) except (BotoCoreError, ClientError) as e: module.fail_json_aws(e, msg="Failed to delete bucket policy") current_policy = wait_policy_is_applied(module, s3_client, name, policy) changed = True elif compare_policies(current_policy, policy): try: put_bucket_policy(s3_client, name, policy) except (BotoCoreError, ClientError) as e: module.fail_json_aws(e, msg="Failed to update bucket policy") current_policy = wait_policy_is_applied(module, s3_client, name, policy, should_fail=False) if current_policy is None: # As for request payement, it happens quite a lot of times that the put request was not taken into # account, so we retry one more time put_bucket_policy(s3_client, name, policy) current_policy = wait_policy_is_applied(module, s3_client, name, policy, should_fail=True) changed = True result['policy'] = current_policy # Tags try: current_tags_dict = get_current_bucket_tags_dict(s3_client, name) except BotoCoreError as exp: module.fail_json_aws(exp, msg="Failed to get bucket tags") except ClientError as exp: if exp.response['Error']['Code'] not in ('NotImplemented', 'XNotImplemented') or tags is not None: module.fail_json_aws(exp, msg="Failed to get bucket tags") else: if tags is not None: # Tags are always returned as text tags = dict((to_text(k), to_text(v)) for k, v in tags.items()) if not purge_tags: # Ensure existing tags that aren't updated by desired tags remain current_copy = current_tags_dict.copy() current_copy.update(tags) tags = current_copy if current_tags_dict != tags: if tags: try: put_bucket_tagging(s3_client, name, tags) except (BotoCoreError, ClientError) as e: module.fail_json_aws(e, msg="Failed to update bucket tags") else: if purge_tags: try: delete_bucket_tagging(s3_client, name) except (BotoCoreError, ClientError) as e: module.fail_json_aws(e, msg="Failed to delete bucket tags") current_tags_dict = wait_tags_are_applied(module, s3_client, name, tags) changed = True result['tags'] = current_tags_dict # Encryption try: current_encryption = get_bucket_encryption(s3_client, name) except (ClientError, BotoCoreError) as e: module.fail_json_aws(e, msg="Failed to get bucket encryption") if encryption is not None: current_encryption_algorithm = current_encryption.get('SSEAlgorithm') if current_encryption else None current_encryption_key = current_encryption.get('KMSMasterKeyID') if current_encryption else None if encryption == 'none' and current_encryption_algorithm is not None: try: delete_bucket_encryption(s3_client, name) except (BotoCoreError, ClientError) as e: module.fail_json_aws(e, msg="Failed to delete bucket encryption") current_encryption = wait_encryption_is_applied(module, s3_client, name, None) changed = True elif encryption != 'none' and (encryption != current_encryption_algorithm) or (encryption == 'aws:kms' and current_encryption_key != encryption_key_id): expected_encryption = {'SSEAlgorithm': encryption} if encryption == 'aws:kms' and encryption_key_id is not None: expected_encryption.update({'KMSMasterKeyID': encryption_key_id}) current_encryption = put_bucket_encryption_with_retry(module, s3_client, name, expected_encryption) changed = True result['encryption'] = current_encryption module.exit_json(changed=changed, name=name, **result)
def test_compare_boolean_policy_bool_and_string_are_equal(self): """ Testing two policies one using a quoted boolean, the other a bool """ self.assertFalse( compare_policies(self.bool_policy_string, self.bool_policy_bool))
def run(ecr, params): # type: (EcsEcr, dict, int) -> Tuple[bool, dict] result = {} try: name = params['name'] state = params['state'] policy_text = params['policy'] purge_policy = params['purge_policy'] registry_id = params['registry_id'] force_set_policy = params['force_set_policy'] image_tag_mutability = params['image_tag_mutability'].upper() lifecycle_policy_text = params['lifecycle_policy'] purge_lifecycle_policy = params['purge_lifecycle_policy'] scan_on_push = params['scan_on_push'] # Parse policies, if they are given try: policy = policy_text and json.loads(policy_text) except ValueError: result['policy'] = policy_text result['msg'] = 'Could not parse policy' return False, result try: lifecycle_policy = \ lifecycle_policy_text and json.loads(lifecycle_policy_text) except ValueError: result['lifecycle_policy'] = lifecycle_policy_text result['msg'] = 'Could not parse lifecycle_policy' return False, result result['state'] = state result['created'] = False repo = ecr.get_repository(registry_id, name) if state == 'present': result['created'] = False if not repo: repo = ecr.create_repository(registry_id, name, image_tag_mutability) result['changed'] = True result['created'] = True else: repo = ecr.put_image_tag_mutability(registry_id, name, image_tag_mutability) result['repository'] = repo if purge_lifecycle_policy: original_lifecycle_policy = \ ecr.get_lifecycle_policy(registry_id, name) result['lifecycle_policy'] = None if original_lifecycle_policy: ecr.purge_lifecycle_policy(registry_id, name) result['changed'] = True elif lifecycle_policy_text is not None: try: lifecycle_policy = sort_json_policy_dict(lifecycle_policy) result['lifecycle_policy'] = lifecycle_policy original_lifecycle_policy = ecr.get_lifecycle_policy( registry_id, name) if original_lifecycle_policy: original_lifecycle_policy = sort_json_policy_dict( original_lifecycle_policy) if original_lifecycle_policy != lifecycle_policy: ecr.put_lifecycle_policy(registry_id, name, lifecycle_policy_text) result['changed'] = True except Exception: # Some failure w/ the policy. It's helpful to know what the # policy is. result['lifecycle_policy'] = lifecycle_policy_text raise if purge_policy: original_policy = ecr.get_repository_policy(registry_id, name) result['policy'] = None if original_policy: ecr.delete_repository_policy(registry_id, name) result['changed'] = True elif policy_text is not None: try: # Sort any lists containing only string types policy = sort_lists_of_strings(policy) result['policy'] = policy original_policy = ecr.get_repository_policy( registry_id, name) if original_policy: original_policy = sort_lists_of_strings( original_policy) if compare_policies(original_policy, policy): ecr.set_repository_policy(registry_id, name, policy_text, force_set_policy) result['changed'] = True except Exception: # Some failure w/ the policy. It's helpful to know what the # policy is. result['policy'] = policy_text raise original_scan_on_push = ecr.get_repository(registry_id, name) if original_scan_on_push is not None: if scan_on_push != original_scan_on_push[ 'imageScanningConfiguration']['scanOnPush']: result['changed'] = True result['repository']['imageScanningConfiguration'][ 'scanOnPush'] = scan_on_push response = ecr.put_image_scanning_configuration( registry_id, name, scan_on_push) elif state == 'absent': result['name'] = name if repo: ecr.delete_repository(registry_id, name) result['changed'] = True except Exception as err: msg = str(err) if isinstance(err, ClientError): msg = boto_exception(err) result['msg'] = msg result['exception'] = traceback.format_exc() return False, result if ecr.skipped: result['skipped'] = True if ecr.changed: result['changed'] = True return True, result
def test_compare_smaller_policy_with_larger(self): """ Testing two policies of different sizes """ self.assertTrue( compare_policies(self.larger_policy_one, self.small_policy_one))
def test_compare_version_policies_with_none(self): """ Testing that comparing with no policy works """ self.assertTrue(compare_policies(self.small_policy_one, None)) self.assertTrue(compare_policies(None, self.small_policy_one)) self.assertFalse(compare_policies(None, None))
def main(): module = AnsibleAWSModule( argument_spec={ 'name': dict(required=True), 'state': dict(choices=['present', 'absent'], default='present'), 'description': dict(default=""), 'kms_key_id': dict(), 'secret_type': dict(choices=['binary', 'string'], default="string"), 'secret': dict(default="", no_log=True), 'resource_policy': dict(type='json', default=None), 'tags': dict(type='dict', default={}), 'rotation_lambda': dict(), 'rotation_interval': dict(type='int', default=30), 'recovery_window': dict(type='int', default=30), }, supports_check_mode=True, ) changed = False state = module.params.get('state') secrets_mgr = SecretsManagerInterface(module) recovery_window = module.params.get('recovery_window') secret = Secret(module.params.get('name'), module.params.get('secret_type'), module.params.get('secret'), description=module.params.get('description'), kms_key_id=module.params.get('kms_key_id'), resource_policy=module.params.get('resource_policy'), tags=module.params.get('tags'), lambda_arn=module.params.get('rotation_lambda'), rotation_interval=module.params.get('rotation_interval')) current_secret = secrets_mgr.get_secret(secret.name) if state == 'absent': if current_secret: if not current_secret.get("DeletedDate"): result = camel_dict_to_snake_dict( secrets_mgr.delete_secret(secret.name, recovery_window=recovery_window)) changed = True elif current_secret.get("DeletedDate") and recovery_window == 0: result = camel_dict_to_snake_dict( secrets_mgr.delete_secret(secret.name, recovery_window=recovery_window)) changed = True else: result = "secret already scheduled for deletion" else: result = "secret does not exist" if state == 'present': if current_secret is None: result = secrets_mgr.create_secret(secret) if secret.resource_policy and result.get("ARN"): result = secrets_mgr.put_resource_policy(secret) changed = True else: if current_secret.get("DeletedDate"): secrets_mgr.restore_secret(secret.name) changed = True if not secrets_mgr.secrets_match(secret, current_secret): result = secrets_mgr.update_secret(secret) changed = True if not rotation_match(secret, current_secret): result = secrets_mgr.update_rotation(secret) changed = True current_resource_policy_response = secrets_mgr.get_resource_policy( secret.name) current_resource_policy = current_resource_policy_response.get( "ResourcePolicy") if compare_policies(secret.resource_policy, current_resource_policy): if secret.resource_policy is None and current_resource_policy: result = secrets_mgr.delete_resource_policy(secret.name) else: result = secrets_mgr.put_resource_policy(secret) changed = True current_tags = boto3_tag_list_to_ansible_dict( current_secret.get('Tags', [])) tags_to_add, tags_to_remove = compare_aws_tags( current_tags, secret.tags) if tags_to_add: secrets_mgr.tag_secret( secret.name, ansible_dict_to_boto3_tag_list(tags_to_add)) changed = True if tags_to_remove: secrets_mgr.untag_secret(secret.name, tags_to_remove) changed = True result = camel_dict_to_snake_dict(secrets_mgr.get_secret(secret.name)) result.pop("response_metadata") module.exit_json(changed=changed, secret=result)
def test_compare_numeric_policy_number_and_string_are_equal(self): """ Testing two policies one using a quoted number, the other an int """ self.assertFalse( compare_policies(self.numeric_policy_string, self.numeric_policy_number))
def compare_assume_role_policy_doc(current_policy_doc, new_policy_doc): if not compare_policies(current_policy_doc, json.loads(new_policy_doc)): return True else: return False
def test_compare_larger_policies_with_difference(self): """ Testing two larger policies which are identical except for: * one different principal """ self.assertTrue( compare_policies(self.larger_policy_two, self.larger_policy_three))