boto3 iot-data published messages not receiving - amazon-web-services

Im trying to publish a message via a python Lambda function to AWS IoT.
I've subscribed to a topic ('test') on the IoT console and triggered the function and the messages aren't getting delivered.
Python Code Snippet:
iot = boto3.client('iot-data','eu-west-1') res = {
"message" : "Hello!"
}
iot.publish(
topic='test', //do we need to pass the thing name here?
qos=0,
payload=json.dumps(res))
IoT policy:
{ "Version": "2012-10-17", "Statement": [
{
"Effect": "Allow",
"Action": "iot:*",
"Resource": "*"
} ] }
Also, I have allocated the the correct IAM privileges to the lambda function to publish to IoT.
Any help to pint me at the right direction much appreciated.

Figured this one out, my lambda function is deployed within a VPC subnet without a internet connection. Created a NAT gateway and now the subnet getting internet access through it.
P.S- To publish messages to IoT (MQTT) needs an internet connection.

Related

How do I publish/Subscribe AWS IoT - server side using Java SDK

I'm really new with AWS and IoT, and my goal is to:
Use the Java SDK v.2 from my serverless application to create/get/update/attach/... certificates and things.
Create client side MQTT demo application to connect publish and subscribe to messages used by my new certificates and thing created in phase 1.
Publish/subscribe messages in the server side in order to talk to my things/clients.
1 & 2 I've managed to do perfectly.
But I don't understand how should I do the 3rd one.
Should I use the IoT device SDK as well in the server side ? If so with what credentials do I connect ?
Is there some objects in the SDK that I've missed?
In order to connect to IoT Core from the server I first configure my SSO connection using the AWSCLI and in the code I simply use my profile name and region to connect.
Your serverless Java application needs to be configured as a "Thing" in the same account/region as your IoT devices. In the console, go to
AWS IoT -> Manage -> Things
and create a thing for your app. In this case you shouldn't need a "Device Shadow", and you can select "Auto Generate Certificates".
For the IoT Policy, you will need the following :
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iot:Connect",
"Resource": "arn:aws:iot:us-east-1:YOUR_AWS_ACCOUNT_ID:client/*"
},
{
"Effect": "Allow",
"Action": "iot:Subscribe",
"Resource": "arn:aws:iot:us-east-1:YOUR_AWS_ACCOUNT_ID:topicfilter/*"
},
{
"Effect": "Allow",
"Action": "iot:Receive",
"Resource": "arn:aws:iot:us-east-1:YOUR_AWS_ACCOUNT_ID:topic/*"
},
{
"Effect": "Allow",
"Action": "iot:Publish",
"Resource": "arn:aws:iot:us-east-1:YOUR_AWS_ACCOUNT_ID:topic/*"
}
]
}
Your application will communicate with IoTCore using the endpoint shown in the Settings screen in IoTCore for the region where you have created your thing. Your application will authenticate using the key/cert you downloaded when creating the thing (username/password auth is not allowed).
Once your application connects to the endpoint, you will want to "subscribe" to the same topic your devices use to send messages. You can also publish to one or more topics.
In order to debug communications, you can use the MQTT client in the AWS IoTCore console, just note the console needs to be refreshed periodically when communication times out. I recommend marking your topics as favorites so they are easy to re-subscribe to on a refresh.
As for coding in Java, you should be able to leverage examples from the AWS IoT Device SDK here :
https://github.com/aws/aws-iot-device-sdk-java-v2/tree/main/samples
Here's a link to the MQTT client class :
http://aws-iot-device-sdk-java-docs.s3-website-us-east-1.amazonaws.com/com/amazonaws/services/iot/client/AWSIotMqttClient.html
Please note that your app will not have access to messages when not in use. There are a few strategies to deal with message persistence, but that's outside the scope of your question, so I won't cover it here.
Hopefully this gets you pointed in the right direction.

Unable to connect AWS IOT with AWS Elasticsearch

