AWS SNS Java program to subscribe - amazon-web-services

I am publishing a String message as message payload using SNS notification from Raspberry Pi using Python program and I want to pass that message payload to a Lambda function.
I have configured the requirement in the SNS console on AWS i.e., I have created a topic and added the lambda function to its subscribers.
Now, I want to get that message payload in the lambda function. But I can't find any method that can help me do that. For example, something like getMessage or something similar to that.
So my questions are: Since I have configured the publishing and subscription on AWS, can I assume that the clients are connected and if I publish a message I should be getting that at the subscriber's end which is my lambda function here?
Also, what's the technique in which I can get the message payload in my lambda function?
I am adding the below as per cjwfuller's suggestion.
Below I have written down the method for publishing in Python
client_boto = boto3.client('sns', aws_access_key_id='###',
aws_secret_access_key='###', region_name='us-west-2')
REGION = 'us-west-2'
TOPIC = 'arn:aws:sns:us-west-2:***:topic_name'
MSG = ntpath.basename(f_string)
SUBJECT_boto = 'File Name'
pub =client_boto.publish(TopicArn = TOPIC, Message = MSG,
Subject=SUBJECT_boto)
I am writing the subscribing code in Java.
Since my lambda func is already subscribed to it on AWS console,
should my Java program include the subscription again or is there a
way to get the msg payload directly.

Which language are you writing the function in? JavaScript as an example:
exports.myHandler = function(event, context, callback) {
console.log("value1 = " + event.key1);
console.log("value2 = " + event.key2);
// ...
}
Source: http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html
It's useful testing the sort of stuff in the AWS Lambda console before writing all the code.
Since I have configured the publishing and subscription on AWS, can I assume that the clients are connected
Clients aren't really "connected", they're simply subscribed to a topic.
publish a message I should be getting that at the subscriber's end which is my lambda function here?
Sounds like you're doing the right sort of thing - posting example code will help us come up with more precise answers.

On searching, I have found the class for SNSEvent which is, https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/SNSEvent.java
This Class contains all the methods related to and needed to get the message payload.
The Lambda function handler in Java goes something like this,
example;
public void handleRequest(SNSEvent input, Context context){
String this_takes_message=input.getRecords().get(0).getSNS().getMessage();
}

Related

Cognito passwordless solution sends code multiple times

