Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In 2018, what is the correct way to allow invocation of a single lambda function?

Are you guys as frustrated with AWS as I am? (IAM - get it? Its punny...)

Checkout this IAM policy which — just a few months ago — was 100% valid and worked fine.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt123456",
            "Effect": "Allow",
            "Action": [
                "lambda:InvokeFunction"
            ],
            "Resource": [
                "arn:aws:lambda:ca-central-1:99999:function:test",
                "arn:aws:lambda:us-east-1:99999:function:test",
                "arn:aws:lambda:us-east-2:99999:function:test",
                "arn:aws:lambda:us-west-1:99999:function:test",
                "arn:aws:lambda:us-west-2:99999:function:test"
            ]
        }
    ]
}

If you paste this 2017 valid policy into the IAM console editor today, you will be told that:

This policy does not grant any permissions. To grant access, policies must have an action that has an applicable resource or condition

Now as you can see for yourself, there are 5 very specific "applicable resources" being given. So what gives here? What did those AWS boys and girls do to all of our existing IAM Lambda policies? And are we still secure as a result?


Life in 2018

So imagine that you just created a new Lambda fn, and you want to grant a single user permission to be able to run THAT specific fn and no other. If you start from scratch and use the new console, this is all that you are allowed to validly construct that comes close:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "lambda:InvokeFunction",
            "Resource": "*"
        }
    ]
}

So we have a big problem here, don't we? That tiny asterisk means this policy can run ANY Lambda fn in the entire account (a fact I have proven). Since you can no longer specify a Resource in the permission Lambda:InvokeFunction, this permission is pretty useless for our use case.

But wait! There is another Lambda permission, called Lambda:Invoke, and with this permission you CAN specify a specific resource in the console editor like so:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "lambda:Invoke",
            "Resource": "arn:aws:lambda:us-east-1:99999:function:test"
        }
    ]
}

Well that looks pretty good doesn't it?! I mean, perhaps AWS just changed the name of the permission from InvokeFunction to Invoke. Heck, thats not so bad and certainly not worth this record long question on SO right? Heh, yeah, well don't do what I did and get all lubed up thinking you're about to score. Welcome to this new hell:

Error: User: arn:aws:iam::99999:user/PersistentDumbass is not authorized to perform: lambda:InvokeFunction on resource: arn:aws:lambda:us-east-1:99999:function:test

WHAT?

Ok, for one, we didn't call a function in the AWS SDK called "InvokeFunction", we called "Invoke". Second, we DID attach this policy to our user. Third, we waited an hour to make sure this wasn't a propagation issue and also checked the relatively useless AWS Service Health Dashboard - which is all green, all the time even when us-east-1 is down. Netflix.

SO wunderkinds, I summon thee to wade through AWS's now obsolete documentation and poor nomenclature choices to create an answer for "the current way" we are supposed to permission ONE user to invoke ONE, SPECIFIC function.

like image 681
Geek Stocks Avatar asked Dec 30 '17 05:12

Geek Stocks


People also ask

How do you give permission to Lambda function?

Open the Functions page of the Lambda console. Choose a function. Choose Configuration and then choose Permissions. Scroll down to Resource-based policy and then choose View policy document.

How many ways can you trigger a Lambda function?

3 Common Ways To Trigger Lambda. To trigger a lambda function, you can choose between many different ways. The 3 most common ways are API Gateways, S3, and DynamoDB table streams.

How do you call one Lambda function from another?

In order to allow the ParentFunction to call the ChildFunction, we need to provide the ParentFunction with specific rights to call another lambda function. This can be done by adding specific policies to a role and then assign that role to the lambda function.


1 Answers

UPDATE 1/8/2018

AWS sent me the following through the Forums:

Hi geekstocks,

We have identified this as an error in the IAM console. We are working to get this fixed. Please continue to use lambda:InvokeFunction and specify the functions in the resource element. Your initial policy should continue to work. Please do not use lambda:Invoke in your policies. I will update you when this is fixed in the IAM console.

When the Amazonians use their forums, its a good day. I will still continue to use AWS-CLI, however.


This "answer" is going to be 100% as messy as the AWS console is right now, and there is no way around it. As Michael - sqlbot eluded to in his comment, his recent experience with the new AWS Lambda console was not great and he wondered if the policy was fine but the console errantly reports it as "not granting permissions". He is partially right. But the problems are deeper. Here is the best stab I have at "2018 Lambda IAM permissions" in the wake of their hurried rollout of a less than stellar product:

Use the AWS-CLI to create your policies; skip the crappy console

  1. Create a policy.json file in a new folder with your policy in it
  2. Create this policy for your AWS-CLI user:

{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "iam:CreatePolicy", "iam:DeletePolicy" ], "Resource": "*" } ] }

  1. Run this command from the AWS-CLI:

aws iam create-policy --policy-name myPolicyName --policy-document file://policy.json

Be aware of some gotchas

There are a few subtle differences which will drive you nuts testing.

  • Even though the documentation will tell you that its fine to add a ":version" or ":alias" to the ARN of your Lambda fn, don't do it. Just end with the fn name. I have not yet found a valid way to restrict down to version or alias successfully. I will update this answer if my testing proves otherwise, but so far I can break a good permission by adding ":PRODUCTION" to my ARN.
  • If you are a veteran of AWS IAM and have experience with lightening fast propogation of IAM policies, like in the 10-15 second range, those days seem to be OVER. Wait a full 2 minutes before your first attempt, then if that fails another 2 minutes. Things have slowed down considerably since the good 'ol days.
  • Test your policies with throw away names and place version numbers on the tests. Consider names like "test-v1", "test-v2", etc. IAM seems to do some brief caching. Testing works faster if you make a policy and never change it, just make a new version, delete the attachment to the previous test and attach the next test. And wait 2 minutes.
  • I am going to do some wildcard testing next; I think I found some more fubar in that area but I have not tested through yet to post about it.

This buggy console and inconsistent documentation cost me 6+ hours of effort. I hope this Q&A spares you some grief.

like image 101
Geek Stocks Avatar answered Nov 01 '22 18:11

Geek Stocks