Example #1
0
def remove_rule_conditions(client, module, rule_id):
    conditions = get_rule(client, module, rule_id)['Predicates']
    updates = [format_for_deletion(camel_dict_to_snake_dict(condition)) for condition in conditions]
    try:
        run_func_with_change_token_backoff(client, module, {'RuleId': rule_id, 'Updates': updates}, client.update_rule)
    except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
        module.fail_json_aws(e, msg='Could not remove rule conditions')
Example #2
0
    def delete_unused_regex_pattern(self, regex_pattern_set_id):
        try:
            regex_pattern_set = self.client.get_regex_pattern_set(
                RegexPatternSetId=regex_pattern_set_id)['RegexPatternSet']
            updates = list()
            for regex_pattern_string in regex_pattern_set[
                    'RegexPatternStrings']:
                updates.append({
                    'Action': 'DELETE',
                    'RegexPatternString': regex_pattern_string
                })
            run_func_with_change_token_backoff(
                self.client, self.module, {
                    'RegexPatternSetId': regex_pattern_set_id,
                    'Updates': updates
                }, self.client.update_regex_pattern_set)

            run_func_with_change_token_backoff(
                self.client,
                self.module, {'RegexPatternSetId': regex_pattern_set_id},
                self.client.delete_regex_pattern_set,
                wait=True)
        except (botocore.exceptions.ClientError,
                botocore.exceptions.BotoCoreError) as e:
            if e.response['Error']['Code'] == 'WAFNonexistentItemException':
                return
            self.module.fail_json_aws(e, msg='Could not delete regex pattern')
 def find_and_delete_condition(self, condition_set_id):
     current_condition = self.get_condition_by_id(condition_set_id)
     in_use_rules = self.find_condition_in_rules(condition_set_id)
     if in_use_rules:
         rulenames = ', '.join(in_use_rules)
         self.module.fail_json(msg="Condition %s is in use by %s" % (current_condition['Name'], rulenames))
     if current_condition[self.conditiontuples]:
         # Filters are deleted using update with the DELETE action
         func = getattr(self.client, 'update_' + self.method_suffix)
         params = self.format_for_deletion(current_condition)
         try:
             # We do not need to wait for the conditiontuple delete because we wait later for the delete_* call
             run_func_with_change_token_backoff(self.client, self.module, params, func)
         except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
             self.module.fail_json_aws(e, msg='Could not delete filters from condition')
     func = getattr(self.client, 'delete_' + self.method_suffix)
     params = dict()
     params[self.conditionsetid] = condition_set_id
     try:
         run_func_with_change_token_backoff(self.client, self.module, params, func, wait=True)
     except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
         self.module.fail_json_aws(e, msg='Could not delete condition')
     # tidy up regex patterns
     if self.type == 'regex':
         self.tidy_up_regex_patterns(current_condition)
     return True, {}
 def find_and_delete_condition(self, condition_set_id):
     current_condition = self.get_condition_by_id(condition_set_id)
     in_use_rules = self.find_condition_in_rules(condition_set_id)
     if in_use_rules:
         rulenames = ', '.join(in_use_rules)
         self.module.fail_json(msg="Condition %s is in use by %s" % (current_condition['Name'], rulenames))
     if current_condition[self.conditiontuples]:
         # Filters are deleted using update with the DELETE action
         func = getattr(self.client, 'update_' + self.method_suffix)
         params = self.format_for_deletion(current_condition)
         try:
             # We do not need to wait for the conditiontuple delete because we wait later for the delete_* call
             run_func_with_change_token_backoff(self.client, self.module, params, func)
         except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
             self.module.fail_json_aws(e, msg='Could not delete filters from condition')
     func = getattr(self.client, 'delete_' + self.method_suffix)
     params = dict()
     params[self.conditionsetid] = condition_set_id
     try:
         run_func_with_change_token_backoff(self.client, self.module, params, func, wait=True)
     except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
         self.module.fail_json_aws(e, msg='Could not delete condition')
     # tidy up regex patterns
     if self.type == 'regex':
         self.tidy_up_regex_patterns(current_condition)
     return True, {}
