Aws-cdk: cfn2ts: some property types are parsed as interfaces instead of structs

Created on 9 Mar 2020  路  7Comments  路  Source: aws/aws-cdk

Using the python cdk, attempting to create a Web ACL with an IP whitelisting rule, but found that creating Web ACL rule properties does not work when trying to define an IP Set. I receive an error stating:
TypeError: Protocols cannot be instantiated

Reproduction Steps

       # Working rule prop, with aws managed rule group
       rule_sql = wafv2.CfnWebACL.RuleProperty(
            name='AWS-AWSManagedRulesSQLRuleSet',
            statement=wafv2.CfnWebACL.StatementOneProperty(
                managed_rule_group_statement=wafv2.CfnWebACL.ManagedRuleGroupStatementProperty(
                    vendor_name='AWS',
                    name='AWSManagedRulesSQLRuleSet'
                )
            ),
            visibility_config=wafv2.CfnWebACL.VisibilityConfigProperty(
                sampled_requests_enabled=True,
                cloud_watch_metrics_enabled=True,
                metric_name='AWS-AWSManagedRulesSQLRuleSet'
            ),
            priority=0,
        )

        # Non-working rule prop, with IP set reference
        rule_ip = wafv2.CfnWebACL.RuleProperty(
            name='IPRule',
            statement=wafv2.CfnWebACL.StatementOneProperty(
                ip_set_reference_statement=wafv2.CfnWebACL.IPSetReferenceStatementProperty(
                    arn='myArn'
                )
            ),
            visibility_config=wafv2.CfnWebACL.VisibilityConfigProperty(
                sampled_requests_enabled=True,
                cloud_watch_metrics_enabled=True,
                metric_name='IPRule'
            ),
            priority=0,
        )

Error Log

When synthing templates, this error is received:

File "...\infra\cdk.env\lib\site-packages\jsii_runtime.py", line 66, in __call__
inst = super().__call__(args, *kwargs)
File "...\infra\cdk\stacks\stacks_lib\static_site_hosting.py", line 56, in __init__
arn='myArn'
File "...\infra\cdk.env\lib\site-packages\typing_extensions.py", line 1545, in _no_init
raise TypeError('Protocols cannot be instantiated')
TypeError: Protocols cannot be instantiated

Environment

  • CLI Version :
  • Framework Version: 1.27
  • OS : Windows
  • Language : Python

Other

Linked somewhat to: https://github.com/aws/aws-cdk/issues/6056


This is :bug: Bug Report

@aws-cdaws-wafv2 @aws-cdcfnspec bug efforsmall p1

Most helpful comment

As a workaround, I was able to implement the IPSetReferenceStatementProperty interface myself in python like so:

        @jsii.implements(wafv2.CfnRuleGroup.IPSetReferenceStatementProperty)
        class IPSetReferenceStatement:
            @property
            def arn(self):
                return self._arn

            @arn.setter
            def arn(self, value):
                self._arn = value

And then reference that new class instead:

        ip_set_ref_stmnt = IPSetReferenceStatement()
        ip_set_ref_stmnt.arn = whitelisted_ip_set.attr_arn

        # Non-working rule prop, with IP set reference
        whitelisted_ip_set_rule = wafv2.CfnWebACL.RuleProperty(
            name='AllowedIPsRule',
            statement=wafv2.CfnWebACL.StatementOneProperty(
                ip_set_reference_statement=ip_set_ref_stmnt
            ),
            visibility_config=wafv2.CfnWebACL.VisibilityConfigProperty(
                sampled_requests_enabled=True,
                cloud_watch_metrics_enabled=True,
                metric_name='AllowedIPsRule'
            ),
            priority=0,
        )

At which point, I am able to CDK synth the template, and it captures the proper reference to the IP Set Reference Statement.

All 7 comments

As a workaround, I was able to implement the IPSetReferenceStatementProperty interface myself in python like so:

        @jsii.implements(wafv2.CfnRuleGroup.IPSetReferenceStatementProperty)
        class IPSetReferenceStatement:
            @property
            def arn(self):
                return self._arn

            @arn.setter
            def arn(self, value):
                self._arn = value

And then reference that new class instead:

        ip_set_ref_stmnt = IPSetReferenceStatement()
        ip_set_ref_stmnt.arn = whitelisted_ip_set.attr_arn

        # Non-working rule prop, with IP set reference
        whitelisted_ip_set_rule = wafv2.CfnWebACL.RuleProperty(
            name='AllowedIPsRule',
            statement=wafv2.CfnWebACL.StatementOneProperty(
                ip_set_reference_statement=ip_set_ref_stmnt
            ),
            visibility_config=wafv2.CfnWebACL.VisibilityConfigProperty(
                sampled_requests_enabled=True,
                cloud_watch_metrics_enabled=True,
                metric_name='AllowedIPsRule'
            ),
            priority=0,
        )

At which point, I am able to CDK synth the template, and it captures the proper reference to the IP Set Reference Statement.

Ha!

Because of JSII naming conventions, IPSetReferenceStatementProperty will be interpreted as an interface, where it actually should be interpreted as a struct.

Our cfn2ts tool should have converted the name to IpSet (and probably WebACL => WebAcl).

In fact it should be an error if any of the L1 generators generate any class that JSII will interpret as an interface. It should be all classes and structs, no?

Since I'm still having issues with https://github.com/aws/aws-cdk/issues/6056, could this be related?

I am also facing this issue with error message TypeError: Protocols cannot be instantiated when using ipset_reference_statement=waf.CfnRuleGroup.IPSetReferenceStatementProperty(arn="arn:XXXXXXXXX".
IS there any ETA when this will be resolved.

As a workaround, I was able to implement the IPSetReferenceStatementProperty interface myself in python like so:

        @jsii.implements(wafv2.CfnRuleGroup.IPSetReferenceStatementProperty)
        class IPSetReferenceStatement:
            @property
            def arn(self):
                return self._arn

            @arn.setter
            def arn(self, value):
                self._arn = value

And then reference that new class instead:

        ip_set_ref_stmnt = IPSetReferenceStatement()
        ip_set_ref_stmnt.arn = whitelisted_ip_set.attr_arn

        # Non-working rule prop, with IP set reference
        whitelisted_ip_set_rule = wafv2.CfnWebACL.RuleProperty(
            name='AllowedIPsRule',
            statement=wafv2.CfnWebACL.StatementOneProperty(
                ip_set_reference_statement=ip_set_ref_stmnt
            ),
            visibility_config=wafv2.CfnWebACL.VisibilityConfigProperty(
                sampled_requests_enabled=True,
                cloud_watch_metrics_enabled=True,
                metric_name='AllowedIPsRule'
            ),
            priority=0,
        )

At which point, I am able to CDK synth the template, and it captures the proper reference to the IP Set Reference Statement.

Thanks @KyleMuellerPFG - this enabled me to get an IP set working!

If anyone else finds this issue, note too that your IP rule can't contain the override_action parameter, or you'll get the error "Error reason: Your statement has multiple values set for a field that requires exactly one value., field: RULE," - because this is only valid for statements that refer to rule groups.

Was this page helpful?
0 / 5 - 0 ratings