@aws-sdk/find-v2 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { dirname, join } from "node:path";
|
|
2
|
+
import { AWS_SDK, NODE_MODULES, PACKAGE_JSON } from "./constants.js";
|
|
3
|
+
const AWS_SDK_PACKAGE_JSON = join(NODE_MODULES, AWS_SDK, PACKAGE_JSON);
|
|
4
|
+
const safeParse = (json) => {
|
|
5
|
+
try {
|
|
6
|
+
return JSON.parse(json);
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
// ToDo: add warning when logging is supported in future.
|
|
10
|
+
return {};
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Maps code file paths to their JS SDK v2 versions.
|
|
15
|
+
*
|
|
16
|
+
* Searches up the directory tree from each code path to find package.json,
|
|
17
|
+
* then resolves SDK version from node_modules/aws-sdk or dependencies.
|
|
18
|
+
*
|
|
19
|
+
* @param codePaths - Code file paths to map.
|
|
20
|
+
* @param packageJsonMap - Map of package.json paths to contents.
|
|
21
|
+
* @param awsSdkPackageJsonMap - Map of aws-sdk package.json paths to contents.
|
|
22
|
+
* @returns Map of code paths to SDK versions (undefined if not found).
|
|
23
|
+
*/
|
|
24
|
+
export const getCodePathToSdkVersionMap = (codePaths, packageJsonMap = new Map(), awsSdkPackageJsonMap = new Map()) => {
|
|
25
|
+
const dirToSdkVersionMap = new Map();
|
|
26
|
+
const getSdkVersion = (dir) => {
|
|
27
|
+
if (dirToSdkVersionMap.has(dir))
|
|
28
|
+
return dirToSdkVersionMap.get(dir);
|
|
29
|
+
let version;
|
|
30
|
+
// Assign version from node_modules aws-sdk package.json, if available.
|
|
31
|
+
const awsSdkPackageJson = awsSdkPackageJsonMap.get(join(dir, AWS_SDK_PACKAGE_JSON)) ??
|
|
32
|
+
awsSdkPackageJsonMap.get(AWS_SDK_PACKAGE_JSON);
|
|
33
|
+
version ??= awsSdkPackageJson && safeParse(awsSdkPackageJson).version;
|
|
34
|
+
// Assign version from package.json dependencies, if not populated yet.
|
|
35
|
+
const pkgJson = packageJsonMap.get(join(dir, PACKAGE_JSON));
|
|
36
|
+
version ??= pkgJson && safeParse(pkgJson).dependencies?.[AWS_SDK];
|
|
37
|
+
// Assign undefined if it's rootDir, else call getSdkVersion on parent dir, if not populated yet.
|
|
38
|
+
const parentDir = dirname(dir);
|
|
39
|
+
version ??= parentDir !== dir ? getSdkVersion(parentDir) : undefined;
|
|
40
|
+
dirToSdkVersionMap.set(dir, version);
|
|
41
|
+
return version;
|
|
42
|
+
};
|
|
43
|
+
return new Map(codePaths.map((codePath) => [codePath, getSdkVersion(dirname(codePath))]));
|
|
44
|
+
};
|
|
@@ -3,17 +3,20 @@ import { AWS_SDK, NODE_MODULES, PACKAGE_JSON } from "./constants.js";
|
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
/**
|
|
5
5
|
* Extracts the contents of a Lambda Function zip file.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
*
|
|
7
|
+
* Parses the zip and returns:
|
|
8
|
+
* - JS/TS source files (excluding node_modules)
|
|
9
|
+
* - package.json files (excluding node_modules)
|
|
10
|
+
* - aws-sdk package.json from node_modules (for version detection)
|
|
8
11
|
*
|
|
9
12
|
* @param zipPath - The path to the zip file of Lambda Function.
|
|
10
|
-
* @returns
|
|
13
|
+
* @returns Extracted contents categorized by file type.
|
|
11
14
|
*/
|
|
12
15
|
export const getLambdaFunctionContents = async (zipPath) => {
|
|
13
16
|
const zip = new StreamZip.async({ file: zipPath });
|
|
14
|
-
const codeMap =
|
|
15
|
-
const packageJsonMap =
|
|
16
|
-
const awsSdkPackageJsonMap =
|
|
17
|
+
const codeMap = new Map();
|
|
18
|
+
const packageJsonMap = new Map();
|
|
19
|
+
const awsSdkPackageJsonMap = new Map();
|
|
17
20
|
let zipEntries = {};
|
|
18
21
|
try {
|
|
19
22
|
zipEntries = await zip.entries();
|
|
@@ -27,7 +30,7 @@ export const getLambdaFunctionContents = async (zipPath) => {
|
|
|
27
30
|
if (zipEntry.name.includes(`${NODE_MODULES}/`)) {
|
|
28
31
|
if (zipEntry.name.endsWith(join(NODE_MODULES, AWS_SDK, PACKAGE_JSON)) && zipEntry.isFile) {
|
|
29
32
|
const packageJsonContent = await zip.entryData(zipEntry.name);
|
|
30
|
-
awsSdkPackageJsonMap
|
|
33
|
+
awsSdkPackageJsonMap.set(zipEntry.name, packageJsonContent.toString());
|
|
31
34
|
}
|
|
32
35
|
continue;
|
|
33
36
|
}
|
|
@@ -38,7 +41,7 @@ export const getLambdaFunctionContents = async (zipPath) => {
|
|
|
38
41
|
if (zipEntry.name.endsWith(PACKAGE_JSON)) {
|
|
39
42
|
try {
|
|
40
43
|
const packageJsonContent = await zip.entryData(zipEntry.name);
|
|
41
|
-
packageJsonMap
|
|
44
|
+
packageJsonMap.set(zipEntry.name, packageJsonContent.toString());
|
|
42
45
|
}
|
|
43
46
|
catch {
|
|
44
47
|
// Continue without adding package.json file, if entry data can't be read.
|
|
@@ -50,7 +53,7 @@ export const getLambdaFunctionContents = async (zipPath) => {
|
|
|
50
53
|
if (zipEntry.name.match(/\.(js|ts|mjs|cjs)$/)) {
|
|
51
54
|
try {
|
|
52
55
|
const codeContent = await zip.entryData(zipEntry.name);
|
|
53
|
-
codeMap
|
|
56
|
+
codeMap.set(zipEntry.name, codeContent.toString());
|
|
54
57
|
}
|
|
55
58
|
catch {
|
|
56
59
|
// Continue without adding code, if entry data can't be read.
|
|
@@ -62,7 +65,7 @@ export const getLambdaFunctionContents = async (zipPath) => {
|
|
|
62
65
|
await zip.close();
|
|
63
66
|
return {
|
|
64
67
|
codeMap,
|
|
65
|
-
...(
|
|
66
|
-
...(
|
|
68
|
+
...(packageJsonMap.size > 0 && { packageJsonMap }),
|
|
69
|
+
...(awsSdkPackageJsonMap.size > 0 && { awsSdkPackageJsonMap }),
|
|
67
70
|
};
|
|
68
71
|
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { satisfies, validate } from "compare-versions";
|
|
2
|
-
import { AWS_SDK, NODE_MODULES, PACKAGE_JSON } from "./constants.js";
|
|
3
2
|
import { downloadFile } from "./downloadFile.js";
|
|
4
3
|
import { getLambdaFunctionContents, } from "./getLambdaFunctionContents.js";
|
|
5
4
|
import { getPossibleHandlerFiles } from "./getPossibleHandlerFiles.js";
|
|
@@ -7,17 +6,22 @@ import { hasSdkV2InBundle } from "./hasSdkV2InBundle.js";
|
|
|
7
6
|
import { hasSdkV2InFile } from "./hasSdkV2InFile.js";
|
|
8
7
|
import { rm } from "node:fs/promises";
|
|
9
8
|
import { tmpdir } from "node:os";
|
|
10
|
-
import {
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
import { getCodePathToSdkVersionMap } from "./getCodePathToSdkVersionMap.js";
|
|
11
11
|
/**
|
|
12
12
|
* Scans a Lambda function to detect AWS SDK for JavaScript v2 usage.
|
|
13
13
|
*
|
|
14
|
-
* Downloads the function code, extracts it, and checks for
|
|
15
|
-
*
|
|
16
|
-
*
|
|
14
|
+
* Downloads the function code, extracts it, and checks for JS SDK v2 signature in handled file if it's a bundle.
|
|
15
|
+
* If not found, it checks for source code files has require/imports JS SDK v2. It also checks dependencies in
|
|
16
|
+
* package.json for version validation.
|
|
17
17
|
*
|
|
18
18
|
* @param client - AWS Lambda client instance
|
|
19
19
|
* @param options - Scan configuration options
|
|
20
|
-
* @
|
|
20
|
+
* @param options.functionName - The name of the Lambda function
|
|
21
|
+
* @param options.region - AWS region the Lambda function is deployed to
|
|
22
|
+
* @param options.runtime - Lambda Function's Node.js runtime
|
|
23
|
+
* @param options.sdkVersionRange - Semver range string to check for AWS SDK for JavaScript v2
|
|
24
|
+
* @returns Scan results including SDK v2 detection status and locations
|
|
21
25
|
*/
|
|
22
26
|
export const getLambdaFunctionScanOutput = async (client, { functionName, region, runtime, sdkVersionRange }) => {
|
|
23
27
|
const output = {
|
|
@@ -51,8 +55,9 @@ export const getLambdaFunctionScanOutput = async (client, { functionName, region
|
|
|
51
55
|
// Process handler as bundle file first.
|
|
52
56
|
const possibleHandlerFiles = getPossibleHandlerFiles(response.Configuration?.Handler ?? "index.handler");
|
|
53
57
|
for (const handlerFile of possibleHandlerFiles) {
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
const handlerContent = codeMap.get(handlerFile);
|
|
59
|
+
if (handlerContent !== undefined) {
|
|
60
|
+
if (hasSdkV2InBundle(handlerContent, sdkVersionRange)) {
|
|
56
61
|
output.ContainsAwsSdkJsV2 = true;
|
|
57
62
|
output.AwsSdkJsV2Locations = [handlerFile];
|
|
58
63
|
return output;
|
|
@@ -61,7 +66,7 @@ export const getLambdaFunctionScanOutput = async (client, { functionName, region
|
|
|
61
66
|
}
|
|
62
67
|
const filesWithJsSdkV2 = [];
|
|
63
68
|
// Search for JS SDK v2 occurrence in source code
|
|
64
|
-
for (const [filePath, fileContent] of
|
|
69
|
+
for (const [filePath, fileContent] of codeMap) {
|
|
65
70
|
try {
|
|
66
71
|
if (hasSdkV2InFile(filePath, fileContent)) {
|
|
67
72
|
filesWithJsSdkV2.push(filePath);
|
|
@@ -69,6 +74,7 @@ export const getLambdaFunctionScanOutput = async (client, { functionName, region
|
|
|
69
74
|
}
|
|
70
75
|
catch {
|
|
71
76
|
// Skip files that fail to parse
|
|
77
|
+
// ToDo: add warning when logging is supported in future.
|
|
72
78
|
}
|
|
73
79
|
}
|
|
74
80
|
// JS SDK v2 not found in source code.
|
|
@@ -76,59 +82,26 @@ export const getLambdaFunctionScanOutput = async (client, { functionName, region
|
|
|
76
82
|
output.ContainsAwsSdkJsV2 = false;
|
|
77
83
|
return output;
|
|
78
84
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
85
|
+
const codePathToSdkVersionMap = getCodePathToSdkVersionMap(filesWithJsSdkV2, packageJsonMap, awsSdkPackageJsonMap);
|
|
86
|
+
const jsSdkV2FilesInSdkVersionRange = [];
|
|
87
|
+
for (const [codePath, version] of codePathToSdkVersionMap) {
|
|
88
|
+
if (version && validate(version)) {
|
|
82
89
|
try {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if (AWS_SDK in dependencies) {
|
|
86
|
-
const awsSdkVersionInPackageJson = dependencies[AWS_SDK];
|
|
87
|
-
const awsSdkPackageJsonPathInNodeModules = join(NODE_MODULES, AWS_SDK, PACKAGE_JSON);
|
|
88
|
-
// Get aws-sdk package.json from nested node_modules or root node_modules.
|
|
89
|
-
const awsSdkPackageJson = awsSdkPackageJsonMap
|
|
90
|
-
? (awsSdkPackageJsonMap[join(dirname(packageJsonPath), awsSdkPackageJsonPathInNodeModules)] ?? awsSdkPackageJsonMap[awsSdkPackageJsonPathInNodeModules])
|
|
91
|
-
: undefined;
|
|
92
|
-
let awsSdkVersionInNodeModules;
|
|
93
|
-
try {
|
|
94
|
-
if (awsSdkPackageJson) {
|
|
95
|
-
awsSdkVersionInNodeModules = JSON.parse(awsSdkPackageJson).version;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
catch {
|
|
99
|
-
// Skip if JSON can't be parsed.
|
|
100
|
-
// ToDo: add warning when logging is supported in future.
|
|
101
|
-
}
|
|
102
|
-
const sdkVersionToCheck = validate(awsSdkVersionInPackageJson) || awsSdkPackageJson === undefined
|
|
103
|
-
? // Use version in package.json dependencies, if fixed version is defined or aws-sdk package.json is not available.
|
|
104
|
-
awsSdkVersionInPackageJson
|
|
105
|
-
: // Use version from aws-sdk package.json, if defined
|
|
106
|
-
(awsSdkVersionInNodeModules ?? awsSdkVersionInPackageJson);
|
|
107
|
-
try {
|
|
108
|
-
if (!satisfies(sdkVersionToCheck, sdkVersionRange)) {
|
|
109
|
-
continue;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
catch (error) {
|
|
113
|
-
const errorPrefix = `Error checking version range '${sdkVersionRange}' for aws-sdk@${dependencies["aws-sdk"]} in '${packageJsonPath}'`;
|
|
114
|
-
output.AwsSdkJsV2Error =
|
|
115
|
-
error instanceof Error ? `${errorPrefix}: ${error.message}` : errorPrefix;
|
|
116
|
-
return output;
|
|
117
|
-
}
|
|
118
|
-
output.ContainsAwsSdkJsV2 = true;
|
|
119
|
-
output.AwsSdkJsV2Locations = filesWithJsSdkV2;
|
|
120
|
-
return output;
|
|
90
|
+
if (satisfies(version, sdkVersionRange)) {
|
|
91
|
+
jsSdkV2FilesInSdkVersionRange.push(codePath);
|
|
121
92
|
}
|
|
122
93
|
}
|
|
123
|
-
catch
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
error instanceof Error ? `${errorPrefix}: ${error.message}` : errorPrefix;
|
|
127
|
-
return output;
|
|
94
|
+
catch {
|
|
95
|
+
// Ignore if satisfies throws error
|
|
96
|
+
// ToDo: add warning when logging is supported in future.
|
|
128
97
|
}
|
|
129
98
|
}
|
|
130
99
|
}
|
|
131
|
-
|
|
100
|
+
if (jsSdkV2FilesInSdkVersionRange.length > 0) {
|
|
101
|
+
output.ContainsAwsSdkJsV2 = true;
|
|
102
|
+
output.AwsSdkJsV2Locations = jsSdkV2FilesInSdkVersionRange;
|
|
103
|
+
return output;
|
|
104
|
+
}
|
|
132
105
|
output.ContainsAwsSdkJsV2 = false;
|
|
133
106
|
return output;
|
|
134
107
|
};
|