community.aws icon indicating copy to clipboard operation
community.aws copied to clipboard

wafv2_web_acl - When using a variable in the `limit` configuration or a rule, it complains that it a string and not an int

Open dj-wasabi opened this issue 2 years ago • 4 comments
trafficstars

Summary

When using a variable in the limit configuration or a rule, it complains that it a string and not an int. If I hardcode it to an int, all goes fine.

Issue Type

Bug Report

Component Name

wafv2_web_acl

Ansible Version

$ ansible --version
ansible [core 2.14.3]
  config file = /Users/wdijkerman/code/bitbucket.org/COERA_Fintech/easytrade/treasurup-deployment/ansible/ansible.cfg
  configured module search path = ['/Users/wdijkerman/code/bitbucket.org/COERA_Fintech/easytrade/treasurup-deployment/ansible/library']
  ansible python module location = /Users/wdijkerman/.venv3101/lib/python3.10/site-packages/ansible
  ansible collection location = /Users/wdijkerman/.ansible/collections:/usr/share/ansible/collections
  executable location = /Users/wdijkerman/.venv3101/bin/ansible
  python version = 3.10.1 (v3.10.1:2cd268a3a9, Dec  6 2021, 14:28:59) [Clang 13.0.0 (clang-1300.0.29.3)] (/Users/wdijkerman/.venv3101/bin/python)
  jinja version = 3.0.3
  libyaml = True

Collection Versions

$ ansible-galaxy collection list

# /Users/wdijkerman/.ansible/collections/ansible_collections
Collection                          Version
----------------------------------- -------
StephenSorriaux.ansible_kafka_admin 0.15.4
amazon.aws                          5.4.0
ansible.netcommon                   4.1.0
ansible.posix                       1.5.2
ansible.utils                       2.9.0
ansible.windows                     1.3.0
azure.azcollection                  1.10.0
community.aws                       5.4.0
community.crypto                    2.11.1
community.docker                    2.0.2
community.general                   3.2.0
community.hashi_vault               4.2.0
community.mongodb                   1.5.2
community.mysql                     3.6.0
community.postgresql                2.3.2
community.zabbix                    1.9.3

AWS SDK versions

$ pip show boto boto3 botocore

WARNING: Package(s) not found: boto
Name: boto3
Version: 1.26.79
Summary: The AWS SDK for Python
Home-page: https://github.com/boto/boto3
Author: Amazon Web Services
Author-email:
License: Apache License 2.0
Location: /Users/wdijkerman/.venv3101/lib/python3.10/site-packages
Requires: botocore, jmespath, s3transfer
Required-by: checkov, cloudsplaining, prowler
---
Name: botocore
Version: 1.29.79
Summary: Low-level, data-driven core of boto 3.
Home-page: https://github.com/boto/botocore
Author: Amazon Web Services
Author-email:
License: Apache License 2.0
Location: /Users/wdijkerman/.venv3101/lib/python3.10/site-packages
Requires: jmespath, python-dateutil, urllib3
Required-by: boto3, cloudsplaining, prowler, s3transfer

Configuration

$ ansible-config dump --only-changed
CONFIG_FILE() = /Users/wdijkerman/code/my-path-to-repo/ansible/ansible.cfg
DEFAULT_MODULE_PATH(/Users/wdijkerman/code/my-path-to-repo/ansible/ansible.cfg) = ['/Users/wdijkerman/code/my-path-to-repo/ansible/library']
DEFAULT_ROLES_PATH(/Users/wdijkerman/code/my-path-to-repo/ansible/ansible.cfg) = ['/Users/wdijkerman/code/my-path-to-repo/ansible/roles']
HOST_KEY_CHECKING(/Users/wdijkerman/code/my-path-to-repo/ansible/ansible.cfg) = False
INTERPRETER_PYTHON(/Users/wdijkerman/code/my-path-to-repo/ansible/ansible.cfg) = /usr/bin/python3
INVENTORY_ANY_UNPARSED_IS_FAILED(/Users/wdijkerman/code/my-path-to-repo/ansible/ansible.cfg) = False
RETRY_FILES_ENABLED(/Users/wdijkerman/code/my-path-to-repo/ansible/ansible.cfg) = False

OS / Environment

Amazon Linux 2

Steps to Reproduce


