I need to give temporary Access Keys to my clients to connect to IoT services (publish, receive, etc.). To provide this access, I've created a Lambda function that calls sts.assumeRole
to create temporary STS keys. Those keys are being created and look fine.
I'm using assumeRole with Lambda in a role with the following inline policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"iot:Connect",
"iot:Subscribe",
"iot:Publish",
"iot:Receive"
],
"Resource": "*",
"Effect": "Allow"
},
{
"Action": [
"ec2:*"
],
"Resource": "*",
"Effect": "Allow"
},
{
"Action": [
"sts:AssumeRole"
],
"Resource": "*",
"Effect": "Allow"
}
]
}
Note: I've added ec2 permissions to try a secondary (simplified) test.
This role has an open trust relationship:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "sts:AssumeRole"
}
]
}
However, in my client code (browser), I can't connect to IoT and I receive the following error:
WebSocket connection to 'wss://my-endpoint.iot.us-east-1.amazonaws.com/mqtt?X-Amz-Algorithm=AWS4-H…Signature=my-signature' failed: Error during WebSocket handshake: Unexpected response code: 403
Trying a simplified test, I've used EC2, but received another permission error. The code used follows below (used browserify to bundle in browse).
const AWS = require('aws-sdk');
// connect to Lambda to retrieve accessKeyId and secretAccessKey
$.ajax({
method: 'GET',
url: 'my-url',
success: function(res) {
// connect to EC2
AWS.config.update({accessKeyId: res.accessKeyId, secretAccessKey: res.secretAccessKey, region: res.region});
const ec2 = new AWS.EC2();
ec2.describeInstances({}, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
});
Error:
POST https://ec2.us-east-1.amazonaws.com/ 401 (Unauthorized)
Error: AWS was not able to validate the provided access credentials(…) "AuthFailure: AWS was not able to validate the provided access credentials"