question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How can I create an SES Receipt Rule such that it has access to write to an S3 Bucket?

See original GitHub issue

I can see what kind of permissions it needs in this documentation: https://docs.aws.amazon.com/ses/latest/DeveloperGuide/receiving-email-permissions.html

Here is what I have so far but it is giving me the error Could not write to bucket:

0/14 | 1:03:28 AM | CREATE_IN_PROGRESS | AWS::S3::Bucket          | JustinIngressStore (JustinIngressStore3228DB9C)
0/14 | 1:03:28 AM | CREATE_IN_PROGRESS | AWS::IAM::Role           | BucketNotificationsHandler050a0587b7544547bf325f094a3db834/Role (BucketNotificationsHandler050a0587b7544547bf325f094a3db834RoleB6FB88EC)
0/14 | 1:03:29 AM | CREATE_IN_PROGRESS | AWS::SES::ReceiptRuleSet | JustinIngressReceiptRuleSet
0/14 | 1:03:29 AM | CREATE_IN_PROGRESS | AWS::CDK::Metadata       | CDKMetadata
0/14 | 1:03:29 AM | CREATE_IN_PROGRESS | AWS::IAM::Role           | BucketNotificationsHandler050a0587b7544547bf325f094a3db834/Role (BucketNotificationsHandler050a0587b7544547bf325f094a3db834RoleB6FB88EC) Resource creation Initiated
0/14 | 1:03:29 AM | CREATE_IN_PROGRESS | AWS::IAM::Role           | JustinIngressFunction/ServiceRole (JustinIngressFunctionServiceRoleDD7720A6)
0/14 | 1:03:29 AM | CREATE_IN_PROGRESS | AWS::S3::Bucket          | JustinIngressStore (JustinIngressStore3228DB9C) Resource creation Initiated
0/14 | 1:03:30 AM | CREATE_IN_PROGRESS | AWS::IAM::Role           | JustinIngressFunction/ServiceRole (JustinIngressFunctionServiceRoleDD7720A6) Resource creation Initiated
0/14 | 1:03:31 AM | CREATE_IN_PROGRESS | AWS::CDK::Metadata       | CDKMetadata Resource creation Initiated
1/14 | 1:03:31 AM | CREATE_COMPLETE    | AWS::CDK::Metadata       | CDKMetadata
1/14 | 1:03:31 AM | CREATE_IN_PROGRESS | AWS::SES::ReceiptRuleSet | JustinIngressReceiptRuleSet Resource creation Initiated
2/14 | 1:03:31 AM | CREATE_COMPLETE    | AWS::SES::ReceiptRuleSet | JustinIngressReceiptRuleSet
2/14 | 1:03:35 AM | CREATE_IN_PROGRESS | AWS::SES::ReceiptRule    | JustinIngressReceiptRule
3/14 | 1:03:38 AM | CREATE_FAILED      | AWS::SES::ReceiptRule    | JustinIngressReceiptRule Could not write to bucket: example-ingress-justin (Service: AmazonSimpleEmailService; Status Code: 400; Error Code: InvalidS3Configuration; Request ID: a38b9e40-3994-11e9-8f5f-d31281c59333)

I am attempting to attach a PolicyStatement to the bucket but

Code

export class IngressStack extends Stack {
  constructor(parent, props) {
    super(parent, `${stageName}IngressStack`, props)

    const bucketName = `${appName}-ingress-${stage}`;
    const bucket = new Bucket(this, `${stageName}IngressStore`, {
      bucketName,
      publicReadAccess: false,
      lifecycleRules: [
        {
          transitions: [
            {
              storageClass: StorageClass.Glacier,
              transitionInDays: 7
            }
          ]
        }
      ]
    })

    const emailRule = new CfnReceiptRuleSet(this, `${stageName}IngressReceiptRuleSet`, {
      ruleSetName: `${stage}-ingress`
    });

    const email = new CfnReceiptRule(this, `${stageName}IngressReceiptRule`, {
      ruleSetName: `${stage}-ingress`,
      rule: {
        enabled: true,
        name: `ingress`,
        actions: [
          { s3Action: { bucketName, objectKeyPrefix: `${appName}-${stage}` } }
        ],
        recipients: [`${appName}.${stage}@example.com`]
      }
    })

    const ingressHandler = new Function(this, `${stageName}IngressFunction`, {
      runtime: Runtime.NodeJS810,
      handler: 'index.handler',
      code: Code.directory(path.resolve(__dirname, '../../funcs/ingress')),
      timeout: 5 * 60, // 5m
      environment: {
        DEBUG: 'info,error',
        STAGE: stage
      }
    })

    // Trigger the ingress lambda when an object lands in the s3 bucket
    bucket.onObjectCreated(ingressHandler)

    // Grant permission to the lambda to read from the bucket
    bucket.grantRead(ingressHandler.role)
    
    const policySatement = new PolicyStatement()
      .addServicePrincipal('ses.amazonaws.com')
      .addActions('s3:PutObject')
      .addResource(bucket.bucketArn)

    bucket.addToResourcePolicy(policySatement)
    email.addDependsOn(emailRule);
    email.addDependsOn(bucket);
    emailRule.addDependsOn(bucket)
  }
}

