Code Monkey home page Code Monkey logo

cfn-ses-provider's Introduction

cfn-ses-provider

A CloudFormation custom provider for managing SES Domain Identities, Identity Notifications, DKIM tokens and the active receipt rule set.

Read the blog on How to configure SES domain identities and DKIM records using cloudformation

How do I add SES Domain Identity in CloudFormation?

It is quite easy: you specify a CloudFormation resource of type Custom::DomainIdentity:

Resources:
  DomainIdentity:
    Type: Custom::DomainIdentity
    Properties:
      Domain: !Ref 'ExternalDomainName'
      Region: !Ref 'EmailRegion'
      ServiceToken: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-ses-provider'

This will create a domain identity in the region, and return the DNS entry as attributes, so you can proof you own the domain by adding a Route53 record:

  DomainVerificationRecord:
    Type: AWS::Route53::RecordSetGroup
    Properties:
        Comment: !Sub 'SES identity for ${ExternalDomainName}'
        HostedZoneId: !Ref 'HostedZone'
        RecordSets: !GetAtt 'DomainIdentity.RecordSets'

To wait until the domain identity is verified, add a Custom::VerifiedIdentity:

  VerifiedDomainIdentity:
    Type: Custom::VerifiedIdentity
    Properties:
      Identity: !GetAtt 'DomainIdentity.Domain'
      Region: !GetAtt 'DomainIdentity.Region'
      ServiceToken: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-ses-provider'

If you wish to add a MAIL FROM domain, add a Custom::MailFromDomain:

Resources:
  MailFromDomain:
    Type: Custom::MailFromDomain
    Properties:
      Domain: !Ref 'ExternalDomainName'
      Region: !Ref 'EmailRegion'
      MailFromSubdomain: 'mail'
      ServiceToken: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-ses-provider'

You can verify the MAIL FROM domain in Route53 like this:

  MailFromDomainVerificationRecords:
    Type: AWS::Route53::RecordSetGroup
    Properties:
        Comment: !Sub 'SES MAIL FROM domain for ${ExternalDomainName}'
        HostedZoneId: !Ref 'HostedZone'
        RecordSets: !GetAtt 'MailFromDomain.RecordSets'

To wait until the MAIL FROM domain is verified, add a Custom::VerifiedMailFromDomain:

  VerifiedMailFromDomain:
    Type: Custom::VerifiedMailFromDomain
    Properties:
      Identity: !GetAtt 'DomainIdentity.Domain'
      Region: !GetAtt 'DomainIdentity.Region'
      ServiceToken: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-ses-provider'

If you wish to configure the notifications, add a Custom::IdentityNotifications:

  DomainNotifications:
    Type: Custom::IdentityNotifications
    Properties:
      Identity: !GetAtt 'DomainIdentity.Domain'
      Region: !GetAtt 'DomainIdentity.Region'
      BounceTopic: !Ref BounceTopic
      ComplaintTopic: !Ref ComplaintTopic
      HeadersInBounceNotificationsEnabled: true
      HeadersInComplaintNotificationsEnabled: true
      ForwardingEnabled: false
      ServiceToken: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-ses-provider'

If you wish to activate a SES Receipt Rule set, add a Custom::ActiveReceiptRuleSet:

  Type: Custom::ActiveReceiptRuleSet
  Properties:
    Region: !Ref 'AWS::Region'
    RuleSetName: !Ref ReceiptRuleSet
    ServiceToken: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-ses-provider'

If you wish to authorize other AWS accounts, IAM users, and AWS services to send for this identity, add an identity policy:

  IdentityPolicy:
    Type: Custom::IdentityPolicy
    Properties:
      Identity: !GetAtt 'DomainIdentity.Domain'
      PolicyName: CrossAccountAllow
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              AWS:
                - 'arn:aws:iam::000111222333:root'
            Action:
              - ses:SendEmail
              - ses:SendRawEmail
            Resource: !Sub 'arn:aws:ses:${AWS::Region}:${AWS::AccountId}:identity/${DomainIdentity.Domain}'
      ServiceToken: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-ses-provider'

How do I get DKIM tokens in CloudFormation?

It is quite easy: you specify a CloudFormation resource of type Custom::DkimTokens:

