@mtndev/cli 1.1.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +91 -0
- package/cjs/__chunks/VH7oDXx4.cjs +28 -0
- package/cjs/commands/aws/ec2/allow-ip/handler.cjs +261 -0
- package/cjs/commands/aws/ec2/allow-ip/handler.d.ts +6 -0
- package/cjs/commands/aws/ec2/allow-ip/index.cjs +25 -0
- package/cjs/commands/aws/ec2/allow-ip/index.d.ts +3 -0
- package/cjs/commands/aws/ec2/allow-ip/schema.cjs +33 -0
- package/cjs/commands/aws/ec2/allow-ip/schema.d.ts +33 -0
- package/cjs/commands/aws/ec2/allow-ip/utils.cjs +379 -0
- package/cjs/commands/aws/ec2/allow-ip/utils.d.ts +189 -0
- package/cjs/commands/aws/iam/admin-group.cjs +111 -0
- package/cjs/commands/aws/iam/admin-group.d.ts +55 -0
- package/cjs/commands/aws/iam/break-glass/handler.cjs +127 -0
- package/cjs/commands/aws/iam/break-glass/handler.d.ts +7 -0
- package/cjs/commands/aws/iam/break-glass/index.cjs +7 -0
- package/cjs/commands/aws/iam/break-glass/index.d.ts +2 -0
- package/cjs/commands/aws/iam/break-glass/schema.cjs +21 -0
- package/cjs/commands/aws/iam/break-glass/schema.d.ts +25 -0
- package/cjs/commands/aws/iam/check-admin/handler.cjs +89 -0
- package/cjs/commands/aws/iam/check-admin/handler.d.ts +5 -0
- package/cjs/commands/aws/iam/check-admin/index.cjs +7 -0
- package/cjs/commands/aws/iam/check-admin/index.d.ts +2 -0
- package/cjs/commands/aws/iam/check-admin/schema.cjs +19 -0
- package/cjs/commands/aws/iam/check-admin/schema.d.ts +19 -0
- package/cjs/commands/aws/iam/policies/s3-restrictions-deny-non-s3-services.json +20 -0
- package/cjs/commands/aws/iam/policies/sts-federation.json +11 -0
- package/cjs/commands/aws/iam/policies/user-admins-deny-list.json +175 -0
- package/cjs/commands/aws/iam/policies/user-admins-deny-regions-list.json +41 -0
- package/cjs/commands/aws/iam/policies/user-admins-self-service-iam.json +56 -0
- package/cjs/commands/aws/iam/policies/user-admins-write-list.json +117 -0
- package/cjs/commands/aws/iam/remove-admin/handler.cjs +120 -0
- package/cjs/commands/aws/iam/remove-admin/handler.d.ts +6 -0
- package/cjs/commands/aws/iam/remove-admin/index.cjs +7 -0
- package/cjs/commands/aws/iam/remove-admin/index.d.ts +2 -0
- package/cjs/commands/aws/iam/remove-admin/schema.cjs +22 -0
- package/cjs/commands/aws/iam/remove-admin/schema.d.ts +28 -0
- package/cjs/commands/aws/iam/setup-acl/handler.cjs +227 -0
- package/cjs/commands/aws/iam/setup-acl/handler.d.ts +6 -0
- package/cjs/commands/aws/iam/setup-acl/index.cjs +13 -0
- package/cjs/commands/aws/iam/setup-acl/index.d.ts +3 -0
- package/cjs/commands/aws/iam/setup-acl/schema.cjs +19 -0
- package/cjs/commands/aws/iam/setup-acl/schema.d.ts +24 -0
- package/cjs/commands/aws/iam/setup-acl/utils.cjs +305 -0
- package/cjs/commands/aws/iam/setup-acl/utils.d.ts +61 -0
- package/cjs/commands/aws/iam/users/handler.cjs +59 -0
- package/cjs/commands/aws/iam/users/handler.d.ts +5 -0
- package/cjs/commands/aws/iam/users/index.cjs +18 -0
- package/cjs/commands/aws/iam/users/index.d.ts +3 -0
- package/cjs/commands/aws/iam/users/schema.cjs +17 -0
- package/cjs/commands/aws/iam/users/schema.d.ts +18 -0
- package/cjs/commands/aws/iam/users/utils.cjs +454 -0
- package/cjs/commands/aws/iam/users/utils.d.ts +119 -0
- package/cjs/commands/aws/index.cjs +223 -0
- package/cjs/commands/aws/index.d.ts +14 -0
- package/cjs/commands/aws/route53/add-record/handler.cjs +264 -0
- package/cjs/commands/aws/route53/add-record/handler.d.ts +36 -0
- package/cjs/commands/aws/route53/add-record/index.cjs +26 -0
- package/cjs/commands/aws/route53/add-record/index.d.ts +3 -0
- package/cjs/commands/aws/route53/add-record/schema.cjs +43 -0
- package/cjs/commands/aws/route53/add-record/schema.d.ts +45 -0
- package/cjs/commands/aws/route53/add-record/utils.cjs +404 -0
- package/cjs/commands/aws/route53/add-record/utils.d.ts +216 -0
- package/cjs/commands/aws/route53/remove-record/handler.cjs +114 -0
- package/cjs/commands/aws/route53/remove-record/handler.d.ts +6 -0
- package/cjs/commands/aws/route53/remove-record/index.cjs +5 -0
- package/cjs/commands/aws/route53/remove-record/index.d.ts +2 -0
- package/cjs/commands/aws/route53/remove-record/schema.cjs +22 -0
- package/cjs/commands/aws/route53/remove-record/schema.d.ts +30 -0
- package/cjs/commands/aws/schema.cjs +19 -0
- package/cjs/commands/aws/schema.d.ts +13 -0
- package/cjs/commands/aws/ses/send-email/handler.cjs +73 -0
- package/cjs/commands/aws/ses/send-email/handler.d.ts +5 -0
- package/cjs/commands/aws/ses/send-email/index.cjs +9 -0
- package/cjs/commands/aws/ses/send-email/index.d.ts +3 -0
- package/cjs/commands/aws/ses/send-email/schema.cjs +24 -0
- package/cjs/commands/aws/ses/send-email/schema.d.ts +39 -0
- package/cjs/commands/aws/ses/send-email/utils.cjs +87 -0
- package/cjs/commands/aws/ses/send-email/utils.d.ts +47 -0
- package/cjs/commands/aws/ses/smtp-password.cjs +72 -0
- package/cjs/commands/aws/ses/smtp-password.d.ts +21 -0
- package/cjs/commands/aws/utils/exec-aws.cjs +145 -0
- package/cjs/commands/aws/utils/exec-aws.d.ts +79 -0
- package/cjs/commands/aws/utils/resolve-policy-path.cjs +15 -0
- package/cjs/commands/aws/utils/resolve-policy-path.d.ts +8 -0
- package/cjs/commands/aws/utils/resolve-profile.cjs +93 -0
- package/cjs/commands/aws/utils/resolve-profile.d.ts +28 -0
- package/cjs/commands/aws/utils/tty.cjs +54 -0
- package/cjs/commands/aws/utils/tty.d.ts +24 -0
- package/cjs/commands/db/create-readonly-user/handler.cjs +254 -0
- package/cjs/commands/db/create-readonly-user/handler.d.ts +5 -0
- package/cjs/commands/db/create-readonly-user/index.cjs +18 -0
- package/cjs/commands/db/create-readonly-user/index.d.ts +3 -0
- package/cjs/commands/db/create-readonly-user/mysql.cjs +102 -0
- package/cjs/commands/db/create-readonly-user/mysql.d.ts +33 -0
- package/cjs/commands/db/create-readonly-user/postgres.cjs +209 -0
- package/cjs/commands/db/create-readonly-user/postgres.d.ts +31 -0
- package/cjs/commands/db/create-readonly-user/schema.cjs +39 -0
- package/cjs/commands/db/create-readonly-user/schema.d.ts +55 -0
- package/cjs/commands/db/create-readonly-user/utils.cjs +160 -0
- package/cjs/commands/db/create-readonly-user/utils.d.ts +112 -0
- package/cjs/commands/db/index.cjs +46 -0
- package/cjs/commands/db/index.d.ts +6 -0
- package/cjs/commands/doppler/handler.cjs +95 -9
- package/cjs/commands/doppler/index.cjs +33 -41
- package/cjs/commands/doppler/index.d.ts +1 -0
- package/cjs/commands/doppler/schema.cjs +130 -6
- package/cjs/commands/doppler/schema.d.ts +233 -17
- package/cjs/commands/doppler/set-secret.cjs +378 -0
- package/cjs/commands/doppler/set-secret.d.ts +113 -0
- package/cjs/commands/doppler/utils/exec.cjs +106 -12
- package/cjs/commands/doppler/utils.cjs +412 -30
- package/cjs/commands/doppler/utils.d.ts +32 -8
- package/cjs/commands/icons/handler.cjs +82 -8
- package/cjs/commands/icons/index.cjs +15 -31
- package/cjs/commands/icons/schema.cjs +101 -13
- package/cjs/commands/icons/schema.d.ts +1 -1
- package/cjs/commands/icons/utils.cjs +131 -13
- package/cjs/commands/index.cjs +54 -82
- package/cjs/commands/schema.cjs +25 -8
- package/cjs/index.cjs +3 -4
- package/esm/commands/aws/ec2/allow-ip/handler.d.ts +6 -0
- package/esm/commands/aws/ec2/allow-ip/handler.js +258 -0
- package/esm/commands/aws/ec2/allow-ip/index.d.ts +3 -0
- package/esm/commands/aws/ec2/allow-ip/index.js +4 -0
- package/esm/commands/aws/ec2/allow-ip/schema.d.ts +33 -0
- package/esm/commands/aws/ec2/allow-ip/schema.js +29 -0
- package/esm/commands/aws/ec2/allow-ip/utils.d.ts +189 -0
- package/esm/commands/aws/ec2/allow-ip/utils.js +363 -0
- package/esm/commands/aws/iam/admin-group.d.ts +55 -0
- package/esm/commands/aws/iam/admin-group.js +104 -0
- package/esm/commands/aws/iam/break-glass/handler.d.ts +7 -0
- package/esm/commands/aws/iam/break-glass/handler.js +124 -0
- package/esm/commands/aws/iam/break-glass/index.d.ts +2 -0
- package/esm/commands/aws/iam/break-glass/index.js +4 -0
- package/esm/commands/aws/iam/break-glass/schema.d.ts +25 -0
- package/esm/commands/aws/iam/break-glass/schema.js +19 -0
- package/esm/commands/aws/iam/check-admin/handler.d.ts +5 -0
- package/esm/commands/aws/iam/check-admin/handler.js +86 -0
- package/esm/commands/aws/iam/check-admin/index.d.ts +2 -0
- package/esm/commands/aws/iam/check-admin/index.js +4 -0
- package/esm/commands/aws/iam/check-admin/schema.d.ts +19 -0
- package/esm/commands/aws/iam/check-admin/schema.js +17 -0
- package/esm/commands/aws/iam/policies/s3-restrictions-deny-non-s3-services.json +20 -0
- package/esm/commands/aws/iam/policies/sts-federation.json +11 -0
- package/esm/commands/aws/iam/policies/user-admins-deny-list.json +175 -0
- package/esm/commands/aws/iam/policies/user-admins-deny-regions-list.json +41 -0
- package/esm/commands/aws/iam/policies/user-admins-self-service-iam.json +56 -0
- package/esm/commands/aws/iam/policies/user-admins-write-list.json +117 -0
- package/esm/commands/aws/iam/remove-admin/handler.d.ts +6 -0
- package/esm/commands/aws/iam/remove-admin/handler.js +117 -0
- package/esm/commands/aws/iam/remove-admin/index.d.ts +2 -0
- package/esm/commands/aws/iam/remove-admin/index.js +4 -0
- package/esm/commands/aws/iam/remove-admin/schema.d.ts +28 -0
- package/esm/commands/aws/iam/remove-admin/schema.js +20 -0
- package/esm/commands/aws/iam/setup-acl/handler.d.ts +6 -0
- package/esm/commands/aws/iam/setup-acl/handler.js +224 -0
- package/esm/commands/aws/iam/setup-acl/index.d.ts +3 -0
- package/esm/commands/aws/iam/setup-acl/index.js +4 -0
- package/esm/commands/aws/iam/setup-acl/schema.d.ts +24 -0
- package/esm/commands/aws/iam/setup-acl/schema.js +18 -0
- package/esm/commands/aws/iam/setup-acl/utils.d.ts +61 -0
- package/esm/commands/aws/iam/setup-acl/utils.js +298 -0
- package/esm/commands/aws/iam/users/handler.d.ts +5 -0
- package/esm/commands/aws/iam/users/handler.js +56 -0
- package/esm/commands/aws/iam/users/index.d.ts +3 -0
- package/esm/commands/aws/iam/users/index.js +4 -0
- package/esm/commands/aws/iam/users/schema.d.ts +18 -0
- package/esm/commands/aws/iam/users/schema.js +16 -0
- package/esm/commands/aws/iam/users/utils.d.ts +119 -0
- package/esm/commands/aws/iam/users/utils.js +440 -0
- package/esm/commands/aws/index.d.ts +14 -0
- package/esm/commands/aws/index.js +142 -0
- package/esm/commands/aws/route53/add-record/handler.d.ts +36 -0
- package/esm/commands/aws/route53/add-record/handler.js +258 -0
- package/esm/commands/aws/route53/add-record/index.d.ts +3 -0
- package/esm/commands/aws/route53/add-record/index.js +4 -0
- package/esm/commands/aws/route53/add-record/schema.d.ts +45 -0
- package/esm/commands/aws/route53/add-record/schema.js +40 -0
- package/esm/commands/aws/route53/add-record/utils.d.ts +216 -0
- package/esm/commands/aws/route53/add-record/utils.js +389 -0
- package/esm/commands/aws/route53/remove-record/handler.d.ts +6 -0
- package/esm/commands/aws/route53/remove-record/handler.js +111 -0
- package/esm/commands/aws/route53/remove-record/index.d.ts +2 -0
- package/esm/commands/aws/route53/remove-record/index.js +3 -0
- package/esm/commands/aws/route53/remove-record/schema.d.ts +30 -0
- package/esm/commands/aws/route53/remove-record/schema.js +21 -0
- package/esm/commands/aws/schema.d.ts +13 -0
- package/esm/commands/aws/schema.js +16 -0
- package/esm/commands/aws/ses/send-email/handler.d.ts +5 -0
- package/esm/commands/aws/ses/send-email/handler.js +70 -0
- package/esm/commands/aws/ses/send-email/index.d.ts +3 -0
- package/esm/commands/aws/ses/send-email/index.js +4 -0
- package/esm/commands/aws/ses/send-email/schema.d.ts +39 -0
- package/esm/commands/aws/ses/send-email/schema.js +23 -0
- package/esm/commands/aws/ses/send-email/utils.d.ts +47 -0
- package/esm/commands/aws/ses/send-email/utils.js +84 -0
- package/esm/commands/aws/ses/smtp-password.d.ts +21 -0
- package/esm/commands/aws/ses/smtp-password.js +69 -0
- package/esm/commands/aws/utils/exec-aws.d.ts +79 -0
- package/esm/commands/aws/utils/exec-aws.js +137 -0
- package/esm/commands/aws/utils/resolve-policy-path.d.ts +8 -0
- package/esm/commands/aws/utils/resolve-policy-path.js +14 -0
- package/esm/commands/aws/utils/resolve-profile.d.ts +28 -0
- package/esm/commands/aws/utils/resolve-profile.js +88 -0
- package/esm/commands/aws/utils/tty.d.ts +24 -0
- package/esm/commands/aws/utils/tty.js +51 -0
- package/esm/commands/db/create-readonly-user/handler.d.ts +5 -0
- package/esm/commands/db/create-readonly-user/handler.js +251 -0
- package/esm/commands/db/create-readonly-user/index.d.ts +3 -0
- package/esm/commands/db/create-readonly-user/index.js +4 -0
- package/esm/commands/db/create-readonly-user/mysql.d.ts +33 -0
- package/esm/commands/db/create-readonly-user/mysql.js +98 -0
- package/esm/commands/db/create-readonly-user/postgres.d.ts +31 -0
- package/esm/commands/db/create-readonly-user/postgres.js +205 -0
- package/esm/commands/db/create-readonly-user/schema.d.ts +55 -0
- package/esm/commands/db/create-readonly-user/schema.js +35 -0
- package/esm/commands/db/create-readonly-user/utils.d.ts +112 -0
- package/esm/commands/db/create-readonly-user/utils.js +151 -0
- package/esm/commands/db/index.d.ts +6 -0
- package/esm/commands/db/index.js +31 -0
- package/esm/commands/doppler/handler.js +92 -9
- package/esm/commands/doppler/index.d.ts +1 -0
- package/esm/commands/doppler/index.js +6 -41
- package/esm/commands/doppler/schema.d.ts +233 -17
- package/esm/commands/doppler/schema.js +125 -7
- package/esm/commands/doppler/set-secret.d.ts +113 -0
- package/esm/commands/doppler/set-secret.js +370 -0
- package/esm/commands/doppler/utils/exec.js +100 -12
- package/esm/commands/doppler/utils.d.ts +32 -8
- package/esm/commands/doppler/utils.js +396 -30
- package/esm/commands/icons/handler.js +79 -8
- package/esm/commands/icons/index.js +4 -31
- package/esm/commands/icons/schema.d.ts +1 -1
- package/esm/commands/icons/schema.js +97 -15
- package/esm/commands/icons/utils.js +125 -13
- package/esm/commands/index.js +49 -78
- package/esm/commands/schema.js +22 -7
- package/esm/index.js +3 -4
- package/package.json +12 -2
- package/vitest.config.ts +11 -0
- package/cjs/__chunks/4GFJUCSP.cjs +0 -52
- package/cjs/__chunks/4SFWHCB3.cjs +0 -133
- package/cjs/__chunks/B2KFW7T7.cjs +0 -1
- package/cjs/__chunks/EMMC33QA.cjs +0 -401
- package/cjs/__chunks/INFOPAHN.cjs +0 -117
- package/cjs/__chunks/J36P6UNE.cjs +0 -75
- package/cjs/__chunks/NIMXXHJQ.cjs +0 -92
- package/cjs/__chunks/NSRFG4DF.cjs +0 -100
- package/cjs/__chunks/WNJ3ZYLI.cjs +0 -1
- package/cjs/__chunks/ZMDIOZPT.cjs +0 -22
- package/esm/__chunks/46HGXFME.js +0 -0
- package/esm/__chunks/6G4PXXKF.js +0 -75
- package/esm/__chunks/6L5RNR7G.js +0 -100
- package/esm/__chunks/FL7AILGH.js +0 -133
- package/esm/__chunks/HJSXC6HP.js +0 -117
- package/esm/__chunks/O262GK4B.js +0 -401
- package/esm/__chunks/O3CCA76Q.js +0 -22
- package/esm/__chunks/SJXQJ7RS.js +0 -92
- package/esm/__chunks/SNCKIAOR.js +0 -0
- package/esm/__chunks/X3R5PSWH.js +0 -52
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_commands_aws_utils_exec_aws = require("../../utils/exec-aws.cjs");
|
|
3
|
+
const require_commands_aws_ec2_allow_ip_schema = require("./schema.cjs");
|
|
4
|
+
//#region src/commands/aws/ec2/allow-ip/utils.js
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {Object} Ec2Instance
|
|
7
|
+
* @property {string} instanceId
|
|
8
|
+
* @property {string} name
|
|
9
|
+
* @property {string} state
|
|
10
|
+
* @property {string} instanceType
|
|
11
|
+
* @property {string | null} publicIp
|
|
12
|
+
* @property {string[]} securityGroupIds
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* @typedef {Object} SecurityGroup
|
|
16
|
+
* @property {string} groupId
|
|
17
|
+
* @property {string} groupName
|
|
18
|
+
* @property {string} description
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* @typedef {Object} SshIngressRule
|
|
22
|
+
* @property {string} cidrIp
|
|
23
|
+
* @property {string} description
|
|
24
|
+
* @property {number} fromPort
|
|
25
|
+
* @property {number} toPort
|
|
26
|
+
* @property {string} ipProtocol
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* Determine the caller's current public IPv4 address.
|
|
30
|
+
* @returns {Promise<string>}
|
|
31
|
+
*/
|
|
32
|
+
async function getCurrentPublicIp() {
|
|
33
|
+
for (const url of ["https://checkip.amazonaws.com", "https://api.ipify.org"]) try {
|
|
34
|
+
const controller = new AbortController();
|
|
35
|
+
const timeout = setTimeout(() => controller.abort(), 8e3);
|
|
36
|
+
const response = await fetch(url, { signal: controller.signal });
|
|
37
|
+
clearTimeout(timeout);
|
|
38
|
+
if (!response.ok) continue;
|
|
39
|
+
const ip = (await response.text()).trim();
|
|
40
|
+
if (ip && ip.includes(".")) return ip;
|
|
41
|
+
} catch {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
throw new Error("Could not determine your current public IP address");
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* List regions that are opted-in / enabled for the profile.
|
|
48
|
+
* @param {{ profile?: string; region: string; verbose?: boolean }} params
|
|
49
|
+
* @returns {string[]}
|
|
50
|
+
*/
|
|
51
|
+
function listEnabledRegions(params) {
|
|
52
|
+
const { profile, region, verbose } = params;
|
|
53
|
+
const data = require_commands_aws_utils_exec_aws.runAws({
|
|
54
|
+
profile,
|
|
55
|
+
region,
|
|
56
|
+
args: [
|
|
57
|
+
"ec2",
|
|
58
|
+
"describe-regions",
|
|
59
|
+
"--query",
|
|
60
|
+
"Regions[?OptInStatus!=`not-opted-in`].RegionName"
|
|
61
|
+
],
|
|
62
|
+
verbose
|
|
63
|
+
});
|
|
64
|
+
return (Array.isArray(data) ? data : []).map((value) => String(value)).sort();
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* List non-terminated EC2 instances in a region.
|
|
68
|
+
* @param {{ profile?: string; region: string; verbose?: boolean }} params
|
|
69
|
+
* @returns {Ec2Instance[]}
|
|
70
|
+
*/
|
|
71
|
+
function listInstances(params) {
|
|
72
|
+
const { profile, region, verbose } = params;
|
|
73
|
+
const data = require_commands_aws_utils_exec_aws.runAws({
|
|
74
|
+
profile,
|
|
75
|
+
region,
|
|
76
|
+
args: ["ec2", "describe-instances"],
|
|
77
|
+
verbose
|
|
78
|
+
});
|
|
79
|
+
/** @type {Ec2Instance[]} */
|
|
80
|
+
const instances = [];
|
|
81
|
+
for (const reservation of data.Reservations ?? []) for (const raw of reservation.Instances ?? []) {
|
|
82
|
+
const state = raw.State?.Name ?? "unknown";
|
|
83
|
+
if (state === "terminated" || state === "shutting-down") continue;
|
|
84
|
+
let name = "";
|
|
85
|
+
for (const tag of raw.Tags ?? []) if (tag.Key === "Name") {
|
|
86
|
+
name = tag.Value ?? "";
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
const securityGroupIds = (raw.SecurityGroups ?? []).map((group) => group.GroupId).filter((id) => Boolean(id));
|
|
90
|
+
instances.push({
|
|
91
|
+
instanceId: raw.InstanceId,
|
|
92
|
+
name,
|
|
93
|
+
state,
|
|
94
|
+
instanceType: raw.InstanceType ?? "unknown",
|
|
95
|
+
publicIp: raw.PublicIpAddress ?? null,
|
|
96
|
+
securityGroupIds
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
instances.sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase()) || a.instanceId.localeCompare(b.instanceId));
|
|
100
|
+
return instances;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Describe security groups by id.
|
|
104
|
+
* @param {{ profile?: string; region: string; groupIds: string[]; verbose?: boolean }} params
|
|
105
|
+
* @returns {SecurityGroup[]}
|
|
106
|
+
*/
|
|
107
|
+
function describeSecurityGroups(params) {
|
|
108
|
+
const { profile, region, groupIds, verbose } = params;
|
|
109
|
+
if (groupIds.length === 0) return [];
|
|
110
|
+
/** @type {SecurityGroup[]} */
|
|
111
|
+
const groups = (require_commands_aws_utils_exec_aws.runAws({
|
|
112
|
+
profile,
|
|
113
|
+
region,
|
|
114
|
+
args: [
|
|
115
|
+
"ec2",
|
|
116
|
+
"describe-security-groups",
|
|
117
|
+
"--group-ids",
|
|
118
|
+
...groupIds
|
|
119
|
+
],
|
|
120
|
+
verbose
|
|
121
|
+
}).SecurityGroups ?? []).map((raw) => ({
|
|
122
|
+
groupId: raw.GroupId,
|
|
123
|
+
groupName: raw.GroupName ?? "",
|
|
124
|
+
description: raw.Description ?? ""
|
|
125
|
+
}));
|
|
126
|
+
groups.sort((a, b) => a.groupName.localeCompare(b.groupName));
|
|
127
|
+
return groups;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Load full details for a single security group.
|
|
131
|
+
* @param {{ profile?: string; region: string; groupId: string; verbose?: boolean }} params
|
|
132
|
+
* @returns {any | null}
|
|
133
|
+
*/
|
|
134
|
+
function getSecurityGroupDetails(params) {
|
|
135
|
+
const { profile, region, groupId, verbose } = params;
|
|
136
|
+
const securityGroups = require_commands_aws_utils_exec_aws.runAws({
|
|
137
|
+
profile,
|
|
138
|
+
region,
|
|
139
|
+
args: [
|
|
140
|
+
"ec2",
|
|
141
|
+
"describe-security-groups",
|
|
142
|
+
"--group-ids",
|
|
143
|
+
groupId
|
|
144
|
+
],
|
|
145
|
+
verbose
|
|
146
|
+
}).SecurityGroups ?? [];
|
|
147
|
+
if (securityGroups.length === 0) return null;
|
|
148
|
+
return securityGroups[0];
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* @param {string} cidrIp
|
|
152
|
+
* @returns {boolean}
|
|
153
|
+
*/
|
|
154
|
+
function isSingleHostCidr(cidrIp) {
|
|
155
|
+
return cidrIp.endsWith("/32") && cidrIp !== "0.0.0.0/0";
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* @param {any} permission
|
|
159
|
+
* @returns {boolean}
|
|
160
|
+
*/
|
|
161
|
+
function portAllowsSsh(permission) {
|
|
162
|
+
const protocol = permission.IpProtocol;
|
|
163
|
+
if (protocol !== "tcp" && protocol !== "6") return false;
|
|
164
|
+
const fromPort = permission.FromPort;
|
|
165
|
+
const toPort = permission.ToPort;
|
|
166
|
+
if (fromPort === void 0 && toPort === void 0) return true;
|
|
167
|
+
if (fromPort === void 0 || toPort === void 0) return false;
|
|
168
|
+
return fromPort <= 22 && 22 <= toPort;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Extract single-host SSH ingress rules (port 22, /32) from a security group.
|
|
172
|
+
* @param {any} securityGroup
|
|
173
|
+
* @returns {SshIngressRule[]}
|
|
174
|
+
*/
|
|
175
|
+
function listSshIngressRules(securityGroup) {
|
|
176
|
+
/** @type {SshIngressRule[]} */
|
|
177
|
+
const rules = [];
|
|
178
|
+
for (const permission of securityGroup.IpPermissions ?? []) {
|
|
179
|
+
if (!portAllowsSsh(permission)) continue;
|
|
180
|
+
const fromPort = permission.FromPort ?? 22;
|
|
181
|
+
const toPort = permission.ToPort ?? 22;
|
|
182
|
+
const ipProtocol = permission.IpProtocol ?? "tcp";
|
|
183
|
+
for (const ipRange of permission.IpRanges ?? []) {
|
|
184
|
+
const cidrIp = ipRange.CidrIp;
|
|
185
|
+
if (!cidrIp || !isSingleHostCidr(cidrIp)) continue;
|
|
186
|
+
rules.push({
|
|
187
|
+
cidrIp,
|
|
188
|
+
description: ipRange.Description ?? "",
|
|
189
|
+
fromPort,
|
|
190
|
+
toPort,
|
|
191
|
+
ipProtocol
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return rules;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Derive a first name from the IAM ARN or profile (md-{name}-...).
|
|
199
|
+
* @param {{ profile?: string; identity: { Arn?: string } }} params
|
|
200
|
+
* @returns {string}
|
|
201
|
+
*/
|
|
202
|
+
function extractRoamingFirstName(params) {
|
|
203
|
+
const { profile, identity } = params;
|
|
204
|
+
const arn = identity.Arn ?? "";
|
|
205
|
+
const username = arn.includes("/") ? arn.split("/").pop() ?? "" : "";
|
|
206
|
+
for (const candidate of [username, profile ?? ""]) {
|
|
207
|
+
if (!candidate) continue;
|
|
208
|
+
const match = /^md-([^-]+)-/.exec(candidate);
|
|
209
|
+
if (match && match[1]) return match[1].charAt(0).toUpperCase() + match[1].slice(1).toLowerCase();
|
|
210
|
+
}
|
|
211
|
+
return require_commands_aws_ec2_allow_ip_schema.DEFAULT_ROAMING_NAME;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* @param {string} firstName
|
|
215
|
+
* @returns {string}
|
|
216
|
+
*/
|
|
217
|
+
function roamingRuleDescription(firstName) {
|
|
218
|
+
return `${firstName} Roaming`;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Find an existing rule whose description matches the roaming rule name.
|
|
222
|
+
* @param {SshIngressRule[]} sshRules
|
|
223
|
+
* @param {string} ruleDescription
|
|
224
|
+
* @returns {SshIngressRule | null}
|
|
225
|
+
*/
|
|
226
|
+
function resolveRoamingRule(sshRules, ruleDescription) {
|
|
227
|
+
const target = ruleDescription.toLowerCase();
|
|
228
|
+
for (const rule of sshRules) if (rule.description.trim().toLowerCase() === target) return rule;
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Find an existing rule that already allows the given CIDR.
|
|
233
|
+
* @param {SshIngressRule[]} sshRules
|
|
234
|
+
* @param {string} newCidr
|
|
235
|
+
* @returns {SshIngressRule | null}
|
|
236
|
+
*/
|
|
237
|
+
function ruleAlreadyAllowsIp(sshRules, newCidr) {
|
|
238
|
+
for (const rule of sshRules) if (rule.cidrIp === newCidr) return rule;
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* @param {{
|
|
243
|
+
* cidrIp: string;
|
|
244
|
+
* description: string;
|
|
245
|
+
* fromPort?: number;
|
|
246
|
+
* toPort?: number;
|
|
247
|
+
* ipProtocol?: string;
|
|
248
|
+
* }} params
|
|
249
|
+
* @returns {string} JSON string for the --ip-permissions argument
|
|
250
|
+
*/
|
|
251
|
+
function buildIpPermissions(params) {
|
|
252
|
+
const { cidrIp, description, fromPort = 22, toPort = 22, ipProtocol = "tcp" } = params;
|
|
253
|
+
return JSON.stringify([{
|
|
254
|
+
IpProtocol: ipProtocol,
|
|
255
|
+
FromPort: fromPort,
|
|
256
|
+
ToPort: toPort,
|
|
257
|
+
IpRanges: [{
|
|
258
|
+
CidrIp: cidrIp,
|
|
259
|
+
Description: description
|
|
260
|
+
}]
|
|
261
|
+
}]);
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Authorize a new SSH ingress rule.
|
|
265
|
+
* @param {{
|
|
266
|
+
* profile?: string;
|
|
267
|
+
* region: string;
|
|
268
|
+
* groupId: string;
|
|
269
|
+
* cidrIp: string;
|
|
270
|
+
* description: string;
|
|
271
|
+
* fromPort?: number;
|
|
272
|
+
* toPort?: number;
|
|
273
|
+
* ipProtocol?: string;
|
|
274
|
+
* verbose?: boolean;
|
|
275
|
+
* }} params
|
|
276
|
+
*/
|
|
277
|
+
function authorizeRule(params) {
|
|
278
|
+
const { profile, region, groupId, verbose, ...rule } = params;
|
|
279
|
+
require_commands_aws_utils_exec_aws.runAws({
|
|
280
|
+
profile,
|
|
281
|
+
region,
|
|
282
|
+
args: [
|
|
283
|
+
"ec2",
|
|
284
|
+
"authorize-security-group-ingress",
|
|
285
|
+
"--group-id",
|
|
286
|
+
groupId,
|
|
287
|
+
"--ip-permissions",
|
|
288
|
+
buildIpPermissions(rule)
|
|
289
|
+
],
|
|
290
|
+
expectJson: false,
|
|
291
|
+
verbose
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Revoke an existing SSH ingress rule.
|
|
296
|
+
* @param {{
|
|
297
|
+
* profile?: string;
|
|
298
|
+
* region: string;
|
|
299
|
+
* groupId: string;
|
|
300
|
+
* rule: SshIngressRule;
|
|
301
|
+
* verbose?: boolean;
|
|
302
|
+
* }} params
|
|
303
|
+
*/
|
|
304
|
+
function revokeRule(params) {
|
|
305
|
+
const { profile, region, groupId, rule, verbose } = params;
|
|
306
|
+
require_commands_aws_utils_exec_aws.runAws({
|
|
307
|
+
profile,
|
|
308
|
+
region,
|
|
309
|
+
args: [
|
|
310
|
+
"ec2",
|
|
311
|
+
"revoke-security-group-ingress",
|
|
312
|
+
"--group-id",
|
|
313
|
+
groupId,
|
|
314
|
+
"--ip-permissions",
|
|
315
|
+
buildIpPermissions({
|
|
316
|
+
cidrIp: rule.cidrIp,
|
|
317
|
+
description: rule.description,
|
|
318
|
+
fromPort: rule.fromPort,
|
|
319
|
+
toPort: rule.toPort,
|
|
320
|
+
ipProtocol: rule.ipProtocol
|
|
321
|
+
})
|
|
322
|
+
],
|
|
323
|
+
expectJson: false,
|
|
324
|
+
verbose
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* @param {Ec2Instance} instance
|
|
329
|
+
* @returns {string}
|
|
330
|
+
*/
|
|
331
|
+
function instanceLabel(instance) {
|
|
332
|
+
const publicIp = instance.publicIp || "no public IP";
|
|
333
|
+
const name = instance.name || "(no name)";
|
|
334
|
+
return `${instance.instanceId} ${name} ${instance.state} ${instance.instanceType} ${publicIp}`;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* @param {SecurityGroup} group
|
|
338
|
+
* @returns {string}
|
|
339
|
+
*/
|
|
340
|
+
function securityGroupLabel(group) {
|
|
341
|
+
return `${group.groupId} ${group.groupName} ${group.description}`;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* @param {SshIngressRule} rule
|
|
345
|
+
* @returns {string}
|
|
346
|
+
*/
|
|
347
|
+
function sshRuleLabel(rule) {
|
|
348
|
+
const description = rule.description || "(no description)";
|
|
349
|
+
return `${rule.cidrIp} ${description}`;
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Print single-host SSH rules using the given logger.
|
|
353
|
+
* @param {SshIngressRule[]} sshRules
|
|
354
|
+
* @param {(message: string) => void} [log]
|
|
355
|
+
*/
|
|
356
|
+
function printSshRules(sshRules, log = console.log) {
|
|
357
|
+
if (sshRules.length === 0) {
|
|
358
|
+
log(" (no single-host SSH rules on port 22)");
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
for (const rule of sshRules) log(` - ${sshRuleLabel(rule)}`);
|
|
362
|
+
}
|
|
363
|
+
//#endregion
|
|
364
|
+
exports.authorizeRule = authorizeRule;
|
|
365
|
+
exports.describeSecurityGroups = describeSecurityGroups;
|
|
366
|
+
exports.extractRoamingFirstName = extractRoamingFirstName;
|
|
367
|
+
exports.getCurrentPublicIp = getCurrentPublicIp;
|
|
368
|
+
exports.getSecurityGroupDetails = getSecurityGroupDetails;
|
|
369
|
+
exports.instanceLabel = instanceLabel;
|
|
370
|
+
exports.listEnabledRegions = listEnabledRegions;
|
|
371
|
+
exports.listInstances = listInstances;
|
|
372
|
+
exports.listSshIngressRules = listSshIngressRules;
|
|
373
|
+
exports.printSshRules = printSshRules;
|
|
374
|
+
exports.resolveRoamingRule = resolveRoamingRule;
|
|
375
|
+
exports.revokeRule = revokeRule;
|
|
376
|
+
exports.roamingRuleDescription = roamingRuleDescription;
|
|
377
|
+
exports.ruleAlreadyAllowsIp = ruleAlreadyAllowsIp;
|
|
378
|
+
exports.securityGroupLabel = securityGroupLabel;
|
|
379
|
+
exports.sshRuleLabel = sshRuleLabel;
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {Object} Ec2Instance
|
|
3
|
+
* @property {string} instanceId
|
|
4
|
+
* @property {string} name
|
|
5
|
+
* @property {string} state
|
|
6
|
+
* @property {string} instanceType
|
|
7
|
+
* @property {string | null} publicIp
|
|
8
|
+
* @property {string[]} securityGroupIds
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* @typedef {Object} SecurityGroup
|
|
12
|
+
* @property {string} groupId
|
|
13
|
+
* @property {string} groupName
|
|
14
|
+
* @property {string} description
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {Object} SshIngressRule
|
|
18
|
+
* @property {string} cidrIp
|
|
19
|
+
* @property {string} description
|
|
20
|
+
* @property {number} fromPort
|
|
21
|
+
* @property {number} toPort
|
|
22
|
+
* @property {string} ipProtocol
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* Determine the caller's current public IPv4 address.
|
|
26
|
+
* @returns {Promise<string>}
|
|
27
|
+
*/
|
|
28
|
+
export function getCurrentPublicIp(): Promise<string>;
|
|
29
|
+
/**
|
|
30
|
+
* List regions that are opted-in / enabled for the profile.
|
|
31
|
+
* @param {{ profile?: string; region: string; verbose?: boolean }} params
|
|
32
|
+
* @returns {string[]}
|
|
33
|
+
*/
|
|
34
|
+
export function listEnabledRegions(params: {
|
|
35
|
+
profile?: string;
|
|
36
|
+
region: string;
|
|
37
|
+
verbose?: boolean;
|
|
38
|
+
}): string[];
|
|
39
|
+
/**
|
|
40
|
+
* List non-terminated EC2 instances in a region.
|
|
41
|
+
* @param {{ profile?: string; region: string; verbose?: boolean }} params
|
|
42
|
+
* @returns {Ec2Instance[]}
|
|
43
|
+
*/
|
|
44
|
+
export function listInstances(params: {
|
|
45
|
+
profile?: string;
|
|
46
|
+
region: string;
|
|
47
|
+
verbose?: boolean;
|
|
48
|
+
}): Ec2Instance[];
|
|
49
|
+
/**
|
|
50
|
+
* Describe security groups by id.
|
|
51
|
+
* @param {{ profile?: string; region: string; groupIds: string[]; verbose?: boolean }} params
|
|
52
|
+
* @returns {SecurityGroup[]}
|
|
53
|
+
*/
|
|
54
|
+
export function describeSecurityGroups(params: {
|
|
55
|
+
profile?: string;
|
|
56
|
+
region: string;
|
|
57
|
+
groupIds: string[];
|
|
58
|
+
verbose?: boolean;
|
|
59
|
+
}): SecurityGroup[];
|
|
60
|
+
/**
|
|
61
|
+
* Load full details for a single security group.
|
|
62
|
+
* @param {{ profile?: string; region: string; groupId: string; verbose?: boolean }} params
|
|
63
|
+
* @returns {any | null}
|
|
64
|
+
*/
|
|
65
|
+
export function getSecurityGroupDetails(params: {
|
|
66
|
+
profile?: string;
|
|
67
|
+
region: string;
|
|
68
|
+
groupId: string;
|
|
69
|
+
verbose?: boolean;
|
|
70
|
+
}): any | null;
|
|
71
|
+
/**
|
|
72
|
+
* Extract single-host SSH ingress rules (port 22, /32) from a security group.
|
|
73
|
+
* @param {any} securityGroup
|
|
74
|
+
* @returns {SshIngressRule[]}
|
|
75
|
+
*/
|
|
76
|
+
export function listSshIngressRules(securityGroup: any): SshIngressRule[];
|
|
77
|
+
/**
|
|
78
|
+
* Derive a first name from the IAM ARN or profile (md-{name}-...).
|
|
79
|
+
* @param {{ profile?: string; identity: { Arn?: string } }} params
|
|
80
|
+
* @returns {string}
|
|
81
|
+
*/
|
|
82
|
+
export function extractRoamingFirstName(params: {
|
|
83
|
+
profile?: string;
|
|
84
|
+
identity: {
|
|
85
|
+
Arn?: string;
|
|
86
|
+
};
|
|
87
|
+
}): string;
|
|
88
|
+
/**
|
|
89
|
+
* @param {string} firstName
|
|
90
|
+
* @returns {string}
|
|
91
|
+
*/
|
|
92
|
+
export function roamingRuleDescription(firstName: string): string;
|
|
93
|
+
/**
|
|
94
|
+
* Find an existing rule whose description matches the roaming rule name.
|
|
95
|
+
* @param {SshIngressRule[]} sshRules
|
|
96
|
+
* @param {string} ruleDescription
|
|
97
|
+
* @returns {SshIngressRule | null}
|
|
98
|
+
*/
|
|
99
|
+
export function resolveRoamingRule(sshRules: SshIngressRule[], ruleDescription: string): SshIngressRule | null;
|
|
100
|
+
/**
|
|
101
|
+
* Find an existing rule that already allows the given CIDR.
|
|
102
|
+
* @param {SshIngressRule[]} sshRules
|
|
103
|
+
* @param {string} newCidr
|
|
104
|
+
* @returns {SshIngressRule | null}
|
|
105
|
+
*/
|
|
106
|
+
export function ruleAlreadyAllowsIp(sshRules: SshIngressRule[], newCidr: string): SshIngressRule | null;
|
|
107
|
+
/**
|
|
108
|
+
* Authorize a new SSH ingress rule.
|
|
109
|
+
* @param {{
|
|
110
|
+
* profile?: string;
|
|
111
|
+
* region: string;
|
|
112
|
+
* groupId: string;
|
|
113
|
+
* cidrIp: string;
|
|
114
|
+
* description: string;
|
|
115
|
+
* fromPort?: number;
|
|
116
|
+
* toPort?: number;
|
|
117
|
+
* ipProtocol?: string;
|
|
118
|
+
* verbose?: boolean;
|
|
119
|
+
* }} params
|
|
120
|
+
*/
|
|
121
|
+
export function authorizeRule(params: {
|
|
122
|
+
profile?: string;
|
|
123
|
+
region: string;
|
|
124
|
+
groupId: string;
|
|
125
|
+
cidrIp: string;
|
|
126
|
+
description: string;
|
|
127
|
+
fromPort?: number;
|
|
128
|
+
toPort?: number;
|
|
129
|
+
ipProtocol?: string;
|
|
130
|
+
verbose?: boolean;
|
|
131
|
+
}): void;
|
|
132
|
+
/**
|
|
133
|
+
* Revoke an existing SSH ingress rule.
|
|
134
|
+
* @param {{
|
|
135
|
+
* profile?: string;
|
|
136
|
+
* region: string;
|
|
137
|
+
* groupId: string;
|
|
138
|
+
* rule: SshIngressRule;
|
|
139
|
+
* verbose?: boolean;
|
|
140
|
+
* }} params
|
|
141
|
+
*/
|
|
142
|
+
export function revokeRule(params: {
|
|
143
|
+
profile?: string;
|
|
144
|
+
region: string;
|
|
145
|
+
groupId: string;
|
|
146
|
+
rule: SshIngressRule;
|
|
147
|
+
verbose?: boolean;
|
|
148
|
+
}): void;
|
|
149
|
+
/**
|
|
150
|
+
* @param {Ec2Instance} instance
|
|
151
|
+
* @returns {string}
|
|
152
|
+
*/
|
|
153
|
+
export function instanceLabel(instance: Ec2Instance): string;
|
|
154
|
+
/**
|
|
155
|
+
* @param {SecurityGroup} group
|
|
156
|
+
* @returns {string}
|
|
157
|
+
*/
|
|
158
|
+
export function securityGroupLabel(group: SecurityGroup): string;
|
|
159
|
+
/**
|
|
160
|
+
* @param {SshIngressRule} rule
|
|
161
|
+
* @returns {string}
|
|
162
|
+
*/
|
|
163
|
+
export function sshRuleLabel(rule: SshIngressRule): string;
|
|
164
|
+
/**
|
|
165
|
+
* Print single-host SSH rules using the given logger.
|
|
166
|
+
* @param {SshIngressRule[]} sshRules
|
|
167
|
+
* @param {(message: string) => void} [log]
|
|
168
|
+
*/
|
|
169
|
+
export function printSshRules(sshRules: SshIngressRule[], log?: (message: string) => void): void;
|
|
170
|
+
export type Ec2Instance = {
|
|
171
|
+
instanceId: string;
|
|
172
|
+
name: string;
|
|
173
|
+
state: string;
|
|
174
|
+
instanceType: string;
|
|
175
|
+
publicIp: string | null;
|
|
176
|
+
securityGroupIds: string[];
|
|
177
|
+
};
|
|
178
|
+
export type SecurityGroup = {
|
|
179
|
+
groupId: string;
|
|
180
|
+
groupName: string;
|
|
181
|
+
description: string;
|
|
182
|
+
};
|
|
183
|
+
export type SshIngressRule = {
|
|
184
|
+
cidrIp: string;
|
|
185
|
+
description: string;
|
|
186
|
+
fromPort: number;
|
|
187
|
+
toPort: number;
|
|
188
|
+
ipProtocol: string;
|
|
189
|
+
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_rolldown_runtime = require("../../../__chunks/VH7oDXx4.cjs");
|
|
3
|
+
const require_commands_aws_utils_exec_aws = require("../utils/exec-aws.cjs");
|
|
4
|
+
let chalk = require("chalk");
|
|
5
|
+
chalk = require_rolldown_runtime.__toESM(chalk, 1);
|
|
6
|
+
let child_process = require("child_process");
|
|
7
|
+
//#region src/commands/aws/iam/admin-group.js
|
|
8
|
+
/**
|
|
9
|
+
* The IAM group that grants break-glass admin access and should normally be empty.
|
|
10
|
+
*/
|
|
11
|
+
const ADMIN_GROUP_NAME = "acl-admin-do-not-use";
|
|
12
|
+
const VAULT_DURATION = process.env.AWS_VAULT_DURATION ?? "15m";
|
|
13
|
+
/**
|
|
14
|
+
* A function bound to a profile's working credential mode (direct or aws-vault).
|
|
15
|
+
* @typedef {(args: string[], options?: { expectJson?: boolean }) => any} ProfileRunner
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* List aws-vault profiles that have stored credentials.
|
|
19
|
+
* @returns {string[]}
|
|
20
|
+
*/
|
|
21
|
+
function listVaultProfiles() {
|
|
22
|
+
const result = (0, child_process.spawnSync)("aws-vault", ["list", "--credentials"], { encoding: "utf-8" });
|
|
23
|
+
if (result.status !== 0) return [];
|
|
24
|
+
return (result.stdout ?? "").split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Resolve which profiles to scan for admin-group commands.
|
|
28
|
+
* Uses `--profile`, then `AWS_PROFILE`, for a single profile unless `--all` is set.
|
|
29
|
+
* @param {{ profile?: string; all?: boolean }} params
|
|
30
|
+
* @returns {string[]}
|
|
31
|
+
*/
|
|
32
|
+
function resolveAdminScanProfiles({ profile, all = false }) {
|
|
33
|
+
const targetProfile = profile ?? process.env.AWS_PROFILE;
|
|
34
|
+
if (!all && targetProfile) return [targetProfile];
|
|
35
|
+
const profiles = listVaultProfiles();
|
|
36
|
+
if (profiles.length === 0) throw new Error("No aws-vault profiles with credentials found.");
|
|
37
|
+
return profiles;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* @param {{ Users?: Array<{ UserName: string }> }} group
|
|
41
|
+
* @returns {string[]}
|
|
42
|
+
*/
|
|
43
|
+
function groupUserNames(group) {
|
|
44
|
+
return (group.Users ?? []).map((user) => user.UserName);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Resolve a working credential runner for a profile and read the admin group.
|
|
48
|
+
* Tries stored credentials first, then falls back to `aws-vault exec`.
|
|
49
|
+
* The returned `run` reuses whichever mode worked, so callers can perform
|
|
50
|
+
* follow-up mutations (e.g. remove-user-from-group) with the same credentials.
|
|
51
|
+
* @param {{ profile: string; verbose?: boolean }} params
|
|
52
|
+
* @returns {{ accountId: string; arn: string; users: string[]; run: ProfileRunner } | null} Null when the profile is skipped
|
|
53
|
+
*/
|
|
54
|
+
function resolveProfileScan(params) {
|
|
55
|
+
const { profile, verbose = false } = params;
|
|
56
|
+
const idArgs = ["sts", "get-caller-identity"];
|
|
57
|
+
const groupArgs = [
|
|
58
|
+
"iam",
|
|
59
|
+
"get-group",
|
|
60
|
+
"--group-name",
|
|
61
|
+
ADMIN_GROUP_NAME
|
|
62
|
+
];
|
|
63
|
+
/** @type {ProfileRunner} */
|
|
64
|
+
const directRun = (args, options = {}) => require_commands_aws_utils_exec_aws.runAws({
|
|
65
|
+
profile,
|
|
66
|
+
args,
|
|
67
|
+
expectJson: options.expectJson ?? true,
|
|
68
|
+
verbose
|
|
69
|
+
});
|
|
70
|
+
/** @type {ProfileRunner} */
|
|
71
|
+
const vaultRun = (args, options = {}) => require_commands_aws_utils_exec_aws.runAwsVault({
|
|
72
|
+
profile,
|
|
73
|
+
args,
|
|
74
|
+
duration: VAULT_DURATION,
|
|
75
|
+
expectJson: options.expectJson ?? true,
|
|
76
|
+
verbose
|
|
77
|
+
});
|
|
78
|
+
try {
|
|
79
|
+
const identity = directRun(idArgs);
|
|
80
|
+
const group = directRun(groupArgs);
|
|
81
|
+
return {
|
|
82
|
+
accountId: identity.Account,
|
|
83
|
+
arn: identity.Arn,
|
|
84
|
+
users: groupUserNames(group),
|
|
85
|
+
run: directRun
|
|
86
|
+
};
|
|
87
|
+
} catch (directError) {
|
|
88
|
+
try {
|
|
89
|
+
const identity = vaultRun(idArgs);
|
|
90
|
+
const group = vaultRun(groupArgs);
|
|
91
|
+
return {
|
|
92
|
+
accountId: identity.Account,
|
|
93
|
+
arn: identity.Arn,
|
|
94
|
+
users: groupUserNames(group),
|
|
95
|
+
run: vaultRun
|
|
96
|
+
};
|
|
97
|
+
} catch {
|
|
98
|
+
if (verbose) {
|
|
99
|
+
const reason = directError instanceof Error ? directError.message.split("\n")[0] ?? "" : String(directError);
|
|
100
|
+
console.log(chalk.default.dim(`skip ${profile} — ${reason}`));
|
|
101
|
+
}
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
//#endregion
|
|
107
|
+
exports.ADMIN_GROUP_NAME = ADMIN_GROUP_NAME;
|
|
108
|
+
exports.groupUserNames = groupUserNames;
|
|
109
|
+
exports.listVaultProfiles = listVaultProfiles;
|
|
110
|
+
exports.resolveAdminScanProfiles = resolveAdminScanProfiles;
|
|
111
|
+
exports.resolveProfileScan = resolveProfileScan;
|