Example #5
0
def remove_rule_conditions(client, module, rule_id):
    conditions = get_rule(client, module, rule_id)['Predicates']
    updates = [format_for_deletion(camel_dict_to_snake_dict(condition)) for condition in conditions]
    try:
        run_func_with_change_token_backoff(client, module, {'RuleId': rule_id, 'Updates': updates}, client.update_rule)
    except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
        module.fail_json_aws(e, msg='Could not remove rule conditions')
 def find_and_update_condition(self, condition_set_id):
     current_condition = self.get_condition_by_id(condition_set_id)
     update = self.format_for_update(condition_set_id)
     missing = self.find_missing(update, current_condition)
     if self.module.params.get('purge_filters'):
         extra = [{
             'Action': 'DELETE',
             self.conditiontuple: current_tuple
         } for current_tuple in current_condition[self.conditiontuples]
                  if current_tuple not in [
                      desired[self.conditiontuple]
                      for desired in update['Updates']
                  ]]
     else:
         extra = []
     changed = bool(missing or extra)
     if changed:
         update['Updates'] = missing + extra
         func = getattr(self.client, 'update_' + self.method_suffix)
         try:
             run_func_with_change_token_backoff(self.client, self.module,
                                                update, func)
         except (botocore.exceptions.ClientError,
                 botocore.exceptions.BotoCoreError) as e:
             self.module.fail_json_aws(e, msg='Could not update condition')
     return changed, self.get_condition_by_id(condition_set_id)
    def ensure_regex_pattern_present(self, regex_pattern):
        name = regex_pattern['name']

        pattern_set = self.get_regex_pattern_by_name(name)
        if not pattern_set:
            pattern_set = run_func_with_change_token_backoff(
                self.client, self.module, {'Name': name},
                self.client.create_regex_pattern_set)['RegexPatternSet']
        missing = set(regex_pattern['regex_strings']) - set(
            pattern_set['RegexPatternStrings'])
        extra = set(pattern_set['RegexPatternStrings']) - set(
            regex_pattern['regex_strings'])
        if not missing and not extra:
            return pattern_set
        updates = [{
            'Action': 'INSERT',
            'RegexPatternString': pattern
        } for pattern in missing]
        updates.extend([{
            'Action': 'DELETE',
            'RegexPatternString': pattern
        } for pattern in extra])
        run_func_with_change_token_backoff(
            self.client, self.module, {
                'RegexPatternSetId': pattern_set['RegexPatternSetId'],
                'Updates': updates
            }, self.client.update_regex_pattern_set)
        return self.get_regex_pattern_set_with_backoff(
            pattern_set['RegexPatternSetId'])['RegexPatternSet']
Example #8
0
def find_and_update_web_acl(client, module, web_acl_id):
    acl = get_web_acl(client, module, web_acl_id)
    rule_lookup = create_rule_lookup(client, module)
    existing_rules = acl['Rules']
    desired_rules = [{
        'RuleId': rule_lookup[rule['name']]['RuleId'],
        'Priority': rule['priority'],
        'Action': {
            'Type': rule['action'].upper()
        },
        'Type': rule.get('type', 'regular').upper()
    } for rule in module.params['rules']]
    missing = [rule for rule in desired_rules if rule not in existing_rules]
    extras = []
    if module.params['purge_rules']:
        extras = [rule for rule in existing_rules if rule not in desired_rules]

    insertions = [format_for_update(rule, 'INSERT') for rule in missing]
    deletions = [format_for_update(rule, 'DELETE') for rule in extras]
    changed = bool(insertions + deletions)

    # Purge rules before adding new ones in case a deletion shares the same
    # priority as an insertion.
    params = {
        'WebACLId': acl['WebACLId'],
        'DefaultAction': acl['DefaultAction']
    }
    change_tokens = []
    if deletions:
        try:
            params['Updates'] = deletions
            result = run_func_with_change_token_backoff(
                client, module, params, client.update_web_acl)
            change_tokens.append(result['ChangeToken'])
            get_waiter(
                client,
                'change_token_in_sync',
            ).wait(ChangeToken=result['ChangeToken'])
        except (botocore.exceptions.ClientError,
                botocore.exceptions.BotoCoreError) as e:
            module.fail_json_aws(e, msg='Could not update Web ACL')
    if insertions:
        try:
            params['Updates'] = insertions
            result = run_func_with_change_token_backoff(
                client, module, params, client.update_web_acl)
            change_tokens.append(result['ChangeToken'])
        except (botocore.exceptions.ClientError,
                botocore.exceptions.BotoCoreError) as e:
            module.fail_json_aws(e, msg='Could not update Web ACL')
    if change_tokens:
        for token in change_tokens:
            get_waiter(
                client,
                'change_token_in_sync',
            ).wait(ChangeToken=token)
    if changed:
        acl = get_web_acl(client, module, web_acl_id)
    return changed, acl
