Testing Java lambda function via API Gateway: Unable to determine service/operation name to be authorized - aws-lambda

I'm playing around with API Gateway. Basically, I have a simple java code that aims to return a greetings message:
public class Greetings implements RequestHandler<GreetingsRequest, String> {
//enable pretty print JSON output
Gson gson = new GsonBuilder().setPrettyPrinting().create();
public String handleRequest(GreetingsRequest input, Context context) {
LambdaLogger logger = context.getLogger();
System.out.println("Welcome to lambda function");
// log execution details
logger.log("ENVIRONMENT VARIABLES: " + gson.toJson(System.getenv()));
logger.log("CONTEXT: " + gson.toJson(context));
// process event
logger.log("EVENT: " + gson.toJson(input));
logger.log("EVENT TYPE: " + input.getClass().toString());
return "Hello " + input.getName();
}
}
I've attached to the lambda function a role with the following characteristics:
4 default policies (AmazonAPIGatewayInvokeFullAccess, CloudWatchFullAccess, AmazonAPIGatewayAdministrator, AWSLambdaBasicExecutionRole) and a custom one (lambda_execute).
Role's Trust Relationship:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": [
"lambda.amazonaws.com",
"apigateway.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
In relation to the custom policy "lambda_execute":
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "lambda:InvokeFunction",
"Resource": "*"
}
]
}
In relation to the API Gateway:
The resource:
The method request:
The integration request:
When I am testing out the resource, the following message is sent out:
<AccessDeniedException>
<Message>Unable to determine service/operation name to be authorized</Message>
</AccessDeniedException>
Anyone could point me out what I'm missing or doing wrong? Tks so much in advance.

Two options to invoke Lambda function from Api Gateway REST Api.
Integration Type Lambda: just need to give Lambda function name.
Integration Type AWS Service: This method is also used to send events directly from Api Gateway to other aws services like Sns, Sqs, Kinesis, etc.
Question is about using second method of invoking lambda using AWS Service.
PathOverride proxies request from Api Gateway to different endpoint.
Full endpoint to invoke a Lambda function is https://lambda.us-east-1.amazonaws.com/2015-03-31/functions/arn:aws:lambda:us-east-1:111122223333:function:my-function-name/invocations
First part https://lambda.us-east-1.amazonaws.com/ will be appended by Api Gateway, second part 2015-03-31/functions/arn:aws:lambda:us-east-1:111122223333:function:my-function-name/invocations should be given in path override.
if path override is incorrect, thats when we get Unable to determine service/operation name to be authorized Error.

Related

CORS error with AWS api gateway and java lambda function

Today I created one api gateway on aws and one java lambda function. Then finally integrated api gateway with lambda function.
So when I hit the api using postman then it returns the result which is basically a list of customer. Till now everything looks fine. Following is the
#Override
public TestResponse handleRequest(Request input, Context context) {
TestService testService = SingletonServiceManager.getInstance().getTestService();
TestListResponse response = (TestListResponse)productListService.executeRequest(input);
return response;
}
After executing it returns following output.
{
"status": 200,
"products": [
{
"name": "test1",
"code": "test1",
"status": true
},
{
"name": "test2",
"code": "test2",
"status": true
}
]
}
but when I started integrating this with api call with Angular from local machine it start throwing CORS issue. Angular client using it CORS setting to connect.
Can someone help me on this. Do I need to enable something special from lambda function.
You need to enable CORS in your API Gateway configuration.

Correct terraform syntax for adding permissions to AWS Lambda

