1
votes

I'm trying to publish MQTT message to AWS IoT Core from Lambda on a different account.

Less assume that Account A is the one with the IoT core and account B is the one that has the lambda function.

On Account A: I created the following role type 'Another AWS account' using the account ID of B with the AWSIoTDataAccess policies:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iot:Connect",
                "iot:Publish",
                "iot:Subscribe",
                "iot:Receive",
                "iot:GetThingShadow",
                "iot:UpdateThingShadow",
                "iot:DeleteThingShadow"
            ],
            "Resource": "*"
        }
    ]
}

On Account B: I have a lambda function nodejs

 // Get the Cross account credentials
const accessparams = new Promise((resolve, reject) => {
        const timestamp = (new Date()).getTime();
        const params = {
            RoleArn: 'arn:aws:iam::' + id + ':role/' + remoteRole,
            RoleSessionName: `be-descriptibe-here-${timestamp}`
        };
        sts.assumeRole(params, (err, data) => {
            if (err) reject(err);
            else {
                resolve({
                    accessKeyId: data.Credentials.AccessKeyId,
                    secretAccessKey: data.Credentials.SecretAccessKey,
                    sessionToken: data.Credentials.SessionToken,
                });
            }
        });
    });

iot.remote = new AWS.IotData({ accessparams, endpoint: accountInfo.endpoint, region: 'ca-central-1', });

    var params = {
        topic: "MyTopic",
        payload: 'payload',
        qos: 0
    };

 try {
        var result = await iot.remote.publish(params).promise();
        console.log('result', result);
        return buildResponse({ "result": "ok" });
    } catch (err) {
        console.log("ERROR => " + JSON.stringify(err));
        return buildErrorResponse("Error");
    }

I haven't been able to publish any data, I'm getting the error below, which looks like it never assumes the role for account A.

{
    "message": "The client used a Server Name Indication (SNI) that is not associated with this account.",
    "code": "ForbiddenException",
    "time": "2021-05-29T16:21:11.254Z",
    "requestId": "c2f78026-cc64-091b-8b66-0322c26a26bb",
    "statusCode": 403,
    "retryable": false,
    "retryDelay": 84.76771000356665
}

Any comment or suggestion will more than appreciated.

Thanks in advance,

Daniel

2

2 Answers

1
votes

I found the error on my code, it was when I was passing the parameter to the IOTData, I have to add the endpoint and region to the accessparameter instead that put it on the same line.

 accessparams.endpoint =iotEndpoint;
 accessparams.region = 'ca-central-1' ;

 iot.remote = new AWS.IotData( accessparams);

Thank you to everyone that took the time to check it and try to find a solution.

0
votes

To get the cross account data interaction we need to follow the below steps:

  1. Create a role in the Account from/to where you want to push/pull data from ( in your example Account A i.e. with IOT Core)

  2. Create a trust for that role

  3. Using "sts:AssumeRole" within Account B ( you are using lambda) to get the access/privilege's assigned with role in account A.

In you code I do not see the "sts:AssumeRole" and probably that is what causing the issue. You can refer to How can I configure a Lambda function to assume a role from another AWS account?