I have successfully implemented these instructions from AWS (https://aws.amazon.com/de/blogs/mobile/implementing-passwordless-email-authentication-with-amazon-cognito/), but as soon as I execute the signIn function via aws-amplify, it often takes up to 7 seconds and I receive 3 emails with different codes.
The reason for this is that the event createAuthChallenge executes the respective lambda function 3 times, which generates and sends the respective code. This only happens if I do not login/register for a certain time (~10 minutes). I thought that this might be because the function is cold and tried to keep it warm by setting "Provisioned Concurrency" in the lambda functions
CreateAuthChallenge
VerifyAuthChallenge
DefineAuthChallenge
PreSignup
PostAuthentication
to 1 and additionally(!) tried to warm up the functions by executing them every 5 minutes via cloudwatch.
I don't know what else I should do.
Thx!
We had followed a different post to setup our custom auth flow, but had the same issue with 3 codes being sent out.
In that post it has the CreateAuthChallenge lambda start with
exports.handler = async (event) => {
const crypto = require('crypto')
const aws = require('aws-sdk')
...
}
We have been able to stop sending 3 verification codes by moving those requires outside of the handler method.
const crypto = require('crypto')
const aws = require('aws-sdk')
exports.handler = async (event) => {
...
}
My guess is that trying to read the entire aws-sdk inside of the function was the cause of the slowness and because this lambda took longer than the cognito system allows for, it ended up getting called multiple times and eventually did complete, thus causing the extra verification codes.
I did not see the same issue from the link you posted, but it would worth reviewing the specific code you have and check if its trying to bring in a package that needs to be handled differently.
You get 5 seconds for the lambda to complete, otherwise it retries. Cold starts and the blocking call to send the email via SES is what is eating all of those 5 seconds. You can make the call to SES asynchronous by writing the code, email address, timestamp and other necessary details to the log instead with some fixed prefix like SEND_EMAIL. Since this is sensitive data, you should encode the data into some format like json, encrypt it and base64 encode it before writing it to the log. Then you can attach a Cloudwatch subscription filter to the lambda log to route the log lines with SEND_EMAIL to a lambda to decrypt and decode the details and send the actual email via SES. This allows you to take longer than 5 seconds to send the email and workaround the timeouts.

How to augment an AWS IoT message in the same topic

In AWS IOT, I'm able to publish an MQTT message from a device to the topic "topic/messages" :
{
"id":"messageID",
"value":"messageValue"
}
And I want to "augment" it in the server by adding a timestamp on it and let the message to continue on the SAME TOPIC.
So I'd like that subscribers on "topic/messages" receive this:
{
"id":"messageID",
"value":"messageValue",
"serverTimestamp":"1637867431920" <--- Here
}
However, I don't find the way how to process this message and let it flow in the same topic:
I can add a rule
SELECT * , timestamp() as serverTimestamp FROM 'topic/#'
But the rule does not augment the original message but creates an augmented copy and redirects it to some other service (Lambda, DynamoDB, Republish, etc..)
Those services work with the copy of the given value, but not with the original message, so the subscribers still receives the original sent message.
{
"id":"messageID",
"value":"messageValue"
}
I can republish the message using the same topic BUT as the topic has an attached rule, after the republishing, the rule's action is triggered again and again in a recursive loop)...
All the AWS examples I've read are meant to take the message, transform it , and do some other different thing with it (save in DynamoDB, save in a Bucket, end to Salesforce....) but none of them modify the message to be sent.
So what I'm looking for is a way to receive the message, add a field (or more) to it and let it flow in the same topic .
What is the simplest way to do this?

Has anyone built an integration with any SMS Receivers?

I want to be able to send a text message to some number and then (upon receiving the text) basically just send a post request off to a different service after receiving the text. Does anyone know of a service I could use to set this up? Would like for it to be as fast as possible
Here's a summary of the steps to setup a sample app:
Navigate to Amazon SNS Service → Topics
Enter Name and create a new Topic
For the newly created topic, create a subscription where the Protocol is AWS Lambda (see image1 below)
Navigate to Amazon Pinpoint Service, create new Pinpoint application
Enable SMS & voice feature for this Pinpoint application
Get a new Long Code (long code price is $1/month)
For the long code, Enable two-way SMS, select the Choose an existing SNS topic option and select the SNS topic created in Step 2 above (see image2 below)
Finally, now you can send a message to that phone number from your phone and it will trigger your lambda function. In your lambda function, you can send a POST request to a different service or do whatever else. You can also respond back to the user's message - see example below.
Here's an example of how to send a message using Amazon Pinpoint in Java:
public void sendSMS(String pinpointPhoneNumber, String userPhoneNumber, String messageContent) {
// define who the message is going to and via what platform
Map<String, AddressConfiguration> addressMap = new HashMap<>();
addressMap.put(userPhoneNumber, new AddressConfiguration().withChannelType(ChannelType.SMS));
SMSMessage smsMessage = new SMSMessage();
smsMessage.setOriginationNumber(pinpointPhoneNumber);
smsMessage.setMessageType(MessageType.TRANSACTIONAL);
smsMessage.setBody(messageContent);
// add sms message to the direct message config
// this can have many other types of messages
DirectMessageConfiguration directMessageConfiguration = new DirectMessageConfiguration()
.withSMSMessage(smsMessage);
// put the phone numbers and all messages in here
MessageRequest messageRequest = new MessageRequest()
.withAddresses(addressMap)
.withMessageConfiguration(directMessageConfiguration);
// create send request
SendMessagesRequest sendMessagesRequest = new SendMessagesRequest()
.withApplicationId("put-pinpoint-app-id-here")
.withMessageRequest(messageRequest);
// send the message
AmazonPinpoint pinpointClient = AmazonPinpointClientBuilder.standard().build();
SendMessagesResult sendMessagesResult = pinpointClient.sendMessages(sendMessagesRequest);
MessageResponse messageResponse = sendMessagesResult.getMessageResponse();
}

Subscribe to an SNS topic and / or SQS queue in golang?

I know how to do this in java, but I just can't figure it out in Go at all.
All I want to do, is have a way to detect that an item got created in an S3 bucket, then have that trigger an SNS topic, which then notifies me of the file location in S3.
Has anybody got a working example of how I can do the go side of this for subscribing to the SNS topic or the SNS queue if I need one? Because all I seem to be able to find is Java and Node. I can find publish examples for go, but they are of little use to my use case.
To use SNS you will need a simple HTTP/HTTPS endpoint to receive SNS notifications. Which is divided into two parts (Confirm the subscription and Processing messages from HTTP/HTTPS endpoint)
1. Confirm the subscription
Do something as simple as this:
func confirmSubscription(subcribeURL string) {
response, err := http.Get(subcribeURL)
if err != nil {
fmt.Printf("Unbale to confirm subscriptions")
} else {
fmt.Printf("Subscription Confirmed sucessfully. %d", response.StatusCode)
}
}
2. Processing messages from HTTP/HTTPS endpoint
Parse the request's body, the documentations mentions how the body should be structured.
Sources:
https://docs.aws.amazon.com/sns/latest/dg/sns-http-https-endpoint-as-subscriber.html
https://github.com/viveksyngh/aws-sns-subscriber/blob/master/subscriber/subscriber.go

AWS SNS - how should I be sending message data, MessageAttributes?

I'm building an application that enables clients to book appointments with service providers. I'm using SNS -> SQS -> Lambda to process various emails that need to be sent when booking an appointment. IE I currently send an SNS message like so (in node.js):
await sns.publish({
Message: 'booking-request',
TopicArn: process.env.AWS_BOOKING_REQUEST_TOPIC_ARN,
MessageAttributes: {
artistEmail: SNSMF.string(artist.email),
artistName: SNSMF.string(artist.name),
clientEmail: SNSMF.string(req.body.email),
clientName: SNSMF.string(`${req.body.firstName} ${req.body.lastName}`),
date: SNSMF.string(moment(req.body.date).tz(studio.timeZone).format())
}
}).promise();
This all works fine, but I'm using MessageAttributes to pass the pertinent appointment details so my notifications layer can send the proper emails.
My main questions is, am I using MessageAttributes in the proper way, or is there a better way to pass all of this data? Should the data be the message itself? I ask because I believe that you can only have 10 MessageAttributes and I'm going to run into a limit with the appointment details (currently collecting about 10-12 data points about the appointment that I want to include in the emails). Any ideas? Thank you!
Normally, the 'main' information you wish to pass would be in the Body of the message. It is quite common the use JSON to pass various types of information.
MessageAttributes are normally something about the message itself rather than the content of the message, such as timestamps, priority and user information.
Given your requirements, I putting your data in the Body (eg in JSON) would avoid hitting limits and would also be more extensible.