Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

aws_cognito.UserPool doesn't wait for a new aws_ses.EmailIdentity to be ready #28531

Open
2 tasks
ppena-LiveData opened this issue Dec 30, 2023 · 1 comment
Open
2 tasks
Labels
@aws-cdk/aws-cognito Related to Amazon Cognito effort/medium Medium work item – several days of effort feature-request A feature should be added or improved. p3

Comments

@ppena-LiveData
Copy link

Describe the feature

I might be doing something wrong, but I'm using aws_cognito.UserPoolEmail.withSes(), and no matter what I tried, I couldn't get CloudFormation to wait until a new aws_ses.EmailIdentity was ready before trying to find it to use it in a Cognito UserPool.

Use Case

I'd like to use a single CDK stack to create both an aws_ses.EmailIdentity and a aws_cognito.UserPool that references the Simple Email Service's EmailIdentity. I'd also like to create an aws_ses.ReceiptRuleSet in the same stack as the aws_ses_EmailIdentity without having to add a lot of addDependency() calls.

Proposed Solution

If it's possible, aws_cognito.UserPoolEmail.withSes should allow an aws_ses.EmailIdentity to be passed in to make sure any dependencies are properly configured. The same would also be nice for an ses.ReceiptRuleSet.

Other Information

The below is what I tried, but no matter what add_dependency() calls I added, I couldn't get it to work with a single stack and had to split it up into two separate stacks. I kept getting errors like this:

CDK-Bug-Test-Cognito |  8/11 | 6:55:26 AM | CREATE_FAILED        | AWS::Cognito::UserPool   | CognitoUserPool (CognitoUserPool53E37E69) Resource handler returned message: "Cognito received the following error from Amazon SES when attempting to send email: Email address is not verified. The following identities failed the check in region US-EAST-2: arn:aws:ses:us-east-2:245161217798:identity/paulie.livedata.com (Service: CognitoIdentityProvider, Status Code: 400, Request ID: c9d4ffe5-7d80-4a30-ad50-fc3ee712a3bc)" (RequestToken: 6af80751-1d91-b041-aaf3-8d086fb31439, HandlerErrorCode: InvalidRequest)

Here's the Python code:

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 SesStack(Stack):
    def __init__(self, scope: Construct, construct_id: str, route53_hosted_zone: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        ses.EmailIdentity(
            self, 'EmailIdentity',
            identity=ses.Identity.public_hosted_zone(
                route_53.HostedZone.from_hosted_zone_attributes(
                    self, 'HostedZone',
                    hosted_zone_id=self.node.try_get_context('route53_hosted_zone_id'),
                    zone_name=route53_hosted_zone,
                )
            ),
            mail_from_domain=f'mail.{route53_hosted_zone}'
        )


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)])

        # ### This did seem to work for the ReceiptRuleSet:
        # 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,
            )
        )

        # ### But this was not sufficient for the UserPool:
        # 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')

# ses_stack = SesStack(
#     app, 'CDK-Bug-Test-SES', route53_hosted_zone,
#     env=Environment(account=app.node.try_get_context('account'), region=app.node.try_get_context('region')),
# )

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')),
)
# stack.add_dependency(ses_stack)

app.synth()

Acknowledgements

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

CDK version used

2.117.0

Environment details (OS name and version, etc.)

Windows 11

@ppena-LiveData ppena-LiveData added feature-request A feature should be added or improved. needs-triage This issue or PR still needs to be triaged. labels Dec 30, 2023
@github-actions github-actions bot added the @aws-cdk/aws-cognito Related to Amazon Cognito label Dec 30, 2023
@ppena-LiveData
Copy link
Author

NOTE: this race condition doesn't happen all the time. I reproduced the problem at least half a dozen times while writing up this ticket, but I just tried it a couple times, and the above code worked without a problem, which of course is very annoying and means this might be hard to fix.

@pahud pahud added p2 effort/medium Medium work item – several days of effort and removed needs-triage This issue or PR still needs to be triaged. labels Jan 2, 2024
@pahud pahud added p3 and removed p2 labels Jun 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
@aws-cdk/aws-cognito Related to Amazon Cognito effort/medium Medium work item – several days of effort feature-request A feature should be added or improved. p3
Projects
None yet
Development

No branches or pull requests

2 participants