Javascript IoT client SDK AttachPolicy call inside AWS lambda blocks and causes the lambda to timeout without any error/exception/log whatsoever

1

Hello,

**Issue in short: **

When I make AttachPolicy call using the Javascript v3 AWS SDK IoT Client inside AWS lambda, the call blocks and causes the lambda to timeout without any error/exception/log whatsoever.

I am having trouble identifying why the call does not succeed and blocks, hence my question here.


Details:

I have a lambda function from which I want to use the Javascript v3 AWS SDK IoT Client.

The request that I want to make to IoT core is AttachPolicy, in order to attach a policy to a Thing's certificate (certificate is identified by ARN).

Basically what I have in my code (excerpts) is this:

**1) Creation of an IoT client: **

new IoTClient({ region: process.env.REGION });

I have not provided any credentials, because I read that they are retrieved from the lambda's execution role:

https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/loading-node-credentials-lambda.html


2) Creation of AttachPolicyCommand - https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-iot/classes/attachpolicycommand.html:

const attachPolicyCommand = new AttachPolicyCommand({ policyName: <NAME_OF_POLICY>, target: <CERTIFICATE_ARN> });
console.log(`Sending attach policy request to attach '${policyName}' to '${targetArn}'.`)

From the log above I double check and make absolutely sure that the policy name and the certificate ARN are the correct ones.

3) AttachPolicy request - this is where the problem arises

const attachPolicyResponse = await this.iotClient.send(attachPolicyCommand);
... // unreachable code after the call above
... // after the configured lambda's timeout, the function execution ceases without executing any other line of code

I have also tried to wrap the above call inside try/catch/finally block, but it didn't make any difference.


One thing that I noticed and thought was causing the issue was that the lambda's execution role didn't have the permission to access the AttachPolicy action.

But once I fixed that and added the needed policy, the issue persists. This is the json of the policy which I added to the lambda execution role in order to allow AttachPolicy:

 {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "iot:AttachPolicy",
            "Resource": "*",
            "Effect": "Allow"
        }
    ]
}

Another thing is that the lambda's timeout configuration seems to make no difference - I tried making it both 5 seconds and 2 minutes - and the blocking is, respectively, for 5 seconds and 2 minutes.

I'll be grateful if you provide some insights on what the problem might be :)).

  • Can you pls post the JSON of the policy you added to Lambda execution role to allow Lambda to call AttachPolicy?

  • @Andrei, I updated the question with the JSON of the policy.

  • Could you add a logger when instantiating the IoTClient new IoTClient({ region: "eu-west-1", logger: logger }); and post the log files of your Lambda. Here a sample code using the pino logger:

    const { IoTClient, DescribeEndpointCommand, DeleteThingCommand } = require("@aws-sdk/client-iot");
    const pino = require("pino");
    const logger = pino({
        transport: {
          target: 'pino-pretty',
          options: {
            colorize: true
          }
        }
      });
    
    (async () => {
        const client = new IoTClient({ region: "eu-west-1", logger: logger });
        const command = new DescribeEndpointCommand({});
        try {
          const results = await client.send(command);
          logger.info(`RESULT: ${results}`);
        } catch (err) {
          logger.error(`ERROR: ${err}`);
        }
      })();
    
  • @Jan, I added a logger as in the example during the creation of IoTClient. Unfortunately it does not log anything. Only when I add line by myself, like logger.info('TEST'), there appears a log entry.

  • Some more information:

    The lambda is a pre provisioning hook - https://docs.aws.amazon.com/iot/latest/developerguide/pre-provisioning-hook.html.

    My idea is to attach a policy to a certificate during the invocation of the pre-provisioning hook lambda (at this point the certificate is still not activated, but I tested that the AttachPolicy operation works from the AWS console, so it should also be OK programatically with the Javascript IoT client).

    Also, the whole solution (policies, lambda, etc...) is deployed with CDK in Java, maybe you might want to check some of the Constructs?

1 Answer
0
Accepted Answer

Hi Stiliyan,

a possible reason for the issue could be that Lambda is running in a VPC lacking access to the internet. To resolve that, you can give your Lambda function public internet access by using a NAT Gateway. To do so, you have to add a NAT gateway in your VPC, and configure the routing table to route the outgoing messages from the subnets of Lambda to the NAT gateway: https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html

The VPC endpoint for IoT Core only supports the data plane and can't be used for the purpose of your use-case: https://docs.aws.amazon.com/iot/latest/developerguide/IoTCore-VPC.html

best regards, Andrei

answered a year ago
  • Hi Andrei,

    The solution with NAT gateway worked. Thanks :) How was I supposed to find out by myself that the lambda being inside VPC was the issue? It is strange that there are no errors/logs whatsoever, or maybe I don't look at the right place for them?

    Best regards, Stiliyan

  • Hi Stiliyan, to me it looks like a failure of AWS SDK for JavaScript v3 to log an error cause by network connectivity issues. Could you please add an issue in https://github.com/aws/aws-sdk-js-v3/issues and post the link here so I can follow-up AWS-internally? Thanks!

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions