Skip to content

Maintenance: refactor AWS SDK client check in Parameters and Idempotency #1707

Closed
@dreamorosi

Description

@dreamorosi

Summary

Customers using the Idempotency and Parameters utilities can optionally pass an AWS SDK client to be used to communicate with AWS APIs. In order to ensure that the object passed at runtime is correct we must perform some conditional logic which at the moment is based on instanceof.

When working with Node.js based AWS Lambda functions, the AWS SDK can come from at least 4 known locations (not in order):

  1. The Lambda runtime
  2. The Lambda Layer (/opt/nodejs/node_modules/@aws-sdk/)
  3. The customer provided zip archive (/var/task/node_modules/@aws-sdk/)
  4. The customer provided bundled code (i.e. a single file bundled with tools like esbuild and placed in /var/task/index.js)

Powertools doesn't ship with the AWS SDK, this allows the user to have control over where the AWS SDK is sourced from among the locations above.

When both Powertools and the SDK are bundled in the same file (4) then Powertools will import/require the SDK from the bundle itself since they are colocated. If both Powertools and the SDK are archived as part of the same zip archive deployed to Lambda (3), Powertools will most likely import the one and the same node_module folder. If instead no SDK is provided, Powertools will use the one present in the Lambda runtime (1).

In all the cases above, since Powertools is always colocated with the customer code the SDK imported/required in the customer code will be the same that Powertools also requires internally. This allows the runtime instanceof check to be successful.

If instead Powertools is shipped as part of a Lambda Layer and the customer brings their own AWS SDK (cases 3 or 4) the instanceof check will fail. This happens because Powertools will always default to using a copy of the SDK from either the Layer itself or from the runtime.

Albeit confusing, since the AWS SDK module is imported from two different locations Node.js will consider it as two separate modules for all intense and purposes and so checks like client instanceof SdkClient will fail because the two objects are not the same.

We should consider adopting alternative means to check whether an object passed to us is indeed the AWS SDK client that we expect so that the edge cases above will also work.

Why is this needed?

We need to work on this because we are having customer demand (#1703) for adding utilities that include this logic to our Lambda Layer. At present this strict check would prevent using our Lambda Layers in some edge cases.

Besides Lambda Layers, once we will start shipping hybrid builds with both CJS and ESM the issue might become ever more likely to happen since we won't be able to guarantee the import paths of code that we don't control.

Which area does this relate to?

Other

Solution

Since we cannot rely on prototype identity we will have to rely on the actual shape of the object and assert the presence of certain properties/methods.

Acknowledgment

Future readers

Please react with 👍 and your use case to help us understand customer demand.

Metadata

Metadata

Assignees

Labels

completedThis item is complete and has been merged/shippedinternalPRs that introduce changes in governance, tech debt and chores (linting setup, baseline, etc.)layersItems related to the Lambda Layers pipeline

Type

No type

Projects

Status

Shipped

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions