AWS API Gateway Not Connecting to Lambda Alias - amazon-web-services

I am trying to connect an API Gateway build to my lambda which has versioned aliases.
This is the setup:
AWS Lambda
Lambda functionName Has two aliases, staging and production. Staging is pointing to $LATEST and production is pointing to the last stable version (let's say version 1).
API Gateway
The API has two stages, staging and production. Each stage is to be associated with a specific lambda alias. funcName is a stage variable added to each stage as either staging or production. The resources are setup as follows:
Resources:
/route1
ANY METHOD -> lambda function -> functionName:${stageVariables.funcName}
/route2/{proxy+}
ANY METHOD -> lambda function -> functionName:${stageVariables.funcName}
When I add these resources and methods AWS let's me know to manually update the lambda function's policies to allow the API to call them using the following script:
For route1:
aws lambda add-permission
--function-name "arn:aws:lambda:us-west-2:account-id:function:functionName:staging"
--source-arn "arn:aws:execute-api:us-west-2:account-id:7aupeov6ak/*/*/route1"
--principal apigateway.amazonaws.com
--statement-id 30bdb347-9b5b-4eed-9221-d3d8de3e6def
--action lambda:InvokeFunction
For route2
aws lambda add-permission
--function-name "arn:aws:lambda:us-west-2:account-id:function:functionName:staging"
--source-arn "arn:aws:execute-api:us-west-2:account-id:7aupeov6ak/*/*/route2/*"
--principal apigateway.amazonaws.com
--statement-id 30bdb347-9b5b-4eed-9221-d3d8de3e6def
--action lambda:InvokeFunction
Policy after CLI commands:
{
"Version": "2012-10-17",
"Id": "default",
"Statement": [
{
"Sid": "30bdb347-9b5b-4eed-9221-d3d8de3e6def",
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:us-west-2:account-id:function:functionName:staging",
"Condition": {
"ArnLike": {
"AWS:SourceArn": "arn:aws:execute-api:us-west-2:account-id:7aupeov6ak/*/*/route2/*"
}
}
},
{
"Sid": "30bdb347-9b5b-4eed-9221-d3d8de3e6def",
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:us-west-2:account-id:function:functionName:staging",
"Condition": {
"ArnLike": {
"AWS:SourceArn": "arn:aws:execute-api:us-west-2:account-id:7aupeov6ak/*/*/route2/*"
}
}
}
]
}
The commands go through successfully, and the policies are added to the lambda alias, however, when I check triggers both are throwing the following error:
"The API with ID 7aupeov6ak doesn’t include a resource with path /route1 having an integration arn:aws:lambda:us-west-2:account-id:function:functionName:staging on the ANY method."
I read both of these tutorials and it appears I've done everything correctly.
https://www.contentstack.com/blog/tech-talk/deploying-aws-lambda-in-different-environments/
https://aws.amazon.com/blogs/compute/using-api-gateway-stage-variables-to-manage-lambda-functions/

Related

Allow Lambda to be invoked by all EC2 instances

Is it possible to allow a lambda to be invoked by all EC2 instance without giving any specific permissions for this on the EC2 side?
For this I tried to add a the following ressource-based policy to my lambda function, hoping it will give permission to all my EC2 instances to invoke it:
{
"Version": "2012-10-17",
"Id": "default",
"Statement": [
{
"Sid": "InvokeLambdaFunction",
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:eu-west-1:123456789012:myLambdaFunction",
"Condition": {
"ArnLike": {
"AWS:SourceArn": "arn:aws:ec2:eu-west-1:123456789012:instance/*"
}
}
}
]
}
However when I invoke my lambda using the aws CLI from within an EC2 instance, I get an access denied:
sh-4.2$ aws lambda invoke --function-name "myLambdaFunction" --payload "{\"instance-id\":\"$EC2_INSTANCE_ID\"}" --region eu-west-1 response.json
An error occurred (AccessDeniedException) when calling the Invoke
operation: User:
arn:aws:sts::123456789012:assumed-role/AmazonSSMRoleForInstancesQuickSetup/i-06e731b382734dc8f
is not authorized to perform: lambda:InvokeFunction on resource:
arn:aws:lambda:eu-west-1:123456789012:function:myLambdaFunction
because no identity-based policy allows the lambda:InvokeFunction
action
Am I missing something here or is this simply not possible?

Secrets Manager - rotate secret with lambda in another account

In a project I'm working on, the secrets are stored in a centralized company Secrets Manager, in a specific AWS account (SECRETS_ACCOUNT).
Project resources (including lambda functions) are in a project specific account (PROJECT_ACCOUNT).
I'm trying to set up secrets rotation, but I get stuck on this error message:
AccessDeniedException: Secrets Manager cannot invoke the specified Lambda function. Ensure that the function policy grants access to the principal secretsmanager.amazonaws.com.
The lambda resource-based policy:
{
"Version": "2012-10-17",
"Id": "default",
"Statement": [
{
"Sid": "SecretsManager",
"Effect": "Allow",
"Principal": {
"Service": "secretsmanager.amazonaws.com"
},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:eu-west-1:PROJECT_ACCOUNT:function:secret-rotation"
}
]
}
The lambda role trust relationship:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
I don't know if it matters, both accounts are in the same region.
Did I miss something? Do I need to add additional permissions to allow a Secrets Manager from another account to invoke the lambda? Do the lambda and the secret have to be in the same account?
Thanks in advance,
Please run the below command to resolve the error "AccessDeniedException: Secrets Manager cannot invoke the specified Lambda function. Ensure that the function policy grants access to the principal secretsmanager.amazonaws.com."
in AWS Cli
aws lambda add-permission --function-name arn:aws:lambda:us-east-1:757147756798:function:"secret name here without quotes" --principal secretsmanager.amazonaws.com --action lambda:InvokeFunction --statement-id SecretsManagerAccess

Does a lambda function IAM role require an IAM permission to invoke itself?

Question
Does the IAM role of a lambda function require an IAM permission to invoke itself?
Background
Reading Tutorial: Process New Items with DynamoDB Streams and Lambda.
It looks the IAM role of the lambda function to process DynamoDB stream records has the IAM permission to invoke the function itself (and plus).
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:region:accountID:function:publishNewBark*"
WooferLambdaRolePolicy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:region:accountID:function:publishNewBark*"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:region:accountID:*"
},
{
"Effect": "Allow",
"Action": [
"dynamodb:DescribeStream",
"dynamodb:GetRecords",
"dynamodb:GetShardIterator",
"dynamodb:ListStreams"
],
"Resource": "arn:aws:dynamodb:region:accountID:table/BarkTable/stream/*"
},
{
"Effect": "Allow",
"Action": [
"sns:Publish"
],
"Resource": [
"*"
]
}
]
}
aws iam put-role-policy --role-name WooferLambdaRole \
--policy-name WooferLambdaRolePolicy \
--policy-document file://role-policy.json
aws lambda create-function \
--region us-east-1 \
--function-name publishNewBark \
--zip-file fileb://publishNewBark.zip \
--role roleARN \ <--- Replace roleARN with the ARN for WooferLambdaRole.
--handler publishNewBark.handler \
--timeout 5 \
--runtime nodejs10.x
Is there a reason why the IAM permission to invoke the lambda function itself needs to be attached to the IAM role of the lambda? Or is there a specific reason related with DynamoDB stream processing?
What you are describing is an example of AWS Lambda Event Source Mapping and its only for Kinesis, DynamDB and SQS.
However, you are not giving permissions to your function to invoke itself. Instead you are giving the AWS Lambda Service (not your function) permissions to invoke your function. The reasons is the Lambda Service will be processing the DynamoDB stream on your behalf in a background and it will be invoking your function with stream's records when available.
Note that the trust policy for WooferLambdaRole role is for lambda.amazonaws.com:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
The trust policy means that the lambda service (again not your function, but the aws lambda service itself) will be able to assume the role containing WooferLambdaRolePolicy. Subsequently the lambda service will be able to work with DynamoDB and invoke your function.

