pythonamazon-web-servicesaws-cdkweb-application-firewallamazon-waf

CDK WAF Python Multiple Statement velues error


I have AWS WAF CDK that is working with rules, and now I'm trying to add a rule in WAF with multiple statements, but I'm getting this error:

Resource handler returned message: "Error reason: You have used none or multiple values for a field that requires exactly one value., field: STATEMENT, parameter: Statement (Service: Wafv2, Status Code: 400, Request ID: 6a36bfe2-543c-458a-9571-e929142f5df1, Extended Request ID: null)" (RequestToken: b751ae12-bb60-bb75-86c0-346926687ea4, HandlerErrorCode: InvalidRequest)

My Code:

                {
            'name': 'ruleName',
            'priority': 3,
            'statement': {
                'orStatement': {
                    'statements': [
                        {
                            'iPSetReferenceStatement': {
                                'arn': 'arn:myARN'
                                }
                        },
                                {
                            'iPSetReferenceStatement': {
                                'arn': 'arn:myARN'
                                }
                        }
                ]
                }
                },
                'action': {
                   'allow': {}
            },
              'visibilityConfig': {
                  'sampledRequestsEnabled': True,
                   'cloudWatchMetricsEnabled': True,
                  'metricName': 'ruleName'
               }
              },

Solution

  • There are two things going on there: Firstly, your capitalization is off. iPSetReferenceStatement cannot be parsed and creates an empty statement reference. The correct key is ipSetReferenceStatement.

    However, as mentioned here, there is a jsii implementation bug causing some issues with the IPSetReferenceStatementProperty. This causes it not to be parsed properly resulting in a jsii error when synthesizing.

    You can fix it by using the workaround mentioned in the post.

    Add to your file containing the construct:

    import jsii
    from aws_cdk import aws_wafv2 as wafv2 # just for clarity, you might already have this imported
    
    
    @jsii.implements(wafv2.CfnRuleGroup.IPSetReferenceStatementProperty)
    class IPSetReferenceStatement:
        @property
        def arn(self):
            return self._arn
    
        @arn.setter
        def arn(self, value):
            self._arn = value
    

    Then define your ip reference statement as follows:

    ip_set_ref_stmnt = IPSetReferenceStatement()
    ip_set_ref_stmnt.arn = "arn:aws:..."
    
    ip_set_ref_stmnt_2 = IPSetReferenceStatement()
    ip_set_ref_stmnt_2.arn = "arn:aws:..."
    

    Then in the rules section of the webacl, you can use it as follows:

    ...
                rules=[
                    {
                        'name': 'ruleName',
                        'priority': 3,
                        'statement': {
                            'orStatement': {
                                'statements': [
                                    wafv2.CfnWebACL.StatementProperty(
                                        ip_set_reference_statement=ip_set_ref_stmnt
                                    ),
                                    wafv2.CfnWebACL.StatementProperty(
                                        ip_set_reference_statement=ip_set_ref_stmnt_2
                                    ),
                                ]
                            }
                        },
                        'action': {
                            'allow': {}
                        },
                        'visibilityConfig': {
                            'sampledRequestsEnabled': True,
                            'cloudWatchMetricsEnabled': True,
                            'metricName': 'ruleName'
                        }
                    }
                ]
    ...
    

    This should synthesize your stack as expected.