I'm learning Terraform and I'm trying to get the correct syntax to specify the IAM role permissions for it. I want these capabailities:
Lambda can be invoked from an API Gateway that I also create in Terraform
Lambda can write to Cloudwatch logs
I have the following which allows the API gateway to invoke the Lambda:
resource "aws_iam_role" "my_lambda_execution_role" {
name = "my_lambda_execution_role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": [
"lambda.amazonaws.com",
"apigateway.amazonaws.com"
]
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
I have seen the snippet below allows the Lambda to write to CloudWatch. I'm trying to combine these snippets to get all of the permissions but I can't get it right. What is the correct syntax to give all of these permissions to the role?
{
"Statement": [
{
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Effect": "Allow",
"Resource": "arn:aws:logs:*:*:*"
}
]
}
https://www.terraform.io/docs/providers/aws/r/iam_role_policy_attachment.html
You need to create the policy and then attach it to your role. The link above includes a more complete example than on the iam role page.
IAM policy along with role.
# iam
data "aws_iam_policy_document" "policy" {
statement {
sid = ""
effect = "Allow"
principals {
identifiers = ["lambda.amazonaws.com"]
type = "Service"
}
actions = ["sts:AssumeRole"]
}
}
resource "aws_iam_role" "iam_for_lambda" {
name = "iam_for_lambda"
assume_role_policy = "${data.aws_iam_policy_document.policy.json}"
}
resource "aws_iam_role_policy" "frontend_lambda_role_policy" {
name = "frontend-lambda-role-policy"
role = "${aws_iam_role.iam_for_lambda.id}"
policy = "${data.aws_iam_policy_document.lambda_log_and_invoke_policy.json}"
}
data "aws_iam_policy_document" "lambda_log_and_invoke_policy" {
statement {
effect = "Allow"
actions = [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
]
resources = ["*"]
}
statement {
effect = "Allow"
actions = ["lambda:InvokeFunction"]
resources = ["arn:aws:lambda:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:function:*"]
}
}
Please find the complete terraform code at my github
In a previous answer I wrote up some background information on how IAM roles work and what an "assume role policy" is. I'm going to assume that background information in this answer.
The policy you've given in your assume_role_policy argument in the resource "aws_iam_role" "my_lambda_execution_role" block is the policy governing which users and services are allowed to "assume" this role. In this case, you are allowing AWS Lambda and Amazon API Gateway to make requests using the privileges granted by this role.
However, by default the role doesn't grant any privileges at all. To address that, we need to attach one or more access policies to the role. The other policy JSON you shared here is an access policy, and to associate it with the role we need to use the aws_iam_role_policy resource type:
resource "aws_iam_role_policy" "logs" {
name = "lambda-logs"
role = aws_iam_role.my_lambda_execution_role.name
policy = jsonencode({
"Statement": [
{
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
],
"Effect": "Allow",
"Resource": "arn:aws:logs:*:*:*",
}
]
})
}
Usually Terraform automatically infers dependencies between resource blocks by noticing references like the aws_iam_role.my_lambda_execution_role expression in the above, and indeed in this case Terraform will determine automatically that it needs to complete the creation of the role before attempting to attach the policy to it.
However, Terraform cannot see automatically here that the policy attachment must complete before the policy itself is operable, and so when you refer to the role from your API Gateway and Lambda resources you must use depends_on to tell Terraform that the policy attachment must complete before the policy will become usable:
resource "aws_lambda_function" "example" {
filename = "${path.module}/example.zip"
function_name = "example"
role = aws_iam_role.my_lambda_execution_role.arn
handler = "example"
# (and any other configuration you need)
# Make sure the role policy is attached before trying to use the role
depends_on = [aws_iam_role_policy.logs]
}
If you don't use depends_on like this, there is a risk that the function will be created and executed before the role attachment is complete, and thus initial executions of your function could fail to write their logs. If your function is not executed immediately after it's created then this probably won't occur in practice, but it's good to include the depends_on to be thorough and to let a future human maintainer know that the role's access policy is also important for the functionality of the Lambda function.

Assigned function policy to lambda which allows all CloudWatch Events rule to invoke lambda?

