5
votes

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.

1
You seem to be working from the assumption that the visual editor is correct that "this policy does not grant any permissions." I don't remember exactly what I was doing recently but it was crying those similar tears about an S3 policy I was writing. Not exactly related, but there's a similar error in the S3 docs that lists an IAM action s3:ListObjects when there is in fact no such action -- the permission for listing objects is s3:ListBucket. A similar set of crossed wires may be occurring here.Michael - sqlbot
If I understand you correctly, you are suggesting using something like the AWS-CLI to create the policy in order to bypass a possibly buggy new console? That is interesting. My brain is fried from all this, but I'll take that approach at my next sitting and update with results. Thanks for the idea.Geek Stocks
Couldn't sleep. Confirmed what @Michael said - I have an "old 2017 version" policy working IF I create it via the AWS-CLI and not via the now CONFIRMED buggy console. However it is not that simple. Things that should work like adding ":version_number" or ":alias" to the end of Lambda ARN's is not working even in AWS-CLI submitted policies. So I would say that a LOT of testing is going to have to happen before we have a complete answer here. But 100% Michael nailed it, the problem is the new console. The policy I posted above DOES grant permissions just like it used to in the old console.Geek Stocks
@Michael-sqlbot — you may be interested in the update from AWS below...Geek Stocks
Thanks for the update.Michael - sqlbot

1 Answers

5
votes

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.