Error reading new Lambda permissions: AccessDeniedException in GitHub Action - aws-lambda

I am deploying the AWS resources using GitHub Actions and I am using terraform to create resources.
I have given the required Assume and IAM policy to the GitHub repo to deploy the resources.
One of my use cases is, that I need a cloud watch event rule which triggers the lambda every 1 hr. The Cloud watch event rule and lambda have been created successfully.
But, I got Error: Error reading new Lambda permissions: AccessDeniedException: error in the below statement during deployment.
Which IAM policy needs to add to execute the above statement.
resource "aws_lambda_permission" "allow-cloudwatch-lambda-execute" {
statement_id = "AllowExecutionFromCloudWatch"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.lambda.function_name
principal = "events.amazonaws.com"
source_arn = aws_cloudwatch_event_rule.lambda-clodwatch-event-rule.arn
}

Related

EventBridge invokes Lambda as a target

We are designing a solution which has a Lambda function as a source and another Lambda function as a target to EventBridge.
I read that for the put_rule part, the RoleArn has the ARN for the role which the rule will use needs to have the permission to invoke the target Lambda function.
But for Lambda we don't use IAM roles, but use resource bases policies instead.
The question is, where we are specifying the resource based policy in the code. In the RoleArn?
And what's the fields in the targets part for the target Lambda function?
eventclient = boto3.client('events')
response = eventclient.put_rule(
Name='notificationScheduler',
ScheduleExpression='at(2023-02-01T02:30:00)',
State='ENABLED',
Description='schedule notifications reminders '
**RoleArn**='string', ## The ARN for the role which the rule will use needs to have the permission to invoke the target lambda function
)
response = eventclient.put_targets(
Rule='notificationScheduler',
Targets=[{ ??? }]
)
You must use a Lambda resource policy to grant EventBridge invoke permissions, not a role.
Docs: Amazon SQS, Amazon SNS, Lambda, CloudWatch Logs, and EventBridge bus targets do not use roles, and permissions to EventBridge must be granted via a resource policy. API Gateway targets can use either resource policies or IAM roles.
Create the Lambda permissions (= resource policy) with the AddPermission API:
lambdaclient.add_permission(FunctionName=func_name, StatementId="MyPermissionId", Action="lambda:Invoke", Principal="events.amazonaws.com")
Add the Lambda function as a rule target by ARN:
eventclient.put_targets(Rule="notificationScheduler", Targets=[{"Id": "MyLambdaTarget", "Arn": func_arn }])

how to resolve error while creating first AWS Lamda function

I am trying to create First Lambda function , i have got the access as "PowerUserAccess" . and its a new console . i am getting error as:
User: arn:aws:iam::387035554709:user/Sulabh#myemail.com is not authorized to perform: iam:CreateRole on resource: arn:aws:iam::387035554709:role/service-role/getListTest-role-9d7tzpx3 because no identity-based policy allows the iam:CreateRole action
how can i resolve this error? and create first lambda function?
also do i need to create Application first to add lambda functions inside that?
PowerUserAccess can not create IAM roles/policies. Contact with admin or login as Admin and follow the instructions below:
https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html

Unpublished user in sns even if has full administrative permission, lambda out of vpc

Good night I have a serious problem when trying to publish in a sns topic, my user has full access and still not publish. I am aware that if the lambda is in a vpc then I would have problems publishing to sns, however I separated my vpc lambda from the internet access lambdas, I use invoke to access the vpc, the lambda that publishes in sns is out of vpc and I can not publish in sns. Anyone with this problem?
message:
{
"code": 1072,
"message": "User: arn:aws:iam::{accountID}:user/s3_developer is not authorized to perform: SNS:Publish on resource: arn:aws:sns:us-east-1:{accountID}:snsMailSend"
}
The user s3_developer has full access admin, but still does not post to sns.
My iam
iamRoleStatements:
- Effect: Allow
Action:
- lambda:InvokeFunction
- lambda:InvokeAsync
Resource: "*"
- Effect: Allow
Action:
- s3:GetObject
- s3:ListBucket
- s3:PutObject
Resource: "arn:aws:s3:::"
- Effect: Allow
Action:
- ses:SendEmail
- ses:SendRawEmail
Resource: "arn:aws:ses:::"
- Effect: Allow
Action:
- sns:*
Resource: "*"
SNS Trigger and create in lambda
var enviroment = "SNS_TOPIC": "snsMailSend"
sendMail:
handler: lib/controllers/smtp/send.emailSend
events:
- sns: ${self:custom.secrets.SNS_TOPIC}
The topic is successfully created, I can publish by a simple lambda, but I can not publish my application where is the lambda that has the trigger and the lambda that publishes. I don't know what's wrong, does anyone see a light?
Finally I solved, I created a specific user for SNS gave proper privileges and when instantiating sns I pass your user access and secrets, resolved. I saw that other people with similar problems hope this helps.
const aws = require('aws-sdk')
const sns = new aws.SNS({ region: process.env.REGION, accessKeyId: process.env.SNS_KEY, secretAccessKey: process.env.SNS_SECRET })

