@aws-sdk/find-v2 0.4.1 → 0.4.3
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.
- package/README.md +12 -25
- package/dist/cli.js +6 -2
- package/dist/scanLambdaFunctions.js +6 -5
- package/dist/utils/getLambdaFunctionContents.js +13 -5
- package/dist/{getLambdaFunctionScanOutput.js → utils/getLambdaFunctionScanOutput.js} +11 -12
- package/dist/utils/printLambdaCommandOutput.js +34 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -32,31 +32,18 @@ Commands:
|
|
|
32
32
|
Run `lambda` command to scan Lambda Node.js Functions for JavaScript SDK v2.
|
|
33
33
|
|
|
34
34
|
```console
|
|
35
|
-
$ npx @aws-sdk/find-v2 lambda --yes
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
"FunctionName": "fn-with-aws-sdk-in-package-json-deps",
|
|
50
|
-
"Region": "us-east-2",
|
|
51
|
-
"ContainsAwsSdkJsV2": true,
|
|
52
|
-
"AwsSdkJsV2Location": "Defined in package.json dependencies."
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
"FunctionName": "fn-without-aws-sdk-in-package-json-deps",
|
|
56
|
-
"Region": "us-east-2",
|
|
57
|
-
"ContainsAwsSdkJsV2": false
|
|
58
|
-
}
|
|
59
|
-
]
|
|
35
|
+
$ npx @aws-sdk/find-v2 lambda --yes --output table
|
|
36
|
+
┌─────────────────────────────────────────┬───────────┬────────────────────────────────────────────────┐
|
|
37
|
+
│ FunctionName │ Region │ ContainsAwsSdkJsV2 │
|
|
38
|
+
├─────────────────────────────────────────┼───────────┼────────────────────────────────────────────────┤
|
|
39
|
+
│ fn-without-aws-sdk-in-bundle │ us-east-2 │ No. │
|
|
40
|
+
├─────────────────────────────────────────┼───────────┼────────────────────────────────────────────────┤
|
|
41
|
+
│ fn-with-aws-sdk-in-bundle │ us-east-2 │ Yes. Bundled in 'index.js' │
|
|
42
|
+
├─────────────────────────────────────────┼───────────┼────────────────────────────────────────────────┤
|
|
43
|
+
│ fn-with-aws-sdk-in-package-json-deps │ us-east-2 │ Yes. Defined in dependencies of 'package.json' │
|
|
44
|
+
├─────────────────────────────────────────┼───────────┼────────────────────────────────────────────────┤
|
|
45
|
+
│ fn-without-aws-sdk-in-package-json-deps │ us-east-2 │ No. │
|
|
46
|
+
└─────────────────────────────────────────┴───────────┴────────────────────────────────────────────────┘
|
|
60
47
|
```
|
|
61
48
|
|
|
62
49
|
This script requires AWS Managed Policy [AWSLambda_ReadOnlyAccess][].
|
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { Command } from "commander";
|
|
1
|
+
import { Command, Option } from "commander";
|
|
2
2
|
import { cpus } from "node:os";
|
|
3
3
|
import packageJson from "../package.json" with { type: "json" };
|
|
4
4
|
import { scanLambdaFunctions } from "./scanLambdaFunctions.js";
|
|
5
|
+
import { LambdaCommandOutputType } from "./utils/printLambdaCommandOutput.js";
|
|
5
6
|
/**
|
|
6
7
|
* Creates and configures the CLI program with available commands.
|
|
7
8
|
*
|
|
@@ -17,9 +18,12 @@ export const createProgram = () => {
|
|
|
17
18
|
program
|
|
18
19
|
.command("lambda")
|
|
19
20
|
.description("Scans Lambda Node.js Functions for JavaScript SDK v2")
|
|
20
|
-
.option("-y, --yes", "answer yes for all prompts")
|
|
21
|
+
.option("-y, --yes", "answer yes for all prompts", false)
|
|
21
22
|
.option("-r, --region <region>", "AWS region to scan")
|
|
22
23
|
.option("-p, --profile <profile>", "AWS profile to use")
|
|
24
|
+
.addOption(new Option("-o, --output <output>", "Output format")
|
|
25
|
+
.choices(Object.values(LambdaCommandOutputType))
|
|
26
|
+
.default(LambdaCommandOutputType.json))
|
|
23
27
|
.option("-j, --jobs <count>", "number of parallel jobs", (value) => {
|
|
24
28
|
const trimmed = value.trim();
|
|
25
29
|
if (!/^\d+$/.test(trimmed)) {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { Lambda } from "@aws-sdk/client-lambda";
|
|
2
2
|
import pLimit from "p-limit";
|
|
3
|
-
import { getLambdaFunctionScanOutput } from "./getLambdaFunctionScanOutput.js";
|
|
4
3
|
import { getDownloadConfirmation } from "./utils/getDownloadConfirmation.js";
|
|
5
4
|
import { getLambdaFunctions } from "./utils/getLambdaFunctions.js";
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
import { getLambdaFunctionScanOutput } from "./utils/getLambdaFunctionScanOutput.js";
|
|
6
|
+
import { LambdaCommandOutputType, printLambdaCommandOutput, } from "./utils/printLambdaCommandOutput.js";
|
|
7
|
+
export const scanLambdaFunctions = async (options) => {
|
|
8
|
+
const { yes, region, profile, output, jobs } = options;
|
|
8
9
|
const client = new Lambda({
|
|
9
10
|
...(region && { region }),
|
|
10
11
|
...(profile && { profile }),
|
|
@@ -32,9 +33,9 @@ export const scanLambdaFunctions = async (options = {}) => {
|
|
|
32
33
|
}
|
|
33
34
|
const clientRegion = await client.config.region();
|
|
34
35
|
const limit = pLimit(concurrency);
|
|
35
|
-
const
|
|
36
|
+
const scanOutput = await Promise.all(functions.map((fn) => limit(() => getLambdaFunctionScanOutput(client, {
|
|
36
37
|
functionName: fn.FunctionName,
|
|
37
38
|
region: clientRegion,
|
|
38
39
|
}))));
|
|
39
|
-
|
|
40
|
+
printLambdaCommandOutput(scanOutput, output);
|
|
40
41
|
};
|
|
@@ -10,7 +10,7 @@ const PACKAGE_JSON_FILENAME = "package.json";
|
|
|
10
10
|
*/
|
|
11
11
|
export const getLambdaFunctionContents = async (zipPath) => {
|
|
12
12
|
const zip = new StreamZip.async({ file: zipPath });
|
|
13
|
-
const
|
|
13
|
+
const packageJsonFiles = [];
|
|
14
14
|
let zipEntries = {};
|
|
15
15
|
try {
|
|
16
16
|
zipEntries = await zip.entries();
|
|
@@ -31,16 +31,19 @@ export const getLambdaFunctionContents = async (zipPath) => {
|
|
|
31
31
|
continue;
|
|
32
32
|
try {
|
|
33
33
|
const packageJsonContent = await zip.entryData(zipEntry.name);
|
|
34
|
-
|
|
34
|
+
packageJsonFiles.push({
|
|
35
|
+
path: zipEntry.name,
|
|
36
|
+
content: packageJsonContent.toString(),
|
|
37
|
+
});
|
|
35
38
|
}
|
|
36
39
|
catch {
|
|
37
40
|
// Continue without adding package.json file, if entry data can't be read.
|
|
38
41
|
// ToDo: add warning when logging is supported in future.
|
|
39
42
|
}
|
|
40
43
|
}
|
|
41
|
-
if (
|
|
44
|
+
if (packageJsonFiles.length !== 0) {
|
|
42
45
|
await zip.close();
|
|
43
|
-
return {
|
|
46
|
+
return { packageJsonFiles };
|
|
44
47
|
}
|
|
45
48
|
for (const path of ["index.js", "index.mjs", "index.cjs"]) {
|
|
46
49
|
if (!zipEntries[path])
|
|
@@ -50,7 +53,12 @@ export const getLambdaFunctionContents = async (zipPath) => {
|
|
|
50
53
|
try {
|
|
51
54
|
const bundleContent = await zip.entryData(path);
|
|
52
55
|
await zip.close();
|
|
53
|
-
return {
|
|
56
|
+
return {
|
|
57
|
+
bundleFile: {
|
|
58
|
+
path,
|
|
59
|
+
content: bundleContent.toString(),
|
|
60
|
+
},
|
|
61
|
+
};
|
|
54
62
|
}
|
|
55
63
|
catch {
|
|
56
64
|
// Continue processing next index file, if entry data can't be read.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { downloadFile } from "./
|
|
2
|
-
import { getLambdaFunctionContents, } from "./
|
|
3
|
-
import { hasSdkV2InBundle } from "./
|
|
1
|
+
import { downloadFile } from "./downloadFile.js";
|
|
2
|
+
import { getLambdaFunctionContents, } from "./getLambdaFunctionContents.js";
|
|
3
|
+
import { hasSdkV2InBundle } from "./hasSdkV2InBundle.js";
|
|
4
4
|
import { rm } from "node:fs/promises";
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
6
6
|
import { join } from "node:path";
|
|
@@ -31,32 +31,31 @@ export const getLambdaFunctionScanOutput = async (client, { functionName, region
|
|
|
31
31
|
finally {
|
|
32
32
|
await rm(zipPath, { force: true });
|
|
33
33
|
}
|
|
34
|
-
const {
|
|
34
|
+
const { packageJsonFiles, bundleFile } = lambdaFunctionContents;
|
|
35
35
|
// Search for "aws-sdk" in package.json dependencies if present.
|
|
36
|
-
if (
|
|
37
|
-
for (const packageJsonContent of
|
|
36
|
+
if (packageJsonFiles && packageJsonFiles.length > 0) {
|
|
37
|
+
for (const { path: packageJsonPath, content: packageJsonContent } of packageJsonFiles) {
|
|
38
38
|
try {
|
|
39
39
|
const packageJson = JSON.parse(packageJsonContent);
|
|
40
40
|
const dependencies = packageJson.dependencies || {};
|
|
41
41
|
if ("aws-sdk" in dependencies) {
|
|
42
42
|
output.ContainsAwsSdkJsV2 = true;
|
|
43
|
-
output.AwsSdkJsV2Location =
|
|
43
|
+
output.AwsSdkJsV2Location = `Defined in dependencies of '${packageJsonPath}'`;
|
|
44
44
|
return output;
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
catch (error) {
|
|
48
|
+
const errorPrefix = `Error parsing '${packageJsonPath}'`;
|
|
48
49
|
output.AwsSdkJsV2Error =
|
|
49
|
-
error instanceof Error
|
|
50
|
-
? `Error parsing package.json: ${error.message}`
|
|
51
|
-
: "Error parsing package.json";
|
|
50
|
+
error instanceof Error ? `${errorPrefix}: ${error.message}` : errorPrefix;
|
|
52
51
|
return output;
|
|
53
52
|
}
|
|
54
53
|
}
|
|
55
54
|
}
|
|
56
55
|
// Check for code of "aws-sdk" in bundle, if not found in package.json dependencies.
|
|
57
|
-
if (
|
|
56
|
+
if (bundleFile && hasSdkV2InBundle(bundleFile.content)) {
|
|
58
57
|
output.ContainsAwsSdkJsV2 = true;
|
|
59
|
-
output.AwsSdkJsV2Location =
|
|
58
|
+
output.AwsSdkJsV2Location = `Bundled in '${bundleFile.path}'`;
|
|
60
59
|
return output;
|
|
61
60
|
}
|
|
62
61
|
// "aws-sdk" dependency/code not found.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import Table from "cli-table3";
|
|
2
|
+
export const LambdaCommandOutputType = {
|
|
3
|
+
// prints output as JSON
|
|
4
|
+
json: "json",
|
|
5
|
+
// prints human-readable representation in a table
|
|
6
|
+
table: "table",
|
|
7
|
+
};
|
|
8
|
+
export const printLambdaCommandOutput = (output, outputType) => {
|
|
9
|
+
// Output as JSON
|
|
10
|
+
if (outputType === LambdaCommandOutputType.json) {
|
|
11
|
+
console.log(JSON.stringify(output, null, 2));
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
// Output as table
|
|
15
|
+
const table = new Table({
|
|
16
|
+
head: ["FunctionName", "Region", "ContainsAwsSdkJsV2"],
|
|
17
|
+
style: { head: ["bold"] },
|
|
18
|
+
});
|
|
19
|
+
for (const scanOutput of output) {
|
|
20
|
+
let notes = scanOutput.ContainsAwsSdkJsV2 === null
|
|
21
|
+
? "N/A."
|
|
22
|
+
: scanOutput.ContainsAwsSdkJsV2
|
|
23
|
+
? "Yes."
|
|
24
|
+
: "No.";
|
|
25
|
+
if (scanOutput.AwsSdkJsV2Error !== undefined) {
|
|
26
|
+
notes += ` ${scanOutput.AwsSdkJsV2Error}`;
|
|
27
|
+
}
|
|
28
|
+
if (scanOutput.AwsSdkJsV2Location !== undefined) {
|
|
29
|
+
notes += ` ${scanOutput.AwsSdkJsV2Location}`;
|
|
30
|
+
}
|
|
31
|
+
table.push([scanOutput.FunctionName, scanOutput.Region, notes]);
|
|
32
|
+
}
|
|
33
|
+
console.log(table.toString());
|
|
34
|
+
};
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aws-sdk/find-v2",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"description": "CLI to find resources which call AWS using JavaScript SDK v2",
|
|
5
5
|
"main": "dist/cli.js",
|
|
6
6
|
"types": "dist/cli.d.ts",
|
|
7
7
|
"bin": "bin/@aws-sdk/find-v2",
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"@aws-sdk/client-lambda": "^3.942.0",
|
|
10
|
+
"cli-table3": "^0.6.5",
|
|
10
11
|
"commander": "^14.0.2",
|
|
11
12
|
"node-stream-zip": "^1.15.0",
|
|
12
13
|
"p-limit": "^7.2.0"
|