Resources:
  DkimTokens:
    Type: Custom::DkimTokens
    Properties:
      Domain: !GetAtt 'DomainIdentity.Domain'
      Region: !GetAtt 'DomainIdentity.Region'
      ServiceToken: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-ses-provider'

This will return the DKIM tokens and the DNS entries as attributes, so that receiver can validate that the messages were sent by the owner of the domain. You can use these values to create the required DKIM DNS records, as follows:

  DkimRecords:
    Type: AWS::Route53::RecordSetGroup
    Properties:
      HostedZoneId: !Ref 'HostedZone'
      RecordSets: !GetAtt 'DkimTokens.RecordSets'

Installation

To install these custom resources, type:

aws cloudformation deploy \
	--capabilities CAPABILITY_IAM \
	--stack-name cfn-ses-provider \
	--template-file ./cloudformation/cfn-resource-provider.yaml

This CloudFormation template will use our pre-packaged provider from s3://binxio-public-{{your-region}}/lambdas/cfn-ses-provider-0.8.3.zip.

Demo

To install the demo you need a domain name and a Route53 hosted zone for the domain. To install the demo of this Custom Resource, type:

read -p "domain name: " DOMAIN_NAME
read -p "hosted zone id: " HOSTED_ZONE
aws --region eu-west-1 \
	cloudformation deploy --stack-name cfn-certificate-provider-demo \
	--template-file cloudformation/demo-stack.yaml \
	--parameter-overrides DomainName=$DOMAIN_NAME HostedZoneId=$HOSTED_ZONE

view the installed identity, the notification attributes and route53 records:

aws --region eu-west-1 ses list-identities
aws --region eu-west-1 ses get-identity-notification-attributes
aws route53 get-resource-record-sets --hosted-zone $HOSTED_ZONE

cfn-ses-provider's People

Contributors

basschipper avatar berenbums avatar darioackermann avatar dc-pm avatar john-tipper avatar matt-pawley avatar mvanholsteijn avatar orieg avatar rhertogh avatar v0xnihili avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

cfn-ses-provider's Issues

InvalidCharacterString

Hi!

using !GetAtt 'MailFromDomain.RecordSets' I'm getting the next error on CloudFormation console:

[Invalid Resource Record: 'FATAL problem: InvalidCharacterString (Value should be enclosed in quotation marks) encountered with 'v=spf1 include:amazonses.com ~all'']

Thank you!

DomainIdentity ResourceRecords quotation removal broken creation of nested resource

Hello,

After committing 49a3ea4
Any idea why the quotation was removed?

Sample CF code which reports issue like:
[Invalid Resource Record: 'FATAL problem: InvalidCharacterString (Value should be enclosed in quotation marks) encountered with 'ccEesV+N/LXO1MqHmXVUuRcsggM1TwsoxNuHrB1T10E='']

Resources:
DomainIdentity:
Type: Custom::DomainIdentity
Properties:
Domain: 'x.sample.com'
Region: 'us-east-1'
ServiceToken: !ImportValue 'ses-provider'
DomainVerificationRecord:
Type: AWS::Route53::RecordSetGroup
Properties:
HostedZoneName: 'sample.com.'
RecordSets: !GetAtt 'DomainIdentity.RecordSets'

Thanks.

project may contain real AWS account numbers

In some places you are clearly using example account numbers, such as 111111111111, 222222222222, etc.

However, you might want to check these files:

  • tests/test_identity_policy_schema.py
  • tests/test_identity_policy_provider.py

Release Python 3-compatible version

Hello,

I see that the code powering this custom resource has been upgraded for Python 3 compatibility - thank you @mvanholsteijn for this work! Are there any plans to release a version v0.3.0 including the Python 3 compatibility to the public S3 bucket? As far as I can tell, the latest publicly available built version is v0.2.3, which targets Python 2.7 and thus is not compatible with the CloudFormation template present on the master branch.

