serverless-plugin-lambda-dead-letter
serverless-plugin-lambda-dead-letter copied to clipboard
Role associated with lamba doesn't have permission to SQS queue
Using this plugin (Awesome, love it!) and I can't seem to get the role configuration to work properly.
So here's an extract from my serverless.yml
service: testProject
provider:
name: aws
runtime: dotnetcore1.0
plugins:
- serverless-plugin-lambda-dead-letter
functions:
Handler-TestHandler:
handler: CsharpHandlers::Test.testProject.Handler::TestHandler
deadLetter:
targetArn:
GetResourceArn: TestDlq
events:
- stream: arn:aws:kinesis:ap-southeast-2:*:stream/TestStream
resources:
Resources:
TestStream:
Type: AWS::Kinesis::Stream
Properties:
Name: TestStream
ShardCount: 1
TestDlq:
Type: AWS::SQS::Queue
Properties:
QueueName: TestDlq
TestDlqPolicy:
Type: AWS::SQS::QueuePolicy
Properties:
Queues:
- Ref: TestDlq
PolicyDocument: {
"Version":"2012-10-17",
"Statement":[
{
"Effect":"Allow",
"Principal": "*",
"Action":["SQS:*"],
"Resource":"*"
}
]}
The SQS is getting created with these permissions (I've really opened it up just to get it to work, then i'll scale it back correctly once i accomplish that)
(Im not even sure if I need to give the above policy document, I would have thought permission would come from the functions ROLE, much like how the Kinesis stream permissions work, through the role)
The SQS is being associated correctly to the lambda function:
However as you can see I have a warning that the Role does not have permissions to that SQS queue
I've got a role being created with the following inline policy which can correctly access the Kinesis stream I have asked it subscribe to, and to CloudWatch in general...
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream"
],
"Resource": "arn:aws:logs:ap-southeast-2:*:*",
"Effect": "Allow"
},
{
"Action": [
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:ap-southeast-2:*:*",
"Effect": "Allow"
},
{
"Action": [
"kinesis:GetRecords",
"kinesis:GetShardIterator",
"kinesis:DescribeStream",
"kinesis:ListStreams"
],
"Resource": [
"arn:aws:kinesis:ap-southeast-2:*:stream/TestStream",
],
"Effect": "Allow"
}
]
}
I would have assumed that the above general policy would also specific access to the SQS DLQ, but it does not?
I had a few iterations trying to figure out the policy as well. With the proposal from #10 there might be a more simplified syntax that would compile the queue resource and policy document for you.
Until then here is the syntax I used in the custom resources...
I can't say which one of these is causing your issue but I noticed a few differences:
- You seem to missing the ID in the policy document.
- The
Statementin the policy document might need anSIDas well. - For
PrincipalI usedAWS: "*" - For
ResourceI directly referenced the queue. - I added a condition on the arn so the policy only applies when it matches the Lambda Function arn.
- To reference the lambda functions in the
Fn::GetAttyou have to infer what serverless is going to use as the Lambda logical id. In CF. In my caseserverlessLambda==>ServerlessLambdaLambaFunction
- To reference the lambda functions in the
Let me know if this works for you.
functions:
serverlessLambda:
name: my-serverless-lambda
description: Lambda to test the serverless utility
deadLetter:
# Use the ARN of a resource defined in the resources section.
targetArn:
GetResourceArn: ServerlessTplLambdaDlQueue
resources:
Resources:
ServerlessTplLambdaDlQueue:
Type: AWS::SQS::Queue
Properties:
QueueName: my-serverless-lambda-retry-queue
ServerlessTplLambdaDlQueuePolicy:
Type: AWS::SQS::QueuePolicy
Properties:
Queues:
- Ref: ServerlessTplLambdaDlQueue
PolicyDocument:
# This probably needs something more unique
# like 'Fn::GetAtt: [ServerlessTplLambdaDlQueue, Arn]' + '/SQSPolicy'
Id: ServerlessTplLambdaDlQueueId
Version: '2012-10-17'
Statement:
- Sid: Allow-Lambda-SendMessage
Effect: Allow
Principal:
AWS: "*"
Action:
- SQS:SendMessage
Resource:
Ref: ServerlessTplLambdaDlQueue
Condition:
ArnEquals:
aws:SourceArn:
Fn::GetAtt: [ServerlessLambdaLambdaFunction, Arn]
Thanks for your reply gmetzker, I've deployed again with
- A (very similar) ID on the policy document
- Adding the same SID to the statement as above
- I've used the same Principal and Action as above
- The resource for the policy is ok
- I've also followed the pattern above for the ArnEquals, and I can see that has worked as in the SQS permissions, the correct arn is in place.

However the ROLE policy attached to the lambda function is still exactly the same as i described above (I'm not sure if I'm meant to see any reflection of this in there). And i still see the same message under the functions SQS queue selector

I've been able to attach an AWS managed policy to the function's role manually as a work around. We can continue to utilise your extension with that in place, as re-deploying the function doesn't UNDO that policy which is nice. It would be nice however to have our serverless.yml be able to deploy all of our infrastructure correctly for this function without requiring any manual intervention/edits.
Let me know if there's any more information that would be useful to work out how we can accomplish this. Thanks for your quick response/help so far!
Interesting. I was under the impression all that was needed was a QueuePolicy, but perhaps the lambda role needs general SQS permission.
In my I'm using an existing IAM role that probably has something like SQS:*
In my environment I typically don't have permissions to modify policies or create roles. I don't think the plugin should modify existing policies but perhaps it could could compile them in auto-magically if iamRoleStatements were being assigned.
Have you tried setting the iamRoleStatements described here? This might be the preferred method.
I need to research a little bit and see if there are analogous scenarios. Do you know if serverless adds SNS or S3 access to the iamRoleStatements if you specify an SNS or S3 event handler?
@AirEssY I've release version 1.2.0 the syntax should be simplified and it will eliminate the need to create the queue or policy in the Resources section.
Your Lambda will still need a role that has SQS permissions though.
On second thought i need to do some more investigation on this. According to the docs serverless can create a default IAM role with rights to some resources.
In my environment I am required to use a predefined role. So I didn't see that serverless has the ability of creating a role for you.
IMHO, you like won't be creating roles in an enterprise environment. A devops will provide that to you, as in my case. The strange thing is that I had to put this permission on the role rather than the user that is running it. I suppose that is because the Lambda is what needs the SQS perms to publish to it out of EC2, so you need to add AmazonSQSFullAccess as well as AWSLambdaVPCAccessExecutionRole to the role you define your serverless.yml file.