Unable to send message from API Gateway to FIFO SQS - amazon-web-services

I have integrated a API Gateway with FIFO SQS queue using below link
https://medium.com/#pranaysankpal/aws-api-gateway-proxy-for-sqs-simple-queue-service-5b08fe18ce50
Below is the snippet of role policy
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"sqs:SendMessageBatch",
"sqs:ReceiveMessage",
"sqs:SendMessage"
],
"Resource": "arn:aws:sqs:*:12345678:Stg"
}
]
}
Whenever is try to test it from API Gateway it throws below error:-
"Message": "The request must contain the parameter MessageGroupId."
So I tried to send it via query string but still the error persist.
I have followed the same steps as per the above link for body template and header.
MessageGroupId=098
Simply passing above value in query string and body is below
{"ty":"ui"}

You need to add MessageGroupId, and MessageDeduplicationId to the URL Query String Parameters in Method Execution. Same way you did for MessageBody.
You'll also need to add MessageGroupId, and MessageDeduplicationId to Integration Request. Again the same way you did with MessageBody.

You can extract the MessageGroupId and MessageDeduplicationId from the response of API gateway. eg: if the payload is something like below, you can extract the any properties from the payload.
Clear video tutorial here. https://www.youtube.com/watch?v=dXa9KA-G9Dg
Assume the payload is like this:
{
"data" :{
"jobNumber": "123456"
}
}
Then the template in api gateway is below. It extract the jobNumber from the payload and set to MessageGroupId. Here the MessageDeduplicationId is getting from the context.
#set($dedupId = $context.requestId)
#set($groupId = $input.json('$.data.jobNumber'))
Action=SendMessage&MessageBody=$input.body&MessageGroupId=$groupId&MessageDeduplicationId=$dedupId

Related

Passing custom data from AWS Lambda Authorizer

In short, I want to pass information from my custom Lambda Authorizer to the backend. I have an rest API GW with a proxy integrated lambda as backend. The return object form the custom authorizer looks like this the json below. In this case I want to pass var1 and var2 to the proxy lambda.
{
"principalId": "ExecuteAPISid",
"policyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Action": "execute-api:Invoke",
"Effect": "Allow",
"Resource": "*"
}]
},
"context": {
"var1": "hello_world",
"var2": "hello_world2"
}
}
I see that this question has been asked and answered previously, however the suggested solution, as mention for example here, refers to "header mappings" under Integration Request in the AWS API Gateway menu. For me however, I have no such options. Thus I have an idea of what I want to do but lack the ability to how to implement it.
Does anyone have an idea of how to implement these header mappings? Complete settings shown in image below.
Edit: After further digging it turns out that the issue relates to me using using a lambda-proxy integration. This answer highlights just that. However, that simply shifts my question to: why is my requestContext not containing the authorizer object.
Turns out that when you are using proxy integration then the context object from the custom Authorizer Lambda is automatically passed through to the event as:
"requestContext": {
"resourceId": "XXXX",
"authorizer": {
"var1": "hello_world1",
"var2": "hello_world2",
"principalId": "ExecuteAPIS",
"integrationLatency": 780
},
The problem was that I had forgotten to "deploy" my API GW.

500 Internal Server Error using DeleteItem from DynamoDB using API-Gateway

Steps to reproduce:
Create a new DynamoDB table Events with partition key id
Create a new item in Events with an id of 123456. All other fields are blank.
Create an API-Gateway. Create path of events and a resource of remove-event under it.
Create a method of POST. AWS Service, DynamoDB, , and an action of DeleteItem. Add an IAM role that has access to the Events table too.
Open postman. Fill out the authorization and add the following parameters:
POST https://<DB GOES HERE>.execute-api.us-east-2.amazonaws.com/prod/events/remove-event
In the body, put (This is following the provided sample request here):
{
"TableName": "Events",
"Key": {
"id": {
"S": "123456"
}
},
"ReturnValues": "NONE"
}
Finally, hit send.
{
"message": "Internal server error"
}
I have no idea what is causing this. Create, Update, and Read work with issue. It is ONLY Delete that fails.
EDIT: In case anyone is curious about my policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:*:<sensitive infomation>:*/*/*/*"
}
]
}
Removing this changes the 500 response to a 403, so this is not a policy issue.

