Пример #1
0
 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"))
Пример #2
0
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')
Пример #3
0
 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))
Пример #4
0
 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))
Пример #5
0
 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))
Пример #6
0
 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))
Пример #7
0
    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
Пример #8
0
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)
Пример #9
0
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))
Пример #11
0
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))
Пример #12
0
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")
Пример #13
0
    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)
Пример #14
0
 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
Пример #15
0
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")
Пример #16
0
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,
    )
Пример #18
0
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)
Пример #19
0
 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))
Пример #20
0
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
Пример #21
0
 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))
Пример #22
0
 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))
Пример #23
0
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)
Пример #24
0
 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))
Пример #25
0
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
Пример #26
0
 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))