Kyle Pericak

"It works in my environment."

Thu 09 January 2020

IAM Auth for Lambda

Posted by Kyle Pericak in cloud   

This post is linked to from the AWS: Deep Dive Project


This post covers how to restrict access to a Lambda function using AWS IAM roles. It builds on the function written in my last post



A note about API Gateway: To me, the intuitive way to do this was to make an API in API Gateway and turn the IAM authentication on for it. That went well until I tried to actually use the API from curl with authentication enabled. It's not apparent how to derive Signature HTTP header from your key id and secret key. Also, in Python I didn't see any good client libraries. Instead I chose to just directly use boto3 with Lambda and skip the REST API entirely. If you know how to do this, please let me know!


Create a policy for your lambda function

Get the ARN of your function

Navigate to your function in the AWS Lambda Console. On the top right, the ARN is displayed. Copy it, you'll use it in the policy.

Create the policy

Open the IAM Console and create a new policy. The JSON looks like this. Note the ARN copied from the Function.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "LambdaInvokeHelloWorld",
            "Effect": "Allow",
            "Action": [
                "lambda:InvokeFunction",
                "lambda:InvokeAsync"
            ],
            "Resource": "arn:aws:lambda:ca-central-1:850047500507:function:HelloWorld"
        }
    ]
}

Name the policy and assign it to your user. This user should have a Key ID and Secret Key.


Invoke Lambda from Python

Note that the payloads are in byte format.

import json
import boto3

key_id = 'XXXXXXXXXXXXXXXXX'
key_secret = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXX'

session = boto3.Session(
    aws_access_key_id=key_id,
    aws_secret_access_key=key_secret)

client = session.client('lambda')

body = {'name': 'Kyle'}
payload = str.encode(json.dumps(body))
response = client.invoke(FunctionName='HelloWorld', Payload=payload)
print(response['Payload'].read())

If the user identified by that key has the above permission, they'll be able to execute this function. Otherwise they'll get a nice permissions error.


Javascript appears to be disabled. Comments can't load.