AWS Step Function keyerror - amazon-web-services

I am following this guide to send approval emails to myself: https://aws.amazon.com/blogs/aws/using-callback-urls-for-approval-emails-with-aws-step-functions/
The code in this guide is exactly the same as mine & I have given this input to the step function:
{
"name": "TestName"
}
Every time I try to run the step function, i get the following error:
Error
KeyError
Cause
{
"errorMessage": "'urls'",
"errorType": "KeyError",
"stackTrace": [
" File \"/var/task/lambda_function.py\", line 35, in lambda_handler\n urls = json.loads(response['Payload'].read())['urls']\n"
]
}
Its referring to this line: urls = json.loads(response['Payload'].read())['urls']
this line is part of the code that is in the AWS Lambda function.
What does this error mean, What can I do to fix this?

I have never tested that Lambda/Python end to end doc so i cannot tell if you it works. However, this one definitely works. It invokes multiple AWS Services via a Lambda function and does include sending email messages. It uses the Java V2 AWS SDK.
Using AWS Step Functions and the AWS SDK for Java to build workflows that sends notifications over multiple channels

Related

Snowflake external function throws "with remote service error: 400" when calling AWS lambda through API gateway

Am trying to call AWS lambda function through Snowflake external function via API gateway.
I had followed the snowflake documentation steps and everything works fine(I can retrieve results in snowflake) when I had used the examples which is there in the document.
But upon modifying the lambda code for as per the flow (Trying to replicate
https://medium.com/snowflake/governed-access-to-files-and-data-sharing-using-snowflake-unstructured-data-management-193b6fcda65e
), i could succesfully execute via lambda function only and not through snowflake external function.
It returns:
Request failed for external function GET_PDF_INFO with remote service error: 400"
When calling through AWS lambda function test code,am passing below JSON payload to test,which successfully returns
{
"body":
"{ \"data\": [ [ 0, \"<pre signed url>", \"page\" ], [ 1, \"<pre signed url>", \"life, the universe, and everything\" ] ] }"
}
But when called from snowflake i believe the JSON payload looks different as we see from the error:
Request failed for external function GET_PDF_INFO with remote service error: 400 '{ "data":[ [0,<pre signed url>","pdf"] ] }'; requests batch-id: 01a005a8-0000-1a86-0002-0d2e00016abe:2:0; request batch size: 1 rows; request retries: 0; response time (last retry): 1.67186s
Please suggest
Apologize my bad!! Issue due to wrong s3 file name been passed to the payload.After correcting it,i could retrieve the output from AWS lambda to Snowflake.

Invoking AWS Lambda via CLI returns ERROR: Could not parse payload into json: Unexpected character ((CTRL-CHAR, code 145)):