Which is the correct way to configure IpAddress condition in Policy document for REST API?

I'm trying to allow only specific IP addresses to access my API Gateway REST API without success.
I configured the following resource policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:eu-west-1:my-account-id:rest-api-id/*/*/*",
"Condition": {
"IpAddress": {
"aws.SourceIp": "MY.IP.MY.IP/32"
}
}
}
]
}
But when I send a request using Postman I receive 403 forbidden.
If I set "aws.SourceIp": "0.0.0.0/0" I receive 403 as well.
If I remove the condition from the policy then it works (I don't receive 403), so I guess something is wrong with IpAdress condition.
I have a C# lambda function integrated with the REST API where I log the SourceIp to CloudWatch using the following code:
context.Logger.LogInformation($"SourceIp: {request.RequestContext.Identity.SourceIp}");
It logs the following:
2022-07-01T06:38:32.634Z 0dc80274-bbbb-494c-ba73-541f053ba5a2 info SourceIp:
MY.IP.MY.IP
What am I missing? How to properly write the policy?
I changed "aws.SourceIp" to "aws:SourceIp" and problem solved. Sorry for the typo.

New AWS Lambda URLs - has anyone got the 'secure' version with the AWS_IAM working?

I have a simple function that returns an item of text.
When I set auth to NONE it works fine.
When I set auth to AWS_IAM and create the resource based policy within the permissions section of AWS Lambda I set the following:
"Version": "2012-10-17",
"Id": "default",
"Statement": [
{
"Sid": "sid8",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::xxxxxxxxxx:user/xxxxxxxxxx"
},
"Action": "lambda:InvokeFunctionUrl",
"Resource": "arn:aws:lambda:eu-west-1:xxxxxxxxx:function:simpleFunction",
"Condition": {
"StringEquals": {
"lambda:FunctionUrlAuthType": "AWS_IAM"
}
}
}
]
}
On this I get a forbidden error.
Every demo / example on the internet uses NONE for auth.
I have also tried adding the lambda:InvokeFunctionUrl to the IAM policy of the user for the specified resource but still getting a forbidden error.
Am I missing something or does this aspect of the new function not work?
The problem is that when you are using IAM_AUTH you're required to sign your requests with SigV4. Essentially, this is identical to using API Gateway with IAM_AUTH type.
There are multiple ways of signing requests you can even use botocore functionality to do so. The easiest would be to use awscurl or postman, also check this doco that confirms this requirement https://docs.aws.amazon.com/lambda/latest/dg/urls-invocation.html

Is it possible to customize API Gateway custom authorizer response message and status code on unauthorized?

How do I set the status code to 429 and return a custom message from an API Gateway custom authorizer?
The functionality here is a bit limited. But I've found that by editing the Gateway Responses for the 403 and 401 status codes. My custom message gets shown to users.
For example, by saving the below and re-deploying the API. I now get my custom message when the lambda authorizer returns a deny policy.
Am also searching for this solution. i got messages like custom message & status code from our custom authorizer is not enabled.
refer here - https://forums.aws.amazon.com/thread.jspa?threadID=226689
But while coding for custom authorizer found that you can send either 401 or 403
//this will send status - 401 , body - {"message":"unauthorized"}
context.fail('Unauthorized')
/*this will send status 403 , body - {
"Message": "User is not authorized to access this resource with an explicit deny"
}*/
context.succeed({
"policyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "execute-api:Invoke",
"Effect": "Deny",
"Resource": [
"arn:aws:execute-api:ap-south-1:************/Development/*/*"
]
}
]
}
})
note : like allow you have to create deny policy