I am new to AWS and IOT. I am trying to connect my raspberry pi with AWS IOT and from there I am trying to push the data to Elasticsearch.
I have managed to to connect raspberry pi with AWS IOT and able to see the data I have sent from Raspberry pi through "Test" in IOT console.
I have created topic rule and configured elasticsearch endpoint, added IAM role.
In rule destination i've entered the elasticsearch endpoint and created it but it shows the following message.
"Awaiting confirmation. Confirmation message sent on 2020-11-26T11:22:55.602Z. The destination responded with HTTP status code - 405."
I am unable see any message in cloudwatch logs to get the token and confirm the destination.
My elastic search access policy is set to open access to domain and the iot policy is as follows
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iot:",
"Resource": ""
}
]
}
I dont know whether I am doing it correct. Please help me to confirm the destination and stream data to elastic search.
Thanks in advance,

Publishing to SQS from a whitelisted IP

Is there any way an application can post messages to a SQS queue by being whitelisted by its machine IP address?
I took a look at https://aws.amazon.com/premiumsupport/knowledge-center/iam-restrict-calls-ip-addresses/ but this is for a role and I'd still need an AWS user to do this.
Is there any way to publish to a SQS queue just from an IP address, without needing an AWS user at all?
There isn't a direct way - you still need your AWS credentials.
But another way would be to have an AWS API Gateway that calls a Lambda that sends the SQS message. The API Gateway would be restricted to a small (or one) set of IP's. This link goes into details but the key is having a resource policy on your API gateway call:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": "*",
"Action": "execute-api:Invoke",
"Resource": "execute-api:/*/*/*"
},
{
"Effect": "Deny",
"Principal": "*",
"Action": "execute-api:Invoke",
"Resource": "execute-api:/*/*/*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": ["1.2.3.4"]
}
}
}
]
}
where 1.2.3.4 is the IP address you want to allow in. This API Gateway call would then call your Lambda. Internally you're still using IAM roles but external to AWS you're not.
If your application runs in a VPC you can use AWS PrivateLink to connect to your SQS queue privately so traffic does not traverse the internet, this normally resolves the need to whitelist an IP address for internal private traffic. SQS and AWS PrivateLink
I found out that for SQS (not SNS) I can do this with whitelists the ip of the sender. Then I can just do a POST and it will work.

How should I write IAM to make only a certain VPC can send mail via SES?

I use Redash on EC2 instance, and I have to send invitation mails via Amazon SES.
I'd like to add a setting to restrict mail sender to inside a certain VPC where the Redash instance is located.
Here's my IAM for SES:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "ses:SendRawEmail",
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:SourceVpce": "vpce-******"
},
"ForAnyValue:StringLike": {
"ses:Recipients": "*#mycompany.com"
}
}
}
]
}
But I can't send any mail. I think it's because I use VPC endpoint in the code above. It's not available for SES yet.
Is there any other way to specify a certain VPC?
This is an interesting challenge!
The Amazon SES interface is on the internet, so theoretically anything can access it. Normally, policy restrictions use permissions on the IAM User or Role that calls SES to determine whether calls are allowed, rather than from where the call is made.
I assume you are doing this because you only want your Production system to send emails, rather than Dev/Test systems.
However, it is not possible to restrict via VPC, because Amazon SES has no visibility to the concept of a VPC. It simply receives API calls via the Internet.
If your application is in a private subnet and sends requests via NAT Gateway, then you could add a policy to restrict based upon the IP address of the NAT Gateway.
You could do this either by putting the restriction on the Allow statement, or by adding a Deny statement.
See: AWS: Denies Access to AWS Based on the Source IP - AWS Identity and Access Management

AWS Iot Rule not getting triggered using MQTT browser client

I have a SNS topic and subscriber set up like so :
The subscribers are correctly notified when the Topic is tested via "Publish to Topic" from AWS console
I have a IoT rule like so :
I have a policy attached to the rule like so :
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "sns:Publish",
"Resource": "arn:aws:sns:ap-southeast-xxxxxx:MySNSTopic"
}
}
Yet when I try and test from the MQTT browser client, the notification is not fired
What am I missing?
Started working after a few minutes. Guess it needs some time to set up