Example #9
0
def remove_rules_from_web_acl(client, module, web_acl_id):
    acl = get_web_acl(client, module, web_acl_id)
    deletions = [format_for_update(rule, 'DELETE') for rule in acl['Rules']]
    try:
        params = {'WebACLId': acl['WebACLId'], 'DefaultAction': acl['DefaultAction'], 'Updates': deletions}
        run_func_with_change_token_backoff(client, module, params, client.update_web_acl)
    except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
        module.fail_json_aws(e, msg='Could not remove rule')
def remove_rules_from_web_acl(client, module, web_acl_id):
    acl = get_web_acl(client, module, web_acl_id)
    deletions = [format_for_update(rule, 'DELETE') for rule in acl['Rules']]
    try:
        params = {'WebACLId': acl['WebACLId'], 'DefaultAction': acl['DefaultAction'], 'Updates': deletions}
        run_func_with_change_token_backoff(client, module, params, client.update_web_acl)
    except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
        module.fail_json_aws(e, msg='Could not remove rule')
Example #11
0
def find_and_update_web_acl(client, module, web_acl_id):
    acl = get_web_acl(client, module, web_acl_id)
    rule_lookup = create_rule_lookup(client, module)
    existing_rules = acl['Rules']
    desired_rules = [{'RuleId': rule_lookup[rule['name']]['RuleId'],
                      'Priority': rule['priority'],
                      'Action': {'Type': rule['action'].upper()},
                      'Type': rule.get('type', 'regular').upper()}
                     for rule in module.params['rules']]
    missing = [rule for rule in desired_rules if rule not in existing_rules]
    extras = []
    if module.params['purge_rules']:
        extras = [rule for rule in existing_rules if rule not in desired_rules]

    insertions = [format_for_update(rule, 'INSERT') for rule in missing]
    deletions = [format_for_update(rule, 'DELETE') for rule in extras]
    changed = bool(insertions + deletions)

    # Purge rules before adding new ones in case a deletion shares the same
    # priority as an insertion.
    params = {
        'WebACLId': acl['WebACLId'],
        'DefaultAction': acl['DefaultAction']
    }
    change_tokens = []
    if deletions:
        try:
            params['Updates'] = deletions
            result = run_func_with_change_token_backoff(client, module, params, client.update_web_acl)
            change_tokens.append(result['ChangeToken'])
            get_waiter(
                client, 'change_token_in_sync',
            ).wait(
                ChangeToken=result['ChangeToken']
            )
        except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
            module.fail_json_aws(e, msg='Could not update Web ACL')
    if insertions:
        try:
            params['Updates'] = insertions
            result = run_func_with_change_token_backoff(client, module, params, client.update_web_acl)
            change_tokens.append(result['ChangeToken'])
        except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
            module.fail_json_aws(e, msg='Could not update Web ACL')
    if change_tokens:
        for token in change_tokens:
            get_waiter(
                client, 'change_token_in_sync',
            ).wait(
                ChangeToken=token
            )
    if changed:
        acl = get_web_acl(client, module, web_acl_id)
    return changed, acl