I am trying to follow along the AWS Getting Started with Lambda Tutorial, but I am having Issues actually invoking my Function using the CLI.
I came across THIS step and got two errors:
An error occurred (InvalidRequestContentException) when calling the
Invoke operation: Could not parse request body into json: Could not
parse payload into json: Unexpected character ((CTRL-CHAR, code 145)):
expected a valid value (JSON String, Number, Array, Object or token
'null', 'true' or 'false') at [Source: (byte[])"��j[�"; line: 1,
column: 2]
and
An error occurred (ResourceNotFoundException) when calling the
GetLogEvents operation: The specified log group does not exist.
I assume the first error is caused by the first command :
aws lambda invoke --function-name my-function --payload '{"key": "value"}' out.json
and the second error accordingly by:
aws logs get-log-events --log-group-name /aws/lambda/my-function --log-stream-name $(cat out) --limit 5
I am more concerned about the first error.
I tried to solve this, by looking at the documentation for invoking a lambda function using the CLI. The most basic example was:
aws lambda invoke --function-name my-function --payload '{ "key":
"value" }' response.json
Using this, I get the same Error code
Could not
parse payload into json: Unexpected character ((CTRL-CHAR, code 145)):
I have asked about this in the AWS Dev Forums, but have not gotten any answer.
There where a few topics about similar errors on Stackoverflow, however they mentioned a specific character that was missing in the payload to be valid JSON.
According to google "CTRL-CHAR" sometimes points out a line break in your JSON, but there are none in this example. As far, as I can tell, the payload is valid JSON.
According to the CLI Documentation, you can also use other data types as payload. So I tried just passing a list:
aws lambda invoke --function-name my-func2 --payload '[2, 3, 4, 5]' out.json
I got the error:
Could not parse request body into json: Could not parse payload into
json: Unrecognized token 'Û': was expecting (JSON String, Number,
Array, Object or token 'null', 'true' or 'false')
Just in case anyone ever gets stuck at the same point while doing the official Lambda Tutorial:
I had the issue solved by adding:
--cli-binary-format raw-in-base64-out
as a parameter.
According to : CLI 2 AWS DOCS
This has something to do with encoding changes from CLI 1 to CLI 2.
It can also be added to to the aws config file, so you dont have to add it manually every time.
However, I am not sure why the Lambda Tutorial would not mention this, since the tutorial assumes you use CLI 2 and also guides you through the steps of the installation...
For me this way it worked in windows:
aws lambda invoke --function-name Func2 --payload {\"key1\":\"val1\"} --cli-binary-format raw-in-base64-out out.json
As suggested by MrTony, I added "--cli-binary-format raw-in-base64-out" args

AWS IoT - Failed to invoke lambda function

I'm trying to get my IoT device to fire off a Lambda function. Been trying for a few hours to no avail.
My lambda function is simple:
exports.handler = async (event) => {
// TODO implement
const response = {
statusCode: 200,
body: JSON.stringify(event.message),
};
return response;
};
I've setup my IoT rule to trigger the lambda function with SELECT * FROM 'iot/trigger-lambda'. When I publish a message to the iot/trigger-lambda topic from AWS IoT's Test functionality, the lambda function triggers successfully. But, when I publish my message from my device, I get the following error:
{
"ruleName": "ruleTriggerLambda",
"topic": "iot/trigger-lambda",
"cloudwatchTraceId": "xxx-yyy-zzz",
"clientId": "ABC123",
"base64OriginalPayload": "eydvcGVyYGTpb24nOiAncHV0T2JqZWN0JywgJ2J1Y2tldCc6ICdyZWR3YXZlLWFwcC1kZXYnLCAna2V5JzogJ3JlYWNoYmFjay56aXAnLQWncmVwbHlUbyc6ICdpb3QvdGhyGHT0aWQtMDAwMS9wcmUtc2lnbmVkLBNzLXVybC1yBBNwb25zZXMnfSBbMV0=",
"failures": [
{
"failedAction": "LambdaAction",
"failedResource": "arn:aws:lambda:us-east-1:xxx:function:lambdaTriggerLambda",
"errorMessage": "Failed to invoke lambda function. Received Server error from Lambda. The error code is 400"
}
]
}
When I added the lambda function to my rule, AWS indicated it would create the correction permissions. I've also tried updating the permissions of the lambda function.
Any suggestions on how to fix this? Any help/information is much appreciated.
Edit: after 4 hours or ripping my hair out
It turned out to be the format of the data that I was sending as a payload from my IoT device. Let me explain, if someone can tell me why this is, I'd love to know.
I was using my mac as my device and I implemented this code from the AWS IoT Python SDK. My message looked like this:
message = {"message": "test message"}
It seems like pretty straight forward json.
The code that is publishing the message looks like this:
mqtt_connection.publish(
topic=args.topic,
payload=args.message,
qos=mqtt.QoS.AT_LEAST_ONCE)
The payload being received at AWS IoT Core looked like this:
{'message': 'test message'} [1]
And was accompanied by an error message like so: We cannot display the message as JSON, and are instead displaying it as UTF-8 String.
I guess I'm a little dense for not connecting the dots but it turns out I had to do the following to my code:
mqtt_connection.publish(
topic=args.topic,
payload=json.dumps(args.message).replace("\"", '').replace("[1]", '').replace("'", '"'),
qos=mqtt.QoS.AT_LEAST_ONCE)
Hopefully this explanation will help someone in the future.

aws pinpoint update-apns-sandbox-channel command results in: missing credentials

aws --version
aws-cli/1.16.76 Python/2.7.10 Darwin/16.7.0 botocore/1.12.66
I'm trying to programmatically add an APNS_SANDBOX channel to a pinpoint app. I'm able to do this successfully via the pinpoint console, but not with aws cli or a lambda function which is the end goal. Changes to our Test/Prod environments can only be made via the CodePipeline, but for testing purposes I'm trying to achieve this with the aws cli.
I've tried both aws cli (using the root credentials) and a lambda function -- both result in the following error:
An error occurred (BadRequestException) when calling the UpdateApnsSandboxChannel operation: Missing credentials
I have tried setting the Certificate field in the UpdateApnsSandboxChannel json object as the path to the .p12 certificate file as well as using a string value retrieved from the openssl tool.
Today I worked with someone from aws support, and they were not able to figure out the issue after trying to debug for a couple of hours. They said they would send an email to the pinpoint team, but they did not have an ETA on when they might respond.
Thanks
I ended up getting this to work successfully -- This is why it was failing:
I was originally making the cli call with the following request object as this is what is including in the documentation:
aws pinpoint update-apns-sandbox-channel --application-id [physicalID] --cli-input-json file:///path-to-requestObject.json
{
"APNSSandboxChannelRequest": {
"BundleId": "com.bundleId.value",
"Certificate":"P12_FILE_PATH_OR_CERT_AS_STRING",
"DefaultAuthenticationMethod": "CERTIFICATE",
"Enabled": true,
"PrivateKey":"PRIVATEKEY_FILE_PATH_OR_AS_STRING",
"TeamId": "",
"TokenKey": "",
"TokenKeyId": ""
},
"ApplicationId": "Pinpoint_PhysicalId"
}
After playing around with it some more I got it to work by removing BundleId, TeamId, TokenKey, and TokenKeyId. I believe these fields are needed when using a p8 certificate.
{
"APNSSandboxChannelRequest": {
"Certificate":"P12_FILE_PATH_OR_CERT_AS_STRING",
"DefaultAuthenticationMethod": "CERTIFICATE",
"Enabled": true,
"PrivateKey":"PRIVATEKEY_FILE_PATH_OR_AS_STRING"
},
"ApplicationId": "Pinpoint_PhysicalId"
}

AWS API Gateway fails with "Unable to invoke" when query string contains key without value

There is a resource /{myvar} defined in API Gateway, with GET method. Integration request points to Lambda function, with Lambda Proxy integration enabled.
When I invoke test execution from API Resource Editor of this resource and method, it works for queries like
/abc
/abc?def=ghi
but it fails to execute query like
/abc?def
with following response body visible in test console:
{
"cause": "Unable to invoke. Please try again later.",
"logref": "f6c905bd-cc71-11e8-a731-37e05a411010",
"message": ""
}
and also Response Headers and Logs boxes below are empty.
When I publish such resource to stage, accessing it through HTTPS in browser results with {"message": "Internal server error"} See edit below
How to deal with that? How can I capture whole resource path with or without query, with no Gateway crash? It fails the same way also for greedy resource /{myvar+}.
EDIT
After redeployment problem no longer occurs on stage. It is still occurs within Method Execution window in API Gateway Resources Editor.
you can capture the query string params through the "event" object sent to your Function Handler, it is called queryStringParameters. You can just log this and go through it on CloudWatch to see what exactly is failing.
P.S. Sorry for posting as an answer, don't have rep for comment ^^