Пример #1
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_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
Пример #2
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))
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 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 ClientError as e:
            module.fail_json(
                msg="Unable to update CORS for bucket {0}: {1}".format(
                    name, to_native(e)),
                exception=traceback.format_exc(),
                **camel_dict_to_snake_dict(e.response))
        except BotoCoreError as e:
            module.fail_json(msg=to_native(e),
                             exception=traceback.format_exc())

    module.exit_json(changed=changed, name=name, rules=rules)
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'),
                         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))
Пример #6
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
Пример #7
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)
Пример #8
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 as e:
        module.fail_json(msg="Couldn't list policy versions: %s" % str(e),
                         exception=traceback.format_exc(),
                         **camel_dict_to_snake_dict(e.response))
    for v in versions:
        try:
            document = iam.get_policy_version(
                PolicyArn=policy['Arn'],
                VersionId=v['VersionId'])['PolicyVersion']['Document']
        except botocore.exceptions.ClientError as e:
            module.fail_json(msg="Couldn't get policy version %s: %s" %
                             (v['VersionId'], str(e)),
                             exception=traceback.format_exc(),
                             **camel_dict_to_snake_dict(e.response))
        # 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 as second_e:
                e = second_e
        # Handle both when the exception isn't LimitExceeded or
        # the second attempt still failed
        module.fail_json(msg="Couldn't create policy version: %s" % str(e),
                         exception=traceback.format_exc(),
                         **camel_dict_to_snake_dict(e.response))
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,
    )
Пример #10
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")
    else:
        return None
Пример #11
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))
Пример #12
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))
Пример #13
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))
Пример #14
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))
Пример #15
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))
Пример #16
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
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']

        # 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

        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
Пример #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'] != 'NotImplemented' 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'] != 'NotImplemented' 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
    if hasattr(s3_client, "get_bucket_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")
    elif encryption is not None:
        module.fail_json(
            msg="Using bucket encryption requires botocore version >= 1.7.41")

    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})
            try:
                put_bucket_encryption(s3_client, name, expected_encryption)
            except (BotoCoreError, ClientError) as e:
                module.fail_json_aws(e, msg="Failed to set bucket encryption")
            current_encryption = wait_encryption_is_applied(
                module, s3_client, name, expected_encryption)
            changed = True

        result['encryption'] = current_encryption

    module.exit_json(changed=changed, name=name, **result)