Example #12
0
def ensure_web_acl_absent(client, module):
    web_acl_id = get_web_acl_by_name(client, module, module.params['name'])
    if web_acl_id:
        web_acl = get_web_acl(client, module, web_acl_id)
        if web_acl['Rules']:
            remove_rules_from_web_acl(client, module, web_acl_id)
        try:
            run_func_with_change_token_backoff(client, module, {'WebACLId': web_acl_id}, client.delete_web_acl, wait=True)
            return True, {}
        except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
            module.fail_json_aws(e, msg='Could not delete Web ACL')
    return False, {}
def ensure_web_acl_absent(client, module):
    web_acl_id = get_web_acl_by_name(client, module, module.params['name'])
    if web_acl_id:
        web_acl = get_web_acl(client, module, web_acl_id)
        if web_acl['Rules']:
            remove_rules_from_web_acl(client, module, web_acl_id)
        try:
            run_func_with_change_token_backoff(client, module, {'WebACLId': web_acl_id}, client.delete_web_acl)
            return True, {}
        except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
            module.fail_json_aws(e, msg='Could not delete Web ACL')
    return False, {}
Example #14
0
def ensure_web_acl_present(client, module):
    changed = False
    result = None
    name = module.params['name']
    web_acl_id = get_web_acl_by_name(client, module, name)
    if web_acl_id:
        (changed, result) = find_and_update_web_acl(client, module, web_acl_id)
    else:
        metric_name = module.params['metric_name']
        if not metric_name:
            metric_name = re.sub(r'[^A-Za-z0-9]', '', module.params['name'])
        default_action = module.params['default_action'].upper()
        try:
            params = {
                'Name': name,
                'MetricName': metric_name,
                'DefaultAction': {
                    'Type': default_action
                }
            }
            new_web_acl = run_func_with_change_token_backoff(
                client, module, params, client.create_web_acl)
        except (botocore.exceptions.ClientError,
                botocore.exceptions.BotoCoreError) as e:
            module.fail_json_aws(e, msg='Could not create Web ACL')
        (changed,
         result) = find_and_update_web_acl(client, module,
                                           new_web_acl['WebACL']['WebACLId'])
    return changed, result
Example #15
0
    def ensure_regex_pattern_present(self, regex_pattern):
        name = regex_pattern['name']

        pattern_set = self.get_regex_pattern_by_name(name)
        if not pattern_set:
            pattern_set = run_func_with_change_token_backoff(self.client, self.module, {'Name': name},
                                                             self.client.create_regex_pattern_set)['RegexPatternSet']
        missing = set(regex_pattern['regex_strings']) - set(pattern_set['RegexPatternStrings'])
        extra = set(pattern_set['RegexPatternStrings']) - set(regex_pattern['regex_strings'])
        if not missing and not extra:
            return pattern_set
        updates = [{'Action': 'INSERT', 'RegexPatternString': pattern} for pattern in missing]
        updates.extend([{'Action': 'DELETE', 'RegexPatternString': pattern} for pattern in extra])
        run_func_with_change_token_backoff(self.client, self.module,
                                           {'RegexPatternSetId': pattern_set['RegexPatternSetId'], 'Updates': updates},
                                           self.client.update_regex_pattern_set, wait=True)
        return self.get_regex_pattern_set_with_backoff(pattern_set['RegexPatternSetId'])['RegexPatternSet']
Example #16
0
    def delete_unused_regex_pattern(self, regex_pattern_set_id):
        try:
            regex_pattern_set = self.client.get_regex_pattern_set(RegexPatternSetId=regex_pattern_set_id)['RegexPatternSet']
            updates = list()
            for regex_pattern_string in regex_pattern_set['RegexPatternStrings']:
                updates.append({'Action': 'DELETE', 'RegexPatternString': regex_pattern_string})
            run_func_with_change_token_backoff(self.client, self.module,
                                               {'RegexPatternSetId': regex_pattern_set_id, 'Updates': updates},
                                               self.client.update_regex_pattern_set)

            run_func_with_change_token_backoff(self.client, self.module,
                                               {'RegexPatternSetId': regex_pattern_set_id},
                                               self.client.delete_regex_pattern_set, wait=True)
        except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
            if e.response['Error']['Code'] == 'WAFNonexistentItemException':
                return
            self.module.fail_json_aws(e, msg='Could not delete regex pattern')
