aws-cfn-ses-domain
aws-cfn-ses-domain copied to clipboard
Option to wait for Email Identity verification
Problem
I'm trying to add an SES Email Identity and configure AWS Cognito to use it in the same CloudFormation stack. This fails because after aws-cfn-ses-domain
creates the Email Identity it is in Verification Status = 'pending'
state. SES sends the verification email but then CloudFormation immediately tries to use the new Email Identity with Cognito without waiting for it to be verified. Before I have a chance to check my inbox and click the link in the verification email, the CloudFormation stack has already failed with an error from Cognito:
Amazon SES account is in Sandbox. Verify Send-to email address or Amazon SES Account (Service: AWSCognitoIdentityProviderService; Status Code: 400; Error Code: InvalidParameterException; Request ID: fd94cd46-b04f-4d4f-a77b-63a440d55fcf; Proxy: null)
(Ignore the "sandbox" part, the account is not actually in the SES sandbox. The problem is the Email Identity has not been verified.)
Solution
Add an option to wait Email Identity to be verified.
Compatibility
If the new option is false by default (don't wait) then existing users should be unaffected.
Additional info
In theory it should be possible to implement this waiting behaviour manually using AWS::CloudFormation::WaitCondition
, but that's awkward at best and it would be really nice if aws-cfn-ses-domain
could handle it automatically.
System
- aws-cfn-ses-domain version: 0.3
@rpaterson thanks for the thoughtful analysis. Being able to wait for SES verification would be helpful not only for email identities, but also for domain identities. (Route53 domain verifications are usually instantaneous, but it can take longer if you're using an outside DNS provider.)
I don't think there's any way to get notified when identity verification completes, so I guess we'd have to poll SES's GetIdentityVerificationAttributes until it comes back with VerificationStatus either Success or Failed.
I'm a little uncomfortable adding polling to the existing Lambda custom resource handlers. I'd like to keep them with the minimum possible permissions and with a short maximum execution time (they currently use the Lambda default 3 seconds max).
What would you think about instead adding a new CF resource Custom::SES_VerifiedIdentity
(or something like that) which takes an SES email or domain identity and waits until either it's successfully verified, verification fails, or it times out. You could use it in a standard CF DependsOn
clause, something like this:
Resources:
MySESSender:
Type: Custom::SES_EmailIdentity
Properties:
EmailAddress: "[email protected]"
MySESSender_Verified:
Type: Custom::SES_VerifiedIdentity
Properties:
Identity: !Ref MySESSender
# This resource won't provision until MySESSender is verified or fails.
# Identity can be a ref to a Custom::SES_Domain or Custom::SES_EmailIdentity.
# Other properties could adjust timeout, polling interval.
MyCognitoUserPool:
Type: AWS::Cognito::UserPool
DependsOn: MySESSender_Verified
Properties:
EmailConfiguration:
From: !GetAtt MySESSender.EmailAddress
If Custom::SES_VerifiedIdentity
is implemented with Lambda, the maximum timeout would be 15 minutes (Lambda doesn't allow longer execution times). A better option might be AWS Step Functions, which could keep checking for verification for hours (theoretically up to the full 24 hours SES allows for verification, though CloudFormation's own 12 hour limit would kick in before that).
~That would work, but if you're going to add another custom resource, why not add one that accepts an arbitrary email/domain identity and waits for it to become verified? That would be even more flexible.~
Edit: ha ha nevermind I see now you suggested the same thing! Yes I think that would work well.
The new resource probably needs a better name. Maybe Custom::SES_WaitForIdentityVerification
?