I am using the Amazon Selling Partner API (SP-API) and am trying to set up a Pub/Sub like system for receiving customer orders etc.
The Notifications API in SP-API sends notifications of different types in 2 different ways depending on what event you are using. Some send directly to eventBridge and others are sent to SQS. https://developer-docs.amazon.com/sp-api/docs/notifications-api-v1-use-case-guide#section-notification-workflows
I have correctly set up the notifications that are directly sent to eventBridge, but am struggling to work the SQS notifications. I want all notifications to be send to my own endpoint.
For the SQS model, I am receiving notifications in SQS, which is set as a trigger for a Lambda function (This part works). The destination for this function is set as another eventBridge (this is that part that doesn't work). This gives the architecture as:
SQS => Lambda => eventBridge => my endpoint
Why is lambda not triggering my eventBridge destination in order to send the notifications?
Execution Role Policies:
Lambda
AWSLambdaBasicExecutionRole
AmazonSQSFullAccess
AmazonEventBridgeFullAccess
AWSLambda_FullAccess
EventBridge
Amazon_EventBridge_Invoke_Api_Destination
AmazonEventBridgeFullAccess
AWSLambda_FullAccess
EventBridge Event Pattern:
{"source": ["aws.lambda"]}
Execution Role Trusted Entities:
EventBridge Role
"Service": ["events.amazonaws.com", "lambda.amazonaws.com", "sqs.amazonaws.com"]
Lambda Role
"Service": ["lambda.amazonaws.com", "events.amazonaws.com", "sqs.amazonaws.com"]
Lambda Code:
exports.handler = function(event, context, callback) {
console.log("Received event: ", event);
context.callbackWaitForEmptyEventLoop = false
callback(null, event);
return {
statusCode: 200,
}
}
Would it be possible to share the access policy for SQS que? I have setup the SQS que to receive notifications but nothing is landing in my SQS que, the subscription and destination is setup, I am suspecting that there is an issue with the access, it would be very helpful is you could share the access policy format that is working for your SQS que.
This is what I am using:
{
"Version": "2012-10-17",
"Id": "Policy1652298563852",
"Statement": [
{
"Sid": "Stmt1652298557402",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::82382xxxx:root"
},
"Action": [
"sqs:SendMessage",
"sqs:SetQueueAttributes"
],
"Resource": "arn:aws:sqs:us-east-1:823829xxxx:SDNotificationsQueue1"
}
]
}
Related
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.
I have to trigger a lambda function once specific stack is created.
I have created the below CloudWatch event rule and associated the target to that lambda function but it is not triggering the lambda.
{
"source": [
"aws.cloudformation"
],
"detail-type": [
"AWS API Call via CloudTrail"
],
"detail": {
"eventSource": [
"cloudformation.amazonaws.com"
],
"eventName": [
"CreateStack"
],
"stackName": [
"sql-automate-04-08"
]
}
}
Please let me know if i am missing anything here.
This doesn’t work using CloudWatch Event Rules because the CloudFormation stack’s lifecycle events don’t reflect individual API calls.
However, you can configure CloudFormation to send stack events to an Amazon SNS topic via its NotificationARNs property. An AWS Lambda function subscribed to that topic can then filter and process the events.
This EventBridge Rule has worked for me:
{
"source": ["aws.cloudformation"],
"detail-type": ["CloudFormation Stack Status Change"],
"region": ["us-east-1"],
"detail": {
"status-details": {
"status": ["CREATE_COMPLETE"]
}
}
}
I'm using a SNS Topic as a Dead Letter Queue to handle errors thrown by multiple Lambdas. In the error messages, there are the following attributes :
RequestID,
ErrorCode,
ErrorMessage,
However, I can't easily find which Lambda threw the error, since nothing related to it appear in the message (eg: ARN, function name...)
Although it's possible to look up the request ID on CloudWatch, or to create multiple topics, there should be a much easier way to find which Lambda threw the error. Below is the structure of the received message:
{
"Records": [
{
"EventSource": "aws:sns",
"EventVersion": "1.0",
"EventSubscriptionArn": "",
"Sns": {
"Type": "Notification",
"MessageId": "",
"TopicArn": "",
"Subject": null,
"Message": "",
"Timestamp": "",
"SignatureVersion": "",
"Signature": "",
"SigningCertUrl": "",
"UnsubscribeUrl": "",
"MessageAttributes": {
"RequestID": {
"Type": "String",
"Value": ""
},
"ErrorCode": {
"Type": "String",
"Value": "200"
},
"ErrorMessage": {
"Type": "String",
"Value": "test"
}
}
}
}
]
}
Is there any way to add information, such as the ARN, on the Lambda which triggered this error message?
You can use AWS CloudTrail to identify which Lambda executed:
https://docs.aws.amazon.com/lambda/latest/dg/logging-using-cloudtrail.html
You should have one DLQ per Lambda function. This will let you know where the dead letter is coming from.
I ended up configuring:
One unique SNS topic for every lambda DLQ.
A lambda listening to the above topic and storing the request ID in S3
A trail on CloudTrail logging every lambda invoke
A lambda matching the failed request ID in S3 and the cloudtrail logs. The latter provide the name of the failed lambda.
This infrastructure might seem a bit complicated but it's working very well. It allows to only add one unique onError: ... line of code in every lambda configuration file.
Not sure if you figured out a solution or not, but i solved a somewhat similar problem with a little help from boto3.
To give some more context about my setup:
I had 2 lambda functions (lambdaA and lambdaB) listening to a SNS topic which gets updated by S3 object creation events.
Both lambda functions use one SNS topic as DLQ which is subscribed by a single dlq lambda (lambdaDLQ).
In the lambdaDLQ's received message, you get a Message attribute which has the message received by the error throwing lambda functions (lambdaA or lambdaB) which contains the information about SNS message received by them.
So the steps i used to figure out the error throwing lambda function were:
Parse the Message attribute from lambdaDLQ's event into json.
Get the EventSubscriptionArn from the above parsed message. This holds the subscription details of the error throwing lambda.
Using boto3 to get Protocol, Endpoint, etc. Which give the name of the error throwing lambda.
sns_client = boto3.client('sns')
arn = 'arn_goes_here'
response = sns_client.get_subscription_attributes(SubscriptionArn=arn)
In case your error throwing lambda functions do not listen to a SNS topic, you might need to change this a little bit.
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.
I'm having trouble understanding why a Cloudwatch event rule is not firing.
I've followed this related question and did the following.
Created a Cloudtrail which sends events to a Cloudwatch log
Created the following CloudWatch event rule:
{
"detail-type": [
"AWS write API Call via CloudTrail"
],
"source": [
"aws.ecr"
],
"detail": {
"eventSource": [
"ecr.amazonaws.com"
],
"eventName": [
"PutImage"
]
}
}
Created a lambda to be invoked by this rule.
I can verify that in my Cloudwatch log group (set up to accept events from Cloudtrail) I am seeing the PutImage event. However, the lambda never fires and the rule metrics show that it is never triggered. I am assuming at this point the rule must be faulty (I would expect to see the rule triggered even if the lambda is faulty) but I can't see what additional logic is required. Is it necessary to link my event to a particular log group?