Allow all cloudwatch event rules to have access to lambda function

I have been encountering a hard limit on lambda function policy when trying to provision access for a cloudwatch event rule to trigger the lambda function on a scheduled basis.
An error occurred (PolicyLengthExceededException) when calling the AddPermission operation: The final policy size (20670) is bigger than the limit (20480).
It works for a new lambda function, but eventually its policy will bloat and will hit a hard limit on the number on cloudwatch event rule that can access it.
Some said to re-create the function (delete/create), but this won't be an option in a production environment where cloudwatch events are already configured in it, resulting to the existing ones to lose access to the lambda function.
Using the aws cli, i was able to extract the policy of my lambda function, it loooks like this:
"Statement": [{
"Sid": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"Effect": "Allow",
"Principal": {
"Service": "events.amazonaws.com"
},
"Action": "lambda:*",
"Resource": "arn:aws:lambda:xxxxx:xxxxxxxxxxx:function:xxxxxxxxxxxxx",
"Condition": {
"ArnLike": {
"AWS:SourceArn": "arn:aws:events:xxxxxxx:xxxxxx:rule/xxxxxxxxx"
}
}
}]
So i was looking onto something like for the AWS:SourceArn
arn:aws:events:xxxxxxx:xxxxxx:rule/*
To avoid hitting a hard limit, but i cannot seem to do it. Even in the lambda function itself on the console, you won't be able to create such a rule that will allow all cloudwatch event of a specified account to have access to the lambda function using a wildcard '*'.
Suggestions are much welcome. Thank you guys
This was accepted without an error:
$ aws lambda add-permission --function-name function_name\
--action 'lambda:InvokeFunction' --principal events.amazonaws.com \
--statement-id '1' \
--source-arn arn:aws:events:ap-southeast-2:123456789012:rule/*
This will accept all CloudWatch Events rules.
You could instead name your rules such that the ones you want to allow can all have the same prefix in their name, eg:
--source-arn arn:aws:events:ap-southeast-2:123456789012:rule/Event-*
I used the above CLI command but got an error in the console, please find the attached screenshot of the errorenter image description here. Please find below function policy of lambda:
{ "Version": "2012-10-17", "Id": "default", "Statement": [
{
"Sid": "events-access",
"Effect": "Allow",
"Principal": {
"Service": "events.amazonaws.com"
},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:us-east-1:096280016729:function:leto_debug_log",
"Condition": {
"ArnLike": {
"AWS:SourceArn": "arn:aws:events:us-east-1:096280016729:rule/*"
}
}
}
] }

Unable to trigger AWS Lambda by upload to AWS S3

I am trying to build a Kibana dashboard fed with twitter data collected via AWS Kinesis firehose where data passes into an S3 bucket which triggers a Lambda function which passes the data to AWS Elastic Search and then to Kibana. I am following this blog https://aws.amazon.com/blogs/big-data/building-a-near-real-time-discovery-platform-with-aws/
The data is loading into the S3 bucket correctly but it never arrives in Kibana, I believe this is because the Lambda function is not being triggered by events in S3 as I would have hoped (there are no invocations or logs). I think this is because I have not set permissions properly. The Lambda function can be invoked manually by the test event.
On the Lambda function page I chose an existing role which I called lambda_s3_exec_role which has the AWSLambdaExecute policy attached to it but I feel I'm missing something else more specific to S3. I have been unable to follow this line in the blog in the create lambda function section because I do not recognise those options:
"10. Choose lambda_s3_exec_role (if this value does not exist, choose Create new role S3 execution role)."
Can anyone help me create the appropriate role/policy for the Lambda function, or spot what the problem may be?
From view permissions on the Lambda function I currently have:
FUNCTION POLICY
{
"Version": "2012-10-17",
"Id": "default",
"Statement": [
{
"Sid": "****",
"Effect": "Allow",
"Principal": {
"Service": "s3.amazonaws.com"
},
"Action": "lambda:InvokeFunction",
"Resource": "****",
"Condition": {
"ArnLike": {
"AWS:SourceArn": "arn:aws:s3:::****"
}
}
}
]
}
EXECUTION ROLE
{
"roleName": "lambda_s3_exec_role",
"policies": [
{
"document": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:*"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::*"
}
]
},
"name": "AWSLambdaExecute",
"id": "****",
"type": "managed",
"arn": "arn:aws:iam::aws:policy/AWSLambdaExecute"
}
]
}
The permissions you have listed look OK so I am going to try provide some steps that might help find the issue as it is difficult to understand specifically where your issue might be.
Does the execution role have the trust relationship with a trusted entity of lambda.amazonaws.com
Does your event prefix match the prefix in firehose. In the tutorial they are both twitter/raw-data/. If firehose is writing to a path that isn't the event prefix then the event won't be invoked.
Does the lambda trigger any errors when you manually invoke it
Does the lambda write to the logs when you manually invoke it
Test the lambda using dummy data (example data below)
CLI
aws lambda invoke \
--invocation-type RequestResponse \
--function-name helloworld \
--region region \
--log-type Tail \
--payload file://dummy_event.json \
--profile adminuser \
outputfile.txt
Example data
source
dummy_event.json
{
"Records":[
{
"eventVersion":"2.0",
"eventSource":"aws:s3",
"awsRegion":"us-west-2",
"eventTime":"1970-01-01T00:00:00.000Z",
"eventName":"ObjectCreated:Put",
"userIdentity":{
"principalId":"AIDAJDPLRKLG7UEXAMPLE"
},
"requestParameters":{
"sourceIPAddress":"127.0.0.1"
},
"responseElements":{
"x-amz-request-id":"C3D13FE58DE4C810",
"x-amz-id-2":"FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANOjpD"
},
"s3":{
"s3SchemaVersion":"1.0",
"configurationId":"testConfigRule",
"bucket":{
"name":"sourcebucket",
"ownerIdentity":{
"principalId":"A3NL1KOZZKExample"
},
"arn":"arn:aws:s3:::sourcebucket"
},
"object":{
"key":"HappyFace.jpg",
"size":1024,
"eTag":"d41d8cd98f00b204e9800998ecf8427e",
"versionId":"096fKKXTRTtl3on89fVO.nfljtsv6qko"
}
}
}
]
}
Struggled with this for a long time and eventually realized that your rule that triggers the lambda cannot have exactly the same name as the lambda itself or it won't work.