diff --git a/packages/@aws-cdk/aws-sqs/lib/perms.ts b/packages/@aws-cdk/aws-sqs/lib/perms.ts new file mode 100644 index 0000000000000..a9062475e14cc --- /dev/null +++ b/packages/@aws-cdk/aws-sqs/lib/perms.ts @@ -0,0 +1,12 @@ +export const QUEUE_GET_ACTIONS = [ + "sqs:ReceiveMessage", +]; + +export const QUEUE_CONSUME_ACTIONS = [ + "sqs:ChangeMessageVisibility", + "sqs:DeleteMessage", +]; + +export const QUEUE_PUT_ACTIONS = [ + "sqs:SendMessage", +]; \ No newline at end of file diff --git a/packages/@aws-cdk/aws-sqs/lib/queue.ts b/packages/@aws-cdk/aws-sqs/lib/queue.ts index ea6133ecbf754..9cea41ee1fc0b 100644 --- a/packages/@aws-cdk/aws-sqs/lib/queue.ts +++ b/packages/@aws-cdk/aws-sqs/lib/queue.ts @@ -1,5 +1,7 @@ +import iam = require('@aws-cdk/aws-iam'); import kms = require('@aws-cdk/aws-kms'); import cdk = require('@aws-cdk/cdk'); +import perms = require('./perms'); import { QueueRef } from './queue-ref'; import { cloudformation } from './sqs.generated'; import { validateProps } from './validate-props'; @@ -275,6 +277,64 @@ export class Queue extends QueueRef { } } + /** + * Grant permissions to consume messages from a queue + * + * This will grant the following permissions: + * + * - sqs:ChangeMessageVisibility + * - sqs:DeleteMessage + * - sqs:ReceiveMessage + * + * @param identity Principal to grant consume rights to + */ + public grantConsumeMessages(identity?: iam.IPrincipal) { + this.grant(identity, perms.QUEUE_GET_ACTIONS.concat(perms.QUEUE_CONSUME_ACTIONS)); + } + + /** + * Grant access to receive messages from a queue to + * the given identity. + * + * This will grant sqs:ReceiveMessage + * + * @param identity Principal to grant receive rights to + */ + public grantReceiveMessages(identity?: iam.IPrincipal) { + this.grant(identity, perms.QUEUE_GET_ACTIONS); + } + + /** + * Grant access to send messages to a queue to the + * given identity. + * + * This will grant sqs:SendMessage + * + * @param identity Principal to grant send rights to + */ + public grantSendMessages(identity?: iam.IPrincipal) { + this.grant(identity, perms.QUEUE_PUT_ACTIONS); + } + + /** + * Grant the actions defined in queueActions + * to the identity Principal given. + * + * @param identity Principal to grant right to + * @param queueActions The actions to grant + */ + private grant(identity: iam.IPrincipal | undefined, + queueActions: string[]) { + + if (!identity) { + return; + } + + identity.addToPolicy(new iam.PolicyStatement() + .addResource(this.queueArn) + .addActions(...queueActions)); + } + /** * Look at the props, see if the FIFO props agree, and return the correct subset of props */ diff --git a/packages/@aws-cdk/aws-sqs/test/test.sqs.ts b/packages/@aws-cdk/aws-sqs/test/test.sqs.ts index d6a0b3cdca289..21f9529d14333 100644 --- a/packages/@aws-cdk/aws-sqs/test/test.sqs.ts +++ b/packages/@aws-cdk/aws-sqs/test/test.sqs.ts @@ -1,5 +1,5 @@ import { expect, haveResource } from '@aws-cdk/assert'; -import { ArnPrincipal, PolicyStatement } from '@aws-cdk/aws-iam'; +import { ArnPrincipal, PolicyStatement, Role, ServicePrincipal } from '@aws-cdk/aws-iam'; import kms = require('@aws-cdk/aws-kms'); import s3 = require('@aws-cdk/aws-s3'); import { resolve, Stack } from '@aws-cdk/cdk'; @@ -113,6 +113,94 @@ export = { test.done(); }, + 'iam': { + 'grants permission to consume messages'(test: Test) { + const stack = new Stack(); + const role = new Role(stack, 'Role', { assumedBy: new ServicePrincipal('lambda.amazonaws.com') }); + const queue = new sqs.Queue(stack, 'Queue'); + queue.grantConsumeMessages(role); + + expect(stack).to(haveResource('AWS::IAM::Policy', { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "sqs:ReceiveMessage", + "sqs:ChangeMessageVisibility", + "sqs:DeleteMessage" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": + [ + "Queue4A7E3555", + "Arn" + ] + } + } + ] + } + })); + + test.done(); + }, + + 'grants permission to receive messages'(test: Test) { + const stack = new Stack(); + const role = new Role(stack, 'Role', { assumedBy: new ServicePrincipal('lambda.amazonaws.com') }); + const queue = new sqs.Queue(stack, 'Queue'); + queue.grantReceiveMessages(role); + + expect(stack).to(haveResource('AWS::IAM::Policy', { + "PolicyDocument": { + "Statement": [ + { + "Action": "sqs:ReceiveMessage", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": + [ + "Queue4A7E3555", + "Arn" + ] + } + } + ] + } + })); + + test.done(); + }, + + 'grants permission to send messages'(test: Test) { + const stack = new Stack(); + const role = new Role(stack, 'Role', { assumedBy: new ServicePrincipal('lambda.amazonaws.com') }); + const queue = new sqs.Queue(stack, 'Queue'); + queue.grantSendMessages(role); + + expect(stack).to(haveResource('AWS::IAM::Policy', { + "PolicyDocument": { + "Statement": [ + { + "Action": "sqs:SendMessage", + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": + [ + "Queue4A7E3555", + "Arn" + ] + } + } + ] + } + })); + + test.done(); + } + + }, + 'queue encryption': { 'encryptionMasterKey can be set to a custom KMS key'(test: Test) { const stack = new Stack();