Example #17
0
 def ensure_condition_present(self):
     name = self.module.params['name']
     condition_set_id = self.get_condition_by_name(name)
     if condition_set_id:
         return self.find_and_update_condition(condition_set_id)
     else:
         params = dict()
         params['Name'] = name
         func = getattr(self.client, 'create_' + self.method_suffix)
         try:
             condition = run_func_with_change_token_backoff(self.client, self.module, params, func)
         except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
             self.module.fail_json_aws(e, msg='Could not create condition')
         return self.find_and_update_condition(condition[self.conditionset][self.conditionsetid])
 def ensure_condition_present(self):
     name = self.module.params['name']
     condition_set_id = self.get_condition_by_name(name)
     if condition_set_id:
         return self.find_and_update_condition(condition_set_id)
     else:
         params = dict()
         params['Name'] = name
         func = getattr(self.client, 'create_' + self.method_suffix)
         try:
             condition = run_func_with_change_token_backoff(self.client, self.module, params, func)
         except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
             self.module.fail_json_aws(e, msg='Could not create condition')
         return self.find_and_update_condition(condition[self.conditionset][self.conditionsetid])
Example #19
0
def ensure_rule_absent(client, module):
    rule_id = get_rule_by_name(client, module, module.params['name'])
    in_use_web_acls = find_rule_in_web_acls(client, module, rule_id)
    if in_use_web_acls:
        web_acl_names = ', '.join(in_use_web_acls)
        module.fail_json(msg="Rule %s is in use by Web ACL(s) %s" %
                         (module.params['name'], web_acl_names))
    if rule_id:
        remove_rule_conditions(client, module, rule_id)
        try:
            return True, run_func_with_change_token_backoff(client, module, {'RuleId': rule_id}, client.delete_rule, wait=True)
        except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
            module.fail_json_aws(e, msg='Could not delete rule')
    return False, {}
Example #20
0
def ensure_rule_absent(client, module):
    rule_id = get_rule_by_name(client, module, module.params['name'])
    in_use_web_acls = find_rule_in_web_acls(client, module, rule_id)
    if in_use_web_acls:
        web_acl_names = ', '.join(in_use_web_acls)
        module.fail_json(msg="Rule %s is in use by Web ACL(s) %s" %
                         (module.params['name'], web_acl_names))
    if rule_id:
        remove_rule_conditions(client, module, rule_id)
        try:
            return True, run_func_with_change_token_backoff(client, module, {'RuleId': rule_id}, client.delete_rule, wait=True)
        except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
            module.fail_json_aws(e, msg='Could not delete rule')
    return False, {}
Example #21
0
def ensure_rule_present(client, module):
    name = module.params['name']
    rule_id = get_rule_by_name(client, module, name)
    params = dict()
    if rule_id:
        return find_and_update_rule(client, module, rule_id)
    else:
        params['Name'] = module.params['name']
        metric_name = module.params['metric_name']
        if not metric_name:
            metric_name = re.sub(r'[^a-zA-Z0-9]', '', module.params['name'])
        params['MetricName'] = metric_name
        try:
            new_rule = run_func_with_change_token_backoff(client, module, params, client.create_rule)['Rule']
        except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
            module.fail_json_aws(e, msg='Could not create rule')
        return find_and_update_rule(client, module, new_rule['RuleId'])
Example #22
0
def ensure_rule_present(client, module):
    name = module.params['name']
    rule_id = get_rule_by_name(client, module, name)
    params = dict()
    if rule_id:
        return find_and_update_rule(client, module, rule_id)
    else:
        params['Name'] = module.params['name']
        metric_name = module.params['metric_name']
        if not metric_name:
            metric_name = re.sub(r'[^a-zA-Z0-9]', '', module.params['name'])
        params['MetricName'] = metric_name
        try:
            new_rule = run_func_with_change_token_backoff(client, module, params, client.create_rule)['Rule']
        except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
            module.fail_json_aws(e, msg='Could not create rule')
        return find_and_update_rule(client, module, new_rule['RuleId'])
Example #23
0
 def find_and_update_condition(self, condition_set_id):
     current_condition = self.get_condition_by_id(condition_set_id)
     update = self.format_for_update(condition_set_id)
     missing = self.find_missing(update, current_condition)
     if self.module.params.get('purge_filters'):
         extra = [{'Action': 'DELETE', self.conditiontuple: current_tuple}
                  for current_tuple in current_condition[self.conditiontuples]
                  if current_tuple not in [desired[self.conditiontuple] for desired in update['Updates']]]
     else:
         extra = []
     changed = bool(missing or extra)
     if changed:
         update['Updates'] = missing + extra
         func = getattr(self.client, 'update_' + self.method_suffix)
         try:
             result = run_func_with_change_token_backoff(self.client, self.module, update, func, wait=True)
         except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
             self.module.fail_json_aws(e, msg='Could not update condition')
     return changed, self.get_condition_by_id(condition_set_id)
Example #24
0
def ensure_web_acl_present(client, module):
    changed = False
    result = None
    name = module.params['name']
    web_acl_id = get_web_acl_by_name(client, module, name)
    if web_acl_id:
        (changed, result) = find_and_update_web_acl(client, module, web_acl_id)
    else:
        metric_name = module.params['metric_name']
        if not metric_name:
            metric_name = re.sub(r'[^A-Za-z0-9]', '', module.params['name'])
        default_action = module.params['default_action'].upper()
        try:
            params = {'Name': name, 'MetricName': metric_name, 'DefaultAction': {'Type': default_action}}
            new_web_acl = run_func_with_change_token_backoff(client, module, params, client.create_web_acl)
        except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
            module.fail_json_aws(e, msg='Could not create Web ACL')
        (changed, result) = find_and_update_web_acl(client, module, new_web_acl['WebACL']['WebACLId'])
    return changed, result
Example #25
0
def find_and_update_rule(client, module, rule_id):
    rule = get_rule(client, module, rule_id)
    rule_id = rule['RuleId']

    existing_conditions = dict((condition_type, dict()) for condition_type in MATCH_LOOKUP)
    desired_conditions = dict((condition_type, dict()) for condition_type in MATCH_LOOKUP)
    all_conditions = dict()

    for condition_type in MATCH_LOOKUP:
        method = 'list_' + MATCH_LOOKUP[condition_type]['method'] + 's'
        all_conditions[condition_type] = dict()
        try:
            paginator = client.get_paginator(method)
            func = paginator.paginate().build_full_result
        except (KeyError, botocore.exceptions.OperationNotPageableError):
            # list_geo_match_sets and list_regex_match_sets do not have a paginator
            # and throw different exceptions
            func = getattr(client, method)
        try:
            pred_results = func()[MATCH_LOOKUP[condition_type]['conditionset'] + 's']
        except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
            module.fail_json_aws(e, msg='Could not list %s conditions' % condition_type)
        for pred in pred_results:
            pred['DataId'] = pred[MATCH_LOOKUP[condition_type]['conditionset'] + 'Id']
            all_conditions[condition_type][pred['Name']] = camel_dict_to_snake_dict(pred)
            all_conditions[condition_type][pred['DataId']] = camel_dict_to_snake_dict(pred)

    for condition in module.params['conditions']:
        desired_conditions[condition['type']][condition['name']] = condition

    reverse_condition_types = dict((v['type'], k) for (k, v) in MATCH_LOOKUP.items())
    for condition in rule['Predicates']:
        existing_conditions[reverse_condition_types[condition['Type']]][condition['DataId']] = camel_dict_to_snake_dict(condition)

    insertions = list()
    deletions = list()

    for condition_type in desired_conditions:
        for (condition_name, condition) in desired_conditions[condition_type].items():
            if condition_name not in all_conditions[condition_type]:
                module.fail_json(msg="Condition %s of type %s does not exist" % (condition_name, condition_type))
            condition['data_id'] = all_conditions[condition_type][condition_name]['data_id']
            if condition['data_id'] not in existing_conditions[condition_type]:
                insertions.append(format_for_insertion(condition))

    if module.params['purge_conditions']:
        for condition_type in existing_conditions:
            deletions.extend([format_for_deletion(condition) for condition in existing_conditions[condition_type].values()
                              if not all_conditions[condition_type][condition['data_id']]['name'] in desired_conditions[condition_type]])

    changed = bool(insertions or deletions)
    update = {
        'RuleId': rule_id,
        'Updates': insertions + deletions
    }
    if changed:
        try:
            run_func_with_change_token_backoff(client, module, update, client.update_rule, wait=True)
        except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
            module.fail_json_aws(e, msg='Could not update rule conditions')

    return changed, get_rule(client, module, rule_id)
Example #26
0
def find_and_update_rule(client, module, rule_id):
    rule = get_rule(client, module, rule_id)
    rule_id = rule['RuleId']

    existing_conditions = dict(
        (condition_type, dict()) for condition_type in MATCH_LOOKUP)
    desired_conditions = dict(
        (condition_type, dict()) for condition_type in MATCH_LOOKUP)
    all_conditions = dict()

    for condition_type in MATCH_LOOKUP:
        method = 'list_' + MATCH_LOOKUP[condition_type]['method'] + 's'
        all_conditions[condition_type] = dict()
        try:
            paginator = client.get_paginator(method)
            func = paginator.paginate().build_full_result
        except (KeyError, botocore.exceptions.OperationNotPageableError):
            # list_geo_match_sets and list_regex_match_sets do not have a paginator
            # and throw different exceptions
            func = getattr(client, method)
        try:
            pred_results = func()[MATCH_LOOKUP[condition_type]['conditionset']
                                  + 's']
        except (botocore.exceptions.ClientError,
                botocore.exceptions.BotoCoreError) as e:
            module.fail_json_aws(e,
                                 msg='Could not list %s conditions' %
                                 condition_type)
        for pred in pred_results:
            pred['DataId'] = pred[MATCH_LOOKUP[condition_type]['conditionset']
                                  + 'Id']
            all_conditions[condition_type][
                pred['Name']] = camel_dict_to_snake_dict(pred)
            all_conditions[condition_type][
                pred['DataId']] = camel_dict_to_snake_dict(pred)

    for condition in module.params['conditions']:
        desired_conditions[condition['type']][condition['name']] = condition

    reverse_condition_types = dict(
        (v['type'], k) for (k, v) in MATCH_LOOKUP.items())
    for condition in rule['Predicates']:
        existing_conditions[reverse_condition_types[condition['Type']]][
            condition['DataId']] = camel_dict_to_snake_dict(condition)

    insertions = list()
    deletions = list()

    for condition_type in desired_conditions:
        for (condition_name,
             condition) in desired_conditions[condition_type].items():
            if condition_name not in all_conditions[condition_type]:
                module.fail_json(msg="Condition %s of type %s does not exist" %
                                 (condition_name, condition_type))
            condition['data_id'] = all_conditions[condition_type][
                condition_name]['data_id']
            if condition['data_id'] not in existing_conditions[condition_type]:
                insertions.append(format_for_insertion(condition))

    if module.params['purge_conditions']:
        for condition_type in existing_conditions:
            deletions.extend([
                format_for_deletion(condition)
                for condition in existing_conditions[condition_type].values()
                if not all_conditions[condition_type][condition['data_id']]
                ['name'] in desired_conditions[condition_type]
            ])

    changed = bool(insertions or deletions)
    update = {'RuleId': rule_id, 'Updates': insertions + deletions}
    if changed:
        try:
            run_func_with_change_token_backoff(client,
                                               module,
                                               update,
                                               client.update_rule,
                                               wait=True)
        except (botocore.exceptions.ClientError,
                botocore.exceptions.BotoCoreError) as e:
            module.fail_json_aws(e, msg='Could not update rule conditions')

    return changed, get_rule(client, module, rule_id)