aws / aws-cdk

The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code
https://aws.amazon.com/cdk
Apache License 2.0
11.36k stars 3.77k forks source link

`aws_ses`: `ReceiptRuleSet` is not made active automatically #28823

Open ppena-LiveData opened 5 months ago

ppena-LiveData commented 5 months ago

Describe the bug

When an aws_ses.ReceiptRule is created, it is automatically set to enabled, but it's not useful because its parent aws_ses.ReceiptRuleSet is created with a status of Inactive. To fix it, I have to manually go into the AWS Console GUI to change the status of the ReceiptRuleSet to click on the Set as active button.

Expected Behavior

I'd expect the aws_ses.ReceiptRuleSet to be created with a status of Active.

Current Behavior

aws_ses.ReceiptRuleSets are created with a status of Inactive.

Reproduction Steps

Here's an example Python CDK script (which can hopefully be made prettier after https://github.com/aws/aws-cdk/issues/28531 is fixed):

import aws_cdk as cdk
from aws_cdk import App, Environment, Stack
from aws_cdk import aws_cognito as cognito
from aws_cdk import aws_route53 as route_53
from aws_cdk import aws_ses as ses
from aws_cdk import aws_ses_actions as ses_actions
from constructs import Construct

class CognitoStack(Stack):
    def __init__(self, scope: Construct, construct_id: str, route53_hosted_zone: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        identity = ses.EmailIdentity(
            self, 'EmailIdentity',
            identity=ses.Identity.public_hosted_zone(
                route_53.HostedZone.from_lookup(self, 'HostedZone', domain_name=route53_hosted_zone)
            ),
            mail_from_domain=f'mail.{route53_hosted_zone}'
        )

        from_email = f'noreply@{route53_hosted_zone}'
        email_rule_set = ses.ReceiptRuleSet(self, 'EmailRuleSet')
        email_rule_set.add_rule('EmailReceiptNoReply', recipients=[from_email],
                                actions=[ses_actions.Bounce(
                                    sender=from_email, template=ses_actions.BounceTemplate.MAILBOX_DOES_NOT_EXIST)])

        # make sure all the SES identity parts are done before the ReceiptRuleSet tries referencing the identity
        for child in identity.node.children:
            if child.node.default_child:  # this is a higher-level construct, so depend on its children
                for grandchild in child.node.children:
                    email_rule_set.node.add_dependency(grandchild)
            else:
                email_rule_set.node.add_dependency(child)

        user_pool = cognito.UserPool(
            self, 'CognitoUserPool',
            user_pool_name='test-cdk-bug',
            removal_policy=cdk.RemovalPolicy.DESTROY,
            email=cognito.UserPoolEmail.with_ses(
                from_email=from_email,
                from_name='Administrator',
                reply_to='support@example.com',
                ses_verified_domain=route53_hosted_zone,
            )
        )

        # make sure all the SES identity parts are done before the UserPool tries referencing the identity
        for child in identity.node.children:
            if child.node.default_child:  # this is a higher-level construct, so depend on its children
                for grandchild in child.node.children:
                    user_pool.node.add_dependency(grandchild)
            else:
                user_pool.node.add_dependency(child)

app = App()
route53_hosted_zone: str = app.node.try_get_context('route53_hosted_zone')

stack = CognitoStack(
    app, 'CDK-Bug-Test-Cognito', route53_hosted_zone,
    env=Environment(account=app.node.try_get_context('account'), region=app.node.try_get_context('region')),
)

app.synth()

Possible Solution

No response

Additional Information/Context

No response

CDK CLI Version

2.118.0 (build a40f2ec)

Framework Version

No response

Node.js Version

v18.18.2

OS

Windows 11

Language

Python

Language Version

Python 3.11.6

Other information

No response

pahud commented 5 months ago

Thank you. Did you see any way to active that from CloudFormation? Looks like just enable this prop? https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ses-receiptrule-rule.html#cfn-ses-receiptrule-rule-enabled

Can you share the CFN template snippet of this resource when you cdk synth and let us know the value of the Enable prop?

ppena-LiveData commented 5 months ago

@pahud, that documentation is about AWS::SES::ReceiptRule (which CDK is already automatically enabling). I am talking about AWS::SES::ReceiptRuleSet, which is like a parent of ReceiptRules.

markusl commented 2 months ago

@pahud enabled is different from "activated" in SES.

You can use something like this as a workaround:

    // The rule set needs to be activated: https://docs.aws.amazon.com/ses/latest/APIReference/API_SetActiveReceiptRuleSet.html
    const setActiveReceiptRuleSetSdkCall: cr.AwsSdkCall = {
      service: 'SES',
      action: 'setActiveReceiptRuleSet',
      physicalResourceId: cr.PhysicalResourceId.of('SesCustomResource'),
      parameters: {
        RuleSetName: ruleSet.receiptRuleSetName,
      }
    };

    new cr.AwsCustomResource(this, "setActiveReceiptRuleSetCustomResource", {
      onCreate: setActiveReceiptRuleSetSdkCall,
      onUpdate: setActiveReceiptRuleSetSdkCall,
      logRetention: RetentionDays.ONE_WEEK,
      policy: cr.AwsCustomResourcePolicy.fromStatements([
        new iam.PolicyStatement({
          sid: 'SesCustomResourceSetActiveReceiptRuleSet',
          effect: iam.Effect.ALLOW,
          actions: ['ses:SetActiveReceiptRuleSet'],
          resources: ['*']
        }),
      ]),
    });
nmussy commented 2 months ago

Beware that if you do decide to activate the rule set with a CR, CloudFormation will not delete it until it is made inactive:

Cannot delete active rule set: <ruleset-name>

Adding an onDelete handler to reset the active rule set would be necessary to allow your stack to be destroyed

pahud commented 2 months ago

@ppena-LiveData @markusl

My bad. OK sounds like it's a limit and feature gap from cloudformation? I suggest we create a feature request for cloudformation-coverage-roadmap/issues. Meanwhile, I will submit an internal ticket to relevant team for that.

pahud commented 2 months ago

internal tracking: V1358648255