Skip to content

feat: Migrate aws-sdk v2 to @aws-sdk v3 for Node 20+ Lambda support#103

Open
mecham-lynn wants to merge 5 commits intomasterfrom
feat/ES-2949-aws-sdk-v3-migration
Open

feat: Migrate aws-sdk v2 to @aws-sdk v3 for Node 20+ Lambda support#103
mecham-lynn wants to merge 5 commits intomasterfrom
feat/ES-2949-aws-sdk-v3-migration

Conversation

@mecham-lynn
Copy link

@mecham-lynn mecham-lynn commented Mar 16, 2026

Summary

  • Migrate all 6 source files from aws-sdk v2 to modular @aws-sdk v3 packages
  • Remove b.external("aws-sdk") from lib/build.js — this was the root cause of Node 20 Lambda failures (Cannot find module 'aws-sdk')
  • Replace v2 service constructors with v3 client/command pattern across S3, Lambda, STS, DynamoDB, and credential providers
  • Remove aws-sdk v2 dependency, add 6 @aws-sdk v3 packages
  • Bump version to 4.0.0-awsv3
  • Fix latent bug in docker-run.js where error handler called undefined callback (now uses process.exit(1))

Files Changed

File Migration
lib/build.js Removed b.external("aws-sdk"), replaced credential handling with env vars + leo-aws
lib/leo-aws.js Replaced aws.STS().credentialsFrom() and aws.SharedIniFileCredentials with static creds and fromIni()
lib/functionWrap.js Removed aws-sdk import (only used in commented-out code)
lib/defaultCronRunner.js Migrated Lambda, S3 clients + presigned URL generation to v3
docker-run.js Migrated Lambda, STS (fromTemporaryCredentials), DynamoDB to v3
docker/run.js Migrated Lambda, DynamoDB to v3
package.json Version bump, dependency swap
docker/package.json Dependency swap

Test Plan

  • Install leo-cli@4.0.0-awsv3 globally
  • leo-cli publish a Lambda project targeting nodejs20.x runtime
  • Verify Lambda zip contains AWS SDK (no longer externalized)
  • Deploy and invoke Lambda — confirm no Cannot find module errors
  • Test with AWS profile switching (--profile flag)
  • Test leo-cli test (local Lambda execution via functionWrap)
  • Test docker-based Lambda execution

Jira

Jira: https://chb.atlassian.net/browse/ES-2949

🤖 Generated with Claude Code


Note

Medium Risk
Broad migration of AWS service/credential codepaths (Lambda/S3/DynamoDB/STS) and packaging behavior; regressions could break local runners, profile-based auth, or deployed Lambda execution if v3 client semantics differ.

Overview
Migrates the CLI and docker lambda runners from aws-sdk v2 to AWS SDK v3 (@aws-sdk/* + Smithy handler), updating Lambda, S3, DynamoDB, and credential usage to the v3 client/command pattern.

Fixes Node 20 runtime packaging issues by stopping browserify from externalizing aws-sdk (so the SDK is bundled when needed), and updates publishing/profile handling to resolve credentials via leo-aws/AWS_PROFILE and pass explicit env creds to the aws s3 CLI.

Improves error handling in the docker runners (async handler() with proper nonzero exits), adds explicit assumed-role env var precedence in docker-run.js, and bumps version to 4.0.0-awsv3 while updating dependencies/lockfile to remove aws-sdk.

Written by Cursor Bugbot for commit 4b2ee27. This will update automatically on new commits. Configure here.

…mbda support

AWS removed aws-sdk v2 from Lambda runtimes starting with Node 18,
causing all Lambdas to fail with "Cannot find module 'aws-sdk'" when
deployed via leo-cli to nodejs18.x or nodejs20.x runtimes.

Changes:
- Remove b.external("aws-sdk") from lib/build.js so AWS SDK is bundled in Lambda zips
- Replace all aws-sdk v2 imports with modular @aws-sdk v3 packages
- Migrate 6 files: lib/build.js, lib/leo-aws.js, lib/functionWrap.js,
  lib/defaultCronRunner.js, docker-run.js, docker/run.js
- Services migrated: S3, Lambda, STS, DynamoDB, credential providers
- Remove aws-sdk v2 dependency, add @aws-sdk v3 modular packages
- Bump version to 4.0.0-awsv3
- Fix latent bug in docker-run.js error handler (callback was undefined)

Task: ES-2949

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ch-snyk-sa
Copy link

ch-snyk-sa commented Mar 16, 2026

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

In v2, aws.config.credentials was a global singleton that all SDK
clients automatically used. In v3 there is no global credential state,
so the resolved temporary credentials must be explicitly exported as
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN
environment variables for the handler's SDK clients to pick up.

Task: ES-2949

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…v3 correctness

- S-2: Guard against corrupt/missing cached STS credentials in leo-aws.js
- B-1: Use process.exit(1) on all error paths (docker-run.js, docker/run.js)
- B-2: Add .catch() to top-level handler() calls for unhandled rejections
- B-3: Guard against empty DynamoDB scan/get results in buildEvent()
- B-4: Use NodeHttpHandler for DynamoDB client (correct v3 config shape)
- B-5: Fix typo "Cannot fund function" → "Cannot find function"
- C-1: Refactor docker-run.js and docker/run.js to consistent async/await
- C-3: Remove dead role-assumption code block in functionWrap.js
- C-5: Add explicit @aws-sdk/client-sts and @smithy/node-http-handler deps

Task: ES-2949

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… zone

`importModule` was declared with `let` after the `try/catch` block but
called inside it, causing a ReferenceError at runtime. Converting to a
`function` declaration leverages hoisting to fix this without moving code.

Task: ES-2949

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

"aws-sdk": "^2.276.1"
"@aws-sdk/client-dynamodb": "^3.1010.0",
"@aws-sdk/client-lambda": "^3.1010.0",
"@aws-sdk/lib-dynamodb": "^3.1010.0"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing dependency in docker package.json breaks container

High Severity

docker/run.js requires @smithy/node-http-handler at line 26, but this package is not declared in docker/package.json. The Dockerfile runs npm install solely from docker/package.json, so the only reason this might resolve is if it happens to be hoisted as a transitive dependency of the listed @aws-sdk/* packages. Relying on undeclared transitive dependencies is fragile and can break across npm versions, lockfile changes, or alternative package managers.

Additional Locations (1)
Fix in Cursor Fix in Web

If Lambda env vars set AWS_SESSION_TOKEN and the resolved credentials
don't include a session token, the stale token would persist alongside
new access key/secret, causing auth failures. Delete it in that case.

Task: ES-2949

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants