From a0519b970294e808f391ebe9dc1e45c2155d2b5a Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Tue, 7 Jun 2022 22:25:13 +0200 Subject: [PATCH] wafv2_rule_group - tagging (#1210) wafv2_rule_group - support for managing tags SUMMARY Add support for returning tags Add support for updating tags Add support for purge_tags Add fix for updating description when rules don't change. Ensure description of rule group is returned when updates happen Split integration tests from full wafv2 tests (full tests are broken) ISSUE TYPE Bugfix Pull Request Feature Pull Request COMPONENT NAME wafv2_rule_group wafv2_rule_group_info ADDITIONAL INFORMATION Reviewed-by: Joseph Torcasso Reviewed-by: Mark Chappell --- wafv2_rule_group.py | 77 ++++++++++++++++++++++++---------------- wafv2_rule_group_info.py | 20 +++++++---- 2 files changed, 60 insertions(+), 37 deletions(-) diff --git a/wafv2_rule_group.py b/wafv2_rule_group.py index 179ac2e85f2..5a6cafdf1dd 100644 --- a/wafv2_rule_group.py +++ b/wafv2_rule_group.py @@ -60,10 +60,6 @@ description: - capacity of wafv2 rule group. type: int - tags: - description: - - tags for wafv2 rule group. - type: dict purge_rules: description: - When set to C(no), keep the existing load balancer rules in place. Will modify and add, but will not delete. @@ -73,6 +69,7 @@ extends_documentation_fragment: - amazon.aws.aws - amazon.aws.ec2 +- amazon.aws.tags ''' @@ -213,15 +210,18 @@ from ansible_collections.community.aws.plugins.module_utils.wafv2 import compare_priority_rules from ansible_collections.community.aws.plugins.module_utils.wafv2 import wafv2_list_rule_groups from ansible_collections.community.aws.plugins.module_utils.wafv2 import wafv2_snake_dict_to_camel_dict +from ansible_collections.community.aws.plugins.module_utils.wafv2 import describe_wafv2_tags +from ansible_collections.community.aws.plugins.module_utils.wafv2 import ensure_wafv2_tags class RuleGroup: def __init__(self, wafv2, name, scope, fail_json_aws): self.wafv2 = wafv2 + self.id = None self.name = name self.scope = scope self.fail_json_aws = fail_json_aws - self.existing_group, self.id, self.locktoken = self.get_group() + self.existing_group = self.get_group() def update(self, description, rules, sampled_requests, cloudwatch_metrics, metric_name): req_obj = { @@ -244,32 +244,38 @@ def update(self, description, rules, sampled_requests, cloudwatch_metrics, metri response = self.wafv2.update_rule_group(**req_obj) except (BotoCoreError, ClientError) as e: self.fail_json_aws(e, msg="Failed to update wafv2 rule group.") - return response + return self.refresh_group() def get_group(self): - response = self.list() - id = None - locktoken = None - arn = None + if self.id is None: + response = self.list() + + for item in response.get('RuleGroups'): + if item.get('Name') == self.name: + self.id = item.get('Id') + self.locktoken = item.get('LockToken') + self.arn = item.get('ARN') - for item in response.get('RuleGroups'): - if item.get('Name') == self.name: - id = item.get('Id') - locktoken = item.get('LockToken') - arn = item.get('ARN') + return self.refresh_group() + def refresh_group(self): existing_group = None - if id: + if self.id: try: - existing_group = self.wafv2.get_rule_group( + response = self.wafv2.get_rule_group( Name=self.name, Scope=self.scope, - Id=id + Id=self.id ) + existing_group = response.get('RuleGroup') + self.locktoken = response.get('LockToken') except (BotoCoreError, ClientError) as e: self.fail_json_aws(e, msg="Failed to get wafv2 rule group.") - return existing_group, id, locktoken + tags = describe_wafv2_tags(self.wafv2, self.arn, self.fail_json_aws) + existing_group['tags'] = tags or {} + + return existing_group def list(self): return wafv2_list_rule_groups(self.wafv2, self.scope, self.fail_json_aws) @@ -315,7 +321,7 @@ def create(self, capacity, description, rules, sampled_requests, cloudwatch_metr except (BotoCoreError, ClientError) as e: self.fail_json_aws(e, msg="Failed to create wafv2 rule group.") - self.existing_group, self.id, self.locktoken = self.get_group() + self.existing_group = self.get_group() return self.existing_group @@ -332,8 +338,9 @@ def main(): sampled_requests=dict(type='bool', default=False), cloudwatch_metrics=dict(type='bool', default=True), metric_name=dict(type='str'), - tags=dict(type='dict'), - purge_rules=dict(default=True, type='bool') + tags=dict(type='dict', aliases=['resource_tags']), + purge_tags=dict(default=True, type='bool'), + purge_rules=dict(default=True, type='bool'), ) module = AnsibleAWSModule( @@ -352,6 +359,7 @@ def main(): cloudwatch_metrics = module.params.get("cloudwatch_metrics") metric_name = module.params.get("metric_name") tags = module.params.get("tags") + purge_tags = module.params.get("purge_tags") purge_rules = module.params.get("purge_rules") check_mode = module.check_mode @@ -363,17 +371,24 @@ def main(): if not metric_name: metric_name = name - rule_group = RuleGroup(module.client('wafv2'), name, scope, module.fail_json_aws) + wafv2 = module.client('wafv2') + rule_group = RuleGroup(wafv2, name, scope, module.fail_json_aws) change = False retval = {} if state == 'present': if rule_group.get(): - change, rules = compare_priority_rules(rule_group.get().get('RuleGroup').get('Rules'), rules, purge_rules, state) - change = change or rule_group.get().get('RuleGroup').get('Description') != description - - if change and not check_mode: + tagging_change = ensure_wafv2_tags(wafv2, rule_group.arn, tags, purge_tags, + module.fail_json_aws, module.check_mode) + rules_change, rules = compare_priority_rules(rule_group.get().get('Rules'), rules, purge_rules, state) + description_change = bool(description) and (rule_group.get().get('Description') != description) + change = tagging_change or rules_change or description_change + retval = rule_group.get() + if module.check_mode: + # In check mode nothing changes... + pass + elif rules_change or description_change: retval = rule_group.update( description, rules, @@ -381,8 +396,8 @@ def main(): cloudwatch_metrics, metric_name ) - else: - retval = rule_group.get().get('RuleGroup') + elif tagging_change: + retval = rule_group.refresh_group() else: change = True @@ -401,7 +416,7 @@ def main(): if rule_group.get(): if rules: if len(rules) > 0: - change, rules = compare_priority_rules(rule_group.get().get('RuleGroup').get('Rules'), rules, purge_rules, state) + change, rules = compare_priority_rules(rule_group.get().get('Rules'), rules, purge_rules, state) if change and not check_mode: retval = rule_group.update( description, @@ -415,7 +430,7 @@ def main(): if not check_mode: retval = rule_group.remove() - module.exit_json(changed=change, **camel_dict_to_snake_dict(retval)) + module.exit_json(changed=change, **camel_dict_to_snake_dict(retval, ignore_list=['tags'])) if __name__ == '__main__': diff --git a/wafv2_rule_group_info.py b/wafv2_rule_group_info.py index 47d1e68cc55..1daa2dd1cf7 100644 --- a/wafv2_rule_group_info.py +++ b/wafv2_rule_group_info.py @@ -17,9 +17,8 @@ options: state: description: - - Whether the rule is present or absent. - choices: ["present", "absent"] - required: true + - This option does nothing, has been deprecated, and will be removed in a release after 2022-12-01. + required: false type: str name: description: @@ -34,8 +33,8 @@ type: str extends_documentation_fragment: -- amazon.aws.aws -- amazon.aws.ec2 + - amazon.aws.aws + - amazon.aws.ec2 ''' @@ -102,6 +101,7 @@ from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule from ansible_collections.amazon.aws.plugins.module_utils.ec2 import camel_dict_to_snake_dict from ansible_collections.community.aws.plugins.module_utils.wafv2 import wafv2_list_rule_groups +from ansible_collections.community.aws.plugins.module_utils.wafv2 import describe_wafv2_tags def get_rule_group(wafv2, name, scope, id, fail_json_aws): @@ -118,7 +118,7 @@ def get_rule_group(wafv2, name, scope, id, fail_json_aws): def main(): arg_spec = dict( - state=dict(type='str', required=True, choices=['present', 'absent']), + state=dict(type='str', required=False), name=dict(type='str', required=True), scope=dict(type='str', required=True, choices=['CLOUDFRONT', 'REGIONAL']) ) @@ -134,6 +134,11 @@ def main(): wafv2 = module.client('wafv2') + if state: + module.deprecate( + 'The state parameter does nothing, has been deprecated, and will be removed in a future release.', + version='6.0.0', collection_name='community.aws') + # check if rule group exists response = wafv2_list_rule_groups(wafv2, scope, module.fail_json_aws) id = None @@ -142,11 +147,14 @@ def main(): for item in response.get('RuleGroups'): if item.get('Name') == name: id = item.get('Id') + arn = item.get('ARN') existing_group = None if id: existing_group = get_rule_group(wafv2, name, scope, id, module.fail_json_aws) retval = camel_dict_to_snake_dict(existing_group.get('RuleGroup')) + tags = describe_wafv2_tags(wafv2, arn, module.fail_json_aws) + retval['tags'] = tags or {} module.exit_json(**retval)