(I discovered this issue while attempting to use v0.2.3 with the cfn template from master, which resulted in an error which I'll leave here to help anyone running into the same thing:)

Unable to import module 'ses': No module named 'Queue'

Function not found...

Hi!

For some reasone it seems the package is not deployed to Frankfurt region. Can you confirm that?

Error message:
Function not found: arn:aws:lambda:eu-central-1:711132361798:function:binxio-cfn-ses-provider (Service: AWSLambda; Status Code: 404; Error Code: ResourceNotFoundException; Request ID: 431b7c05-f909-4862-b807-1e0c9266745c; Proxy: null)

ses:GetIdentityMailFromDomainAttributes permission is missing

When attempting to include a verified "MAIL FROM" Resource in the Stack, deployment of the stack will fail with

botocore.exceptions.ClientError: An error occurred (AccessDenied) when calling the GetIdentityMailFromDomainAttributes operation

The ses:GetIdentityMailFromDomainAttributes permission is missing in the provider stack

Cannot create IdentityPolicy with Principal Service

In version 0.7.0 it is not possible to create an IdentityPolicy with an AWS service as the principal.

Example of such a policy

  IdentityPolicy:
    Type: Custom::IdentityPolicy
    Properties:
      Identity: !GetAtt 'DomainIdentity.Domain'
      PolicyName: AllowMailFromCognito
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: cognito-idp.amazonaws.com
            Action:
              - ses:SendEmail
              - ses:SendRawEmail
            Resource: !Sub 'arn:aws:ses:${AWS::Region}:${AWS::AccountId}:identity/${DomainIdentity.Domain}'
      ServiceToken: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:binxio-cfn-ses-provider'

This fails with the error message in CloudFormation:
Received response status [FAILED] from custom resource. Message returned: invalid resource properties: <instance> is not valid under any of the given schemas

The schema in https://github.com/binxio/cfn-ses-provider/blob/master/src/identity_policy_provider.py#L38 only allows for AWS, but not for Service

Missing S3 permissions for 0.7.0

Good stuff. I just hit a snag with 0.7.0. When I deploy cfn-resource-provider in the CFNSESProvider resource with:

S3Key: !If - UsePublicLambda - lambdas/cfn-ses-provider-0.7.0.zip

I get the following error:
Your access has been denied by S3, please make sure your request credentials have permission to GetObject for binxio-public-us-west-2/lambdas/cfn-ses-provider-0.7.0.zip. S3 Error Code: AccessDenied. S3 Error Message: Access Denied (Service: AWSLambdaInternal; Status Code: 403; Error Code: AccessDeniedException; Request ID: 6da6066e-5f87-431b-9abe-8e42c3c5151a; Proxy: null)

But if I run

S3Key: !If - UsePublicLambda - lambdas/cfn-ses-provider-0.6.1.zip

The stack successfully deploys.

Does not support multiple regions

Hi,

Great tool, however deploying in multiple regions with the same DNS name it fails to update the TXT record adding the new txt entry with the information. It looks to just do a create only, and fails if it exists.

The CFN error is below:

[Tried to create resource record set [name='_amazonses.domain.name.', type='TXT'] 
but it already exists]

I'm guessing the same issue exists for DKIM records, but it never got to that step to check.

Encrypted SNS topics not supported by

Heyho,

when i am using something like:

XXXXSESIdentityNotifications:
Type: Custom::IdentityNotifications
Properties:
Identity: !GetAtt XXXXSESVerifiedIdentity.Identity
Region: !GetAtt XXXXSESVerifiedIdentity.Region
BounceTopic: !Ref XXXXNotificationTopic
ComplaintTopic: !Ref XXXXNotificationTopic
HeadersInBounceNotificationsEnabled: true
HeadersInComplaintNotificationsEnabled: true
ForwardingEnabled: false
ServiceToken: !Ref XXXXSESProviderArn

In my cloudformation template usually it works. exept i use an encrypted SNS topioc for Bount/Complaint Topic like:

XXXXNotificationTopic:
Type: AWS::SNS::Topic
Properties:
KmsMasterKeyId: alias/aws/sns
Subscription:
- Endpoint:
Ref: XXXXOperatorEMail
Protocol: email

then i get an Error:

Received response status [FAILED] from custom resource. Message returned: botocore.exceptions.ClientError: An error occurred (InvalidParameterValue) when calling the SetIdentityNotificationTopic operation: SNS topic arn:aws:sns:eu-central-1:XXXXXXX:XXXXXX... (RequestId: XXXXXXX )

tested with version 0.6.5 as well as 0.7.0
Any idea? :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.