Allow Lambda to be invoked by all EC2 instances - amazon-web-services

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?

Related

Official example on AWS documentation on how to add a service principal on a resource based policy does not work

I several lambda functions on my account to be able to access a secret.
(I cannot use identity policies, don't ask why)
I am following this example from the official documentation so I am creating this resource based policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"lambda.amazonaws.com"
]
},
"Action": "secretsmanager:GetSecretValue",
"Resource": "*",
"Condition": {
"ArnLike": {
"aws:sourceArn": "arn:aws:lambda::1234567891911:*"
},
"StringEquals": {
"aws:sourceAccount": "1234567891911"
}
}
}
]
}
My lambda invocation fails as follows:
"An error occurred (AccessDeniedException) when calling the GetSecretValue operation: User: arn:aws:sts::1234567891911:assumed-role/my-secret-name/my-lambda-name is not authorized to perform: secretsmanager:GetSecretValue on resource: ps-shield-token because no identity-based policy allows the secretsmanager:GetSecretValue action",
????
I don't see the problem. Your policy example is valid for services that support service-linked roles1. Lambda functions do not support service-linked roles. Therefore, the policy example is not valid for Lambda.
Service-linked roles, which are AWS-managed, are referenced by service name in resource-based policies, as in the OP. For instance, the principal { “Service”: “elasticloadbalancing.amazonaws.com” } refers to the AWS-managed ELB service-linked-role, which is called AWSServiceRoleForElasticLoadBalancing. Again, there's no equivalent lambda.amazon.aws option here, because Lambda has no service-linked role2.
Functions have user-managed execution roles. Execution roles (EC2 Instances and ECS Tasks have something similar) are referenced by the role ARN in the resource-based policy "Principal": { AWS: <Lambda Role Arn> }, as in #jellycsc's answer.
Although the docs could definitely be clearer, your Example: Service principal does refer to just to service-linked roles. The first link on the page, AWS Service Principal, refers to "service principal" as used "services that support service-linked roles".
Lambda#Edge does support service-linked roles.
It's not the lambda service that's getting the secret value. The lambda service first assumes the execution role which you set in your lambda function, and the execution role is the principle of the secretsmanager:GetSecretValue action. Therefore, the following policy should work.
{
"Version": "2012-10-17",
"Statement":
[
{
"Effect": "Allow",
"Principal":
{
"AWS": "arn:aws:iam::1234567891911:role/<lambda-execution-role-name>"
},
"Action": "secretsmanager:GetSecretValue",
"Resource": "*"
}
]
}

AWS API Gateway Not Connecting to Lambda Alias

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/

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.

embed quicksight dashboard : (AccessDeniedException) when calling the RegisterUser operation

I am trying CLI based command to embed QuickSight Dashboard as per this link quicksightembed and this AWS Video AWSQuickSight
.
CLI Command :
aws configure
aws sts assume-role --role-arn "arn:aws:iam::842034702001:role/QuickSightEmbed" --role-session-name QSviewer
aws quicksight register-user --aws-account-id 842034702001 --namespace default --identity-type IAM --iam-arn "arn:aws:iam::842034702001:role/QuickSightEmbed" --user-role READER --session-name QuickSightEmbed --email String#email.com
Assumed Role is successful but while registering the user, I am getting below error :
An error occurred (AccessDeniedException) when calling the RegisterUser operation: User: arn:aws:iam::238683320570:user/String is not authorized to perform: quicksight:RegisterUser on resource: arn:aws:quicksight:eu-west-1:842034702001:user/default/QuickSightEmbed/QuickSightEmbed
Please suggest how we can avoid this error.
Custom Policy which we are using :
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "quicksight:RegisterUser",
"Resource": "*",
"Effect": "Allow"
},
{
"Action": "quicksight:GetDashboardEmbedUrl",
"Resource": "*",
"Effect": "Allow"
},
{
"Action": "sts:AssumeRole",
"Resource": "*",
"Effect": "Allow"
}
]
}
One thing that stands out is that the session name must match between calls.
In the first call you're using --role-session-name QSviewer but in the second you're using --session-name QuickSightEmbed. These ought to match.