Skip to content

Commit 686c21d

Browse files
Command line parameters, AWS credentials
1 parent 6ef9748 commit 686c21d

File tree

8 files changed

+1423
-339
lines changed

8 files changed

+1423
-339
lines changed

package-lock.json

Lines changed: 1304 additions & 302 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,13 @@
2727
"@aws-sdk/client-iot-data-plane": "^3.523.0",
2828
"@aws-sdk/client-lambda": "^3.518.0",
2929
"@aws-sdk/client-s3": "^3.515.0",
30+
"@aws-sdk/credential-providers": "^3.515.0",
3031
"chokidar": "^3.6.0",
3132
"esbuild": "^0.20.1",
3233
"@types/aws-iot-device-sdk": "^2.2.8",
3334
"aws-iot-device-sdk": "^2.2.13",
34-
"node-machine-id": "^1.1.12"
35+
"node-machine-id": "^1.1.12",
36+
"commander": "^12.0.0"
3537
},
3638
"peerDependencies": {
3739
"aws-cdk": "^2",

src/awsCredentials.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export * as AwsCredentials from "./awsCredentials.js";
2+
import { fromNodeProviderChain } from "@aws-sdk/credential-providers";
3+
import * as LlDebugger from "./lldebugger.js";
4+
import type { AwsCredentialIdentityProvider } from "@smithy/types";
5+
6+
export function getCredentialsProvider(): AwsCredentialIdentityProvider {
7+
return fromNodeProviderChain({
8+
clientConfig: { region: LlDebugger.argOptions.region },
9+
profile: LlDebugger.argOptions.profile,
10+
roleArn: LlDebugger.argOptions.role,
11+
});
12+
}

src/cdkResourcesDiscovery.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { outputFolder } from "./constants.js";
88
import type { BundlingOptions } from "aws-cdk-lib/aws-lambda-nodejs";
99
import { BundlingType } from "./functionProps.js";
1010
import { findAboveFolderWithAFile } from "./findAboveFolderWithAFile.js";
11+
import { LlDebugger } from "./lldebugger.js";
1112

1213
// this is global variable to store the data from the CDK code once it is executed
1314
declare global {
@@ -342,18 +343,21 @@ async function getLambdasDataFromCdkByCompilingAndRunning(
342343
async function getCdkContext(cdkConfigPath: string) {
343344
// get CDK context from the command line
344345
// get all "-c" and "--context" arguments from the command line
346+
345347
const contextArgs = process.argv.filter(
346348
(arg) => arg.startsWith("-c") ?? arg.startsWith("--context")
347349
);
348350

351+
//const contextArgs = LlDebugger.argOptions.context;
352+
349353
//parameter can be like:
350354
// -c key=value
351355
// -c=key=value
352356
// --context key=value
353357
// --context=key=value
354358
// extract the key and value from the parameter
355359
// take into account that first seperator can be "=" or " "
356-
const contextFromCli = contextArgs.reduce((acc, arg) => {
360+
const contextFromCli = contextArgs?.reduce((acc, arg) => {
357361
const [key, value] = arg.split(/=| /).slice(1);
358362
(acc as any)[key] = value;
359363
return acc;

src/getIoTEndpoint.ts

Lines changed: 0 additions & 15 deletions
This file was deleted.

src/infraDeploy.ts

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,27 @@ import { getDebuggerId, getVersion, moduleDirname } from "./lldebugger.js";
1717
import * as Functions from "./functions.js";
1818
import fs from "fs/promises";
1919
import * as path from "path";
20+
import * as AwsCredentials from "./awsCredentials.js";
2021

21-
const lambdaClient = new LambdaClient({});
22-
const iamClient = new IAMClient({});
22+
let lambdaClient: LambdaClient | undefined;
23+
function getLambdaClient(): LambdaClient {
24+
if (!lambdaClient) {
25+
lambdaClient = new LambdaClient({
26+
credentials: AwsCredentials.getCredentialsProvider(),
27+
});
28+
}
29+
return lambdaClient;
30+
}
31+
32+
let iamClient: IAMClient | undefined;
33+
function getIAMClient(): IAMClient {
34+
if (!iamClient) {
35+
iamClient = new IAMClient({
36+
credentials: AwsCredentials.getCredentialsProvider(),
37+
});
38+
}
39+
return iamClient;
40+
}
2341

2442
const inlinePolicyName = "LambdaLiveDebuggerPolicy";
2543
const layerName = "LambdaLiveDebugger"; // Replace with your layer name
@@ -39,7 +57,7 @@ async function findExistingLayer(layerName: string) {
3957
LayerName: layerName,
4058
});
4159

42-
const response = await lambdaClient.send(listLayerVersionsCommand);
60+
const response = await getLambdaClient().send(listLayerVersionsCommand);
4361
if (response.LayerVersions && response.LayerVersions.length > 0) {
4462
return response.LayerVersions[0];
4563
}
@@ -84,7 +102,7 @@ async function deployLayer() {
84102
LayerName: layerName,
85103
VersionNumber: existingLayer.Version,
86104
});
87-
await lambdaClient.send(deleteLayerVersionCommand);
105+
await getLambdaClient().send(deleteLayerVersionCommand);
88106
// console.log("Layer already deployed.");
89107
// return existingLayer.LayerVersionArn;
90108
}
@@ -103,7 +121,7 @@ async function deployLayer() {
103121
CompatibleRuntimes: ["nodejs18.x", "nodejs20.x"],
104122
});
105123

106-
const response = await lambdaClient.send(publishLayerVersionCommand);
124+
const response = await getLambdaClient().send(publishLayerVersionCommand);
107125

108126
if (!response.LayerVersionArn) {
109127
throw new Error("Failed to retrieve the layer version ARN");
@@ -116,7 +134,7 @@ async function deployLayer() {
116134
async function deleteLayer() {
117135
let nextMarker: string | undefined;
118136
do {
119-
const layers = await lambdaClient.send(
137+
const layers = await getLambdaClient().send(
120138
new ListLayersCommand({
121139
Marker: nextMarker,
122140
MaxItems: 10,
@@ -138,7 +156,7 @@ async function deleteLayer() {
138156
async function deleteAllVersionsOfLayer(layerArn: string): Promise<void> {
139157
let nextMarker: string | undefined;
140158
do {
141-
const versions = await lambdaClient.send(
159+
const versions = await getLambdaClient().send(
142160
new ListLayerVersionsCommand({
143161
LayerName: layerArn,
144162
Marker: nextMarker,
@@ -159,7 +177,7 @@ async function deleteLayerVersion(
159177
versionNumber: number
160178
): Promise<void> {
161179
try {
162-
await lambdaClient.send(
180+
await getLambdaClient().send(
163181
new DeleteLayerVersionCommand({
164182
LayerName: layerArn,
165183
VersionNumber: versionNumber,
@@ -217,7 +235,7 @@ async function removeLayerFromFunction(functionName: string) {
217235
Timeout: initialTimeout,
218236
});
219237

220-
lambdaClient.send(updateFunctionConfigurationCommand);
238+
getLambdaClient().send(updateFunctionConfigurationCommand);
221239

222240
console.log(`Function configuration cleared ${functionName}`);
223241
} else {
@@ -226,7 +244,7 @@ async function removeLayerFromFunction(functionName: string) {
226244
}
227245

228246
async function getFunctionCongfiguration(functionName: string) {
229-
const getFunctionResponse = await lambdaClient.send(
247+
const getFunctionResponse = await getLambdaClient().send(
230248
new GetFunctionCommand({
231249
FunctionName: functionName,
232250
})
@@ -313,7 +331,7 @@ async function attachLayerToFunction(
313331
Timeout: 300, // Increase the timeout to 5 minutes
314332
});
315333

316-
lambdaClient.send(updateFunctionConfigurationCommand);
334+
getLambdaClient().send(updateFunctionConfigurationCommand);
317335

318336
console.log(`Function configuration updated for ${functionName}`);
319337
} else {
@@ -336,7 +354,7 @@ function getDdlEnvironmentVarables(
336354

337355
async function addPolicyToLambdaRole(functionName: string) {
338356
// Retrieve the Lambda function's execution role ARN
339-
const getFunctionResponse = await lambdaClient.send(
357+
const getFunctionResponse = await getLambdaClient().send(
340358
new GetFunctionCommand({
341359
FunctionName: functionName,
342360
})
@@ -373,7 +391,7 @@ async function addPolicyToLambdaRole(functionName: string) {
373391

374392
if (addPolicy) {
375393
// add inline policy to the role using PutRolePolicyCommand
376-
await iamClient.send(
394+
await getIAMClient().send(
377395
new PutRolePolicyCommand({
378396
RoleName: roleName,
379397
PolicyName: inlinePolicyName,
@@ -385,7 +403,7 @@ async function addPolicyToLambdaRole(functionName: string) {
385403

386404
async function getPolicyDocument(roleName: string) {
387405
try {
388-
const policy = await iamClient.send(
406+
const policy = await getIAMClient().send(
389407
new GetRolePolicyCommand({
390408
RoleName: roleName,
391409
PolicyName: inlinePolicyName,

src/ioTService.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
export * as IoTService from "./ioTService.js";
22
import * as iot from "aws-iot-device-sdk";
33
import { splitMessageToChunks, MessageChunk } from "./splitIoTMessage.js";
4-
import { getIoTEndpoint } from "./getIoTEndpoint.js";
4+
import { IoTClient, DescribeEndpointCommand } from "@aws-sdk/client-iot";
5+
import type {
6+
AwsCredentialIdentityProvider,
7+
AwsCredentialIdentity,
8+
} from "@smithy/types";
59

610
let device: iot.device;
711

@@ -54,18 +58,45 @@ export type IoTMessage =
5458

5559
export type IoTMessageTypes = IoTMessage["type"];
5660

61+
export async function getIoTEndpoint({
62+
credentials,
63+
}: {
64+
credentials?: AwsCredentialIdentity;
65+
}) {
66+
const iot = new IoTClient({ credentials });
67+
const response = await iot.send(
68+
new DescribeEndpointCommand({
69+
endpointType: "iot:Data-ATS",
70+
})
71+
);
72+
73+
if (!response.endpointAddress)
74+
throw new Error("IoT Endpoint address not found");
75+
76+
return response.endpointAddress;
77+
}
78+
5779
export async function connect(props: {
5880
onMessage: (message: IoTMessage) => void;
5981
topic: string;
82+
credentialsProvider?: AwsCredentialIdentityProvider;
6083
}): Promise<{
6184
publish: (payload: IoTMessage, topic: string) => Promise<void>;
6285
}> {
63-
const endpoint = await getIoTEndpoint();
86+
const credentials = props.credentialsProvider
87+
? await props.credentialsProvider()
88+
: undefined;
89+
90+
const endpoint = await getIoTEndpoint({ credentials });
91+
6492
device = new iot.device({
6593
protocol: "wss",
6694
host: endpoint,
6795
reconnectPeriod: 1,
6896
keepalive: 60,
97+
accessKeyId: credentials?.accessKeyId,
98+
secretKey: credentials?.secretAccessKey,
99+
sessionToken: credentials?.sessionToken,
69100
});
70101

71102
device.subscribe(props.topic, { qos: 1 });

src/lldebugger.ts

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// ****** support require in for CJS modules ******
2+
export * as LlDebugger from "./lldebugger.js";
23
import { createRequire } from "module";
34
// @ts-ignore
45
const require = createRequire(import.meta.url);
@@ -17,17 +18,44 @@ import * as FileWatcher from "./fileWatcher.js";
1718
import * as fs from "fs";
1819
import { fileURLToPath } from "url";
1920
import * as path from "path";
21+
import { Command } from "commander";
22+
import * as AwsCredentials from "./awsCredentials.js";
2023

2124
const __filename = fileURLToPath(import.meta.url);
2225
const __dirname = path.dirname(__filename);
2326

2427
export let resources: ResourcesToDebug;
2528
let debuggerId: string;
2629

30+
export let argOptions: {
31+
destroy?: boolean;
32+
verbose?: boolean;
33+
context?: string;
34+
profile?: string;
35+
region?: string;
36+
role?: string;
37+
};
38+
2739
async function run() {
40+
const version = await getVersion();
41+
const program = new Command();
42+
43+
program.name("lld").description("Lambda Live Debugger").version(version);
44+
45+
program.option("-d, --destroy", "Destroy the infrastructure");
46+
program.option("-v, --verbose", "Verbose logs");
47+
program.option("-c, --context <context>", "AWS CDK context");
48+
program.option("--profile <profile>", "AWS profile to use");
49+
program.option("--region <region>", "AWS region to use");
50+
program.option("--role <role>", "AWS role to use");
51+
52+
program.parse(process.argv);
53+
54+
argOptions = program.opts();
55+
2856
debuggerId = await generateDebuggerId();
2957
console.log(
30-
`Welcome to Lambda Live Debugger version: ${await getVersion()}! Starting the debugger (ID ${debuggerId})...`
58+
`Welcome to Lambda Live Debugger version: ${version}! Starting the debugger (ID ${debuggerId})...`
3159
);
3260
resources = await CdkResourcesDiscovery.resourcesDiscovery();
3361

@@ -44,9 +72,10 @@ async function run() {
4472
.join("\n - ")}`
4573
);
4674

47-
// await InfraDeploy.destroyInfrastructure();
48-
49-
// return;
75+
if (argOptions.destroy) {
76+
await InfraDeploy.destroyInfrastructure();
77+
return;
78+
}
5079
await InfraDeploy.deployInfrastructure();
5180

5281
const topic = `${debuggerId}/events`;
@@ -104,6 +133,7 @@ async function run() {
104133
}
105134
},
106135
topic,
136+
credentialsProvider: AwsCredentials.getCredentialsProvider(),
107137
});
108138
console.log("Debugger started!");
109139
}

0 commit comments

Comments
 (0)