From b34953eeb83baf0584c45d09cd4a252af1dbdec7 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Fri, 3 Jun 2022 20:54:11 +0200 Subject: [PATCH] wafv2_rule_group - tagging --- .../1210-tagging-wafv2_rule_group.yml | 8 + plugins/modules/wafv2_rule_group.py | 79 +- plugins/modules/wafv2_rule_group_info.py | 20 +- .../targets/wafv2_rule_group/aliases | 3 + .../wafv2_rule_group/defaults/main.yml | 11 + .../targets/wafv2_rule_group/meta/main.yml | 1 + .../wafv2_rule_group/tasks/description.yml | 131 ++++ .../targets/wafv2_rule_group/tasks/main.yml | 731 ++++++++++++++++++ .../wafv2_rule_group/tasks/tagging.yml | 256 ++++++ 9 files changed, 1203 insertions(+), 37 deletions(-) create mode 100644 changelogs/fragments/1210-tagging-wafv2_rule_group.yml create mode 100644 tests/integration/targets/wafv2_rule_group/aliases create mode 100644 tests/integration/targets/wafv2_rule_group/defaults/main.yml create mode 100644 tests/integration/targets/wafv2_rule_group/meta/main.yml create mode 100644 tests/integration/targets/wafv2_rule_group/tasks/description.yml create mode 100644 tests/integration/targets/wafv2_rule_group/tasks/main.yml create mode 100644 tests/integration/targets/wafv2_rule_group/tasks/tagging.yml diff --git a/changelogs/fragments/1210-tagging-wafv2_rule_group.yml b/changelogs/fragments/1210-tagging-wafv2_rule_group.yml new file mode 100644 index 00000000000..b01727dd73e --- /dev/null +++ b/changelogs/fragments/1210-tagging-wafv2_rule_group.yml @@ -0,0 +1,8 @@ +bugfixes: +- wafv2_rule_group - fix bug where updating just the description did not update the changed state (https://github.com/ansible-collections/community.aws/pull/1210). +- wafv2_rule_group - fix bug where description of resource state was missing when rule groups were updated (https://github.com/ansible-collections/community.aws/pull/1210). +minor_changes: +- wafv2_rule_group - Added support for ``purge_tags`` parameter (https://github.com/ansible-collections/community.aws/pull/1210). +- wafv2_rule_group - Added support for updating tags (https://github.com/ansible-collections/community.aws/pull/1210). +- wafv2_rule_group - Added support for returning tags (https://github.com/ansible-collections/community.aws/pull/1210). +- wafv2_rule_group_info - Added support for returning tags (https://github.com/ansible-collections/community.aws/pull/1210). diff --git a/plugins/modules/wafv2_rule_group.py b/plugins/modules/wafv2_rule_group.py index 179ac2e85f2..e396b7783b5 100644 --- a/plugins/modules/wafv2_rule_group.py +++ b/plugins/modules/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,39 @@ 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') + + return self.refresh_group() - for item in response.get('RuleGroups'): - if item.get('Name') == self.name: - id = item.get('Id') - locktoken = item.get('LockToken') - arn = item.get('ARN') + 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 +322,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 +339,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 +360,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 +372,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 +397,9 @@ 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 +418,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 +432,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/plugins/modules/wafv2_rule_group_info.py b/plugins/modules/wafv2_rule_group_info.py index 47d1e68cc55..1daa2dd1cf7 100644 --- a/plugins/modules/wafv2_rule_group_info.py +++ b/plugins/modules/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) diff --git a/tests/integration/targets/wafv2_rule_group/aliases b/tests/integration/targets/wafv2_rule_group/aliases new file mode 100644 index 00000000000..2c61ab765e7 --- /dev/null +++ b/tests/integration/targets/wafv2_rule_group/aliases @@ -0,0 +1,3 @@ +cloud/aws + +wafv2_rule_group_info diff --git a/tests/integration/targets/wafv2_rule_group/defaults/main.yml b/tests/integration/targets/wafv2_rule_group/defaults/main.yml new file mode 100644 index 00000000000..ac23638ca83 --- /dev/null +++ b/tests/integration/targets/wafv2_rule_group/defaults/main.yml @@ -0,0 +1,11 @@ +--- +web_acl_name: '{{ tiny_prefix }}-web-acl' +rule_group_name: '{{ tiny_prefix }}-rule-group' +alb_name: "my-alb-{{ tiny_prefix }}" +tg_name: "my-tg-{{ tiny_prefix }}" +cidr: + main: 10.228.228.0/22 + a: 10.228.228.0/24 + b: 10.228.229.0/24 + c: 10.228.230.0/24 + d: 10.228.231.0/24 diff --git a/tests/integration/targets/wafv2_rule_group/meta/main.yml b/tests/integration/targets/wafv2_rule_group/meta/main.yml new file mode 100644 index 00000000000..32cf5dda7ed --- /dev/null +++ b/tests/integration/targets/wafv2_rule_group/meta/main.yml @@ -0,0 +1 @@ +dependencies: [] diff --git a/tests/integration/targets/wafv2_rule_group/tasks/description.yml b/tests/integration/targets/wafv2_rule_group/tasks/description.yml new file mode 100644 index 00000000000..e20eed58ed3 --- /dev/null +++ b/tests/integration/targets/wafv2_rule_group/tasks/description.yml @@ -0,0 +1,131 @@ +- name: Tests relating to setting the descriptions of wavf2_ip_sets + vars: + description_one: 'a Description - {{ resource_prefix }}' + description_two: 'Another_Description - {{ resource_prefix }}' + # Mandatory settings + module_defaults: + community.aws.wafv2_rule_group: + name: '{{ rule_group_name }}' + state: present + scope: REGIONAL + purge_rules: no + rules: [] + capacity: 500 + community.aws.wafv2_rule_group_info: + name: '{{ rule_group_name }}' + scope: REGIONAL + block: + + - name: test setting description wafv2_rule_group (check mode) + wafv2_rule_group: + description: '{{ description_one }}' + register: update_result + check_mode: yes + - name: assert that update succeeded + assert: + that: + - update_result is changed + + - name: test setting description wafv2_rule_group + wafv2_rule_group: + description: '{{ description_one }}' + register: update_result + - name: assert that update succeeded + assert: + that: + - update_result is changed + - update_result.description == description_one + + - name: test setting description wafv2_rule_group - idempotency (check mode) + wafv2_rule_group: + description: '{{ description_one }}' + register: update_result + check_mode: yes + - name: assert that update succeeded + assert: + that: + - update_result is not changed + + - name: test setting description wafv2_rule_group - idempotency + wafv2_rule_group: + description: '{{ description_one }}' + register: update_result + - name: assert that update succeeded + assert: + that: + - update_result is not changed + - update_result.description == description_one + + ### + + - name: test updating description on wafv2_rule_group (check mode) + wafv2_rule_group: + description: '{{ description_two }}' + register: update_result + check_mode: yes + - name: assert that update succeeded + assert: + that: + - update_result is changed + + - name: test updating description on wafv2_rule_group + wafv2_rule_group: + description: '{{ description_two }}' + register: update_result + - name: assert that update succeeded + assert: + that: + - update_result is changed + - update_result.description == description_two + + - name: test updating description on wafv2_rule_group - idempotency (check mode) + wafv2_rule_group: + description: '{{ description_two }}' + register: update_result + check_mode: yes + - name: assert that update succeeded + assert: + that: + - update_result is not changed + + - name: test updating description on wafv2_rule_group - idempotency + wafv2_rule_group: + description: '{{ description_two }}' + register: update_result + - name: assert that update succeeded + assert: + that: + - update_result is not changed + - update_result.description == description_two + + ### + + - name: test that wafv2_rule_group_info returns the description + wafv2_rule_group_info: + register: tag_info + - name: assert description present + assert: + that: + - tag_info.description == description_two + + ### + + - name: test no description param wafv2_rule_group (check mode) + wafv2_rule_group: {} + register: update_result + check_mode: yes + - name: assert no change + assert: + that: + - update_result is not changed + - update_result.description == description_two + + + - name: test no description param wafv2_rule_group + wafv2_rule_group: {} + register: update_result + - name: assert no change + assert: + that: + - update_result is not changed + - update_result.description == description_two diff --git a/tests/integration/targets/wafv2_rule_group/tasks/main.yml b/tests/integration/targets/wafv2_rule_group/tasks/main.yml new file mode 100644 index 00000000000..630d5de295a --- /dev/null +++ b/tests/integration/targets/wafv2_rule_group/tasks/main.yml @@ -0,0 +1,731 @@ +--- +- module_defaults: + group/aws: + aws_access_key: "{{ aws_access_key }}" + aws_secret_key: "{{ aws_secret_key }}" + security_token: "{{ security_token | default(omit) }}" + region: "{{ aws_region }}" + block: + #################################### + # Create and test rule group + #################################### + - name: check_mode create rule group + wafv2_rule_group: + name: "{{ rule_group_name }}" + state: present + description: hallo eins + scope: REGIONAL + capacity: 500 + rules: + - name: eins + priority: 1 + action: + allow: {} + visibility_config: + sampled_requests_enabled: yes + cloud_watch_metrics_enabled: yes + metric_name: fsd + statement: + byte_match_statement: + search_string: ansible.com + positional_constraint: CONTAINS + field_to_match: + single_header: + name: host + text_transformations: + - type: LOWERCASE + priority: 0 + cloudwatch_metrics: yes + tags: + A: B + C: D + register: out + check_mode: yes + + - name: check_mode verify create + assert: + that: + - out is changed + + - name: create rule group + wafv2_rule_group: + name: "{{ rule_group_name }}" + state: present + description: hallo eins + scope: REGIONAL + capacity: 500 + rules: + - name: eins + priority: 1 + action: + allow: {} + visibility_config: + sampled_requests_enabled: yes + cloud_watch_metrics_enabled: yes + metric_name: fsd + statement: + byte_match_statement: + search_string: ansible.com + positional_constraint: CONTAINS + field_to_match: + single_header: + name: host + text_transformations: + - type: LOWERCASE + priority: 0 + cloudwatch_metrics: yes + tags: + A: B + C: D + register: out + + - name: verify create + assert: + that: + - out is changed + + - name: rule group info + wafv2_rule_group_info: + name: "{{ rule_group_name }}" + state: present + scope: REGIONAL + register: out + + - name: verify one rule + assert: + that: + - out.rules | count == 1 + + - name: immutable create rule group + wafv2_rule_group: + name: "{{ rule_group_name }}" + state: present + description: hallo eins + scope: REGIONAL + capacity: 500 + rules: + - name: eins + priority: 1 + action: + allow: {} + visibility_config: + sampled_requests_enabled: yes + cloud_watch_metrics_enabled: yes + metric_name: fsd + statement: + byte_match_statement: + search_string: ansible.com + positional_constraint: CONTAINS + field_to_match: + single_header: + name: host + text_transformations: + - type: LOWERCASE + priority: 0 + cloudwatch_metrics: yes + tags: + A: B + C: D + register: out + + - name: verify immutable create + assert: + that: + - out is not changed + + - name: change description + wafv2_rule_group: + name: "{{ rule_group_name }}" + state: present + description: hallo eins zwei + scope: REGIONAL + capacity: 500 + rules: + - name: eins + priority: 1 + action: + allow: {} + visibility_config: + sampled_requests_enabled: yes + cloud_watch_metrics_enabled: yes + metric_name: fsd + statement: + byte_match_statement: + search_string: ansible.com + positional_constraint: CONTAINS + field_to_match: + single_header: + name: host + text_transformations: + - type: LOWERCASE + priority: 0 + cloudwatch_metrics: yes + tags: + A: B + C: D + register: out + + - name: verify change + assert: + that: + - out is changed + + - name: iummutable change description + wafv2_rule_group: + name: "{{ rule_group_name }}" + state: present + description: hallo eins zwei + scope: REGIONAL + capacity: 500 + rules: + - name: eins + priority: 1 + action: + allow: {} + visibility_config: + sampled_requests_enabled: yes + cloud_watch_metrics_enabled: yes + metric_name: fsd + statement: + byte_match_statement: + search_string: ansible.com + positional_constraint: CONTAINS + field_to_match: + single_header: + name: host + text_transformations: + - type: LOWERCASE + priority: 0 + cloudwatch_metrics: yes + tags: + A: B + C: D + register: out + + - name: verify no change + assert: + that: + - out is not changed + + - name: add rule + wafv2_rule_group: + name: "{{ rule_group_name }}" + state: present + description: hallo eins zwei + scope: REGIONAL + capacity: 500 + rules: + - name: eins + priority: 1 + action: + allow: {} + visibility_config: + sampled_requests_enabled: yes + cloud_watch_metrics_enabled: yes + metric_name: fsd + statement: + byte_match_statement: + search_string: ansible.com + positional_constraint: CONTAINS + field_to_match: + single_header: + name: host + text_transformations: + - type: LOWERCASE + priority: 0 + - name: zwei + priority: 2 + action: + block: {} + visibility_config: + sampled_requests_enabled: yes + cloud_watch_metrics_enabled: yes + metric_name: ddos + statement: + or_statement: + statements: + - byte_match_statement: + search_string: ansible.com + positional_constraint: CONTAINS + field_to_match: + single_header: + name: host + text_transformations: + - type: LOWERCASE + priority: 0 + - xss_match_statement: + field_to_match: + body: {} + text_transformations: + - type: NONE + priority: 0 + cloudwatch_metrics: yes + tags: + A: B + C: D + register: out + + - name: verify change + assert: + that: + - out is changed + + - name: immutable add rule + wafv2_rule_group: + name: "{{ rule_group_name }}" + state: present + description: hallo eins zwei + scope: REGIONAL + capacity: 500 + rules: + - name: eins + priority: 1 + action: + allow: {} + visibility_config: + sampled_requests_enabled: yes + cloud_watch_metrics_enabled: yes + metric_name: fsd + statement: + byte_match_statement: + search_string: ansible.com + positional_constraint: CONTAINS + field_to_match: + single_header: + name: host + text_transformations: + - type: LOWERCASE + priority: 0 + - name: zwei + priority: 2 + action: + block: {} + visibility_config: + sampled_requests_enabled: yes + cloud_watch_metrics_enabled: yes + metric_name: ddos + statement: + or_statement: + statements: + - byte_match_statement: + search_string: ansible.com + positional_constraint: CONTAINS + field_to_match: + single_header: + name: host + text_transformations: + - type: LOWERCASE + priority: 0 + - xss_match_statement: + field_to_match: + body: {} + text_transformations: + - type: NONE + priority: 0 + cloudwatch_metrics: yes + tags: + A: B + C: D + register: out + + - name: verify no change + assert: + that: + - out is not changed + + - name: change rule + wafv2_rule_group: + name: "{{ rule_group_name }}" + state: present + description: hallo eins zwei + scope: REGIONAL + capacity: 500 + rules: + - name: eins + priority: 1 + action: + allow: {} + visibility_config: + sampled_requests_enabled: yes + cloud_watch_metrics_enabled: yes + metric_name: fsd + statement: + byte_match_statement: + search_string: ansible.com + positional_constraint: CONTAINS + field_to_match: + single_header: + name: host + text_transformations: + - type: LOWERCASE + priority: 0 + - name: zwei + priority: 3 + action: + block: {} + visibility_config: + sampled_requests_enabled: yes + cloud_watch_metrics_enabled: yes + metric_name: ddos + statement: + or_statement: + statements: + - byte_match_statement: + search_string: ansible.com + positional_constraint: CONTAINS + field_to_match: + single_header: + name: host + text_transformations: + - type: LOWERCASE + priority: 0 + - xss_match_statement: + field_to_match: + body: {} + text_transformations: + - type: NONE + priority: 0 + cloudwatch_metrics: yes + tags: + A: B + C: D + register: out + + - name: verify change + assert: + that: + - out is changed + + - name: immutable change rule + wafv2_rule_group: + name: "{{ rule_group_name }}" + state: present + description: hallo eins zwei + scope: REGIONAL + capacity: 500 + rules: + - name: eins + priority: 1 + action: + allow: {} + visibility_config: + sampled_requests_enabled: yes + cloud_watch_metrics_enabled: yes + metric_name: fsd + statement: + byte_match_statement: + search_string: ansible.com + positional_constraint: CONTAINS + field_to_match: + single_header: + name: host + text_transformations: + - type: LOWERCASE + priority: 0 + - name: zwei + priority: 3 + action: + block: {} + visibility_config: + sampled_requests_enabled: yes + cloud_watch_metrics_enabled: yes + metric_name: ddos + statement: + or_statement: + statements: + - byte_match_statement: + search_string: ansible.com + positional_constraint: CONTAINS + field_to_match: + single_header: + name: host + text_transformations: + - type: LOWERCASE + priority: 0 + - xss_match_statement: + field_to_match: + body: {} + text_transformations: + - type: NONE + priority: 0 + cloudwatch_metrics: yes + tags: + A: B + C: D + register: out + + - name: verify no change + assert: + that: + - out is not changed + + - name: change rule again + wafv2_rule_group: + name: "{{ rule_group_name }}" + state: present + description: hallo eins zwei + scope: REGIONAL + capacity: 500 + rules: + - name: zwei + priority: 1 + action: + block: {} + visibility_config: + sampled_requests_enabled: yes + cloud_watch_metrics_enabled: yes + metric_name: ddos + statement: + or_statement: + statements: + - byte_match_statement: + search_string: ansible.com + positional_constraint: CONTAINS + field_to_match: + single_header: + name: host + text_transformations: + - type: LOWERCASE + priority: 0 + - xss_match_statement: + field_to_match: + body: {} + text_transformations: + - type: NONE + priority: 0 + - name: eins + priority: 2 + action: + allow: {} + visibility_config: + sampled_requests_enabled: yes + cloud_watch_metrics_enabled: yes + metric_name: fsd + statement: + byte_match_statement: + search_string: ansible.com + positional_constraint: CONTAINS + field_to_match: + single_header: + name: host + text_transformations: + - type: LOWERCASE + priority: 0 + cloudwatch_metrics: yes + tags: + A: B + C: D + register: out + + - name: verify change + assert: + that: + - out is changed + + - name: add one rule + wafv2_rule_group: + name: "{{ rule_group_name }}" + state: present + description: hallo eins zwei + scope: REGIONAL + capacity: 500 + purge_rules: no + rules: + - name: allow-admin-svg + priority: 3 + action: + allow: {} + visibility_config: + sampled_requests_enabled: yes + cloud_watch_metrics_enabled: yes + metric_name: allow-admin-svg + statement: + byte_match_statement: + search_string: admin.svg + positional_constraint: CONTAINS + field_to_match: + uri_path: {} + text_transformations: + - type: LOWERCASE + priority: 0 + cloudwatch_metrics: yes + tags: + A: B + C: D + register: out + + - name: verify change + assert: + that: + - out is changed + + - name: rule group info + wafv2_rule_group_info: + name: "{{ rule_group_name }}" + state: present + scope: REGIONAL + register: out + + - name: verify create + assert: + that: + - out.rules | count == 3 + + - name: immutable add one rule + wafv2_rule_group: + name: "{{ rule_group_name }}" + state: present + description: hallo eins zwei + scope: REGIONAL + capacity: 500 + purge_rules: no + rules: + - name: allow-admin-svg + priority: 3 + action: + allow: {} + visibility_config: + sampled_requests_enabled: yes + cloud_watch_metrics_enabled: yes + metric_name: allow-admin-svg + statement: + byte_match_statement: + search_string: admin.svg + positional_constraint: CONTAINS + field_to_match: + uri_path: {} + text_transformations: + - type: LOWERCASE + priority: 0 + cloudwatch_metrics: yes + tags: + A: B + C: D + register: out + + - name: verify no change + assert: + that: + - out is not changed + + - name: purge rules + wafv2_rule_group: + name: "{{ rule_group_name }}" + state: present + description: hallo eins zwei + scope: REGIONAL + capacity: 500 + purge_rules: yes + rules: + - name: allow-admin-svg + priority: 3 + action: + allow: {} + visibility_config: + sampled_requests_enabled: yes + cloud_watch_metrics_enabled: yes + metric_name: allow-admin-svg + statement: + byte_match_statement: + search_string: admin.svg + positional_constraint: CONTAINS + field_to_match: + uri_path: {} + text_transformations: + - type: LOWERCASE + priority: 0 + cloudwatch_metrics: yes + tags: + A: B + C: D + register: out + + - name: verify change + assert: + that: + - out is changed + + - name: absent one rule rules + wafv2_rule_group: + name: "{{ rule_group_name }}" + state: absent + description: hallo eins zwei + scope: REGIONAL + rules: + - name: allow-admin-svg + priority: 3 + action: + allow: {} + visibility_config: + sampled_requests_enabled: yes + cloud_watch_metrics_enabled: yes + metric_name: allow-admin-svg + statement: + byte_match_statement: + search_string: admin.svg + positional_constraint: CONTAINS + field_to_match: + uri_path: {} + text_transformations: + - type: LOWERCASE + priority: 0 + register: out + + - name: verify change + assert: + that: + - out is changed + + - name: rule group info + wafv2_rule_group_info: + name: "{{ rule_group_name }}" + state: present + scope: REGIONAL + register: out + + - name: verify change + assert: + that: + - out.rules | count == 0 + + - include_tasks: 'tagging.yml' + - include_tasks: 'description.yml' + + ############################## + # test delete wafv2 resources + ############################## + - name: remove rule group + wafv2_rule_group: + name: "{{ rule_group_name }}" + state: absent + scope: REGIONAL + register: out + + - name: verify change + assert: + that: + - out is changed + + - name: immutable remove rule group + wafv2_rule_group: + name: "{{ rule_group_name }}" + state: absent + scope: REGIONAL + register: out + + - name: verify no change + assert: + that: + - out is not changed + + always: + ################################### + # always delete wafv2 components + ################################### + + - name: take care rule group is removed + wafv2_rule_group: + name: "{{ rule_group_name }}" + state: absent + scope: REGIONAL + ignore_errors: true diff --git a/tests/integration/targets/wafv2_rule_group/tasks/tagging.yml b/tests/integration/targets/wafv2_rule_group/tasks/tagging.yml new file mode 100644 index 00000000000..31a6674ca3a --- /dev/null +++ b/tests/integration/targets/wafv2_rule_group/tasks/tagging.yml @@ -0,0 +1,256 @@ +- name: Tests relating to tagging wavf2_ip_sets + vars: + first_tags: + 'Key with Spaces': Value with spaces + CamelCaseKey: CamelCaseValue + pascalCaseKey: pascalCaseValue + snake_case_key: snake_case_value + second_tags: + 'New Key with Spaces': Value with spaces + NewCamelCaseKey: CamelCaseValue + newPascalCaseKey: pascalCaseValue + new_snake_case_key: snake_case_value + third_tags: + 'Key with Spaces': Value with spaces + CamelCaseKey: CamelCaseValue + pascalCaseKey: pascalCaseValue + snake_case_key: snake_case_value + 'New Key with Spaces': Updated Value with spaces + final_tags: + 'Key with Spaces': Value with spaces + CamelCaseKey: CamelCaseValue + pascalCaseKey: pascalCaseValue + snake_case_key: snake_case_value + 'New Key with Spaces': Updated Value with spaces + NewCamelCaseKey: CamelCaseValue + newPascalCaseKey: pascalCaseValue + new_snake_case_key: snake_case_value + # Mandatory settings + module_defaults: + community.aws.wafv2_rule_group: + name: '{{ rule_group_name }}' + state: present + scope: REGIONAL + purge_rules: no + rules: [] + capacity: 500 + community.aws.wafv2_rule_group_info: + name: '{{ rule_group_name }}' + scope: REGIONAL + block: + + ### + + - name: test adding tags to wafv2_rule_group (check mode) + wafv2_rule_group: + tags: '{{ first_tags }}' + purge_tags: True + register: update_result + check_mode: yes + - name: assert that update succeeded + assert: + that: + - update_result is changed + + - name: test adding tags to wafv2_rule_group + wafv2_rule_group: + tags: '{{ first_tags }}' + purge_tags: True + register: update_result + - name: assert that update succeeded + assert: + that: + - update_result is changed + - update_result.tags == first_tags + + - name: test adding tags to wafv2_rule_group - idempotency (check mode) + wafv2_rule_group: + tags: '{{ first_tags }}' + purge_tags: True + register: update_result + check_mode: yes + - name: assert that update succeeded + assert: + that: + - update_result is not changed + + - name: test adding tags to wafv2_rule_group - idempotency + wafv2_rule_group: + tags: '{{ first_tags }}' + purge_tags: True + register: update_result + - name: assert that update succeeded + assert: + that: + - update_result is not changed + - update_result.tags == first_tags + + ### + + - name: test updating tags with purge on wafv2_rule_group (check mode) + wafv2_rule_group: + tags: '{{ second_tags }}' + purge_tags: True + register: update_result + check_mode: yes + - name: assert that update succeeded + assert: + that: + - update_result is changed + + - name: test updating tags with purge on wafv2_rule_group + wafv2_rule_group: + tags: '{{ second_tags }}' + purge_tags: True + register: update_result + - name: assert that update succeeded + assert: + that: + - update_result is changed + - update_result.tags == second_tags + + - name: test updating tags with purge on wafv2_rule_group - idempotency (check mode) + wafv2_rule_group: + tags: '{{ second_tags }}' + purge_tags: True + register: update_result + check_mode: yes + - name: assert that update succeeded + assert: + that: + - update_result is not changed + + - name: test updating tags with purge on wafv2_rule_group - idempotency + wafv2_rule_group: + tags: '{{ second_tags }}' + purge_tags: True + register: update_result + - name: assert that update succeeded + assert: + that: + - update_result is not changed + - update_result.tags == second_tags + + ### + + - name: test updating tags without purge on wafv2_rule_group (check mode) + wafv2_rule_group: + tags: '{{ third_tags }}' + purge_tags: False + register: update_result + check_mode: yes + - name: assert that update succeeded + assert: + that: + - update_result is changed + + - name: test updating tags without purge on wafv2_rule_group + wafv2_rule_group: + tags: '{{ third_tags }}' + purge_tags: False + register: update_result + - name: assert that update succeeded + assert: + that: + - update_result is changed + - update_result.tags == final_tags + + - name: test updating tags without purge on wafv2_rule_group - idempotency (check mode) + wafv2_rule_group: + tags: '{{ third_tags }}' + purge_tags: False + register: update_result + check_mode: yes + - name: assert that update succeeded + assert: + that: + - update_result is not changed + + - name: test updating tags without purge on wafv2_rule_group - idempotency + wafv2_rule_group: + tags: '{{ third_tags }}' + purge_tags: False + register: update_result + - name: assert that update succeeded + assert: + that: + - update_result is not changed + - update_result.tags == final_tags + + ### + + - name: test that wafv2_rule_group_info returns the tags + wafv2_rule_group_info: + register: tag_info + - name: assert tags present + assert: + that: + - tag_info.tags == final_tags + + ### + + - name: test no tags param wafv2_rule_group (check mode) + wafv2_rule_group: {} + register: update_result + check_mode: yes + - name: assert no change + assert: + that: + - update_result is not changed + - update_result.tags == final_tags + + + - name: test no tags param wafv2_rule_group + wafv2_rule_group: {} + register: update_result + - name: assert no change + assert: + that: + - update_result is not changed + - update_result.tags == final_tags + + ### + + - name: test removing tags from wafv2_rule_group (check mode) + wafv2_rule_group: + tags: {} + purge_tags: True + register: update_result + check_mode: yes + - name: assert that update succeeded + assert: + that: + - update_result is changed + + - name: test removing tags from wafv2_rule_group + wafv2_rule_group: + tags: {} + purge_tags: True + register: update_result + - name: assert that update succeeded + assert: + that: + - update_result is changed + - update_result.tags == {} + + - name: test removing tags from wafv2_rule_group - idempotency (check mode) + wafv2_rule_group: + tags: {} + purge_tags: True + register: update_result + check_mode: yes + - name: assert that update succeeded + assert: + that: + - update_result is not changed + + - name: test removing tags from wafv2_rule_group - idempotency + wafv2_rule_group: + tags: {} + purge_tags: True + register: update_result + - name: assert that update succeeded + assert: + that: + - update_result is not changed + - update_result.tags == {}