I used the above CLI command but got an error in the console, please find the attached screenshot of the error
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/*"
}
}
} ] }
I followed the answer from the below link but still got an error:
Allow all cloudwatch event rules to have access to lambda function
Perhaps a clue to this, is that a CloudWatch Event rule name of * does not appear to be valid. For example, if you try to delete this rule in the AWS lambda console area, you will get an error like this on the trigger UI area:
It would be nice if this approach was formally supported in some way, but I don't think it is. idk

Using AWS lambda function to call lex chat bot

I am trying to use boto3 from within AWS lambda function in order to do post_text to a Lex chat bot.
Python code:
client = boto3.client('lex-runtime')
data = "string input"
response = client.post_text(
botName='xxx',
botAlias='yyy',
userId='id',
inputText= data)
but i get:
An error occurred (AccessDeniedException) when calling the PostText
operation: User: arn:aws:sts::111111111:assumed-
role/functionName/functionName is not authorized to perform: lex:PostText on
resource: arn:aws:lex:us-east-1:111111111:bot:xxx:yyyy"
So i set up IAM rule an and policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"lex:PostText"
],
"Resource": [
"arn:aws:lex:us-east-1:111111111:bot:xxx:yyyy"
]
}
]
}
Trust relationship:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
But it still doesn't work and i get the same error.
I experienced the same issue recently.
It is most certainly related to the permissions assigned to the IAM role that you're using when running the Lambda function.
The easiest way to resolve this is below:-
Open the Lambda function on the AWS Console.
Scroll down to the "Execution role" section.
Click the link under the role to view the role in a new window. It
should look something like this: "View the role".
In the new window under the permissions tab click on "Attach
policies".
This takes you to a new screen. On this screen filter the listed
policies by typing in "lex" in the input field.
The filtered list will contain a policy call "AmazonLexRunBotsOnly".
Attach this policy to your role.
Save the changes and make your way back to your lambda function.
Save the lambda function and retest.
This will resolve your issue.

Serverless framework Lambda AppSync error

I'm using the serverless framework to upload an AWS Lambda function to be used as a data source in AppSync. The serverless.yml that I have is very basic:
service: mongoose-lambda-srvrls
provider:
name: aws
runtime: nodejs6.10
region: us-west-2
functions:
mongoose:
handler: index.handler
When I run an AppSync GraphQL query I get the error:
{
"data": {
"getPost": null
},
"errors": [
{
"path": [
"getPost"
],
"data": null,
"errorType": "Lambda:AWSLambdaException",
"errorInfo": null,
"locations": [
{
"line": 43,
"column": 2
}
],
"message": "User: arn:aws:sts::433333333335:assumed-role/appsync-datasource-lam-kkzuep-mongoose-lambda-srvr/APPSYNC_ASSUME_ROLE is not authorized to perform: lambda:InvokeFunction on resource: arn:aws:lambda:us-west-2:43333333333335:function:mongoose-lambda-srvrls-dev-mongoose (Service: AWSLambda; Status Code: 403; Error Code: AccessDeniedException; Request ID: 9fa82eb9-3a64-11e8-88a1-09c4e639fc45)"
}
]
}
I'm pretty sure that I need to flesh out my YML so that this lambda stack will play nice with AppSync but I'm not quite sure what to do.
A little more info. When looking at the resources in Lambda's CloudFormation, I see:
IamRoleLambdaExecution mongoose-lambda-srvrls-dev-us-west-2-lambdaRole AWS::IAM::Role
MongooseLambdaFunction mongoose-lambda-srvrls-dev-mongoose AWS::Lambda::Function
MongooseLambdaVersionwCQ1... arn:aws:lambda:us-west-2:4542242445:function:mongoose-lambda-srvrls-dev-mongoose:4 AWS::Lambda::Version
MongooseLogGroup /aws/lambda/mongoose-lambda-srvrls-dev-mongoose AWS::Logs::LogGroup
ServerlessDeploymentBucket mongoose-lambda-srvrls-d-serverlessdeploymentbuck-qwp8sdfgjr AWS::S3::Bucket
Whereas in the Lambda that I made using the AppSync docs (AWS CLI) has the following CloudFormation resources:
AppSyncLambdaInvokePolicy Fulls-AppS-15SHASDFSADZ03N AWS::IAM::Policy
AppSyncServiceRole Fullstack-Lamba-AppSyncServiceRole-DK8QHASDFE5R AWS::IAM::Role
LambdaExecutionRole Fullstack-Lamba-LambdaExecutionRole-OJHASDF3AHG1 AWS::IAM::Role
LambdaFunction fullstack-lambda AWS::Lambda::Function
It looks like the role you gave AppSync to run the lambda function does not have permission to invoke that particular lambda.
You will need to create or modify a role so it has the following permissions.
The IAM role should have a policy which enables anybody who assumes it to run/invoke your lambda function:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"lambda:Invoke"
],
"Resource": "arn:aws:lambda:REGION:ACCOUNTNUMBER:function/LAMBDA_FUNCTION"
}
]
}
The role should also have a trust policy. This trust policy will allow AppSync to assume the role on your behalf. This is how AppSync invokes your lambda whenever a graphQL request comes in.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "appsync.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Once you have an IAM role with necessary permissions, you will need to make sure it is associated with the lambda data source in AppSync. You can select the role in the Data Sources section of the AppSync console or use the AppSync CLI to update the lambda data source and make it use your role.
For more information about creating a lambda function which plays nice with AppSync, here is the documentation: https://docs.aws.amazon.com/appsync/latest/devguide/tutorial-lambda-resolvers.html#configure-data-source-for-aws-lambda
I think they made a mistake in the https://docs.aws.amazon.com/appsync/latest/devguide/tutorial-lambda-resolvers.html#configure-data-source-for-aws-lambda documentation.
The allowed action should be lambda:InvokeFunction and NOT lambda:Invoke
This is working:
{
"Version" : "2012-10-17",
"Statement" : [{
"Effect" : "Allow",
"Action" : "lambda:InvokeFunction",
"Resource" : "arn:aws:lambda:REGION:ACCOUNTNUMBER:function/LAMBDA_FUNCTION"
}]
}

Resources