How can I use permissions generated in AWS Custom Authorizer in my lambda code?

I'd like to generate a custom policy that provides fine grained access to DynamoDB tables inside an AWS custom authorizer. Is this possible?
In serverless, my configuration looks like this:
functions:
APIAuthorizer:
handler: src/services/auth/handlers.apiAuthorizer
cors: true
GraphQLAPI:
handler: src/services/graphql/handlers.apiHandler
events:
- http:
path: "/api"
method: post
cors: true
authorizer:
name: APIAuthorizer
type: request
resultTtlInSeconds: 0
I've verified that my custom authorizer is being called, and that various permissions it generates (sts:AssumeRole, lambda:InvokeFunction, execute-api:Invoke, and others) are required for successfully invoking the API handler. So my custom authorizer is working and the result it provides is necessary.
However, when the authorizer includes dynamodb permissions, e.g., a statement like
{ Effect: "Allow", Action: "dynamodb:", "Resource": "" }
my API handler (the GraphQLAPI function) fails with a message like
User: arn:aws:sts::<myaccountid>:assumed-role/<mydefaultrole>/myservice-mystage-GraphQLAPI is not authorized to perform: dynamodb:Query on resource: arn:aws:dynamodb:us-east-1:<myaccountId>:table/<mytable>/index/<someIndex>
(I noticed the complaint is about an index permission, so also tried adding specific permissions for that index and/or for all indexes, but this has no effect.)
The bottom line, after many different attempts, is that dynamodb permissions issued by the custom authorizer are completely ignored. My lambda node.js code is using the AWS node SDK, which should be picking up permissions from the instance environment. I assumed this would include permissions generated by the custom authorizer.
Finally, I noticed that the AWS javascript SDK documentation on how credentials are loaded says only "The execution role provides the Lambda function with the credentials it needs to run and to invoke other web services". I.e., it doesn't mention the dynamically generated credentials issued by the custom authorizer.
This seems to explain the behavior I'm seeing. My API handler only has permissions from the statically defined execution role (the error message indicates that too), and isn't granted permissions generated by the custom authorizer.
Is there anyway to use the permissions my custom authorizer generates inside my API handler?
I think you misunderstood the IAM policy output from Lambda authorizers. The purpose of the IAM policy output from the authorizer is to reflect what the outcome should be for API gateway with respect to continuing to process the request.
The policy returned is not necessarily applied to the invoked function, but applied to the invocation of the function. It merely tells API Gateway which APIs the requesting user is authorized to access.
If you wish to give the API functions being invoked specific access to resources such as DynamoDB tables, or any other AWS resources, those have to be configured in the role assigned to the Lambda function. Otherwise, you may be able to specify a role that the Lambda function to be invoked would assume that grants it additional permissions. This role can be passed via the context parameters from the authorizer.

Cognito, API Gateway and Lambda assuming the identity of the cognito user

I’m building a React app, using API Gateway, lambda and cognito (basically starting from the https://serverless-stack.com tutorial). I would like to setup fine grained access control to my DynamoDb (i.e. through IAM policies that restrict access to DynamoDb tables based upon the logged-in user - like https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_examples_dynamodb_rows.html)
AFAIK, a lambda function assumes a service role, as defined in the serverless.yml file, that has in itself nothing to do with the AIM policy that is attached to the logged in cognito user. I know that using an aim_authorizer, I can get info on the logged in user.
My question: is it possible to have the lambda do AWS calls on behalf of the given cognito user, thus honoring the IAM policies attached to that user? (a bit similar as to how the serverless-stack tutorial interacts with S3)
All suggestions welcome.
You can explicitly specify to any AWS client library which credentials to use in order to sign requests (by default they are taken from the runtime environment):
import { DocumentClient } from 'aws-sdk/clients/dynamodb';
const client = new DocumentClient({
credentials: ...
});
Those security credentials are obtain via STS. There are various scenarios how to get a hold of the user's identity to obtain credentials, but usually you would either assumeRole, if you have an arn of a role, or assumeRoleWithWebIdentity, if there is an actual user that did a flow of OpenID Connect:
import { Credentials, STS } from 'aws-sdk';
const sts = new STS();
const stsResponse = await sts.assumeRole({ RoleArn: 'can-be-cognito-group-arn' }).promise();
// or
// const stsResponse = await sts.assumeRoleWithWebIdentity({ WebIdentityToken: 'open-id-token' }).promise();
const credentials = new Credentials(
response.Credentials.AccessKeyId,
response.Credentials.SecretAccessKey,
response.Credentials.SessionToken);

Resources