Looking at the generated CloudFormation template it appears that the JustinIngressReceiptRule lacks a DependsOn to the bucket despite adding it in code.

JustinIngressReceiptRuleSet:
  Type: AWS::SES::ReceiptRuleSet
  Properties:
    RuleSetName: justin-ingress
  Metadata:
    aws:cdk:path: JustinIngressStack/JustinIngressReceiptRuleSet
JustinIngressReceiptRule:
  Type: AWS::SES::ReceiptRule
  Properties:
    Rule:
      Actions:
        - S3Action:
            BucketName: example-ingress-justin
            ObjectKeyPrefix: example-justin
      Enabled: true
      Name: ingress
      Recipients:
        - example.justin@example.com
    RuleSetName: justin-ingress
  DependsOn:
    - JustinIngressReceiptRuleSet
  Metadata:
    aws:cdk:path: JustinIngressStack/JustinIngressReceiptRule

What am I doing wrong?

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:1
  • Comments:8 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
justinmchasecommented, Mar 5, 2019

Psuedo Snippet:

export class IngressStack extends Stack {
  public readonly ingressBucket: BucketImportProps;
  constructor(parent) {
    super(parent, config.resourceName('IngressStack'))
    const bucketName = config.serviceName('ingress')
    const bucket = new Bucket(this, config.resourceName(`IngressBucket`), {
      bucketName,
      publicReadAccess: false
    })

    // https://docs.aws.amazon.com/ses/latest/DeveloperGuide/receiving-email-permissions.html
    const policySatement = new PolicyStatement()
      .describe('AllowSESPuts')
      .addServicePrincipal('ses.amazonaws.com')
      .addActions('s3:PutObject')
      .addResource(`arn:aws:s3:::${bucketName}/*`)
      .addCondition('StringEquals', { 'aws:Referer': accountId }) // accountId is my aws accountId

    bucket.addToResourcePolicy(policySatement)

    // Exports
    this.ingressBucket = bucket.export()
  }
}

export class EmailStack extends Stack {
  constructor(parent, props) {
    super(parent, config.resourceName(`StorageStack`), props)
    const { ingressBucket: { bucketName } } = props
    const rule = new CfnReceiptRule(this, config.resourceName(`IngressReceiptRule`), {
      ruleSetName: 'default-rule-set',
      rule: {
        enabled: true,
        name: config.serviceName('ingress-rule'),
        actions: [
          { s3Action: { bucketName, objectKeyPrefix: `ingress` } }
        ],
        recipients: [emailRecipient]
      }
    })
  }
}

const app = new App()
const { ingressBucket } = new IngressStack(app)
new EmailStack(app, { ingressBucket })
app.run()
Read more comments on GitHub >

github_iconTop Results From Across the Web

Giving permissions to Amazon SES for email receiving
When you apply the following policy to an S3 bucket, it gives Amazon SES permission to write to that bucket. For more information...
Read more >
Using Receipt Rules in Amazon SES
Each receipt rule for Amazon SES contains an ordered list of actions. This example creates a receipt rule with an Amazon S3 action,...
Read more >
How to Give Amazon SES Permission to Write to Your ...
This problem has been resolved. Create the policy on the bucket you want to grant the SES permission, not in the IAM.
Read more >
Creating and managing email rules with the SES API - AWS
This example shows you how to create a receipt rule that sends incoming messages to an Amazon S3 bucket, but you can also...
Read more >
Use Amazon SES to receive emails in S3 and Forward ...
Email receiving Endpoints ; 1. Open Amazon Route 53 ; 2. Once S3 Bucket get created click on S3 bucket name >> Click...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found