aws-pdk icon indicating copy to clipboard operation
aws-pdk copied to clipboard

[FEATURE] Add support for RuleActionOverrides for WAF using TypeSafeApi constructs

Open dbryson opened this issue 1 year ago • 3 comments

Describe the feature

Rule Action Overrides allow customizing WAF rules. It seems this support is missing from PDK:

https://github.com/aws/aws-pdk/blob/83d1dbfeec047c078b38801b8df2c9e8caf4e9b0/packages/static-website/src/webacl_event_handler/index.ts#L98

Here is a link to Rule Action Overrides: https://docs.aws.amazon.com/waf/latest/APIReference/API_RuleActionOverride.html

Use Case

The current configuration lets me specify which WAF rule I wish to use:

Api(self, id, web_acl_options=TypeSafeApiWebAclOptions( cidr_allow_list=CidrAllowList( cidr_type="IPV4", cidr_ranges=["1.2.3.4/5"] ), managed_rules=[ManagedRule(vendor="AWS", name="AWSManagedRulesSQLiRuleSet")] ), ... )

But it doesn't provide the ability to customize the managed rule, despite the documentation indicating it supports these fields:

`import aws.pdk.type_safe_api

aws.pdk.type_safe_api.ManagedRule( name: str, excluded_rules: typing.Union[IResolvable, typing.List[typing.Union[IResolvable, ExcludedRuleProperty]]] = None, managed_rule_group_configs: typing.Union[IResolvable, typing.List[typing.Union[IResolvable, ManagedRuleGroupConfigProperty]]] = None, rule_action_overrides: typing.Union[IResolvable, typing.List[typing.Union[IResolvable, RuleActionOverrideProperty]]] = None, scope_down_statement: typing.Union[IResolvable, StatementProperty] = None, version: str = None, vendor: str = None, vendor_name: str = None )`

Proposed Solution

Add support for the additional arguments.

Other Information

No response

Acknowledgements

  • [ ] I may be able to implement this feature request
  • [ ] This feature might incur a breaking change

PDK version used

0.23.43

What languages will this feature affect?

Python

Environment details (OS name and version, etc.)

MacOS, Sonoma 14.3

dbryson avatar Jun 28 '24 22:06 dbryson

This issue is now marked as stale because it hasn't seen activity for a while. Add a comment or it will be closed soon. If you wish to exclude this issue from being marked as stale, add the "backlog" label.

github-actions[bot] avatar Sep 02 '24 00:09 github-actions[bot]

Closing this issue as it hasn't seen activity for a while. Please add a comment @mentioning a maintainer to reopen. If you wish to exclude this issue from being marked as stale, add the "backlog" label.

github-actions[bot] avatar Sep 09 '24 00:09 github-actions[bot]

Hi David,

Sorry this was auto-closed - just back from leave!

The code you linked here is for the static website web ACL, but your issue is mentioning Type Safe API's web ACL - I just wanted to check that it's the Type Safe API one you're having issues with?

The rule action overrides should be configurable for Type Safe API - support was added in https://github.com/aws/aws-pdk/pull/712

I notice you're using python - do you definitely have the dependency on PDK 0.23.43 in your python infrastructure package?

Cheers, Jack

cogwirrel avatar Sep 17 '24 04:09 cogwirrel

Hey @dbryson!

Hope you're well! :)

Had a bit of time to look at this again just now - I was able to customise rule action overrides in Python with the following:

from constructs import Construct
from api_python_infra.api import Api
from api_python_infra.mock_integrations import MockIntegrations
from aws_cdk import Stack
from aws_pdk.identity import UserIdentity
from aws_pdk.type_safe_api import Authorizers, TypeSafeApiWebAclOptions, ManagedRule
from aws_cdk.aws_apigateway import CorsOptions, Cors
from aws_cdk.aws_wafv2 import CfnWebACL
from aws_cdk.aws_iam import AccountPrincipal, AnyPrincipal, Effect, PolicyDocument, PolicyStatement

# Infrastructure construct to deploy a Type Safe API.
class MyApi(Construct):
    def __init__(self, scope: Construct, id: str, user_identity: UserIdentity, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        self.api = Api(self, id,
            default_authorizer=Authorizers.iam(),
            cors_options=CorsOptions(
                allow_origins=Cors.ALL_ORIGINS,
                allow_methods=Cors.ALL_METHODS
            ),
            integrations=MockIntegrations.mock_all(),
            web_acl_options=TypeSafeApiWebAclOptions(
                managed_rules=[
                    ManagedRule(
                        vendor_name="AWS",
                        name="AWSManagedRulesCommonRuleSet",
                        rule_action_overrides=[
                            CfnWebACL.RuleActionOverrideProperty(
                                name="SizeRestrictions_BODY",
                                action_to_use=CfnWebACL.RuleActionProperty(
                                    allow={}
                                )
                            )
                        ]
                    )
                ]
            ),
            policy=PolicyDocument(
                statements=[
                    # Here we grant any AWS credentials from the account that the prototype is deployed in to call the api.
                    # Machine to machine fine-grained access can be defined here using more specific principals (eg roles or
                    # users) and resources (ie which api paths may be invoked by which principal) if required.
                    # If doing so, the cognito identity pool authenticated role must still be granted access for cognito users to
                    # still be granted access to the API.
                    PolicyStatement(
                        effect=Effect.ALLOW,
                        principals=[AccountPrincipal(Stack.of(self).account)],
                        actions=['execute-api:Invoke'],
                        resources=['execute-api:/*']
                    ),
                    # Open up OPTIONS to allow browsers to make unauthenticated preflight requests
                    PolicyStatement(
                        effect=Effect.ALLOW,
                        principals=[AnyPrincipal()],
                        actions=['execute-api:Invoke'],
                        resources=['execute-api:/*/OPTIONS/*']
                    )
                ]
            ))

        user_identity.identity_pool.authenticated_role.add_to_principal_policy(
            PolicyStatement(
                effect=Effect.ALLOW,
                actions=['execute-api:Invoke'],
                resources=[self.api.api.arn_for_execute_api('*', '/*', '*')]
            )
        )

I'm going to close this, but feel free to reopen if there's still something missing :)

Cheers, Jack

cogwirrel avatar Oct 22 '24 00:10 cogwirrel