@dsmrt/axiom-cli 0.3.1 → 1.1.0
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/CHANGELOG.md +23 -0
- package/dist/bin/axiom.js +110 -48
- package/dist/bin/axiom.mjs +1 -1
- package/dist/{chunk-QT654PKF.mjs → chunk-CORLQJO7.mjs} +106 -44
- package/dist/index.d.mts +9 -10
- package/dist/index.d.ts +9 -10
- package/dist/index.js +180 -114
- package/dist/index.mjs +1 -1
- package/package.json +9 -12
- package/tsconfig.json +10 -10
- package/vitest.config.mts +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# @dsmrt/axiom-cli
|
|
2
2
|
|
|
3
|
+
## 1.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- b1a56bc: adding debug logging to the cli and config packages
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [b1a56bc]
|
|
12
|
+
- @dsmrt/axiom-config@1.1.0
|
|
13
|
+
|
|
14
|
+
## 1.0.0
|
|
15
|
+
|
|
16
|
+
### Major Changes
|
|
17
|
+
|
|
18
|
+
- d767a0e: Making loadConfig return a promise; adding typescript config support and better esm/mjs/mts support; better docs
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- Updated dependencies [d767a0e]
|
|
23
|
+
- @dsmrt/axiom-aws-sdk@1.0.0
|
|
24
|
+
- @dsmrt/axiom-config@1.0.0
|
|
25
|
+
|
|
3
26
|
## 0.3.1
|
|
4
27
|
|
|
5
28
|
### Patch Changes
|
package/dist/bin/axiom.js
CHANGED
|
@@ -28,6 +28,16 @@ var import_yargs = __toESM(require("yargs"));
|
|
|
28
28
|
|
|
29
29
|
// src/commands/config.ts
|
|
30
30
|
var import_axiom_config = require("@dsmrt/axiom-config");
|
|
31
|
+
|
|
32
|
+
// src/debug.ts
|
|
33
|
+
var isDebugEnabled = () => process.env.AXIOM_DEBUG === "true" || process.env.AXIOM_DEBUG === "1";
|
|
34
|
+
var debug = (message, ...args) => {
|
|
35
|
+
if (isDebugEnabled()) {
|
|
36
|
+
console.error(`[axiom:cli] ${message}`, ...args);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// src/commands/config.ts
|
|
31
41
|
var Config = class {
|
|
32
42
|
command = "config";
|
|
33
43
|
describe = "print the config";
|
|
@@ -38,9 +48,13 @@ var Config = class {
|
|
|
38
48
|
return args;
|
|
39
49
|
};
|
|
40
50
|
handler = async (args) => {
|
|
41
|
-
|
|
51
|
+
debug(`Config command handler called with env: ${args.env}`);
|
|
52
|
+
const config = await this.loadConfig(args);
|
|
53
|
+
debug(`Config loaded successfully, outputting as JSON`);
|
|
54
|
+
console.log(JSON.stringify(config));
|
|
42
55
|
};
|
|
43
56
|
loadConfig = async (args) => {
|
|
57
|
+
debug(`Loading config with env: ${args.env}`);
|
|
44
58
|
return (0, import_axiom_config.loadConfig)(args);
|
|
45
59
|
};
|
|
46
60
|
};
|
|
@@ -59,9 +73,10 @@ var ParamsCommand = class {
|
|
|
59
73
|
};
|
|
60
74
|
|
|
61
75
|
// src/commands/params/get.ts
|
|
62
|
-
var import_axiom_config2 = require("@dsmrt/axiom-config");
|
|
63
|
-
var import_axiom_aws_sdk = require("@dsmrt/axiom-aws-sdk");
|
|
64
76
|
var import_client_ssm = require("@aws-sdk/client-ssm");
|
|
77
|
+
var import_axiom_aws_sdk = require("@dsmrt/axiom-aws-sdk");
|
|
78
|
+
var import_axiom_config2 = require("@dsmrt/axiom-config");
|
|
79
|
+
var import_chalk = __toESM(require("chalk"));
|
|
65
80
|
|
|
66
81
|
// src/aws/credentials-provider.ts
|
|
67
82
|
var import_credential_providers = require("@aws-sdk/credential-providers");
|
|
@@ -69,19 +84,19 @@ var import_client_sts = require("@aws-sdk/client-sts");
|
|
|
69
84
|
var import_inquirer = __toESM(require("inquirer"));
|
|
70
85
|
|
|
71
86
|
// src/cache.ts
|
|
72
|
-
var
|
|
73
|
-
var
|
|
74
|
-
var DEFAULT_DIRECTORY = `${
|
|
87
|
+
var import_node_fs = __toESM(require("fs"));
|
|
88
|
+
var import_node_os = __toESM(require("os"));
|
|
89
|
+
var DEFAULT_DIRECTORY = `${import_node_os.default.homedir()}/.axiom/cache`;
|
|
75
90
|
var cache_default = class {
|
|
76
91
|
constructor(cacheDir = DEFAULT_DIRECTORY) {
|
|
77
92
|
this.cacheDir = cacheDir;
|
|
78
93
|
}
|
|
79
94
|
get(name) {
|
|
80
95
|
const file = `${this.cacheDir}/${name}`;
|
|
81
|
-
if (!
|
|
96
|
+
if (!import_node_fs.default.existsSync(file)) {
|
|
82
97
|
return;
|
|
83
98
|
}
|
|
84
|
-
const buffer =
|
|
99
|
+
const buffer = import_node_fs.default.readFileSync(file);
|
|
85
100
|
const item = JSON.parse(buffer.toString());
|
|
86
101
|
if (item.expires === void 0) {
|
|
87
102
|
return item.data;
|
|
@@ -94,16 +109,16 @@ var cache_default = class {
|
|
|
94
109
|
return item.data;
|
|
95
110
|
}
|
|
96
111
|
delete(name) {
|
|
97
|
-
|
|
112
|
+
import_node_fs.default.unlinkSync(`${this.cacheDir}/${name}`);
|
|
98
113
|
}
|
|
99
114
|
set(name, value, expires) {
|
|
100
|
-
if (!
|
|
101
|
-
|
|
115
|
+
if (!import_node_fs.default.existsSync(this.cacheDir)) {
|
|
116
|
+
import_node_fs.default.mkdirSync(this.cacheDir, {
|
|
102
117
|
recursive: true,
|
|
103
118
|
mode: 448
|
|
104
119
|
});
|
|
105
120
|
}
|
|
106
|
-
|
|
121
|
+
import_node_fs.default.writeFileSync(
|
|
107
122
|
`${this.cacheDir}/${name}`,
|
|
108
123
|
JSON.stringify({
|
|
109
124
|
expires,
|
|
@@ -199,38 +214,31 @@ var awsOptions = () => {
|
|
|
199
214
|
};
|
|
200
215
|
};
|
|
201
216
|
|
|
202
|
-
// src/commands/params/utils.ts
|
|
203
|
-
var buildPath = (config, path) => {
|
|
204
|
-
if (path === void 0) {
|
|
205
|
-
return config.aws?.baseParameterPath;
|
|
206
|
-
}
|
|
207
|
-
if (/^\//.test(path)) {
|
|
208
|
-
return path;
|
|
209
|
-
}
|
|
210
|
-
return `${config.aws?.baseParameterPath.replace(/\/$/, "")}/${path}`;
|
|
211
|
-
};
|
|
212
|
-
|
|
213
217
|
// src/commands/params/get.ts
|
|
214
|
-
var import_chalk = __toESM(require("chalk"));
|
|
215
218
|
var GetCommand = class {
|
|
216
219
|
command = "get [path]";
|
|
217
220
|
describe = "Get all parameters under the base path";
|
|
218
221
|
builder = (args) => {
|
|
219
|
-
const config = (0, import_axiom_config2.loadConfig)();
|
|
220
222
|
args.options({ ...commonOptions(), ...awsOptions() });
|
|
221
223
|
args.positional("path", {
|
|
222
224
|
type: "string",
|
|
223
225
|
describe: `OPTIONAL path to parameter. Supports absolute and relative paths.
|
|
224
226
|
Example:
|
|
225
|
-
"/root/myParam" or "service/secret"
|
|
226
|
-
config,
|
|
227
|
-
"service/secret"
|
|
228
|
-
)})`
|
|
227
|
+
"/root/myParam" or "service/secret"`
|
|
229
228
|
});
|
|
230
229
|
return args;
|
|
231
230
|
};
|
|
232
231
|
handler = async (args) => {
|
|
233
|
-
|
|
232
|
+
debug(
|
|
233
|
+
`Get command handler called with env: ${args.env}, path: ${args.path}`
|
|
234
|
+
);
|
|
235
|
+
const config = await (0, import_axiom_config2.loadConfig)({ env: args.env });
|
|
236
|
+
debug(
|
|
237
|
+
`Config loaded successfully, base parameter path: ${config.aws?.baseParameterPath}`
|
|
238
|
+
);
|
|
239
|
+
debug(
|
|
240
|
+
`Creating SSM client with region: ${config.aws.region}, profile: ${config.aws.profile}`
|
|
241
|
+
);
|
|
234
242
|
const collection = new import_axiom_aws_sdk.ParameterCollection(
|
|
235
243
|
config.aws?.baseParameterPath,
|
|
236
244
|
new import_client_ssm.SSMClient({
|
|
@@ -243,11 +251,13 @@ Example:
|
|
|
243
251
|
})
|
|
244
252
|
})
|
|
245
253
|
);
|
|
254
|
+
debug(`Fetching parameters from SSM...`);
|
|
246
255
|
const params = await collection.get();
|
|
256
|
+
debug(`Retrieved ${params.size} parameters`);
|
|
247
257
|
params.forEach((parameter) => {
|
|
248
258
|
console.log(
|
|
249
259
|
import_chalk.default.gray(
|
|
250
|
-
parameter.Name?.replace(/\/([^/]+)$/,
|
|
260
|
+
parameter.Name?.replace(/\/([^/]+)$/, `/${import_chalk.default.bold.green("$1")}`)
|
|
251
261
|
),
|
|
252
262
|
import_chalk.default.bold.white(parameter.Value)
|
|
253
263
|
);
|
|
@@ -256,22 +266,31 @@ Example:
|
|
|
256
266
|
};
|
|
257
267
|
|
|
258
268
|
// src/commands/params/set.ts
|
|
259
|
-
var import_axiom_config3 = require("@dsmrt/axiom-config");
|
|
260
|
-
var import_inquirer2 = __toESM(require("inquirer"));
|
|
261
269
|
var import_client_ssm2 = require("@aws-sdk/client-ssm");
|
|
270
|
+
var import_axiom_config3 = require("@dsmrt/axiom-config");
|
|
262
271
|
var import_chalk2 = __toESM(require("chalk"));
|
|
272
|
+
var import_inquirer2 = __toESM(require("inquirer"));
|
|
273
|
+
|
|
274
|
+
// src/commands/params/utils.ts
|
|
275
|
+
var buildPath = (config, path) => {
|
|
276
|
+
if (path === void 0) {
|
|
277
|
+
return config.aws?.baseParameterPath;
|
|
278
|
+
}
|
|
279
|
+
if (/^\//.test(path)) {
|
|
280
|
+
return path;
|
|
281
|
+
}
|
|
282
|
+
return `${config.aws?.baseParameterPath.replace(/\/$/, "")}/${path}`;
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
// src/commands/params/set.ts
|
|
263
286
|
var SetCommand = class {
|
|
264
287
|
command = "set <path> <value>";
|
|
265
288
|
describe = "Set all parameters under the base path";
|
|
266
289
|
builder = (args) => {
|
|
267
|
-
const config = (0, import_axiom_config3.loadConfig)();
|
|
268
290
|
args.positional("path", {
|
|
269
291
|
type: "string",
|
|
270
292
|
describe: `Path to parameter. Supports absolute and relative paths.
|
|
271
|
-
Example: "/root/myParam" or "service/secret"
|
|
272
|
-
config,
|
|
273
|
-
"service/secret"
|
|
274
|
-
)})`
|
|
293
|
+
Example: "/root/myParam" or "service/secret"`
|
|
275
294
|
});
|
|
276
295
|
args.demandOption("path", "Path is required");
|
|
277
296
|
args.positional("value", {
|
|
@@ -300,53 +319,68 @@ Example: "/root/myParam" or "service/secret" (which translates to, "${buildPath(
|
|
|
300
319
|
});
|
|
301
320
|
};
|
|
302
321
|
handler = async (args) => {
|
|
303
|
-
|
|
322
|
+
debug(
|
|
323
|
+
`Set command handler called with path: ${args.path}, secure: ${args.secure}, overwrite: ${args.overwrite}, force: ${args.force}`
|
|
324
|
+
);
|
|
325
|
+
const config = await (0, import_axiom_config3.loadConfig)({ env: args.env });
|
|
326
|
+
debug(
|
|
327
|
+
`Config loaded successfully, base parameter path: ${config.aws?.baseParameterPath}`
|
|
328
|
+
);
|
|
329
|
+
const fullPath = buildPath(config, args.path);
|
|
330
|
+
debug(`Full parameter path: ${fullPath}`);
|
|
304
331
|
if (args.force !== true) {
|
|
332
|
+
debug(`Prompting user for confirmation...`);
|
|
305
333
|
const res = await import_inquirer2.default.prompt({
|
|
306
334
|
type: "confirm",
|
|
307
335
|
name: "setParam",
|
|
308
336
|
message: `Are you sure you want to set '${args.path}'?`
|
|
309
337
|
});
|
|
310
338
|
if (!res.setParam) {
|
|
339
|
+
debug(`User declined, aborting`);
|
|
311
340
|
console.log("Doing nothing.");
|
|
312
341
|
return;
|
|
313
342
|
}
|
|
343
|
+
debug(`User confirmed`);
|
|
344
|
+
} else {
|
|
345
|
+
debug(`Force flag set, skipping confirmation`);
|
|
314
346
|
}
|
|
347
|
+
debug(
|
|
348
|
+
`Creating SSM client with region: ${config.aws.region}, profile: ${config.aws.profile}`
|
|
349
|
+
);
|
|
315
350
|
const client = new import_client_ssm2.SSMClient({
|
|
316
351
|
region: config.aws.region,
|
|
317
352
|
credentials: await CachedCredentialProvider(config.aws)
|
|
318
353
|
});
|
|
354
|
+
debug(
|
|
355
|
+
`Sending parameter to SSM with type: ${args.secure ? "SecureString" : "String"}`
|
|
356
|
+
);
|
|
319
357
|
const params = await client.send(
|
|
320
358
|
new import_client_ssm2.PutParameterCommand({
|
|
321
|
-
Name:
|
|
359
|
+
Name: fullPath,
|
|
322
360
|
Value: args.value,
|
|
323
361
|
Type: args.secure ? import_client_ssm2.ParameterType.SECURE_STRING : import_client_ssm2.ParameterType.STRING,
|
|
324
362
|
Overwrite: args.overwrite
|
|
325
363
|
})
|
|
326
364
|
);
|
|
365
|
+
debug(`Parameter set successfully, version: ${params.Version}`);
|
|
327
366
|
console.log(import_chalk2.default.green("Version: "), import_chalk2.default.white.bold(params.Version));
|
|
328
367
|
};
|
|
329
368
|
};
|
|
330
369
|
|
|
331
370
|
// src/commands/params/delete.ts
|
|
371
|
+
var import_client_ssm3 = require("@aws-sdk/client-ssm");
|
|
332
372
|
var import_axiom_config4 = require("@dsmrt/axiom-config");
|
|
333
373
|
var import_inquirer3 = __toESM(require("inquirer"));
|
|
334
|
-
var import_client_ssm3 = require("@aws-sdk/client-ssm");
|
|
335
374
|
var log = console.log;
|
|
336
375
|
var DeleteCommand = class {
|
|
337
376
|
command = "delete <path>";
|
|
338
377
|
describe = "Delete SSM parameters";
|
|
339
378
|
client;
|
|
340
379
|
builder = (args) => {
|
|
341
|
-
const config = (0, import_axiom_config4.loadConfig)();
|
|
342
380
|
args.positional("path", {
|
|
343
381
|
type: "string",
|
|
344
382
|
describe: `Path to parameter. Supports absolute and relative paths.
|
|
345
|
-
Example: "/root/myParam" or "service/secret"
|
|
346
|
-
config,
|
|
347
|
-
"service/secret"
|
|
348
|
-
)})`,
|
|
349
|
-
default: config.aws?.baseParameterPath,
|
|
383
|
+
Example: "/root/myParam" or "service/secret"`,
|
|
350
384
|
demandOption: true
|
|
351
385
|
}).demandOption("path", "Path is required");
|
|
352
386
|
args.option("force", {
|
|
@@ -358,33 +392,51 @@ Example: "/root/myParam" or "service/secret" (which translates to, "${buildPath(
|
|
|
358
392
|
return args;
|
|
359
393
|
};
|
|
360
394
|
handler = async (args) => {
|
|
361
|
-
|
|
395
|
+
debug(
|
|
396
|
+
`Delete command handler called with path: ${args.path}, force: ${args.force}`
|
|
397
|
+
);
|
|
398
|
+
const config = await (0, import_axiom_config4.loadConfig)({ env: args.env });
|
|
399
|
+
debug(
|
|
400
|
+
`Config loaded successfully, base parameter path: ${config.aws?.baseParameterPath}`
|
|
401
|
+
);
|
|
362
402
|
const path = buildPath(args, args.path);
|
|
403
|
+
debug(`Full parameter path: ${path}`);
|
|
404
|
+
debug(
|
|
405
|
+
`Creating SSM client with region: ${config.aws?.region}, profile: ${config.aws?.profile}`
|
|
406
|
+
);
|
|
363
407
|
const client = new import_client_ssm3.SSMClient({
|
|
364
408
|
region: config.aws?.region,
|
|
365
409
|
credentials: await CachedCredentialProvider(config.aws)
|
|
366
410
|
});
|
|
367
411
|
if (path === args.aws.baseParameterPath) {
|
|
412
|
+
debug(`Delete blocked: path matches base parameter path`);
|
|
368
413
|
throw new Error(
|
|
369
414
|
`Deleting the path (path: ${path}) that matches the base path (awsSsmParameterPath: ${args.awsSsmParameterPath}) is prohibited.`
|
|
370
415
|
);
|
|
371
416
|
}
|
|
372
417
|
if (args.force !== true) {
|
|
418
|
+
debug(`Prompting user for confirmation...`);
|
|
373
419
|
const res = await import_inquirer3.default.prompt({
|
|
374
420
|
type: "confirm",
|
|
375
421
|
name: "delete",
|
|
376
422
|
message: `Are you sure you want to delete '${path}'?`
|
|
377
423
|
});
|
|
378
424
|
if (!res.delete) {
|
|
425
|
+
debug(`User declined, aborting`);
|
|
379
426
|
log("Doing nothing.");
|
|
380
427
|
return;
|
|
381
428
|
}
|
|
429
|
+
debug(`User confirmed`);
|
|
430
|
+
} else {
|
|
431
|
+
debug(`Force flag set, skipping confirmation`);
|
|
382
432
|
}
|
|
433
|
+
debug(`Sending delete command to SSM for: ${path}`);
|
|
383
434
|
await client.send(
|
|
384
435
|
new import_client_ssm3.DeleteParameterCommand({
|
|
385
436
|
Name: path
|
|
386
437
|
})
|
|
387
438
|
);
|
|
439
|
+
debug(`Parameter deleted successfully`);
|
|
388
440
|
log("\u{1F44D}");
|
|
389
441
|
};
|
|
390
442
|
};
|
|
@@ -393,6 +445,16 @@ Example: "/root/myParam" or "service/secret" (which translates to, "${buildPath(
|
|
|
393
445
|
(0, import_yargs.default)(process.argv.slice(2)).env("AXIOM").scriptName("axiom").option("config", {
|
|
394
446
|
alias: "c",
|
|
395
447
|
string: true
|
|
448
|
+
}).option("debug", {
|
|
449
|
+
alias: "d",
|
|
450
|
+
type: "boolean",
|
|
451
|
+
description: "Enable debug output",
|
|
452
|
+
default: false,
|
|
453
|
+
global: true
|
|
454
|
+
}).middleware((argv) => {
|
|
455
|
+
if (argv.debug) {
|
|
456
|
+
process.env.AXIOM_DEBUG = "true";
|
|
457
|
+
}
|
|
396
458
|
}).command(new Config()).command(new ParamsCommand()).strict().usage(
|
|
397
459
|
`
|
|
398
460
|
Axiom - an AWS focused config cli
|
package/dist/bin/axiom.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import "../chunk-
|
|
2
|
+
import "../chunk-CORLQJO7.mjs";
|
|
@@ -3,6 +3,16 @@ import yargs from "yargs";
|
|
|
3
3
|
|
|
4
4
|
// src/commands/config.ts
|
|
5
5
|
import { loadConfig } from "@dsmrt/axiom-config";
|
|
6
|
+
|
|
7
|
+
// src/debug.ts
|
|
8
|
+
var isDebugEnabled = () => process.env.AXIOM_DEBUG === "true" || process.env.AXIOM_DEBUG === "1";
|
|
9
|
+
var debug = (message, ...args) => {
|
|
10
|
+
if (isDebugEnabled()) {
|
|
11
|
+
console.error(`[axiom:cli] ${message}`, ...args);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// src/commands/config.ts
|
|
6
16
|
var Config = class {
|
|
7
17
|
command = "config";
|
|
8
18
|
describe = "print the config";
|
|
@@ -13,9 +23,13 @@ var Config = class {
|
|
|
13
23
|
return args;
|
|
14
24
|
};
|
|
15
25
|
handler = async (args) => {
|
|
16
|
-
|
|
26
|
+
debug(`Config command handler called with env: ${args.env}`);
|
|
27
|
+
const config = await this.loadConfig(args);
|
|
28
|
+
debug(`Config loaded successfully, outputting as JSON`);
|
|
29
|
+
console.log(JSON.stringify(config));
|
|
17
30
|
};
|
|
18
31
|
loadConfig = async (args) => {
|
|
32
|
+
debug(`Loading config with env: ${args.env}`);
|
|
19
33
|
return loadConfig(args);
|
|
20
34
|
};
|
|
21
35
|
};
|
|
@@ -34,9 +48,10 @@ var ParamsCommand = class {
|
|
|
34
48
|
};
|
|
35
49
|
|
|
36
50
|
// src/commands/params/get.ts
|
|
37
|
-
import { loadConfig as loadConfig2 } from "@dsmrt/axiom-config";
|
|
38
|
-
import { ParameterCollection } from "@dsmrt/axiom-aws-sdk";
|
|
39
51
|
import { SSMClient } from "@aws-sdk/client-ssm";
|
|
52
|
+
import { ParameterCollection } from "@dsmrt/axiom-aws-sdk";
|
|
53
|
+
import { loadConfig as loadConfig2 } from "@dsmrt/axiom-config";
|
|
54
|
+
import chalk from "chalk";
|
|
40
55
|
|
|
41
56
|
// src/aws/credentials-provider.ts
|
|
42
57
|
import { fromNodeProviderChain } from "@aws-sdk/credential-providers";
|
|
@@ -47,8 +62,8 @@ import {
|
|
|
47
62
|
import inquirer from "inquirer";
|
|
48
63
|
|
|
49
64
|
// src/cache.ts
|
|
50
|
-
import os from "os";
|
|
51
65
|
import fs from "fs";
|
|
66
|
+
import os from "os";
|
|
52
67
|
var DEFAULT_DIRECTORY = `${os.homedir()}/.axiom/cache`;
|
|
53
68
|
var cache_default = class {
|
|
54
69
|
constructor(cacheDir = DEFAULT_DIRECTORY) {
|
|
@@ -177,38 +192,31 @@ var awsOptions = () => {
|
|
|
177
192
|
};
|
|
178
193
|
};
|
|
179
194
|
|
|
180
|
-
// src/commands/params/utils.ts
|
|
181
|
-
var buildPath = (config, path) => {
|
|
182
|
-
if (path === void 0) {
|
|
183
|
-
return config.aws?.baseParameterPath;
|
|
184
|
-
}
|
|
185
|
-
if (/^\//.test(path)) {
|
|
186
|
-
return path;
|
|
187
|
-
}
|
|
188
|
-
return `${config.aws?.baseParameterPath.replace(/\/$/, "")}/${path}`;
|
|
189
|
-
};
|
|
190
|
-
|
|
191
195
|
// src/commands/params/get.ts
|
|
192
|
-
import chalk from "chalk";
|
|
193
196
|
var GetCommand = class {
|
|
194
197
|
command = "get [path]";
|
|
195
198
|
describe = "Get all parameters under the base path";
|
|
196
199
|
builder = (args) => {
|
|
197
|
-
const config = loadConfig2();
|
|
198
200
|
args.options({ ...commonOptions(), ...awsOptions() });
|
|
199
201
|
args.positional("path", {
|
|
200
202
|
type: "string",
|
|
201
203
|
describe: `OPTIONAL path to parameter. Supports absolute and relative paths.
|
|
202
204
|
Example:
|
|
203
|
-
"/root/myParam" or "service/secret"
|
|
204
|
-
config,
|
|
205
|
-
"service/secret"
|
|
206
|
-
)})`
|
|
205
|
+
"/root/myParam" or "service/secret"`
|
|
207
206
|
});
|
|
208
207
|
return args;
|
|
209
208
|
};
|
|
210
209
|
handler = async (args) => {
|
|
211
|
-
|
|
210
|
+
debug(
|
|
211
|
+
`Get command handler called with env: ${args.env}, path: ${args.path}`
|
|
212
|
+
);
|
|
213
|
+
const config = await loadConfig2({ env: args.env });
|
|
214
|
+
debug(
|
|
215
|
+
`Config loaded successfully, base parameter path: ${config.aws?.baseParameterPath}`
|
|
216
|
+
);
|
|
217
|
+
debug(
|
|
218
|
+
`Creating SSM client with region: ${config.aws.region}, profile: ${config.aws.profile}`
|
|
219
|
+
);
|
|
212
220
|
const collection = new ParameterCollection(
|
|
213
221
|
config.aws?.baseParameterPath,
|
|
214
222
|
new SSMClient({
|
|
@@ -221,11 +229,13 @@ Example:
|
|
|
221
229
|
})
|
|
222
230
|
})
|
|
223
231
|
);
|
|
232
|
+
debug(`Fetching parameters from SSM...`);
|
|
224
233
|
const params = await collection.get();
|
|
234
|
+
debug(`Retrieved ${params.size} parameters`);
|
|
225
235
|
params.forEach((parameter) => {
|
|
226
236
|
console.log(
|
|
227
237
|
chalk.gray(
|
|
228
|
-
parameter.Name?.replace(/\/([^/]+)$/,
|
|
238
|
+
parameter.Name?.replace(/\/([^/]+)$/, `/${chalk.bold.green("$1")}`)
|
|
229
239
|
),
|
|
230
240
|
chalk.bold.white(parameter.Value)
|
|
231
241
|
);
|
|
@@ -234,26 +244,35 @@ Example:
|
|
|
234
244
|
};
|
|
235
245
|
|
|
236
246
|
// src/commands/params/set.ts
|
|
237
|
-
import { loadConfig as loadConfig3 } from "@dsmrt/axiom-config";
|
|
238
|
-
import inquirer2 from "inquirer";
|
|
239
247
|
import {
|
|
240
|
-
|
|
248
|
+
ParameterType,
|
|
241
249
|
PutParameterCommand,
|
|
242
|
-
|
|
250
|
+
SSMClient as SSMClient2
|
|
243
251
|
} from "@aws-sdk/client-ssm";
|
|
252
|
+
import { loadConfig as loadConfig3 } from "@dsmrt/axiom-config";
|
|
244
253
|
import chalk2 from "chalk";
|
|
254
|
+
import inquirer2 from "inquirer";
|
|
255
|
+
|
|
256
|
+
// src/commands/params/utils.ts
|
|
257
|
+
var buildPath = (config, path) => {
|
|
258
|
+
if (path === void 0) {
|
|
259
|
+
return config.aws?.baseParameterPath;
|
|
260
|
+
}
|
|
261
|
+
if (/^\//.test(path)) {
|
|
262
|
+
return path;
|
|
263
|
+
}
|
|
264
|
+
return `${config.aws?.baseParameterPath.replace(/\/$/, "")}/${path}`;
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
// src/commands/params/set.ts
|
|
245
268
|
var SetCommand = class {
|
|
246
269
|
command = "set <path> <value>";
|
|
247
270
|
describe = "Set all parameters under the base path";
|
|
248
271
|
builder = (args) => {
|
|
249
|
-
const config = loadConfig3();
|
|
250
272
|
args.positional("path", {
|
|
251
273
|
type: "string",
|
|
252
274
|
describe: `Path to parameter. Supports absolute and relative paths.
|
|
253
|
-
Example: "/root/myParam" or "service/secret"
|
|
254
|
-
config,
|
|
255
|
-
"service/secret"
|
|
256
|
-
)})`
|
|
275
|
+
Example: "/root/myParam" or "service/secret"`
|
|
257
276
|
});
|
|
258
277
|
args.demandOption("path", "Path is required");
|
|
259
278
|
args.positional("value", {
|
|
@@ -282,53 +301,68 @@ Example: "/root/myParam" or "service/secret" (which translates to, "${buildPath(
|
|
|
282
301
|
});
|
|
283
302
|
};
|
|
284
303
|
handler = async (args) => {
|
|
285
|
-
|
|
304
|
+
debug(
|
|
305
|
+
`Set command handler called with path: ${args.path}, secure: ${args.secure}, overwrite: ${args.overwrite}, force: ${args.force}`
|
|
306
|
+
);
|
|
307
|
+
const config = await loadConfig3({ env: args.env });
|
|
308
|
+
debug(
|
|
309
|
+
`Config loaded successfully, base parameter path: ${config.aws?.baseParameterPath}`
|
|
310
|
+
);
|
|
311
|
+
const fullPath = buildPath(config, args.path);
|
|
312
|
+
debug(`Full parameter path: ${fullPath}`);
|
|
286
313
|
if (args.force !== true) {
|
|
314
|
+
debug(`Prompting user for confirmation...`);
|
|
287
315
|
const res = await inquirer2.prompt({
|
|
288
316
|
type: "confirm",
|
|
289
317
|
name: "setParam",
|
|
290
318
|
message: `Are you sure you want to set '${args.path}'?`
|
|
291
319
|
});
|
|
292
320
|
if (!res.setParam) {
|
|
321
|
+
debug(`User declined, aborting`);
|
|
293
322
|
console.log("Doing nothing.");
|
|
294
323
|
return;
|
|
295
324
|
}
|
|
325
|
+
debug(`User confirmed`);
|
|
326
|
+
} else {
|
|
327
|
+
debug(`Force flag set, skipping confirmation`);
|
|
296
328
|
}
|
|
329
|
+
debug(
|
|
330
|
+
`Creating SSM client with region: ${config.aws.region}, profile: ${config.aws.profile}`
|
|
331
|
+
);
|
|
297
332
|
const client = new SSMClient2({
|
|
298
333
|
region: config.aws.region,
|
|
299
334
|
credentials: await CachedCredentialProvider(config.aws)
|
|
300
335
|
});
|
|
336
|
+
debug(
|
|
337
|
+
`Sending parameter to SSM with type: ${args.secure ? "SecureString" : "String"}`
|
|
338
|
+
);
|
|
301
339
|
const params = await client.send(
|
|
302
340
|
new PutParameterCommand({
|
|
303
|
-
Name:
|
|
341
|
+
Name: fullPath,
|
|
304
342
|
Value: args.value,
|
|
305
343
|
Type: args.secure ? ParameterType.SECURE_STRING : ParameterType.STRING,
|
|
306
344
|
Overwrite: args.overwrite
|
|
307
345
|
})
|
|
308
346
|
);
|
|
347
|
+
debug(`Parameter set successfully, version: ${params.Version}`);
|
|
309
348
|
console.log(chalk2.green("Version: "), chalk2.white.bold(params.Version));
|
|
310
349
|
};
|
|
311
350
|
};
|
|
312
351
|
|
|
313
352
|
// src/commands/params/delete.ts
|
|
353
|
+
import { DeleteParameterCommand, SSMClient as SSMClient3 } from "@aws-sdk/client-ssm";
|
|
314
354
|
import { loadConfig as loadConfig4 } from "@dsmrt/axiom-config";
|
|
315
355
|
import inquirer3 from "inquirer";
|
|
316
|
-
import { SSMClient as SSMClient3, DeleteParameterCommand } from "@aws-sdk/client-ssm";
|
|
317
356
|
var log = console.log;
|
|
318
357
|
var DeleteCommand = class {
|
|
319
358
|
command = "delete <path>";
|
|
320
359
|
describe = "Delete SSM parameters";
|
|
321
360
|
client;
|
|
322
361
|
builder = (args) => {
|
|
323
|
-
const config = loadConfig4();
|
|
324
362
|
args.positional("path", {
|
|
325
363
|
type: "string",
|
|
326
364
|
describe: `Path to parameter. Supports absolute and relative paths.
|
|
327
|
-
Example: "/root/myParam" or "service/secret"
|
|
328
|
-
config,
|
|
329
|
-
"service/secret"
|
|
330
|
-
)})`,
|
|
331
|
-
default: config.aws?.baseParameterPath,
|
|
365
|
+
Example: "/root/myParam" or "service/secret"`,
|
|
332
366
|
demandOption: true
|
|
333
367
|
}).demandOption("path", "Path is required");
|
|
334
368
|
args.option("force", {
|
|
@@ -340,33 +374,51 @@ Example: "/root/myParam" or "service/secret" (which translates to, "${buildPath(
|
|
|
340
374
|
return args;
|
|
341
375
|
};
|
|
342
376
|
handler = async (args) => {
|
|
343
|
-
|
|
377
|
+
debug(
|
|
378
|
+
`Delete command handler called with path: ${args.path}, force: ${args.force}`
|
|
379
|
+
);
|
|
380
|
+
const config = await loadConfig4({ env: args.env });
|
|
381
|
+
debug(
|
|
382
|
+
`Config loaded successfully, base parameter path: ${config.aws?.baseParameterPath}`
|
|
383
|
+
);
|
|
344
384
|
const path = buildPath(args, args.path);
|
|
385
|
+
debug(`Full parameter path: ${path}`);
|
|
386
|
+
debug(
|
|
387
|
+
`Creating SSM client with region: ${config.aws?.region}, profile: ${config.aws?.profile}`
|
|
388
|
+
);
|
|
345
389
|
const client = new SSMClient3({
|
|
346
390
|
region: config.aws?.region,
|
|
347
391
|
credentials: await CachedCredentialProvider(config.aws)
|
|
348
392
|
});
|
|
349
393
|
if (path === args.aws.baseParameterPath) {
|
|
394
|
+
debug(`Delete blocked: path matches base parameter path`);
|
|
350
395
|
throw new Error(
|
|
351
396
|
`Deleting the path (path: ${path}) that matches the base path (awsSsmParameterPath: ${args.awsSsmParameterPath}) is prohibited.`
|
|
352
397
|
);
|
|
353
398
|
}
|
|
354
399
|
if (args.force !== true) {
|
|
400
|
+
debug(`Prompting user for confirmation...`);
|
|
355
401
|
const res = await inquirer3.prompt({
|
|
356
402
|
type: "confirm",
|
|
357
403
|
name: "delete",
|
|
358
404
|
message: `Are you sure you want to delete '${path}'?`
|
|
359
405
|
});
|
|
360
406
|
if (!res.delete) {
|
|
407
|
+
debug(`User declined, aborting`);
|
|
361
408
|
log("Doing nothing.");
|
|
362
409
|
return;
|
|
363
410
|
}
|
|
411
|
+
debug(`User confirmed`);
|
|
412
|
+
} else {
|
|
413
|
+
debug(`Force flag set, skipping confirmation`);
|
|
364
414
|
}
|
|
415
|
+
debug(`Sending delete command to SSM for: ${path}`);
|
|
365
416
|
await client.send(
|
|
366
417
|
new DeleteParameterCommand({
|
|
367
418
|
Name: path
|
|
368
419
|
})
|
|
369
420
|
);
|
|
421
|
+
debug(`Parameter deleted successfully`);
|
|
370
422
|
log("\u{1F44D}");
|
|
371
423
|
};
|
|
372
424
|
};
|
|
@@ -375,6 +427,16 @@ Example: "/root/myParam" or "service/secret" (which translates to, "${buildPath(
|
|
|
375
427
|
yargs(process.argv.slice(2)).env("AXIOM").scriptName("axiom").option("config", {
|
|
376
428
|
alias: "c",
|
|
377
429
|
string: true
|
|
430
|
+
}).option("debug", {
|
|
431
|
+
alias: "d",
|
|
432
|
+
type: "boolean",
|
|
433
|
+
description: "Enable debug output",
|
|
434
|
+
default: false,
|
|
435
|
+
global: true
|
|
436
|
+
}).middleware((argv) => {
|
|
437
|
+
if (argv.debug) {
|
|
438
|
+
process.env.AXIOM_DEBUG = "true";
|
|
439
|
+
}
|
|
378
440
|
}).command(new Config()).command(new ParamsCommand()).strict().usage(
|
|
379
441
|
`
|
|
380
442
|
Axiom - an AWS focused config cli
|
|
@@ -385,10 +447,10 @@ USAGE:
|
|
|
385
447
|
).demandCommand(1, "").alias("h", "help").argv;
|
|
386
448
|
|
|
387
449
|
export {
|
|
388
|
-
commonOptions,
|
|
389
|
-
awsOptions,
|
|
390
450
|
Config,
|
|
391
451
|
ParamsCommand,
|
|
452
|
+
commonOptions,
|
|
453
|
+
awsOptions,
|
|
392
454
|
GetCommand,
|
|
393
455
|
SetCommand,
|
|
394
456
|
DeleteCommand
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Options as Options$1, CommandModule, CommandBuilder, ArgumentsCamelCase, Argv } from 'yargs';
|
|
2
1
|
import * as _dsmrt_axiom_config from '@dsmrt/axiom-config';
|
|
3
2
|
import { AwsConfigs, Config as Config$1 } from '@dsmrt/axiom-config';
|
|
3
|
+
import { CommandModule, CommandBuilder, ArgumentsCamelCase, Argv, Options as Options$1 } from 'yargs';
|
|
4
4
|
import { SSMClient } from '@aws-sdk/client-ssm';
|
|
5
5
|
|
|
6
6
|
interface Item {
|
|
@@ -8,13 +8,6 @@ interface Item {
|
|
|
8
8
|
data: unknown;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
declare const commonOptions: () => {
|
|
12
|
-
[key: string]: Options$1;
|
|
13
|
-
};
|
|
14
|
-
declare const awsOptions: () => {
|
|
15
|
-
[key: string]: Options$1;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
11
|
interface ConfigOptions {
|
|
19
12
|
env: string;
|
|
20
13
|
}
|
|
@@ -26,8 +19,7 @@ declare class Config<U extends ConfigOptions> implements CommandModule<object, U
|
|
|
26
19
|
loadConfig: (args: ConfigOptions) => Promise<_dsmrt_axiom_config.ConfigContainer & object>;
|
|
27
20
|
}
|
|
28
21
|
|
|
29
|
-
|
|
30
|
-
}
|
|
22
|
+
type Options = object;
|
|
31
23
|
declare class ParamsCommand<U extends Options> implements CommandModule<object, U> {
|
|
32
24
|
command: string;
|
|
33
25
|
describe: string;
|
|
@@ -75,4 +67,11 @@ declare class DeleteCommand<U extends config> implements CommandModule<object, U
|
|
|
75
67
|
handler: (args: ArgumentsCamelCase<U>) => Promise<void>;
|
|
76
68
|
}
|
|
77
69
|
|
|
70
|
+
declare const commonOptions: () => {
|
|
71
|
+
[key: string]: Options$1;
|
|
72
|
+
};
|
|
73
|
+
declare const awsOptions: () => {
|
|
74
|
+
[key: string]: Options$1;
|
|
75
|
+
};
|
|
76
|
+
|
|
78
77
|
export { Config, DeleteCommand, type DeleteOptions, GetCommand, type GetOptions, type Item, ParamsCommand, SetCommand, type SetOptions, awsOptions, commonOptions };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Options as Options$1, CommandModule, CommandBuilder, ArgumentsCamelCase, Argv } from 'yargs';
|
|
2
1
|
import * as _dsmrt_axiom_config from '@dsmrt/axiom-config';
|
|
3
2
|
import { AwsConfigs, Config as Config$1 } from '@dsmrt/axiom-config';
|
|
3
|
+
import { CommandModule, CommandBuilder, ArgumentsCamelCase, Argv, Options as Options$1 } from 'yargs';
|
|
4
4
|
import { SSMClient } from '@aws-sdk/client-ssm';
|
|
5
5
|
|
|
6
6
|
interface Item {
|
|
@@ -8,13 +8,6 @@ interface Item {
|
|
|
8
8
|
data: unknown;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
declare const commonOptions: () => {
|
|
12
|
-
[key: string]: Options$1;
|
|
13
|
-
};
|
|
14
|
-
declare const awsOptions: () => {
|
|
15
|
-
[key: string]: Options$1;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
11
|
interface ConfigOptions {
|
|
19
12
|
env: string;
|
|
20
13
|
}
|
|
@@ -26,8 +19,7 @@ declare class Config<U extends ConfigOptions> implements CommandModule<object, U
|
|
|
26
19
|
loadConfig: (args: ConfigOptions) => Promise<_dsmrt_axiom_config.ConfigContainer & object>;
|
|
27
20
|
}
|
|
28
21
|
|
|
29
|
-
|
|
30
|
-
}
|
|
22
|
+
type Options = object;
|
|
31
23
|
declare class ParamsCommand<U extends Options> implements CommandModule<object, U> {
|
|
32
24
|
command: string;
|
|
33
25
|
describe: string;
|
|
@@ -75,4 +67,11 @@ declare class DeleteCommand<U extends config> implements CommandModule<object, U
|
|
|
75
67
|
handler: (args: ArgumentsCamelCase<U>) => Promise<void>;
|
|
76
68
|
}
|
|
77
69
|
|
|
70
|
+
declare const commonOptions: () => {
|
|
71
|
+
[key: string]: Options$1;
|
|
72
|
+
};
|
|
73
|
+
declare const awsOptions: () => {
|
|
74
|
+
[key: string]: Options$1;
|
|
75
|
+
};
|
|
76
|
+
|
|
78
77
|
export { Config, DeleteCommand, type DeleteOptions, GetCommand, type GetOptions, type Item, ParamsCommand, SetCommand, type SetOptions, awsOptions, commonOptions };
|
package/dist/index.js
CHANGED
|
@@ -40,86 +40,21 @@ __export(index_exports, {
|
|
|
40
40
|
});
|
|
41
41
|
module.exports = __toCommonJS(index_exports);
|
|
42
42
|
|
|
43
|
-
// src/
|
|
44
|
-
var
|
|
45
|
-
var import_fs = __toESM(require("fs"));
|
|
46
|
-
var DEFAULT_DIRECTORY = `${import_os.default.homedir()}/.axiom/cache`;
|
|
47
|
-
var cache_default = class {
|
|
48
|
-
constructor(cacheDir = DEFAULT_DIRECTORY) {
|
|
49
|
-
this.cacheDir = cacheDir;
|
|
50
|
-
}
|
|
51
|
-
get(name) {
|
|
52
|
-
const file = `${this.cacheDir}/${name}`;
|
|
53
|
-
if (!import_fs.default.existsSync(file)) {
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
const buffer = import_fs.default.readFileSync(file);
|
|
57
|
-
const item = JSON.parse(buffer.toString());
|
|
58
|
-
if (item.expires === void 0) {
|
|
59
|
-
return item.data;
|
|
60
|
-
}
|
|
61
|
-
item.expires = new Date(item.expires);
|
|
62
|
-
if (item.expires < /* @__PURE__ */ new Date()) {
|
|
63
|
-
this.delete(name);
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
return item.data;
|
|
67
|
-
}
|
|
68
|
-
delete(name) {
|
|
69
|
-
import_fs.default.unlinkSync(`${this.cacheDir}/${name}`);
|
|
70
|
-
}
|
|
71
|
-
set(name, value, expires) {
|
|
72
|
-
if (!import_fs.default.existsSync(this.cacheDir)) {
|
|
73
|
-
import_fs.default.mkdirSync(this.cacheDir, {
|
|
74
|
-
recursive: true,
|
|
75
|
-
mode: 448
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
import_fs.default.writeFileSync(
|
|
79
|
-
`${this.cacheDir}/${name}`,
|
|
80
|
-
JSON.stringify({
|
|
81
|
-
expires,
|
|
82
|
-
data: value
|
|
83
|
-
}),
|
|
84
|
-
{
|
|
85
|
-
mode: 384
|
|
86
|
-
}
|
|
87
|
-
);
|
|
88
|
-
}
|
|
89
|
-
};
|
|
43
|
+
// src/bin/axiom.ts
|
|
44
|
+
var import_yargs = __toESM(require("yargs"));
|
|
90
45
|
|
|
91
|
-
// src/
|
|
92
|
-
var
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
var awsOptions = () => {
|
|
101
|
-
return {
|
|
102
|
-
account: {
|
|
103
|
-
string: true,
|
|
104
|
-
desc: "AWS Account number like, 1243944546"
|
|
105
|
-
},
|
|
106
|
-
region: {
|
|
107
|
-
string: true,
|
|
108
|
-
desc: "AWS region like, us-east-1"
|
|
109
|
-
},
|
|
110
|
-
profile: {
|
|
111
|
-
string: true,
|
|
112
|
-
desc: "AWS configured profile"
|
|
113
|
-
},
|
|
114
|
-
baseParameterPath: {
|
|
115
|
-
string: true,
|
|
116
|
-
desc: "SSM parameter path base where configs like secrets and infrastucture managed items are set"
|
|
117
|
-
}
|
|
118
|
-
};
|
|
46
|
+
// src/commands/config.ts
|
|
47
|
+
var import_axiom_config = require("@dsmrt/axiom-config");
|
|
48
|
+
|
|
49
|
+
// src/debug.ts
|
|
50
|
+
var isDebugEnabled = () => process.env.AXIOM_DEBUG === "true" || process.env.AXIOM_DEBUG === "1";
|
|
51
|
+
var debug = (message, ...args) => {
|
|
52
|
+
if (isDebugEnabled()) {
|
|
53
|
+
console.error(`[axiom:cli] ${message}`, ...args);
|
|
54
|
+
}
|
|
119
55
|
};
|
|
120
56
|
|
|
121
57
|
// src/commands/config.ts
|
|
122
|
-
var import_axiom_config = require("@dsmrt/axiom-config");
|
|
123
58
|
var Config = class {
|
|
124
59
|
command = "config";
|
|
125
60
|
describe = "print the config";
|
|
@@ -130,9 +65,13 @@ var Config = class {
|
|
|
130
65
|
return args;
|
|
131
66
|
};
|
|
132
67
|
handler = async (args) => {
|
|
133
|
-
|
|
68
|
+
debug(`Config command handler called with env: ${args.env}`);
|
|
69
|
+
const config = await this.loadConfig(args);
|
|
70
|
+
debug(`Config loaded successfully, outputting as JSON`);
|
|
71
|
+
console.log(JSON.stringify(config));
|
|
134
72
|
};
|
|
135
73
|
loadConfig = async (args) => {
|
|
74
|
+
debug(`Loading config with env: ${args.env}`);
|
|
136
75
|
return (0, import_axiom_config.loadConfig)(args);
|
|
137
76
|
};
|
|
138
77
|
};
|
|
@@ -151,14 +90,65 @@ var ParamsCommand = class {
|
|
|
151
90
|
};
|
|
152
91
|
|
|
153
92
|
// src/commands/params/get.ts
|
|
154
|
-
var import_axiom_config2 = require("@dsmrt/axiom-config");
|
|
155
|
-
var import_axiom_aws_sdk = require("@dsmrt/axiom-aws-sdk");
|
|
156
93
|
var import_client_ssm = require("@aws-sdk/client-ssm");
|
|
94
|
+
var import_axiom_aws_sdk = require("@dsmrt/axiom-aws-sdk");
|
|
95
|
+
var import_axiom_config2 = require("@dsmrt/axiom-config");
|
|
96
|
+
var import_chalk = __toESM(require("chalk"));
|
|
157
97
|
|
|
158
98
|
// src/aws/credentials-provider.ts
|
|
159
99
|
var import_credential_providers = require("@aws-sdk/credential-providers");
|
|
160
100
|
var import_client_sts = require("@aws-sdk/client-sts");
|
|
161
101
|
var import_inquirer = __toESM(require("inquirer"));
|
|
102
|
+
|
|
103
|
+
// src/cache.ts
|
|
104
|
+
var import_node_fs = __toESM(require("fs"));
|
|
105
|
+
var import_node_os = __toESM(require("os"));
|
|
106
|
+
var DEFAULT_DIRECTORY = `${import_node_os.default.homedir()}/.axiom/cache`;
|
|
107
|
+
var cache_default = class {
|
|
108
|
+
constructor(cacheDir = DEFAULT_DIRECTORY) {
|
|
109
|
+
this.cacheDir = cacheDir;
|
|
110
|
+
}
|
|
111
|
+
get(name) {
|
|
112
|
+
const file = `${this.cacheDir}/${name}`;
|
|
113
|
+
if (!import_node_fs.default.existsSync(file)) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const buffer = import_node_fs.default.readFileSync(file);
|
|
117
|
+
const item = JSON.parse(buffer.toString());
|
|
118
|
+
if (item.expires === void 0) {
|
|
119
|
+
return item.data;
|
|
120
|
+
}
|
|
121
|
+
item.expires = new Date(item.expires);
|
|
122
|
+
if (item.expires < /* @__PURE__ */ new Date()) {
|
|
123
|
+
this.delete(name);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
return item.data;
|
|
127
|
+
}
|
|
128
|
+
delete(name) {
|
|
129
|
+
import_node_fs.default.unlinkSync(`${this.cacheDir}/${name}`);
|
|
130
|
+
}
|
|
131
|
+
set(name, value, expires) {
|
|
132
|
+
if (!import_node_fs.default.existsSync(this.cacheDir)) {
|
|
133
|
+
import_node_fs.default.mkdirSync(this.cacheDir, {
|
|
134
|
+
recursive: true,
|
|
135
|
+
mode: 448
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
import_node_fs.default.writeFileSync(
|
|
139
|
+
`${this.cacheDir}/${name}`,
|
|
140
|
+
JSON.stringify({
|
|
141
|
+
expires,
|
|
142
|
+
data: value
|
|
143
|
+
}),
|
|
144
|
+
{
|
|
145
|
+
mode: 384
|
|
146
|
+
}
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
// src/aws/credentials-provider.ts
|
|
162
152
|
var CACHE_KEY_PREFIX = "axiom#aws-credentials";
|
|
163
153
|
var cache = new cache_default();
|
|
164
154
|
var returnCredentialsFromAssumerole = (creds) => {
|
|
@@ -211,38 +201,61 @@ var CachedCredentialProvider = (config) => {
|
|
|
211
201
|
return CachedCredentialViaProfileAndRegion(config.profile, config.region);
|
|
212
202
|
};
|
|
213
203
|
|
|
214
|
-
// src/
|
|
215
|
-
var
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
}
|
|
222
|
-
|
|
204
|
+
// src/options.ts
|
|
205
|
+
var commonOptions = () => {
|
|
206
|
+
return {
|
|
207
|
+
env: {
|
|
208
|
+
string: true,
|
|
209
|
+
desc: "Environment name like, prod, staging, dev, etc."
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
};
|
|
213
|
+
var awsOptions = () => {
|
|
214
|
+
return {
|
|
215
|
+
account: {
|
|
216
|
+
string: true,
|
|
217
|
+
desc: "AWS Account number like, 1243944546"
|
|
218
|
+
},
|
|
219
|
+
region: {
|
|
220
|
+
string: true,
|
|
221
|
+
desc: "AWS region like, us-east-1"
|
|
222
|
+
},
|
|
223
|
+
profile: {
|
|
224
|
+
string: true,
|
|
225
|
+
desc: "AWS configured profile"
|
|
226
|
+
},
|
|
227
|
+
baseParameterPath: {
|
|
228
|
+
string: true,
|
|
229
|
+
desc: "SSM parameter path base where configs like secrets and infrastucture managed items are set"
|
|
230
|
+
}
|
|
231
|
+
};
|
|
223
232
|
};
|
|
224
233
|
|
|
225
234
|
// src/commands/params/get.ts
|
|
226
|
-
var import_chalk = __toESM(require("chalk"));
|
|
227
235
|
var GetCommand = class {
|
|
228
236
|
command = "get [path]";
|
|
229
237
|
describe = "Get all parameters under the base path";
|
|
230
238
|
builder = (args) => {
|
|
231
|
-
const config = (0, import_axiom_config2.loadConfig)();
|
|
232
239
|
args.options({ ...commonOptions(), ...awsOptions() });
|
|
233
240
|
args.positional("path", {
|
|
234
241
|
type: "string",
|
|
235
242
|
describe: `OPTIONAL path to parameter. Supports absolute and relative paths.
|
|
236
243
|
Example:
|
|
237
|
-
"/root/myParam" or "service/secret"
|
|
238
|
-
config,
|
|
239
|
-
"service/secret"
|
|
240
|
-
)})`
|
|
244
|
+
"/root/myParam" or "service/secret"`
|
|
241
245
|
});
|
|
242
246
|
return args;
|
|
243
247
|
};
|
|
244
248
|
handler = async (args) => {
|
|
245
|
-
|
|
249
|
+
debug(
|
|
250
|
+
`Get command handler called with env: ${args.env}, path: ${args.path}`
|
|
251
|
+
);
|
|
252
|
+
const config = await (0, import_axiom_config2.loadConfig)({ env: args.env });
|
|
253
|
+
debug(
|
|
254
|
+
`Config loaded successfully, base parameter path: ${config.aws?.baseParameterPath}`
|
|
255
|
+
);
|
|
256
|
+
debug(
|
|
257
|
+
`Creating SSM client with region: ${config.aws.region}, profile: ${config.aws.profile}`
|
|
258
|
+
);
|
|
246
259
|
const collection = new import_axiom_aws_sdk.ParameterCollection(
|
|
247
260
|
config.aws?.baseParameterPath,
|
|
248
261
|
new import_client_ssm.SSMClient({
|
|
@@ -255,11 +268,13 @@ Example:
|
|
|
255
268
|
})
|
|
256
269
|
})
|
|
257
270
|
);
|
|
271
|
+
debug(`Fetching parameters from SSM...`);
|
|
258
272
|
const params = await collection.get();
|
|
273
|
+
debug(`Retrieved ${params.size} parameters`);
|
|
259
274
|
params.forEach((parameter) => {
|
|
260
275
|
console.log(
|
|
261
276
|
import_chalk.default.gray(
|
|
262
|
-
parameter.Name?.replace(/\/([^/]+)$/,
|
|
277
|
+
parameter.Name?.replace(/\/([^/]+)$/, `/${import_chalk.default.bold.green("$1")}`)
|
|
263
278
|
),
|
|
264
279
|
import_chalk.default.bold.white(parameter.Value)
|
|
265
280
|
);
|
|
@@ -268,22 +283,31 @@ Example:
|
|
|
268
283
|
};
|
|
269
284
|
|
|
270
285
|
// src/commands/params/set.ts
|
|
271
|
-
var import_axiom_config3 = require("@dsmrt/axiom-config");
|
|
272
|
-
var import_inquirer2 = __toESM(require("inquirer"));
|
|
273
286
|
var import_client_ssm2 = require("@aws-sdk/client-ssm");
|
|
287
|
+
var import_axiom_config3 = require("@dsmrt/axiom-config");
|
|
274
288
|
var import_chalk2 = __toESM(require("chalk"));
|
|
289
|
+
var import_inquirer2 = __toESM(require("inquirer"));
|
|
290
|
+
|
|
291
|
+
// src/commands/params/utils.ts
|
|
292
|
+
var buildPath = (config, path) => {
|
|
293
|
+
if (path === void 0) {
|
|
294
|
+
return config.aws?.baseParameterPath;
|
|
295
|
+
}
|
|
296
|
+
if (/^\//.test(path)) {
|
|
297
|
+
return path;
|
|
298
|
+
}
|
|
299
|
+
return `${config.aws?.baseParameterPath.replace(/\/$/, "")}/${path}`;
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
// src/commands/params/set.ts
|
|
275
303
|
var SetCommand = class {
|
|
276
304
|
command = "set <path> <value>";
|
|
277
305
|
describe = "Set all parameters under the base path";
|
|
278
306
|
builder = (args) => {
|
|
279
|
-
const config = (0, import_axiom_config3.loadConfig)();
|
|
280
307
|
args.positional("path", {
|
|
281
308
|
type: "string",
|
|
282
309
|
describe: `Path to parameter. Supports absolute and relative paths.
|
|
283
|
-
Example: "/root/myParam" or "service/secret"
|
|
284
|
-
config,
|
|
285
|
-
"service/secret"
|
|
286
|
-
)})`
|
|
310
|
+
Example: "/root/myParam" or "service/secret"`
|
|
287
311
|
});
|
|
288
312
|
args.demandOption("path", "Path is required");
|
|
289
313
|
args.positional("value", {
|
|
@@ -312,53 +336,68 @@ Example: "/root/myParam" or "service/secret" (which translates to, "${buildPath(
|
|
|
312
336
|
});
|
|
313
337
|
};
|
|
314
338
|
handler = async (args) => {
|
|
315
|
-
|
|
339
|
+
debug(
|
|
340
|
+
`Set command handler called with path: ${args.path}, secure: ${args.secure}, overwrite: ${args.overwrite}, force: ${args.force}`
|
|
341
|
+
);
|
|
342
|
+
const config = await (0, import_axiom_config3.loadConfig)({ env: args.env });
|
|
343
|
+
debug(
|
|
344
|
+
`Config loaded successfully, base parameter path: ${config.aws?.baseParameterPath}`
|
|
345
|
+
);
|
|
346
|
+
const fullPath = buildPath(config, args.path);
|
|
347
|
+
debug(`Full parameter path: ${fullPath}`);
|
|
316
348
|
if (args.force !== true) {
|
|
349
|
+
debug(`Prompting user for confirmation...`);
|
|
317
350
|
const res = await import_inquirer2.default.prompt({
|
|
318
351
|
type: "confirm",
|
|
319
352
|
name: "setParam",
|
|
320
353
|
message: `Are you sure you want to set '${args.path}'?`
|
|
321
354
|
});
|
|
322
355
|
if (!res.setParam) {
|
|
356
|
+
debug(`User declined, aborting`);
|
|
323
357
|
console.log("Doing nothing.");
|
|
324
358
|
return;
|
|
325
359
|
}
|
|
360
|
+
debug(`User confirmed`);
|
|
361
|
+
} else {
|
|
362
|
+
debug(`Force flag set, skipping confirmation`);
|
|
326
363
|
}
|
|
364
|
+
debug(
|
|
365
|
+
`Creating SSM client with region: ${config.aws.region}, profile: ${config.aws.profile}`
|
|
366
|
+
);
|
|
327
367
|
const client = new import_client_ssm2.SSMClient({
|
|
328
368
|
region: config.aws.region,
|
|
329
369
|
credentials: await CachedCredentialProvider(config.aws)
|
|
330
370
|
});
|
|
371
|
+
debug(
|
|
372
|
+
`Sending parameter to SSM with type: ${args.secure ? "SecureString" : "String"}`
|
|
373
|
+
);
|
|
331
374
|
const params = await client.send(
|
|
332
375
|
new import_client_ssm2.PutParameterCommand({
|
|
333
|
-
Name:
|
|
376
|
+
Name: fullPath,
|
|
334
377
|
Value: args.value,
|
|
335
378
|
Type: args.secure ? import_client_ssm2.ParameterType.SECURE_STRING : import_client_ssm2.ParameterType.STRING,
|
|
336
379
|
Overwrite: args.overwrite
|
|
337
380
|
})
|
|
338
381
|
);
|
|
382
|
+
debug(`Parameter set successfully, version: ${params.Version}`);
|
|
339
383
|
console.log(import_chalk2.default.green("Version: "), import_chalk2.default.white.bold(params.Version));
|
|
340
384
|
};
|
|
341
385
|
};
|
|
342
386
|
|
|
343
387
|
// src/commands/params/delete.ts
|
|
388
|
+
var import_client_ssm3 = require("@aws-sdk/client-ssm");
|
|
344
389
|
var import_axiom_config4 = require("@dsmrt/axiom-config");
|
|
345
390
|
var import_inquirer3 = __toESM(require("inquirer"));
|
|
346
|
-
var import_client_ssm3 = require("@aws-sdk/client-ssm");
|
|
347
391
|
var log = console.log;
|
|
348
392
|
var DeleteCommand = class {
|
|
349
393
|
command = "delete <path>";
|
|
350
394
|
describe = "Delete SSM parameters";
|
|
351
395
|
client;
|
|
352
396
|
builder = (args) => {
|
|
353
|
-
const config = (0, import_axiom_config4.loadConfig)();
|
|
354
397
|
args.positional("path", {
|
|
355
398
|
type: "string",
|
|
356
399
|
describe: `Path to parameter. Supports absolute and relative paths.
|
|
357
|
-
Example: "/root/myParam" or "service/secret"
|
|
358
|
-
config,
|
|
359
|
-
"service/secret"
|
|
360
|
-
)})`,
|
|
361
|
-
default: config.aws?.baseParameterPath,
|
|
400
|
+
Example: "/root/myParam" or "service/secret"`,
|
|
362
401
|
demandOption: true
|
|
363
402
|
}).demandOption("path", "Path is required");
|
|
364
403
|
args.option("force", {
|
|
@@ -370,42 +409,69 @@ Example: "/root/myParam" or "service/secret" (which translates to, "${buildPath(
|
|
|
370
409
|
return args;
|
|
371
410
|
};
|
|
372
411
|
handler = async (args) => {
|
|
373
|
-
|
|
412
|
+
debug(
|
|
413
|
+
`Delete command handler called with path: ${args.path}, force: ${args.force}`
|
|
414
|
+
);
|
|
415
|
+
const config = await (0, import_axiom_config4.loadConfig)({ env: args.env });
|
|
416
|
+
debug(
|
|
417
|
+
`Config loaded successfully, base parameter path: ${config.aws?.baseParameterPath}`
|
|
418
|
+
);
|
|
374
419
|
const path = buildPath(args, args.path);
|
|
420
|
+
debug(`Full parameter path: ${path}`);
|
|
421
|
+
debug(
|
|
422
|
+
`Creating SSM client with region: ${config.aws?.region}, profile: ${config.aws?.profile}`
|
|
423
|
+
);
|
|
375
424
|
const client = new import_client_ssm3.SSMClient({
|
|
376
425
|
region: config.aws?.region,
|
|
377
426
|
credentials: await CachedCredentialProvider(config.aws)
|
|
378
427
|
});
|
|
379
428
|
if (path === args.aws.baseParameterPath) {
|
|
429
|
+
debug(`Delete blocked: path matches base parameter path`);
|
|
380
430
|
throw new Error(
|
|
381
431
|
`Deleting the path (path: ${path}) that matches the base path (awsSsmParameterPath: ${args.awsSsmParameterPath}) is prohibited.`
|
|
382
432
|
);
|
|
383
433
|
}
|
|
384
434
|
if (args.force !== true) {
|
|
435
|
+
debug(`Prompting user for confirmation...`);
|
|
385
436
|
const res = await import_inquirer3.default.prompt({
|
|
386
437
|
type: "confirm",
|
|
387
438
|
name: "delete",
|
|
388
439
|
message: `Are you sure you want to delete '${path}'?`
|
|
389
440
|
});
|
|
390
441
|
if (!res.delete) {
|
|
442
|
+
debug(`User declined, aborting`);
|
|
391
443
|
log("Doing nothing.");
|
|
392
444
|
return;
|
|
393
445
|
}
|
|
446
|
+
debug(`User confirmed`);
|
|
447
|
+
} else {
|
|
448
|
+
debug(`Force flag set, skipping confirmation`);
|
|
394
449
|
}
|
|
450
|
+
debug(`Sending delete command to SSM for: ${path}`);
|
|
395
451
|
await client.send(
|
|
396
452
|
new import_client_ssm3.DeleteParameterCommand({
|
|
397
453
|
Name: path
|
|
398
454
|
})
|
|
399
455
|
);
|
|
456
|
+
debug(`Parameter deleted successfully`);
|
|
400
457
|
log("\u{1F44D}");
|
|
401
458
|
};
|
|
402
459
|
};
|
|
403
460
|
|
|
404
461
|
// src/bin/axiom.ts
|
|
405
|
-
var import_yargs = __toESM(require("yargs"));
|
|
406
462
|
(0, import_yargs.default)(process.argv.slice(2)).env("AXIOM").scriptName("axiom").option("config", {
|
|
407
463
|
alias: "c",
|
|
408
464
|
string: true
|
|
465
|
+
}).option("debug", {
|
|
466
|
+
alias: "d",
|
|
467
|
+
type: "boolean",
|
|
468
|
+
description: "Enable debug output",
|
|
469
|
+
default: false,
|
|
470
|
+
global: true
|
|
471
|
+
}).middleware((argv) => {
|
|
472
|
+
if (argv.debug) {
|
|
473
|
+
process.env.AXIOM_DEBUG = "true";
|
|
474
|
+
}
|
|
409
475
|
}).command(new Config()).command(new ParamsCommand()).strict().usage(
|
|
410
476
|
`
|
|
411
477
|
Axiom - an AWS focused config cli
|
package/dist/index.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dsmrt/axiom-cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "axiom cli for managing configs including secrets",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -28,20 +28,17 @@
|
|
|
28
28
|
},
|
|
29
29
|
"license": "MIT",
|
|
30
30
|
"devDependencies": {
|
|
31
|
+
"@biomejs/biome": "^2.3.8",
|
|
31
32
|
"@changesets/cli": "^2.27.11",
|
|
32
33
|
"@types/inquirer": "^8.2.10",
|
|
33
|
-
"@types/node": "^
|
|
34
|
+
"@types/node": "^22.12.0",
|
|
34
35
|
"@types/yargs": "^17.0.33",
|
|
35
|
-
"@
|
|
36
|
-
"@typescript-eslint/parser": "^6.21.0",
|
|
37
|
-
"@vitest/coverage-v8": "^1.6.0",
|
|
36
|
+
"@vitest/coverage-v8": "^4.0.0",
|
|
38
37
|
"aws-sdk-client-mock": "^3.1.0",
|
|
39
|
-
"eslint": "^8.57.1",
|
|
40
|
-
"prettier": "^3.4.2",
|
|
41
38
|
"ts-node": "^10.9.2",
|
|
42
39
|
"tsup": "^8.3.5",
|
|
43
40
|
"typescript": "^5.7.2",
|
|
44
|
-
"vitest": "^
|
|
41
|
+
"vitest": "^4.0.0"
|
|
45
42
|
},
|
|
46
43
|
"dependencies": {
|
|
47
44
|
"@aws-sdk/client-ssm": "^3.716.0",
|
|
@@ -51,12 +48,12 @@
|
|
|
51
48
|
"chalk": "^4.1.2",
|
|
52
49
|
"inquirer": "^8.2.6",
|
|
53
50
|
"yargs": "^17.7.2",
|
|
54
|
-
"@dsmrt/axiom-aws-sdk": "^0.
|
|
55
|
-
"@dsmrt/axiom-config": "^
|
|
51
|
+
"@dsmrt/axiom-aws-sdk": "^1.0.0",
|
|
52
|
+
"@dsmrt/axiom-config": "^1.1.0"
|
|
56
53
|
},
|
|
57
54
|
"scripts": {
|
|
58
|
-
"lint": "
|
|
59
|
-
"lint:fix": "
|
|
55
|
+
"lint": "biome lint",
|
|
56
|
+
"lint:fix": "biome lint --fix",
|
|
60
57
|
"test": "vitest run --coverage",
|
|
61
58
|
"watch": "vitest watch --coverage",
|
|
62
59
|
"build": "tsup --entry ./src/bin/axiom.ts --entry ./src/index.ts --format cjs,esm --dts --clean",
|
package/tsconfig.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es2022",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"esModuleInterop": true,
|
|
6
|
+
"forceConsistentCasingInFileNames": true,
|
|
7
|
+
"strict": true,
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
"noEmit": true
|
|
10
|
+
},
|
|
11
|
+
"include": ["src/index.ts"]
|
|
12
12
|
}
|
package/vitest.config.mts
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
import { defineConfig } from "vitest/config";
|
|
3
3
|
|
|
4
4
|
export default defineConfig({
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
5
|
+
test: {
|
|
6
|
+
include: ["src/**/*.test.ts"],
|
|
7
|
+
coverage: {
|
|
8
|
+
provider: "v8",
|
|
9
|
+
all: true,
|
|
10
|
+
exclude: ["lib/**/*", "src/__mocks__/**/*"],
|
|
11
|
+
reporter: ["text-summary", "json-summary"],
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
14
|
});
|