dotsec 0.1.1 → 0.2.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/dist/cli.js CHANGED
@@ -24,11 +24,11 @@ var __export = (target, all) => {
24
24
  for (var name in all)
25
25
  __defProp(target, name, { get: all[name], enumerable: true });
26
26
  };
27
- var __reExport = (target, module2, desc4) => {
27
+ var __reExport = (target, module2, desc8) => {
28
28
  if (module2 && typeof module2 === "object" || typeof module2 === "function") {
29
29
  for (let key of __getOwnPropNames(module2))
30
30
  if (!__hasOwnProp.call(target, key) && key !== "default")
31
- __defProp(target, key, { get: () => module2[key], enumerable: !(desc4 = __getOwnPropDesc(module2, key)) || desc4.enumerable });
31
+ __defProp(target, key, { get: () => module2[key], enumerable: !(desc8 = __getOwnPropDesc(module2, key)) || desc8.enumerable });
32
32
  }
33
33
  return target;
34
34
  };
@@ -40,19 +40,15 @@ var __toModule = (module2) => {
40
40
  var import_helpers = __toModule(require("yargs/helpers"));
41
41
  var import_yargs = __toModule(require("yargs/yargs"));
42
42
 
43
- // src/commands/decryptSecCommand.ts
44
- var decryptSecCommand_exports = {};
45
- __export(decryptSecCommand_exports, {
43
+ // src/commands/debugCommand.ts
44
+ var debugCommand_exports = {};
45
+ __export(debugCommand_exports, {
46
46
  builder: () => builder,
47
47
  command: () => command,
48
48
  desc: () => desc,
49
49
  handler: () => handler
50
50
  });
51
- var import_client_kms = __toModule(require("@aws-sdk/client-kms"));
52
- var import_chalk2 = __toModule(require("chalk"));
53
- var import_dotenv = __toModule(require("dotenv"));
54
- var import_node_fs = __toModule(require("node:fs"));
55
- var import_node_path = __toModule(require("node:path"));
51
+ var import_client_ssm2 = __toModule(require("@aws-sdk/client-ssm"));
56
52
 
57
53
  // src/commonCliOptions.ts
58
54
  var commonCliOptions = {
@@ -66,12 +62,27 @@ var commonCliOptions = {
66
62
  },
67
63
  awsKeyAlias: {
68
64
  string: true,
65
+ default: "alias/top-secret",
69
66
  describe: "AWS KMS asymmetric key alias"
70
67
  },
71
68
  awsKey: {
72
69
  string: true,
73
70
  describe: "AWS KMS asymmetric key arn"
74
71
  },
72
+ envFile: {
73
+ string: true,
74
+ describe: ".env file",
75
+ default: ".env"
76
+ },
77
+ secFile: {
78
+ string: true,
79
+ describe: ".sec file",
80
+ default: ".sec"
81
+ },
82
+ awsAssumeRoleArn: {
83
+ string: true,
84
+ describe: "arn or role to assume"
85
+ },
75
86
  verbose: {
76
87
  boolean: true,
77
88
  describe: "Be verbose"
@@ -92,7 +103,14 @@ var import_shared_ini_file_loader = __toModule(require("@aws-sdk/shared-ini-file
92
103
 
93
104
  // src/utils/logger.ts
94
105
  var import_chalk = __toModule(require("chalk"));
95
- var bold = (str) => import_chalk.default.yellowBright.bold(str);
106
+ var _logger;
107
+ var getLogger = () => {
108
+ if (!_logger) {
109
+ _logger = console;
110
+ }
111
+ return _logger;
112
+ };
113
+ var bold = (str) => import_chalk.default.greenBright.bold(str);
96
114
  var underline = (str) => import_chalk.default.cyanBright.bold(str);
97
115
 
98
116
  // src/utils/getCredentialsProfileRegion.ts
@@ -106,12 +124,25 @@ var getCredentialsProfileRegion = async ({
106
124
  let profileAndOrigin = void 0;
107
125
  let regionAndOrigin = void 0;
108
126
  if (argv.profile) {
109
- profileAndOrigin = { value: argv.profile, origin: `command line option: ${bold(argv.profile)}` };
110
- credentialsAndOrigin = { value: await (0, import_credential_providers.fromIni)({ profile: argv.profile })(), origin: `${bold(`[${argv.profile}]`)} in credentials file` };
127
+ profileAndOrigin = {
128
+ value: argv.profile,
129
+ origin: `command line option: ${bold(argv.profile)}`
130
+ };
131
+ credentialsAndOrigin = {
132
+ value: await (0, import_credential_providers.fromIni)({
133
+ profile: argv.profile
134
+ })(),
135
+ origin: `${bold(`[${argv.profile}]`)} in credentials file`
136
+ };
111
137
  } else if (env.AWS_PROFILE) {
112
- profileAndOrigin = { value: env.AWS_PROFILE, origin: `env variable ${bold("AWS_PROFILE")}: ${underline(env.AWS_PROFILE)}` };
138
+ profileAndOrigin = {
139
+ value: env.AWS_PROFILE,
140
+ origin: `env variable ${bold("AWS_PROFILE")}: ${underline(env.AWS_PROFILE)}`
141
+ };
113
142
  credentialsAndOrigin = {
114
- value: await (0, import_credential_providers.fromIni)({ profile: env.AWS_PROFILE })(),
143
+ value: await (0, import_credential_providers.fromIni)({
144
+ profile: env.AWS_PROFILE
145
+ })(),
115
146
  origin: `env variable ${underline("AWS_PROFILE")}: ${bold(env.AWS_PROFILE)}`
116
147
  };
117
148
  } else if (env.AWS_ACCESS_KEY_ID && env.AWS_SECRET_ACCESS_KEY) {
@@ -120,13 +151,27 @@ var getCredentialsProfileRegion = async ({
120
151
  origin: `env variables ${bold("AWS_ACCESS_KEY_ID")} and ${bold("AWS_SECRET_ACCESS_KEY")}`
121
152
  };
122
153
  } else if ((_a = sharedConfigFiles.credentialsFile) == null ? void 0 : _a.default) {
123
- profileAndOrigin = { value: "default", origin: `${bold("[default]")} in credentials file` };
124
- credentialsAndOrigin = { value: await (0, import_credential_providers.fromIni)({ profile: "default" })(), origin: `profile ${bold("[default]")}` };
154
+ profileAndOrigin = {
155
+ value: "default",
156
+ origin: `${bold("[default]")} in credentials file`
157
+ };
158
+ credentialsAndOrigin = {
159
+ value: await (0, import_credential_providers.fromIni)({
160
+ profile: "default"
161
+ })(),
162
+ origin: `profile ${bold("[default]")}`
163
+ };
125
164
  }
126
165
  if (argv.region) {
127
- regionAndOrigin = { value: argv.region, origin: `command line option: ${bold(argv.region)}` };
166
+ regionAndOrigin = {
167
+ value: argv.region,
168
+ origin: `command line option: ${bold(argv.region)}`
169
+ };
128
170
  } else if (env.AWS_REGION) {
129
- regionAndOrigin = { value: env.AWS_REGION, origin: `env variable ${bold("AWS_REGION")}: ${underline(env.AWS_REGION)}` };
171
+ regionAndOrigin = {
172
+ value: env.AWS_REGION,
173
+ origin: `env variable ${bold("AWS_REGION")}: ${underline(env.AWS_REGION)}`
174
+ };
130
175
  } else if (env.AWS_DEFAULT_REGION) {
131
176
  regionAndOrigin = {
132
177
  value: env.AWS_DEFAULT_REGION,
@@ -135,9 +180,27 @@ var getCredentialsProfileRegion = async ({
135
180
  } else if (profileAndOrigin) {
136
181
  const foundRegion = (_c = (_b = sharedConfigFiles == null ? void 0 : sharedConfigFiles.configFile) == null ? void 0 : _b[profileAndOrigin.value]) == null ? void 0 : _c.region;
137
182
  if (foundRegion) {
138
- regionAndOrigin = { value: foundRegion, origin: `${bold(`[profile ${profileAndOrigin.value}]`)} in config file` };
183
+ regionAndOrigin = {
184
+ value: foundRegion,
185
+ origin: `${bold(`[profile ${profileAndOrigin.value}]`)} in config file`
186
+ };
139
187
  }
140
188
  }
189
+ if (argv.assumeRoleArn) {
190
+ console.log("assume this yo");
191
+ credentialsAndOrigin = {
192
+ value: await (0, import_credential_providers.fromTemporaryCredentials)({
193
+ masterCredentials: credentialsAndOrigin == null ? void 0 : credentialsAndOrigin.value,
194
+ params: {
195
+ RoleArn: argv.assumeRoleArn
196
+ },
197
+ clientConfig: {
198
+ region: regionAndOrigin == null ? void 0 : regionAndOrigin.value
199
+ }
200
+ })(),
201
+ origin: `assume role ${bold(`[${argv.assumeRoleArn}]`)}`
202
+ };
203
+ }
141
204
  return { credentialsAndOrigin, regionAndOrigin, profileAndOrigin };
142
205
  };
143
206
  var printVerboseCredentialsProfileRegion = ({
@@ -163,12 +226,20 @@ var handleCredentialsAndRegion = async ({
163
226
  argv,
164
227
  env
165
228
  }) => {
166
- const { credentialsAndOrigin, regionAndOrigin } = await getCredentialsProfileRegion({
167
- argv: { region: argv.awsRegion, profile: argv.awsProfile },
229
+ const { credentialsAndOrigin, regionAndOrigin, profileAndOrigin } = await getCredentialsProfileRegion({
230
+ argv: {
231
+ region: argv.awsRegion,
232
+ profile: argv.awsProfile,
233
+ assumeRoleArn: argv.awsAssumeRoleArn
234
+ },
168
235
  env: __spreadValues({}, env)
169
236
  });
170
237
  if (argv.verbose === true) {
171
- console.log(printVerboseCredentialsProfileRegion({ credentialsAndOrigin, regionAndOrigin }));
238
+ console.log(printVerboseCredentialsProfileRegion({
239
+ credentialsAndOrigin,
240
+ regionAndOrigin,
241
+ profileAndOrigin
242
+ }));
172
243
  }
173
244
  if (!credentialsAndOrigin || !regionAndOrigin) {
174
245
  if (!credentialsAndOrigin) {
@@ -183,8 +254,67 @@ var handleCredentialsAndRegion = async ({
183
254
  return { credentialsAndOrigin, regionAndOrigin };
184
255
  };
185
256
 
257
+ // src/utils/ssm.ts
258
+ var import_client_ssm = __toModule(require("@aws-sdk/client-ssm"));
259
+ var getSSMClient = ({
260
+ configuration
261
+ }) => {
262
+ const ssmClient = new import_client_ssm.SSMClient(configuration);
263
+ return ssmClient;
264
+ };
265
+
266
+ // src/commands/debugCommand.ts
267
+ var command = "debug";
268
+ var desc = "Debugs all the things";
269
+ var builder = {
270
+ "aws-profile": commonCliOptions.awsProfile,
271
+ "aws-region": commonCliOptions.awsRegion,
272
+ "aws-key-alias": commonCliOptions.awsKeyAlias,
273
+ "aws-assume-role-arn": commonCliOptions.awsAssumeRoleArn,
274
+ verbose: commonCliOptions.verbose,
275
+ yes: __spreadValues({}, commonCliOptions.yes)
276
+ };
277
+ var handler = async (argv) => {
278
+ try {
279
+ const { credentialsAndOrigin, regionAndOrigin } = await handleCredentialsAndRegion({
280
+ argv: __spreadValues({}, argv),
281
+ env: __spreadValues({}, process.env)
282
+ });
283
+ const ssmClient = getSSMClient({
284
+ configuration: {
285
+ credentials: credentialsAndOrigin.value,
286
+ region: regionAndOrigin.value
287
+ },
288
+ verbose: argv.verbose
289
+ });
290
+ const getParametersByPathCommand = new import_client_ssm2.GetParametersByPathCommand({
291
+ Path: `arn:aws:ssm:eu-west-1:060014838622:parameter/dotsec/*`,
292
+ Recursive: true
293
+ });
294
+ const commandResult = await ssmClient.send(getParametersByPathCommand);
295
+ console.log(commandResult);
296
+ } catch (e) {
297
+ console.error(e);
298
+ }
299
+ };
300
+
301
+ // src/commands/decryptSecCommand.ts
302
+ var decryptSecCommand_exports = {};
303
+ __export(decryptSecCommand_exports, {
304
+ builder: () => builder2,
305
+ command: () => command2,
306
+ desc: () => desc2,
307
+ handler: () => handler2
308
+ });
309
+ var import_client_kms = __toModule(require("@aws-sdk/client-kms"));
310
+ var import_chalk2 = __toModule(require("chalk"));
311
+ var import_dotenv = __toModule(require("dotenv"));
312
+ var import_node_fs = __toModule(require("node:fs"));
313
+ var import_node_path = __toModule(require("node:path"));
314
+
186
315
  // src/utils/io.ts
187
316
  var import_promises = __toModule(require("fs/promises"));
317
+ var import_prompts = __toModule(require("prompts"));
188
318
  var fileExists = async (source) => {
189
319
  try {
190
320
  await (0, import_promises.stat)(source);
@@ -193,30 +323,43 @@ var fileExists = async (source) => {
193
323
  return false;
194
324
  }
195
325
  };
326
+ var promptOverwriteIfFileExists = async ({
327
+ filePath,
328
+ skip
329
+ }) => {
330
+ let overwriteResponse;
331
+ if (await fileExists(filePath) && skip !== true) {
332
+ overwriteResponse = await (0, import_prompts.default)({
333
+ type: "confirm",
334
+ name: "overwrite",
335
+ message: () => {
336
+ return `Overwrite '${filePath}' ?`;
337
+ }
338
+ });
339
+ } else {
340
+ overwriteResponse = void 0;
341
+ }
342
+ return overwriteResponse;
343
+ };
196
344
 
197
345
  // src/commands/decryptSecCommand.ts
198
- var command = "decrypt-sec";
199
- var desc = "Decrypts a dotsec file";
200
- var builder = {
201
- "aws-profile": __spreadValues({}, commonCliOptions.awsProfile),
202
- "aws-region": __spreadValues({}, commonCliOptions.awsRegion),
203
- "aws-key-alias": { string: true, default: "alias/top-secret" },
204
- "env-file": {
205
- string: true,
206
- describe: ".env file",
207
- default: ".env"
208
- },
209
- "sec-file": {
210
- string: true,
211
- describe: ".sec file",
212
- default: ".sec"
213
- },
214
- verbose: __spreadValues({}, commonCliOptions.verbose),
215
- yes: __spreadValues({}, commonCliOptions.yes)
346
+ var command2 = "decrypt-sec";
347
+ var desc2 = "Decrypts a dotsec file";
348
+ var builder2 = {
349
+ "aws-profile": commonCliOptions.awsProfile,
350
+ "aws-region": commonCliOptions.awsRegion,
351
+ "aws-key-alias": commonCliOptions.awsKeyAlias,
352
+ "assume-role-arn": commonCliOptions.awsAssumeRoleArn,
353
+ "env-file": commonCliOptions.envFile,
354
+ "sec-file": commonCliOptions.secFile,
355
+ verbose: commonCliOptions.verbose
216
356
  };
217
- var handler = async (argv) => {
357
+ var handler2 = async (argv) => {
218
358
  try {
219
- const { credentialsAndOrigin, regionAndOrigin } = await handleCredentialsAndRegion({ argv: __spreadValues({}, argv), env: __spreadValues({}, process.env) });
359
+ const { credentialsAndOrigin, regionAndOrigin } = await handleCredentialsAndRegion({
360
+ argv: __spreadValues({}, argv),
361
+ env: __spreadValues({}, process.env)
362
+ });
220
363
  const secSource = import_node_path.default.resolve(process.cwd(), argv.secFile);
221
364
  if (!await fileExists(secSource)) {
222
365
  console.error(`Could not open ${(0, import_chalk2.redBright)(secSource)}`);
@@ -235,7 +378,11 @@ var handler = async (argv) => {
235
378
  });
236
379
  const decryptionResult = await kmsClient.send(decryptCommand);
237
380
  if (!(decryptionResult == null ? void 0 : decryptionResult.Plaintext)) {
238
- throw new Error(`No: ${JSON.stringify({ key, cipherText, decryptCommand })}`);
381
+ throw new Error(`No: ${JSON.stringify({
382
+ key,
383
+ cipherText,
384
+ decryptCommand
385
+ })}`);
239
386
  }
240
387
  const value = Buffer.from(decryptionResult.Plaintext).toString();
241
388
  return [key, value];
@@ -246,57 +393,177 @@ var handler = async (argv) => {
246
393
  }
247
394
  };
248
395
 
249
- // src/commands/defaultCommand.ts
250
- var defaultCommand_exports = {};
251
- __export(defaultCommand_exports, {
252
- builder: () => builder2,
253
- command: () => command2,
254
- desc: () => desc2,
255
- handler: () => handler2
396
+ // src/commands/decryptSecretsJson.ts
397
+ var decryptSecretsJson_exports = {};
398
+ __export(decryptSecretsJson_exports, {
399
+ builder: () => builder3,
400
+ command: () => command3,
401
+ desc: () => desc3,
402
+ handler: () => handler3
256
403
  });
257
- var import_client_kms2 = __toModule(require("@aws-sdk/client-kms"));
404
+ var import_client_kms3 = __toModule(require("@aws-sdk/client-kms"));
258
405
  var import_chalk3 = __toModule(require("chalk"));
259
- var import_cross_spawn = __toModule(require("cross-spawn"));
260
- var import_dotenv2 = __toModule(require("dotenv"));
406
+ var import_flat = __toModule(require("flat"));
261
407
  var import_node_fs2 = __toModule(require("node:fs"));
262
408
  var import_node_path2 = __toModule(require("node:path"));
263
- var command2 = "$0 <command>";
264
- var desc2 = "Decrypts a .sec file, injects the results into a separate process and runs a command";
265
- var builder2 = {
266
- "aws-profile": __spreadValues({}, commonCliOptions.awsProfile),
267
- "aws-region": __spreadValues({}, commonCliOptions.awsRegion),
268
- "aws-key-alias": { string: true, default: "alias/top-secret" },
269
- "sec-file": {
409
+
410
+ // src/utils/kms.ts
411
+ var import_client_kms2 = __toModule(require("@aws-sdk/client-kms"));
412
+ var getKMSClient = ({
413
+ configuration
414
+ }) => {
415
+ const kmsClient = new import_client_kms2.KMSClient(configuration);
416
+ return kmsClient;
417
+ };
418
+
419
+ // src/commands/decryptSecretsJson.ts
420
+ var command3 = "decrypt-secrets-json";
421
+ var desc3 = "Derypts an encrypted file";
422
+ var builder3 = {
423
+ "aws-profile": commonCliOptions.awsProfile,
424
+ "aws-region": commonCliOptions.awsRegion,
425
+ "aws-key-alias": commonCliOptions.awsKeyAlias,
426
+ "secrets-file": {
270
427
  string: true,
271
- describe: ".sec file",
272
- default: ".sec"
428
+ describe: "filename of json file writing secrets",
429
+ default: "secrets.json"
430
+ },
431
+ "encrypted-secrets-file": {
432
+ string: true,
433
+ describe: "filename of json file for reading encrypted secrets",
434
+ default: "secrets.encrypted.json"
273
435
  },
274
- verbose: __spreadValues({}, commonCliOptions.verbose),
275
- yes: __spreadValues({}, commonCliOptions.yes),
436
+ "assume-role-arn": commonCliOptions.awsAssumeRoleArn,
437
+ verbose: commonCliOptions.verbose,
438
+ yes: __spreadValues({}, commonCliOptions.yes)
439
+ };
440
+ var handler3 = async (argv) => {
441
+ const { info, error } = getLogger();
442
+ try {
443
+ const { credentialsAndOrigin, regionAndOrigin } = await handleCredentialsAndRegion({
444
+ argv: __spreadValues({}, argv),
445
+ env: __spreadValues({}, process.env)
446
+ });
447
+ const encryptedSecretsPath = import_node_path2.default.resolve(process.cwd(), argv.encryptedSecretsFile);
448
+ if (!await fileExists(encryptedSecretsPath)) {
449
+ error(`Could not open ${(0, import_chalk3.redBright)(encryptedSecretsPath)}`);
450
+ return;
451
+ }
452
+ const encryptedSecrets = JSON.parse(import_node_fs2.default.readFileSync(encryptedSecretsPath, { encoding: "utf8" }));
453
+ if (!encryptedSecrets.encryptedParameters) {
454
+ throw new Error(`Expected 'encryptedParameters' property, but got none`);
455
+ }
456
+ const flatEncryptedParameters = (0, import_flat.default)(encryptedSecrets.encryptedParameters, { delimiter: "/" });
457
+ const kmsClient = getKMSClient({
458
+ configuration: {
459
+ credentials: credentialsAndOrigin.value,
460
+ region: regionAndOrigin.value
461
+ },
462
+ verbose: argv.verbose
463
+ });
464
+ if (argv.verbose) {
465
+ info(`Encrypting using key alias ${bold(argv.awsKeyAlias)} in ${bold(await kmsClient.config.region())}`);
466
+ const describeKeyCommand = new import_client_kms3.DescribeKeyCommand({
467
+ KeyId: argv.awsKeyAlias
468
+ });
469
+ const describeKeyResult = await kmsClient.send(describeKeyCommand);
470
+ console.log("describeKeyResult", { describeKeyResult });
471
+ }
472
+ const flatParameters = Object.fromEntries(await Promise.all(Object.entries(flatEncryptedParameters).map(async ([parameterName, encryptedParameter]) => {
473
+ const decryptCommand = new import_client_kms3.DecryptCommand({
474
+ KeyId: argv.awsKeyAlias,
475
+ CiphertextBlob: Buffer.from(encryptedParameter, "base64"),
476
+ EncryptionAlgorithm: "RSAES_OAEP_SHA_256"
477
+ });
478
+ const decryptionResult = await kmsClient.send(decryptCommand);
479
+ if (!decryptionResult.Plaintext) {
480
+ throw new Error(`Something bad happened: ${JSON.stringify({
481
+ key: parameterName,
482
+ cipherText: encryptedParameter,
483
+ decryptCommand
484
+ })}`);
485
+ }
486
+ if (argv.verbose) {
487
+ info(`Encrypting key ${bold(parameterName)} ${underline("ok")}`);
488
+ }
489
+ const value = Buffer.from(decryptionResult.Plaintext).toString();
490
+ return [parameterName, value];
491
+ })));
492
+ const parameters = import_flat.default.unflatten(flatParameters, { delimiter: "/" });
493
+ const secrets = {
494
+ config: encryptedSecrets.config,
495
+ parameters
496
+ };
497
+ const secretsPath = import_node_path2.default.resolve(process.cwd(), argv.secretsFile);
498
+ const overwriteResponse = await promptOverwriteIfFileExists({
499
+ filePath: secretsPath,
500
+ skip: argv.yes
501
+ });
502
+ if (overwriteResponse === void 0 || overwriteResponse.overwrite === true) {
503
+ import_node_fs2.default.writeFileSync(secretsPath, JSON.stringify(secrets, null, 4));
504
+ }
505
+ } catch (e) {
506
+ error(e);
507
+ }
508
+ };
509
+
510
+ // src/commands/defaultCommand.ts
511
+ var defaultCommand_exports = {};
512
+ __export(defaultCommand_exports, {
513
+ builder: () => builder4,
514
+ command: () => command4,
515
+ desc: () => desc4,
516
+ handler: () => handler4
517
+ });
518
+ var import_client_kms4 = __toModule(require("@aws-sdk/client-kms"));
519
+ var import_chalk4 = __toModule(require("chalk"));
520
+ var import_cross_spawn = __toModule(require("cross-spawn"));
521
+ var import_dotenv2 = __toModule(require("dotenv"));
522
+ var import_node_fs3 = __toModule(require("node:fs"));
523
+ var import_node_path3 = __toModule(require("node:path"));
524
+ var command4 = "$0 <command>";
525
+ var desc4 = "Decrypts a .sec file, injects the results into a separate process and runs a command";
526
+ var builder4 = {
527
+ "aws-profile": commonCliOptions.awsProfile,
528
+ "aws-region": commonCliOptions.awsRegion,
529
+ "aws-key-alias": commonCliOptions.awsKeyAlias,
530
+ "sec-file": commonCliOptions.secFile,
531
+ "assume-role-arn": commonCliOptions.awsAssumeRoleArn,
532
+ verbose: commonCliOptions.verbose,
276
533
  command: { string: true, required: true }
277
534
  };
278
- var handler2 = async (argv) => {
535
+ var handler4 = async (argv) => {
279
536
  try {
280
- const { credentialsAndOrigin, regionAndOrigin } = await handleCredentialsAndRegion({ argv: __spreadValues({}, argv), env: __spreadValues({}, process.env) });
281
- const secSource = import_node_path2.default.resolve(process.cwd(), argv.secFile);
537
+ const { credentialsAndOrigin, regionAndOrigin } = await handleCredentialsAndRegion({
538
+ argv: __spreadValues({}, argv),
539
+ env: __spreadValues({}, process.env)
540
+ });
541
+ if (argv.verbose) {
542
+ console.log({ credentialsAndOrigin, regionAndOrigin });
543
+ }
544
+ const secSource = import_node_path3.default.resolve(process.cwd(), argv.secFile);
282
545
  if (!await fileExists(secSource)) {
283
- console.error(`Could not open ${(0, import_chalk3.redBright)(secSource)}`);
546
+ console.error(`Could not open ${(0, import_chalk4.redBright)(secSource)}`);
284
547
  return;
285
548
  }
286
- const parsedSec = (0, import_dotenv2.parse)(import_node_fs2.default.readFileSync(secSource, { encoding: "utf8" }));
287
- const kmsClient = new import_client_kms2.KMSClient({
549
+ const parsedSec = (0, import_dotenv2.parse)(import_node_fs3.default.readFileSync(secSource, { encoding: "utf8" }));
550
+ const kmsClient = new import_client_kms4.KMSClient({
288
551
  credentials: credentialsAndOrigin.value,
289
552
  region: regionAndOrigin.value
290
553
  });
291
554
  const envEntries = await Promise.all(Object.entries(parsedSec).map(async ([key, cipherText]) => {
292
- const decryptCommand = new import_client_kms2.DecryptCommand({
555
+ const decryptCommand = new import_client_kms4.DecryptCommand({
293
556
  KeyId: argv.awsKeyAlias,
294
557
  CiphertextBlob: Buffer.from(cipherText, "base64"),
295
558
  EncryptionAlgorithm: "RSAES_OAEP_SHA_256"
296
559
  });
297
560
  const decryptionResult = await kmsClient.send(decryptCommand);
298
561
  if (!(decryptionResult == null ? void 0 : decryptionResult.Plaintext)) {
299
- throw new Error(`No: ${JSON.stringify({ key, cipherText, decryptCommand })}`);
562
+ throw new Error(`No: ${JSON.stringify({
563
+ key,
564
+ cipherText,
565
+ decryptCommand
566
+ })}`);
300
567
  }
301
568
  const value = Buffer.from(decryptionResult.Plaintext).toString();
302
569
  return [key, value];
@@ -318,67 +585,289 @@ var handler2 = async (argv) => {
318
585
  // src/commands/encryptEnvCommand.ts
319
586
  var encryptEnvCommand_exports = {};
320
587
  __export(encryptEnvCommand_exports, {
321
- builder: () => builder3,
322
- command: () => command3,
323
- desc: () => desc3,
324
- handler: () => handler3
588
+ builder: () => builder5,
589
+ command: () => command5,
590
+ desc: () => desc5,
591
+ handler: () => handler5
325
592
  });
326
- var import_client_kms3 = __toModule(require("@aws-sdk/client-kms"));
327
- var import_chalk4 = __toModule(require("chalk"));
593
+ var import_client_kms5 = __toModule(require("@aws-sdk/client-kms"));
594
+ var import_chalk5 = __toModule(require("chalk"));
328
595
  var import_dotenv3 = __toModule(require("dotenv"));
329
- var import_node_fs3 = __toModule(require("node:fs"));
330
- var import_node_path3 = __toModule(require("node:path"));
331
- var command3 = "encrypt-env";
332
- var desc3 = "Encrypts a dotenv file";
333
- var builder3 = {
334
- "aws-profile": __spreadValues({}, commonCliOptions.awsProfile),
335
- "aws-region": __spreadValues({}, commonCliOptions.awsRegion),
336
- "aws-key-alias": { string: true, default: "alias/top-secret" },
337
- "env-file": {
338
- string: true,
339
- describe: ".env file",
340
- default: ".env"
341
- },
342
- "sec-file": {
343
- string: true,
344
- describe: ".sec file",
345
- default: ".sec"
346
- },
347
- verbose: __spreadValues({}, commonCliOptions.verbose),
348
- yes: __spreadValues({}, commonCliOptions.yes)
596
+ var import_node_fs4 = __toModule(require("node:fs"));
597
+ var import_node_path4 = __toModule(require("node:path"));
598
+ var command5 = "encrypt-env";
599
+ var desc5 = "Encrypts a dotenv file";
600
+ var builder5 = {
601
+ "aws-profile": commonCliOptions.awsProfile,
602
+ "aws-region": commonCliOptions.awsRegion,
603
+ "aws-key-alias": commonCliOptions.awsKeyAlias,
604
+ "env-file": commonCliOptions.envFile,
605
+ "sec-file": commonCliOptions.secFile,
606
+ "assume-role-arn": commonCliOptions.awsAssumeRoleArn,
607
+ verbose: commonCliOptions.verbose
349
608
  };
350
- var handler3 = async (argv) => {
609
+ var handler5 = async (argv) => {
610
+ const { info, error } = getLogger();
351
611
  try {
352
- const { credentialsAndOrigin, regionAndOrigin } = await handleCredentialsAndRegion({ argv: __spreadValues({}, argv), env: __spreadValues({}, process.env) });
353
- const envSource = import_node_path3.default.resolve(process.cwd(), argv.envFile);
612
+ const { credentialsAndOrigin, regionAndOrigin } = await handleCredentialsAndRegion({
613
+ argv: __spreadValues({}, argv),
614
+ env: __spreadValues({}, process.env)
615
+ });
616
+ const envSource = import_node_path4.default.resolve(process.cwd(), argv.envFile);
354
617
  if (!await fileExists(envSource)) {
355
- console.error(`Could not open ${(0, import_chalk4.redBright)(envSource)}`);
618
+ error(`Could not open ${(0, import_chalk5.redBright)(envSource)}`);
356
619
  return;
357
620
  }
358
- const parsedEnv = (0, import_dotenv3.parse)(import_node_fs3.default.readFileSync(envSource, { encoding: "utf8" }));
359
- const kmsClient = new import_client_kms3.KMSClient({
360
- credentials: credentialsAndOrigin.value,
361
- region: regionAndOrigin.value
621
+ const parsedEnv = (0, import_dotenv3.parse)(import_node_fs4.default.readFileSync(envSource, { encoding: "utf8" }));
622
+ const kmsClient = getKMSClient({
623
+ configuration: {
624
+ credentials: credentialsAndOrigin.value,
625
+ region: regionAndOrigin.value
626
+ },
627
+ verbose: argv.verbose
362
628
  });
629
+ if (argv.verbose) {
630
+ info(`Encrypting using key alias ${bold(argv.awsKeyAlias)} in ${bold(await kmsClient.config.region())}`);
631
+ const describeKeyCommand = new import_client_kms5.DescribeKeyCommand({
632
+ KeyId: argv.awsKeyAlias
633
+ });
634
+ const describeKeyResult = await kmsClient.send(describeKeyCommand);
635
+ console.log("describeKeyResult", { describeKeyResult });
636
+ }
363
637
  const sec = (await Promise.all(Object.entries(parsedEnv).map(async ([key, value]) => {
364
- const encryptCommand = new import_client_kms3.EncryptCommand({
638
+ const encryptCommand = new import_client_kms5.EncryptCommand({
365
639
  KeyId: argv.awsKeyAlias,
366
640
  Plaintext: Buffer.from(value),
367
641
  EncryptionAlgorithm: "RSAES_OAEP_SHA_256"
368
642
  });
369
643
  const encryptionResult = await kmsClient.send(encryptCommand);
370
644
  if (!encryptionResult.CiphertextBlob) {
371
- throw new Error(`No: ${JSON.stringify({ key, value, encryptCommand })}`);
645
+ throw new Error(`Something bad happened: ${JSON.stringify({
646
+ key,
647
+ value,
648
+ encryptCommand
649
+ })}`);
650
+ }
651
+ if (argv.verbose) {
652
+ info(`Encrypting key ${bold(key)} ${underline("ok")}`);
372
653
  }
373
654
  const cipherText = Buffer.from(encryptionResult.CiphertextBlob).toString("base64");
374
655
  return `${key}="${cipherText}"`;
375
656
  }))).join("\n");
376
- import_node_fs3.default.writeFileSync(import_node_path3.default.resolve(process.cwd(), argv.secFile), sec);
657
+ import_node_fs4.default.writeFileSync(import_node_path4.default.resolve(process.cwd(), argv.secFile), sec);
377
658
  } catch (e) {
378
- console.error(e);
659
+ error(e);
660
+ }
661
+ };
662
+
663
+ // src/commands/encryptSecretsJson.ts
664
+ var encryptSecretsJson_exports = {};
665
+ __export(encryptSecretsJson_exports, {
666
+ builder: () => builder6,
667
+ command: () => command6,
668
+ desc: () => desc6,
669
+ handler: () => handler6
670
+ });
671
+ var import_client_kms6 = __toModule(require("@aws-sdk/client-kms"));
672
+ var import_chalk6 = __toModule(require("chalk"));
673
+ var import_flat2 = __toModule(require("flat"));
674
+ var import_node_fs5 = __toModule(require("node:fs"));
675
+ var import_node_path5 = __toModule(require("node:path"));
676
+ var command6 = "encrypt-secrets-json";
677
+ var desc6 = "Encrypts an unencrypted file";
678
+ var builder6 = {
679
+ "aws-profile": commonCliOptions.awsProfile,
680
+ "aws-region": commonCliOptions.awsRegion,
681
+ "aws-key-alias": commonCliOptions.awsKeyAlias,
682
+ "secrets-file": {
683
+ string: true,
684
+ describe: "filename of json file reading secrets",
685
+ default: "secrets.json"
686
+ },
687
+ "encrypted-secrets-file": {
688
+ string: true,
689
+ describe: "filename of json file for writing encrypted secrets",
690
+ default: "secrets.encrypted.json"
691
+ },
692
+ "assume-role-arn": commonCliOptions.awsAssumeRoleArn,
693
+ verbose: commonCliOptions.verbose,
694
+ yes: __spreadValues({}, commonCliOptions.yes)
695
+ };
696
+ var handler6 = async (argv) => {
697
+ const { info, error } = getLogger();
698
+ try {
699
+ const { credentialsAndOrigin, regionAndOrigin } = await handleCredentialsAndRegion({
700
+ argv: __spreadValues({}, argv),
701
+ env: __spreadValues({}, process.env)
702
+ });
703
+ const secretsPath = import_node_path5.default.resolve(process.cwd(), argv.secretsFile);
704
+ if (!await fileExists(secretsPath)) {
705
+ error(`Could not open ${(0, import_chalk6.redBright)(secretsPath)}`);
706
+ return;
707
+ }
708
+ const secrets = JSON.parse(import_node_fs5.default.readFileSync(secretsPath, { encoding: "utf8" }));
709
+ if (!secrets.parameters) {
710
+ throw new Error(`Expected 'parameters' property, but got none`);
711
+ }
712
+ const flatParameters = (0, import_flat2.default)(secrets.parameters, { delimiter: "/" });
713
+ if (argv.verbose) {
714
+ console.log(flatParameters);
715
+ }
716
+ const kmsClient = getKMSClient({
717
+ configuration: {
718
+ credentials: credentialsAndOrigin.value,
719
+ region: regionAndOrigin.value
720
+ },
721
+ verbose: argv.verbose
722
+ });
723
+ if (argv.verbose) {
724
+ info(`Encrypting using key alias ${bold(argv.awsKeyAlias)} in ${bold(await kmsClient.config.region())}`);
725
+ const describeKeyCommand = new import_client_kms6.DescribeKeyCommand({
726
+ KeyId: argv.awsKeyAlias
727
+ });
728
+ const describeKeyResult = await kmsClient.send(describeKeyCommand);
729
+ console.log("describeKeyResult", { describeKeyResult });
730
+ }
731
+ const encryptedFlatParameters = Object.fromEntries(await Promise.all(Object.entries(flatParameters).map(async ([parameterName, parameter]) => {
732
+ const encryptCommand = new import_client_kms6.EncryptCommand({
733
+ KeyId: argv.awsKeyAlias,
734
+ Plaintext: Buffer.from(parameter),
735
+ EncryptionAlgorithm: "RSAES_OAEP_SHA_256"
736
+ });
737
+ const encryptionResult = await kmsClient.send(encryptCommand);
738
+ if (!encryptionResult.CiphertextBlob) {
739
+ throw new Error(`Something bad happened: ${JSON.stringify({
740
+ key: parameterName,
741
+ value: parameter,
742
+ encryptCommand
743
+ })}`);
744
+ }
745
+ if (argv.verbose) {
746
+ info(`Encrypting key ${bold(parameterName)} ${underline("ok")}`);
747
+ }
748
+ const cipherText = Buffer.from(encryptionResult.CiphertextBlob).toString("base64");
749
+ return [parameterName, cipherText];
750
+ })));
751
+ const encryptedParameters = import_flat2.default.unflatten(encryptedFlatParameters, { delimiter: "/" });
752
+ const encryptedSecrets = {
753
+ config: secrets.config,
754
+ encryptedParameters
755
+ };
756
+ const encryptedSecretsPath = import_node_path5.default.resolve(process.cwd(), argv.encryptedSecretsFile);
757
+ const overwriteResponse = await promptOverwriteIfFileExists({
758
+ filePath: encryptedSecretsPath,
759
+ skip: argv.yes
760
+ });
761
+ if (overwriteResponse === void 0 || overwriteResponse.overwrite === true) {
762
+ import_node_fs5.default.writeFileSync(encryptedSecretsPath, JSON.stringify(encryptedSecrets, null, 4));
763
+ }
764
+ } catch (e) {
765
+ error(e);
766
+ }
767
+ };
768
+
769
+ // src/commands/offloadToSSMCommand.ts
770
+ var offloadToSSMCommand_exports = {};
771
+ __export(offloadToSSMCommand_exports, {
772
+ builder: () => builder7,
773
+ command: () => command7,
774
+ desc: () => desc7,
775
+ handler: () => handler7
776
+ });
777
+ var import_client_kms7 = __toModule(require("@aws-sdk/client-kms"));
778
+ var import_client_ssm3 = __toModule(require("@aws-sdk/client-ssm"));
779
+ var import_chalk7 = __toModule(require("chalk"));
780
+ var import_flat3 = __toModule(require("flat"));
781
+ var import_node_fs6 = __toModule(require("node:fs"));
782
+ var import_node_path6 = __toModule(require("node:path"));
783
+ var command7 = "offload-secrets-json-to-ssm";
784
+ var desc7 = "Sends decrypted values of secrets.encrypted.json file to SSM parameter store";
785
+ var builder7 = {
786
+ "aws-profile": commonCliOptions.awsProfile,
787
+ "aws-region": commonCliOptions.awsRegion,
788
+ "aws-key-alias": commonCliOptions.awsKeyAlias,
789
+ "encrypted-secrets-file": {
790
+ string: true,
791
+ describe: "filename of json file for reading encrypted secrets",
792
+ default: "secrets.encrypted.json"
793
+ },
794
+ "assume-role-arn": commonCliOptions.awsAssumeRoleArn,
795
+ verbose: commonCliOptions.verbose,
796
+ yes: __spreadValues({}, commonCliOptions.yes)
797
+ };
798
+ var handler7 = async (argv) => {
799
+ const { info, error } = getLogger();
800
+ try {
801
+ const { credentialsAndOrigin, regionAndOrigin } = await handleCredentialsAndRegion({
802
+ argv: __spreadValues({}, argv),
803
+ env: __spreadValues({}, process.env)
804
+ });
805
+ const encryptedSecretsPath = import_node_path6.default.resolve(process.cwd(), argv.encryptedSecretsFile);
806
+ if (!await fileExists(encryptedSecretsPath)) {
807
+ error(`Could not open ${(0, import_chalk7.redBright)(encryptedSecretsPath)}`);
808
+ return;
809
+ }
810
+ const encryptedSecrets = JSON.parse(import_node_fs6.default.readFileSync(encryptedSecretsPath, { encoding: "utf8" }));
811
+ if (!encryptedSecrets.encryptedParameters) {
812
+ throw new Error(`Expected 'encryptedParameters' property, but got none`);
813
+ }
814
+ const flatEncryptedParameters = (0, import_flat3.default)(encryptedSecrets.encryptedParameters, { delimiter: "/" });
815
+ const kmsClient = getKMSClient({
816
+ configuration: {
817
+ credentials: credentialsAndOrigin.value,
818
+ region: regionAndOrigin.value
819
+ },
820
+ verbose: argv.verbose
821
+ });
822
+ if (argv.verbose) {
823
+ info(`Encrypting using key alias ${bold(argv.awsKeyAlias)} in ${bold(await kmsClient.config.region())}`);
824
+ const describeKeyCommand = new import_client_kms7.DescribeKeyCommand({
825
+ KeyId: argv.awsKeyAlias
826
+ });
827
+ const describeKeyResult = await kmsClient.send(describeKeyCommand);
828
+ console.log("describeKeyResult", { describeKeyResult });
829
+ }
830
+ const flatParameters = Object.fromEntries(await Promise.all(Object.entries(flatEncryptedParameters).map(async ([parameterName, encryptedParameter]) => {
831
+ const decryptCommand = new import_client_kms7.DecryptCommand({
832
+ KeyId: argv.awsKeyAlias,
833
+ CiphertextBlob: Buffer.from(encryptedParameter, "base64"),
834
+ EncryptionAlgorithm: "RSAES_OAEP_SHA_256"
835
+ });
836
+ const decryptionResult = await kmsClient.send(decryptCommand);
837
+ if (!decryptionResult.Plaintext) {
838
+ throw new Error(`Something bad happened: ${JSON.stringify({
839
+ key: parameterName,
840
+ cipherText: encryptedParameter,
841
+ decryptCommand
842
+ })}`);
843
+ }
844
+ if (argv.verbose) {
845
+ info(`Encrypting key ${bold(parameterName)} ${underline("ok")}`);
846
+ }
847
+ const value = Buffer.from(decryptionResult.Plaintext).toString();
848
+ return [parameterName, value];
849
+ })));
850
+ const ssmClient = getSSMClient({
851
+ configuration: {
852
+ credentials: credentialsAndOrigin.value,
853
+ region: regionAndOrigin.value
854
+ },
855
+ verbose: argv.verbose
856
+ });
857
+ await Promise.all(Object.entries(flatParameters).map(([parameterName, value]) => {
858
+ const putParameterCommand = new import_client_ssm3.PutParameterCommand({
859
+ Name: `/${parameterName}`,
860
+ Value: value,
861
+ Type: "String",
862
+ Overwrite: true
863
+ });
864
+ return ssmClient.send(putParameterCommand);
865
+ }));
866
+ } catch (e) {
867
+ error(e);
379
868
  }
380
869
  };
381
870
 
382
871
  // src/cli.ts
383
- void (0, import_yargs.default)((0, import_helpers.hideBin)(process.argv)).command(defaultCommand_exports).command(encryptEnvCommand_exports).command(decryptSecCommand_exports).parse();
872
+ void (0, import_yargs.default)((0, import_helpers.hideBin)(process.argv)).command(defaultCommand_exports).command(offloadToSSMCommand_exports).command(debugCommand_exports).command(encryptEnvCommand_exports).command(decryptSecCommand_exports).command(encryptSecretsJson_exports).command(decryptSecretsJson_exports).parse();
384
873
  //# sourceMappingURL=cli.js.map