- name: Create or change Web Application Firewall with custom rules and AWS managed rules
  community.aws.wafv2_web_acl:
    name: "my-amazing-waf"
    region: "eu-west-1"
    state: present
    description: Web Application Firewall
    scope: REGIONAL
    default_action: Allow
    sampled_requests: yes
    cloudwatch_metrics: no
    metric_name: ""
    rules:
      - name: Request-rate-limiter
        priority: 1
        action:
          block: { }
        visibility_config:
          sampled_requests_enabled: yes
          cloud_watch_metrics_enabled: yes
          metric_name: Request-rate-limiter
        statement:
          rate_based_statement:
            limit: "{{ waf_rate_request_limit_value | default(1500) | int }}"
            aggregate_key_type: IP

Executing fails. If I would hardcode limit to 1500, then all will be fine. When I have set somewhere in the group_vars waf_rate_request_limit_value: 1500 it fails with the same error.

Expected Results

I expected that the rule is created.

Actual Results

An exception occurred during task execution. To see the full traceback, use -vvv. The error was: Invalid type for parameter Rules[0].Statement.RateBasedStatement.Limit, value: 1500, type: <class 'str'>, valid types: <class 'int'>
fatal: [ip-10-2-52-10.eu-west-1.compute.internal]: FAILED! => {"boto3_version": "1.24.80", "botocore_version": "1.27.80", "changed": false, "msg": "Failed to create wafv2 web acl.: Parameter validation failed:\nInvalid type for parameter Rules[0].Statement.RateBasedStatement.Limit, value: 1500, type: <class 'str'>, valid types: <class 'int'>"}

Code of Conduct

  • [X] I agree to follow the Ansible Code of Conduct

dj-wasabi avatar Apr 19 '23 09:04 dj-wasabi

+1

We are seeing the exact same issue with more up to date versions.

$ ansible-galaxy collection list --collections-path /home/controller/.ansible/collections/ansible_collections
# /home/controller/.ansible/collections/ansible_collections
Collection            Version
--------------------- -------
amazon.aws            7.1.0  
ansible.posix         1.5.4  
ansible.utils         3.0.0  
ansible.windows       2.2.0  
community.aws         7.0.0  
community.general     8.1.0  
community.sops        1.6.7  
prometheus.prometheus 0.10.0 

I'm not sure how this value is getting cast as a string. In our defaults it looks like this, clearly cast as an integer:

waf:
  cloud_front_arn: "arn:something/123456"
  rate_limit: 600

We even tried this in our role but it made no difference:

      # Rate Limit
      - name: rate_limit
        priority: 2
        action:
          block: {}
        visibility_config:
          sampled_requests_enabled: true
          cloud_watch_metrics_enabled: true
          metric_name: rate_limit
        statement:
          rate_based_statement:
            limit: "{{ waf.rate_limit | int }}"
            aggregate_key_type: IP

gregharvey avatar Dec 19 '23 10:12 gregharvey

It feels related to jinja templating issues, which I've come across before and there's a good explanation here:

  • https://github.com/ansible/ansible/issues/17992#issuecomment-253837999

But I don't quite understand why it's a particular issue with this module. Maybe other modules defend against this sort of case?

gregharvey avatar Dec 19 '23 10:12 gregharvey

Hmmm, we set the values as integers also in roles/wafv2/defaults/main.yml and we're not hitting this error.

markuman avatar Dec 19 '23 12:12 markuman

It's really weird. We have worked around it like this for now:

vars

aws_waf:
  cloud_front_arn: "arn:aws:cloudfront::123456:distribution/ABCDEFGH"
  acl_name: "dummy_master_acl"
  rate_limit: 600

role

# Workaround for rate limit rule in ACL (any variable gets interpreted as string instead of int)
- name: Set rate_limit variable
  ansible.builtin.set_fact:
    rate_limit: "{{ aws_waf.rate_limit }}"

# then further down in module call where we add rules:
      # Rate Limit
      - name: rate_limit
        priority: 2
        action:
          block: {}
        visibility_config:
          sampled_requests_enabled: true
          cloud_watch_metrics_enabled: true
          metric_name: rate_limit
        statement:
          rate_based_statement:
            limit: "{{ rate_limit }}"
            aggregate_key_type: IP

That works. No idea why we can't set it in defaults, we've tried everything!

gregharvey avatar Dec 19 '23 17:12 gregharvey