@prism-d1/cli 1.3.0 → 1.4.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.
Files changed (95) hide show
  1. package/dist/src/aws/advice.d.ts +33 -0
  2. package/dist/src/aws/advice.d.ts.map +1 -0
  3. package/dist/src/aws/advice.js +174 -0
  4. package/dist/src/aws/advice.js.map +1 -0
  5. package/dist/src/aws/check.d.ts +64 -0
  6. package/dist/src/aws/check.d.ts.map +1 -0
  7. package/dist/src/aws/check.js +269 -0
  8. package/dist/src/aws/check.js.map +1 -0
  9. package/dist/src/aws/connect.d.ts +65 -0
  10. package/dist/src/aws/connect.d.ts.map +1 -0
  11. package/dist/src/aws/connect.js +250 -0
  12. package/dist/src/aws/connect.js.map +1 -0
  13. package/dist/src/aws/connection.d.ts +67 -0
  14. package/dist/src/aws/connection.d.ts.map +1 -0
  15. package/dist/src/aws/connection.js +137 -0
  16. package/dist/src/aws/connection.js.map +1 -0
  17. package/dist/src/aws/recommend.d.ts +70 -0
  18. package/dist/src/aws/recommend.d.ts.map +1 -0
  19. package/dist/src/aws/recommend.js +244 -0
  20. package/dist/src/aws/recommend.js.map +1 -0
  21. package/dist/src/aws/run-check.d.ts +31 -0
  22. package/dist/src/aws/run-check.d.ts.map +1 -0
  23. package/dist/src/aws/run-check.js +91 -0
  24. package/dist/src/aws/run-check.js.map +1 -0
  25. package/dist/src/codewatch/results.d.ts +32 -1
  26. package/dist/src/codewatch/results.d.ts.map +1 -1
  27. package/dist/src/codewatch/results.js +4 -0
  28. package/dist/src/codewatch/results.js.map +1 -1
  29. package/dist/src/commands/aws/check.d.ts +25 -0
  30. package/dist/src/commands/aws/check.d.ts.map +1 -0
  31. package/dist/src/commands/aws/check.js +42 -0
  32. package/dist/src/commands/aws/check.js.map +1 -0
  33. package/dist/src/commands/aws/connect.d.ts +16 -0
  34. package/dist/src/commands/aws/connect.d.ts.map +1 -0
  35. package/dist/src/commands/aws/connect.js +39 -0
  36. package/dist/src/commands/aws/connect.js.map +1 -0
  37. package/dist/src/commands/aws/recommend.d.ts +12 -0
  38. package/dist/src/commands/aws/recommend.d.ts.map +1 -0
  39. package/dist/src/commands/aws/recommend.js +21 -0
  40. package/dist/src/commands/aws/recommend.js.map +1 -0
  41. package/dist/src/commands/bedrock-protection/scan-account.d.ts.map +1 -1
  42. package/dist/src/commands/bedrock-protection/scan-account.js +14 -35
  43. package/dist/src/commands/bedrock-protection/scan-account.js.map +1 -1
  44. package/dist/src/commands/bedrock-protection/scan-org.d.ts.map +1 -1
  45. package/dist/src/commands/bedrock-protection/scan-org.js +12 -5
  46. package/dist/src/commands/bedrock-protection/scan-org.js.map +1 -1
  47. package/dist/src/commands/enable/security.d.ts.map +1 -1
  48. package/dist/src/commands/enable/security.js +5 -7
  49. package/dist/src/commands/enable/security.js.map +1 -1
  50. package/dist/src/commands/security/code-review.d.ts.map +1 -1
  51. package/dist/src/commands/security/code-review.js +4 -3
  52. package/dist/src/commands/security/code-review.js.map +1 -1
  53. package/dist/src/commands/security/findings.d.ts.map +1 -1
  54. package/dist/src/commands/security/findings.js +6 -4
  55. package/dist/src/commands/security/findings.js.map +1 -1
  56. package/dist/src/commands/security/pentest.d.ts.map +1 -1
  57. package/dist/src/commands/security/pentest.js +4 -3
  58. package/dist/src/commands/security/pentest.js.map +1 -1
  59. package/dist/src/commands/security/threat-model.d.ts.map +1 -1
  60. package/dist/src/commands/security/threat-model.js +2 -1
  61. package/dist/src/commands/security/threat-model.js.map +1 -1
  62. package/dist/src/commands/security/threats.d.ts.map +1 -1
  63. package/dist/src/commands/security/threats.js +2 -1
  64. package/dist/src/commands/security/threats.js.map +1 -1
  65. package/dist/src/commands/securityagent/setup.d.ts.map +1 -1
  66. package/dist/src/dashboard/aws.d.ts +39 -0
  67. package/dist/src/dashboard/aws.d.ts.map +1 -0
  68. package/dist/src/dashboard/aws.js +35 -0
  69. package/dist/src/dashboard/aws.js.map +1 -0
  70. package/dist/src/dashboard/codewatch.js +1 -1
  71. package/dist/src/dashboard/codewatch.js.map +1 -1
  72. package/dist/src/dashboard/page.d.ts.map +1 -1
  73. package/dist/src/dashboard/page.js +34 -1
  74. package/dist/src/dashboard/page.js.map +1 -1
  75. package/dist/src/dashboard/payload.d.ts +3 -0
  76. package/dist/src/dashboard/payload.d.ts.map +1 -1
  77. package/dist/src/dashboard/payload.js +2 -0
  78. package/dist/src/dashboard/payload.js.map +1 -1
  79. package/dist/src/security/marker.d.ts +1 -1
  80. package/dist/src/security/marker.d.ts.map +1 -1
  81. package/dist/src/security/marker.js +4 -4
  82. package/dist/src/security/marker.js.map +1 -1
  83. package/dist/src/security/setup.d.ts +18 -2
  84. package/dist/src/security/setup.d.ts.map +1 -1
  85. package/dist/src/security/setup.js +28 -14
  86. package/dist/src/security/setup.js.map +1 -1
  87. package/dist/src/utils/audit-account.d.ts +50 -0
  88. package/dist/src/utils/audit-account.d.ts.map +1 -0
  89. package/dist/src/utils/audit-account.js +69 -0
  90. package/dist/src/utils/audit-account.js.map +1 -0
  91. package/dist/src/utils/audit-iam.d.ts +1 -1
  92. package/dist/src/utils/audit-iam.d.ts.map +1 -1
  93. package/dist/src/utils/audit-iam.js +11 -7
  94. package/dist/src/utils/audit-iam.js.map +1 -1
  95. package/package.json +1 -1
@@ -0,0 +1,65 @@
1
+ import type { AwsResult } from '../utils/aws.js';
2
+ import type { RunResult } from '../utils/exec.js';
3
+ export interface ConnectOptions {
4
+ profile?: string;
5
+ region?: string;
6
+ /** Write (or clear) the per-repo file instead of the per-user one. */
7
+ repo?: boolean;
8
+ status?: boolean;
9
+ clear?: boolean;
10
+ }
11
+ export interface ConnectDeps {
12
+ /** A read-only `aws <args>` call as `profile` in `region` (JSON output). */
13
+ aws(args: string[], profile: string, region: string): AwsResult;
14
+ listProfiles(): string[];
15
+ configRegion(profile?: string): string | null;
16
+ git(args: string[]): RunResult;
17
+ env: NodeJS.ProcessEnv;
18
+ home: string;
19
+ cwd(): string;
20
+ isTTY: boolean;
21
+ ask(question: string): Promise<string>;
22
+ log(line?: string): void;
23
+ now(): Date;
24
+ }
25
+ export declare const CONNECT_NOTICE = "Read-only (aws connect): it checks the profile with STS and reads the account alias, Organizations and IAM; nothing in AWS is changed. No credentials are stored, only the profile name and region.";
26
+ export interface Identity {
27
+ account: string;
28
+ arn: string;
29
+ }
30
+ export type OrgRole = {
31
+ kind: 'management';
32
+ orgId: string;
33
+ } | {
34
+ kind: 'member';
35
+ orgId: string;
36
+ } | {
37
+ kind: 'none';
38
+ } | {
39
+ kind: 'unknown';
40
+ reason: string;
41
+ };
42
+ export interface AccessLevel {
43
+ level: 'admin' | 'read-only' | 'unknown';
44
+ basis: string;
45
+ }
46
+ export declare function callerIdentity(d: ConnectDeps, profile: string, region: string): Identity | {
47
+ error: string;
48
+ };
49
+ export declare function accountAlias(d: ConnectDeps, profile: string, region: string): string | null;
50
+ /** Whether the account is its organization's management account. AccessDenied is "unknown", never "no". */
51
+ export declare function orgRole(d: ConnectDeps, profile: string, region: string, account: string): OrgRole;
52
+ /** The principal behind a caller ARN: an assumed role, an IAM user, or root. */
53
+ export declare function principalOf(arn: string): {
54
+ kind: 'role' | 'user' | 'root' | 'other';
55
+ name: string;
56
+ };
57
+ /**
58
+ * Admin or read-only, as far as can be told without simulating policies:
59
+ * the attached managed policies when they can be read, else the role or user
60
+ * name. "unknown" whenever neither is conclusive.
61
+ */
62
+ export declare function accessLevel(d: ConnectDeps, profile: string, region: string, arn: string): AccessLevel;
63
+ /** Runs `aws connect`. Returns the exit code. */
64
+ export declare function awsConnect(o: ConnectOptions, d: ConnectDeps): Promise<number>;
65
+ //# sourceMappingURL=connect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../../src/aws/connect.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAQlD,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,4EAA4E;IAC5E,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAChE,YAAY,IAAI,MAAM,EAAE,CAAC;IACzB,YAAY,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC9C,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC/B,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,IAAI,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACvC,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,GAAG,IAAI,IAAI,CAAC;CACb;AAED,eAAO,MAAM,cAAc,wMAAwM,CAAC;AAEpO,MAAM,WAAW,QAAQ;IAAG,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE;AAC1D,MAAM,MAAM,OAAO,GAAG;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AACzJ,MAAM,WAAW,WAAW;IAAG,KAAK,EAAE,OAAO,GAAG,WAAW,GAAG,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AAIxF,wBAAgB,cAAc,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAK5G;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI3F;AAED,2GAA2G;AAC3G,wBAAgB,OAAO,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAUjG;AAOD,gFAAgF;AAChF,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAOnG;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,WAAW,CAarG;AA8ED,iDAAiD;AACjD,wBAAsB,UAAU,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAsDnF"}
@@ -0,0 +1,250 @@
1
+ /**
2
+ * `prism-cli aws connect`: choose the AWS profile and region the other AWS
3
+ * commands default to, verify them, and save the choice. Read-only in AWS;
4
+ * stores no credentials (see connection.ts for the files and precedence).
5
+ */
6
+ import { existsSync } from 'node:fs';
7
+ import { ensureMarkerIgnored } from '../security/marker.js';
8
+ import { accountChangeWarning, applyConnection, clearConnectionFile, connectionLabel, ENV_CREDENTIAL_VARS, loadConnection, PROFILE_RE, readConnectionFile, REGION_RE, REPO_CONNECTION_PATH, repoConnectionPath, repoRootOf, userConnectionPath, writeConnectionFile, } from './connection.js';
9
+ export const CONNECT_NOTICE = 'Read-only (aws connect): it checks the profile with STS and reads the account alias, Organizations and IAM; nothing in AWS is changed. No credentials are stored, only the profile name and region.';
10
+ const reason = (r) => r.errorCode || r.raw.split('\n').map((l) => l.trim()).filter(Boolean).pop() || 'unknown error';
11
+ export function callerIdentity(d, profile, region) {
12
+ const r = d.aws(['sts', 'get-caller-identity'], profile, region);
13
+ if (!r.ok)
14
+ return { error: reason(r) };
15
+ const account = String(r.json?.Account || '');
16
+ return account ? { account, arn: String(r.json?.Arn || '') } : { error: 'get-caller-identity returned no account' };
17
+ }
18
+ export function accountAlias(d, profile, region) {
19
+ const r = d.aws(['iam', 'list-account-aliases'], profile, region);
20
+ const a = r.ok && Array.isArray(r.json?.AccountAliases) ? r.json.AccountAliases[0] : null;
21
+ return a ? String(a) : null;
22
+ }
23
+ /** Whether the account is its organization's management account. AccessDenied is "unknown", never "no". */
24
+ export function orgRole(d, profile, region, account) {
25
+ const r = d.aws(['organizations', 'describe-organization'], profile, region);
26
+ if (r.ok) {
27
+ const org = r.json?.Organization ?? {};
28
+ // The API names the management account's id field MasterAccountId.
29
+ const managementId = String(org.MasterAccountId || '');
30
+ return managementId === account ? { kind: 'management', orgId: String(org.Id || '') } : { kind: 'member', orgId: String(org.Id || '') };
31
+ }
32
+ if (r.errorCode === 'AWSOrganizationsNotInUseException')
33
+ return { kind: 'none' };
34
+ return { kind: 'unknown', reason: reason(r) };
35
+ }
36
+ const ADMIN_POLICY = /^(AdministratorAccess|PowerUserAccess)$|FullAccess$/;
37
+ const READ_POLICY = /^(ReadOnlyAccess|ViewOnlyAccess|SecurityAudit)$|ReadOnly/;
38
+ const ADMIN_NAME = /admin|poweruser|fullaccess/i;
39
+ const READ_NAME = /read-?only|view-?only|audit/i;
40
+ /** The principal behind a caller ARN: an assumed role, an IAM user, or root. */
41
+ export function principalOf(arn) {
42
+ const m = /^arn:[^:]+:(sts|iam)::\d{12}:(assumed-role|user|root|role)(?:\/(.*))?$/.exec(arn);
43
+ if (!m)
44
+ return { kind: 'other', name: '' };
45
+ if (m[2] === 'root')
46
+ return { kind: 'root', name: 'root' };
47
+ const parts = (m[3] || '').split('/');
48
+ if (m[2] === 'assumed-role' || m[2] === 'role')
49
+ return { kind: 'role', name: m[2] === 'assumed-role' ? parts[0] : parts[parts.length - 1] };
50
+ return { kind: 'user', name: parts[parts.length - 1] };
51
+ }
52
+ /**
53
+ * Admin or read-only, as far as can be told without simulating policies:
54
+ * the attached managed policies when they can be read, else the role or user
55
+ * name. "unknown" whenever neither is conclusive.
56
+ */
57
+ export function accessLevel(d, profile, region, arn) {
58
+ const p = principalOf(arn);
59
+ if (p.kind === 'root')
60
+ return { level: 'admin', basis: 'the root user' };
61
+ if (p.kind === 'other' || !p.name)
62
+ return { level: 'unknown', basis: 'the caller ARN has an unexpected form' };
63
+ const call = p.kind === 'role' ? ['iam', 'list-attached-role-policies', '--role-name', p.name] : ['iam', 'list-attached-user-policies', '--user-name', p.name];
64
+ const r = d.aws(call, profile, region);
65
+ const names = r.ok ? (r.json?.AttachedPolicies || []).map((x) => String(x?.PolicyName || '')).filter(Boolean) : [];
66
+ if (names.some((n) => ADMIN_POLICY.test(n)))
67
+ return { level: 'admin', basis: `attached policy ${names.find((n) => ADMIN_POLICY.test(n))}` };
68
+ if (names.length && names.every((n) => READ_POLICY.test(n)))
69
+ return { level: 'read-only', basis: `attached policies ${names.join(', ')}` };
70
+ const why = r.ok ? (names.length ? `custom policies (${names.join(', ')})` : 'no managed policies attached') : `policies not readable (${reason(r)})`;
71
+ if (ADMIN_NAME.test(p.name))
72
+ return { level: 'admin', basis: `the ${p.kind} name ${p.name}; ${why}` };
73
+ if (READ_NAME.test(p.name))
74
+ return { level: 'read-only', basis: `the ${p.kind} name ${p.name}; ${why}` };
75
+ return { level: 'unknown', basis: why };
76
+ }
77
+ const orgText = (o) => o.kind === 'management' ? `yes, the management account of ${o.orgId}`
78
+ : o.kind === 'member' ? `no, a member account of ${o.orgId}` : o.kind === 'none' ? 'no, not in an organization' : `unknown (${o.reason})`;
79
+ async function chooseProfile(o, d, saved) {
80
+ if (o.profile)
81
+ return o.profile;
82
+ const profiles = d.listProfiles();
83
+ if (!d.isTTY) {
84
+ if (d.env.AWS_PROFILE)
85
+ return d.env.AWS_PROFILE;
86
+ return { error: 'no --profile given and there is no terminal to choose on. Pass --profile <name> (see aws configure list-profiles).' };
87
+ }
88
+ if (!profiles.length)
89
+ return { error: 'no AWS profiles are configured. Create one with aws configure sso (or aws configure --profile <name>), then re-run.' };
90
+ const preferred = d.env.AWS_PROFILE || saved?.profile || (profiles.includes('default') ? 'default' : profiles[0]);
91
+ const def = Math.max(0, profiles.indexOf(preferred));
92
+ d.log('AWS profiles (from aws configure list-profiles):');
93
+ profiles.forEach((p, i) => d.log(` ${i + 1}) ${p}${i === def ? ' (default)' : ''}`));
94
+ const a = (await d.ask(`Profile [${def + 1}]: `)).trim();
95
+ if (!a)
96
+ return profiles[def];
97
+ const n = Number.parseInt(a, 10);
98
+ if (String(n) === a && n >= 1 && n <= profiles.length)
99
+ return profiles[n - 1];
100
+ return profiles.includes(a) ? a : { error: `"${a}" is not one of the listed profiles.` };
101
+ }
102
+ async function chooseRegion(o, d, profile) {
103
+ if (o.region)
104
+ return o.region;
105
+ const def = d.env.AWS_REGION || d.env.AWS_DEFAULT_REGION || d.configRegion(profile) || '';
106
+ if (!d.isTTY)
107
+ return def || { error: `no --region given and profile ${profile} has no configured region. Pass --region <region>.` };
108
+ const a = (await d.ask(`Region${def ? ` [${def}]` : ''}: `)).trim();
109
+ return a || def || { error: 'a region is required.' };
110
+ }
111
+ function repoRoot(d) {
112
+ return repoRootOf(d.cwd(), d.git);
113
+ }
114
+ /** `--clear`: removes the user file, or the repo file with --repo. */
115
+ function clear(o, d) {
116
+ let path;
117
+ if (o.repo) {
118
+ const root = repoRoot(d);
119
+ if (!root) {
120
+ d.log('Error: --repo needs to run inside a git repository.');
121
+ return 1;
122
+ }
123
+ path = repoConnectionPath(root);
124
+ }
125
+ else
126
+ path = userConnectionPath(d.home);
127
+ d.log(clearConnectionFile(path) ? `Removed ${path}. Nothing in AWS was changed.` : `Nothing to clear: ${path} does not exist.`);
128
+ return 0;
129
+ }
130
+ function describeFile(label, path, d) {
131
+ const c = readConnectionFile(path);
132
+ if (c)
133
+ d.log(` ${label}: ${path}\n profile ${c.profile}, region ${c.region}, account ${c.account}${c.alias ? ` (${c.alias})` : ''}, verified ${c.verifiedAt || 'unknown'}`);
134
+ else
135
+ d.log(` ${label}: ${path} (${existsSync(path) ? 'not a valid connection; ignored. Re-run prism-cli aws connect' : 'not set'})`);
136
+ }
137
+ /** `--status`: what is saved, which file applies, and whether it still validates. */
138
+ function status(d) {
139
+ const root = repoRoot(d);
140
+ d.log('Saved AWS connection:');
141
+ describeFile('user', userConnectionPath(d.home), d);
142
+ if (root)
143
+ describeFile('repo', repoConnectionPath(root), d);
144
+ else
145
+ d.log(' repo: (not in a git repository)');
146
+ const saved = loadConnection(d.home, root);
147
+ if (!saved) {
148
+ d.log('');
149
+ d.log('No saved connection: AWS commands use the default credential chain. Save one with: prism-cli aws connect');
150
+ return 0;
151
+ }
152
+ const applied = applyConnection({}, saved, d.env);
153
+ d.log('');
154
+ if (applied.profileSource)
155
+ d.log(`In use: profile ${saved.profile}, region ${saved.region} (${connectionLabel(saved)}, ${saved.path})`);
156
+ else {
157
+ const v = ENV_CREDENTIAL_VARS.find((k) => d.env[k]);
158
+ d.log(`Not in use for credentials: ${v} is set, and the environment wins over the saved connection${applied.connection ? ` (the saved region ${saved.region} still applies)` : ''}.`);
159
+ }
160
+ if (d.env.AWS_REGION || d.env.AWS_DEFAULT_REGION)
161
+ d.log(`Region note: ${d.env.AWS_REGION ? 'AWS_REGION' : 'AWS_DEFAULT_REGION'} is set and wins over the saved region.`);
162
+ const id = callerIdentity(d, saved.profile, saved.region);
163
+ if ('error' in id) {
164
+ d.log(`Validation: FAILED for profile ${saved.profile}: ${id.error}. Sign in again (e.g. aws sso login --profile ${saved.profile}) or re-run prism-cli aws connect.`);
165
+ return 1;
166
+ }
167
+ const w = accountChangeWarning(saved, id.account);
168
+ d.log(w ?? `Validation: ok, profile ${saved.profile} is account ${id.account} as saved (caller ${id.arn}).`);
169
+ return w ? 1 : 0;
170
+ }
171
+ /** Runs `aws connect`. Returns the exit code. */
172
+ export async function awsConnect(o, d) {
173
+ if (o.status && o.clear) {
174
+ d.log('Error: --status and --clear cannot be combined.');
175
+ return 1;
176
+ }
177
+ if (o.clear)
178
+ return clear(o, d);
179
+ d.log(CONNECT_NOTICE);
180
+ d.log('');
181
+ if (o.status)
182
+ return status(d);
183
+ const root = repoRoot(d);
184
+ if (o.repo && !root) {
185
+ d.log('Error: --repo needs to run inside a git repository.');
186
+ return 1;
187
+ }
188
+ const before = loadConnection(d.home, root);
189
+ const profile = await chooseProfile(o, d, before);
190
+ if (typeof profile !== 'string') {
191
+ d.log(`Error: ${profile.error}`);
192
+ return 1;
193
+ }
194
+ if (!PROFILE_RE.test(profile)) {
195
+ d.log(`Error: "${profile}" is not a valid profile name.`);
196
+ return 1;
197
+ }
198
+ const known = d.listProfiles();
199
+ if (known.length && !known.includes(profile)) {
200
+ d.log(`Error: profile ${profile} is not configured here (aws configure list-profiles lists: ${known.join(', ')}).`);
201
+ return 1;
202
+ }
203
+ const region = await chooseRegion(o, d, profile);
204
+ if (typeof region !== 'string') {
205
+ d.log(`Error: ${region.error}`);
206
+ return 1;
207
+ }
208
+ if (!REGION_RE.test(region)) {
209
+ d.log(`Error: "${region}" is not a valid AWS region name (e.g. us-west-2).`);
210
+ return 1;
211
+ }
212
+ const id = callerIdentity(d, profile, region);
213
+ if ('error' in id) {
214
+ d.log(`Error: profile ${profile} does not validate: ${id.error}. Sign in (e.g. aws sso login --profile ${profile}) and re-run. Nothing was saved.`);
215
+ return 1;
216
+ }
217
+ const alias = accountAlias(d, profile, region);
218
+ const org = orgRole(d, profile, region, id.account);
219
+ const access = accessLevel(d, profile, region, id.arn);
220
+ d.log(`Profile: ${profile}`);
221
+ d.log(`Region: ${region}`);
222
+ d.log(`Account: ${id.account}${alias ? ` (${alias})` : ' (no account alias)'}`);
223
+ d.log(`Caller: ${id.arn || 'unknown'}`);
224
+ d.log(`Org management account: ${orgText(org)}`);
225
+ d.log(`Access: ${access.level} (${access.basis})`);
226
+ if (access.level === 'admin')
227
+ d.log(' prism-cli aws check and aws recommend only need read access; a read-only profile is enough for them.');
228
+ const path = o.repo && root ? repoConnectionPath(root) : userConnectionPath(d.home);
229
+ const prev = readConnectionFile(path);
230
+ if (prev && prev.profile === profile && prev.account !== id.account) {
231
+ d.log(`Warning: profile ${profile} was saved as account ${prev.account}; it now resolves to account ${id.account}.`);
232
+ }
233
+ const conn = { profile, region, account: id.account, alias, verifiedAt: d.now().toISOString() };
234
+ if (o.repo && root) {
235
+ const excluded = ensureMarkerIgnored(root, d.git, REPO_CONNECTION_PATH, 'prism-cli aws connect');
236
+ if (excluded)
237
+ d.log(`Added ${REPO_CONNECTION_PATH} to ${excluded} so git ignores it in this clone.`);
238
+ }
239
+ writeConnectionFile(path, conn);
240
+ d.log('');
241
+ d.log(`Saved ${path} (profile name, region, account and alias; no credentials).`);
242
+ d.log(`AWS commands now default to profile ${profile} in ${region}${o.repo ? ' in this repo' : ''}. --profile/--region and AWS_PROFILE/AWS_REGION still win.`);
243
+ const env = ENV_CREDENTIAL_VARS.find((k) => d.env[k]);
244
+ if (env && d.env.AWS_PROFILE !== profile)
245
+ d.log(`Note: ${env} is set in this shell, so it wins here until it is unset.`);
246
+ if (!o.repo && root && readConnectionFile(repoConnectionPath(root)))
247
+ d.log(`Note: this repo has its own ${REPO_CONNECTION_PATH}, which wins over the user file here.`);
248
+ return 0;
249
+ }
250
+ //# sourceMappingURL=connect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect.js","sourceRoot":"","sources":["../../../src/aws/connect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ import { type RunResult } from '../utils/exec.js';
2
+ export declare const USER_CONNECTION_PATH = "~/.prism/aws.json";
3
+ export declare const REPO_CONNECTION_PATH = ".prism/aws.local.json";
4
+ export interface AwsConnection {
5
+ profile: string;
6
+ region: string;
7
+ account: string;
8
+ alias: string | null;
9
+ verifiedAt: string;
10
+ }
11
+ export type ConnectionScope = 'repo' | 'user';
12
+ export interface SavedConnection extends AwsConnection {
13
+ scope: ConnectionScope;
14
+ path: string;
15
+ }
16
+ /** What a command's options gain from the resolver. */
17
+ export interface ConnectionDefaults {
18
+ profile?: string;
19
+ /** Where `profile` came from, e.g. "--profile" or "aws connect, user". Unset when no profile is used. */
20
+ profileSource?: string;
21
+ /** The saved connection whose region (and account, for the change warning) applies. */
22
+ connection?: SavedConnection;
23
+ }
24
+ /** Credential env vars that the AWS CLI prefers over any profile; when set, the saved profile is not applied. */
25
+ export declare const ENV_CREDENTIAL_VARS: string[];
26
+ export declare const PROFILE_RE: RegExp;
27
+ export declare const REGION_RE: RegExp;
28
+ export declare const userConnectionPath: (home: string) => string;
29
+ export declare const repoConnectionPath: (root: string) => string;
30
+ /** The connection in `path`; null when the file is absent or not a valid connection. */
31
+ export declare function readConnectionFile(path: string): AwsConnection | null;
32
+ /** Atomic write, owner-only (no secrets inside, but it is per-user state). */
33
+ export declare function writeConnectionFile(path: string, c: AwsConnection): void;
34
+ /** Removes the file; true when there was one. */
35
+ export declare function clearConnectionFile(path: string): boolean;
36
+ /** The repo file first, then the user file. `home` '' means no user file. */
37
+ export declare function loadConnection(home: string, repoRoot: string | null): SavedConnection | null;
38
+ export declare const connectionLabel: (c: Pick<SavedConnection, "scope">) => string;
39
+ /**
40
+ * Fills the profile from the saved connection when neither a flag nor the
41
+ * environment chose the credentials, and attaches the connection whose region
42
+ * applies. Pure: the caller loads the connection.
43
+ */
44
+ export declare function applyConnection<T extends {
45
+ profile?: string;
46
+ region?: string;
47
+ }>(opts: T, saved: SavedConnection | null, env: NodeJS.ProcessEnv): T & ConnectionDefaults;
48
+ /** `git -C dir rev-parse --show-toplevel`, or null outside a repository. */
49
+ export declare function repoRootOf(dir: string, git?: (args: string[]) => RunResult): string | null;
50
+ /**
51
+ * The real-runtime entry point: loads the saved connection for the working
52
+ * directory (or `opts.path`) and applies it. With an explicit `env` (tests),
53
+ * the user file is looked up under env.HOME only, so a developer's own saved
54
+ * connection never leaks into a test run.
55
+ */
56
+ export declare function connectionDefaults<T extends {
57
+ profile?: string;
58
+ region?: string;
59
+ path?: string;
60
+ }>(opts: T, env?: NodeJS.ProcessEnv): T & ConnectionDefaults;
61
+ /** The account-change warning, or null when the account is the one that was verified. */
62
+ export declare function accountChangeWarning(c: SavedConnection | undefined, account: string): string | null;
63
+ /** `aws configure get region [--profile p]`: local config only, no AWS call. */
64
+ export declare function configuredRegion(profile?: string): string | null;
65
+ /** `aws configure list-profiles`: local config only, no AWS call. */
66
+ export declare function listProfiles(): string[];
67
+ //# sourceMappingURL=connection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../../src/aws/connection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,137 @@
1
+ /**
2
+ * The saved AWS connection from `prism-cli aws connect`, and the one resolver
3
+ * every AWS command uses to pick its default profile and region.
4
+ *
5
+ * What is saved is a profile NAME, a region and what that pair was verified
6
+ * as (account, alias, when). Never a credential: the AWS CLI still resolves
7
+ * the profile's credentials itself, every time.
8
+ *
9
+ * Files:
10
+ * ~/.prism/aws.json per user
11
+ * .prism/aws.local.json per repo override (git-ignored via .git/info/exclude)
12
+ *
13
+ * Precedence, per field:
14
+ * profile: --profile > env credentials (AWS_PROFILE, AWS_ACCESS_KEY_ID, ...) > repo file > user file > default chain
15
+ * region: --region > AWS_REGION > AWS_DEFAULT_REGION > saved region > the profile's configured region
16
+ * The saved region is used only together with its saved profile (the two were
17
+ * verified as a pair): `--profile other` falls through to other's own region.
18
+ */
19
+ import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
20
+ import { homedir } from 'node:os';
21
+ import { dirname, join, resolve } from 'node:path';
22
+ import { run } from '../utils/exec.js';
23
+ export const USER_CONNECTION_PATH = '~/.prism/aws.json';
24
+ export const REPO_CONNECTION_PATH = '.prism/aws.local.json';
25
+ /** Credential env vars that the AWS CLI prefers over any profile; when set, the saved profile is not applied. */
26
+ export const ENV_CREDENTIAL_VARS = ['AWS_PROFILE', 'AWS_ACCESS_KEY_ID', 'AWS_WEB_IDENTITY_TOKEN_FILE', 'AWS_CONTAINER_CREDENTIALS_FULL_URI', 'AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'];
27
+ export const PROFILE_RE = /^[A-Za-z0-9_.+=,@:-]{1,128}$/;
28
+ export const REGION_RE = /^[a-z]{2}(-[a-z]+)+-\d{1,2}$/;
29
+ const ACCOUNT_RE = /^\d{12}$/;
30
+ export const userConnectionPath = (home) => join(home, '.prism', 'aws.json');
31
+ export const repoConnectionPath = (root) => resolve(root, REPO_CONNECTION_PATH);
32
+ function parse(x) {
33
+ if (!x || typeof x !== 'object')
34
+ return null;
35
+ if (typeof x.profile !== 'string' || !PROFILE_RE.test(x.profile))
36
+ return null;
37
+ if (typeof x.region !== 'string' || !REGION_RE.test(x.region))
38
+ return null;
39
+ if (typeof x.account !== 'string' || !ACCOUNT_RE.test(x.account))
40
+ return null;
41
+ return {
42
+ profile: x.profile, region: x.region, account: x.account,
43
+ alias: typeof x.alias === 'string' && x.alias ? x.alias : null,
44
+ verifiedAt: typeof x.verifiedAt === 'string' ? x.verifiedAt : '',
45
+ };
46
+ }
47
+ /** The connection in `path`; null when the file is absent or not a valid connection. */
48
+ export function readConnectionFile(path) {
49
+ try {
50
+ return parse(JSON.parse(readFileSync(path, 'utf8')));
51
+ }
52
+ catch {
53
+ return null;
54
+ }
55
+ }
56
+ /** Atomic write, owner-only (no secrets inside, but it is per-user state). */
57
+ export function writeConnectionFile(path, c) {
58
+ mkdirSync(dirname(path), { recursive: true });
59
+ const tmp = `${path}.${process.pid}.tmp`;
60
+ const body = { profile: c.profile, region: c.region, account: c.account, alias: c.alias, verifiedAt: c.verifiedAt };
61
+ writeFileSync(tmp, JSON.stringify(body, null, 2) + '\n', { mode: 0o600 });
62
+ renameSync(tmp, path);
63
+ }
64
+ /** Removes the file; true when there was one. */
65
+ export function clearConnectionFile(path) {
66
+ if (!existsSync(path))
67
+ return false;
68
+ rmSync(path, { force: true });
69
+ return true;
70
+ }
71
+ /** The repo file first, then the user file. `home` '' means no user file. */
72
+ export function loadConnection(home, repoRoot) {
73
+ if (repoRoot) {
74
+ const p = repoConnectionPath(repoRoot);
75
+ const c = readConnectionFile(p);
76
+ if (c)
77
+ return { ...c, scope: 'repo', path: p };
78
+ }
79
+ if (home) {
80
+ const p = userConnectionPath(home);
81
+ const c = readConnectionFile(p);
82
+ if (c)
83
+ return { ...c, scope: 'user', path: p };
84
+ }
85
+ return null;
86
+ }
87
+ export const connectionLabel = (c) => `aws connect, ${c.scope}`;
88
+ /**
89
+ * Fills the profile from the saved connection when neither a flag nor the
90
+ * environment chose the credentials, and attaches the connection whose region
91
+ * applies. Pure: the caller loads the connection.
92
+ */
93
+ export function applyConnection(opts, saved, env) {
94
+ if (opts.profile)
95
+ return { ...opts, profileSource: '--profile', connection: saved && saved.profile === opts.profile ? saved : undefined };
96
+ if (ENV_CREDENTIAL_VARS.some((k) => env[k])) {
97
+ return { ...opts, connection: saved && env.AWS_PROFILE === saved.profile ? saved : undefined };
98
+ }
99
+ if (saved)
100
+ return { ...opts, profile: saved.profile, profileSource: connectionLabel(saved), connection: saved };
101
+ return { ...opts };
102
+ }
103
+ /** `git -C dir rev-parse --show-toplevel`, or null outside a repository. */
104
+ export function repoRootOf(dir, git = (a) => run('git', a)) {
105
+ const r = git(['-C', dir, 'rev-parse', '--show-toplevel']);
106
+ return r.ok && r.stdout ? r.stdout.trim() : null;
107
+ }
108
+ /**
109
+ * The real-runtime entry point: loads the saved connection for the working
110
+ * directory (or `opts.path`) and applies it. With an explicit `env` (tests),
111
+ * the user file is looked up under env.HOME only, so a developer's own saved
112
+ * connection never leaks into a test run.
113
+ */
114
+ export function connectionDefaults(opts, env) {
115
+ const e = env ?? process.env;
116
+ const home = env ? (env.HOME ?? '') : homedir();
117
+ const root = repoRootOf(opts.path ? resolve(opts.path) : process.cwd());
118
+ return applyConnection(opts, loadConnection(home, root), e);
119
+ }
120
+ /** The account-change warning, or null when the account is the one that was verified. */
121
+ export function accountChangeWarning(c, account) {
122
+ if (!c || !account || c.account === account)
123
+ return null;
124
+ return `Warning: aws connect verified profile ${c.profile} as account ${c.account}${c.verifiedAt ? ` on ${c.verifiedAt}` : ''}, but it now resolves to account ${account}. `
125
+ + `Check the profile, then re-run prism-cli aws connect${c.scope === 'repo' ? ' --repo' : ''}.`;
126
+ }
127
+ /** `aws configure get region [--profile p]`: local config only, no AWS call. */
128
+ export function configuredRegion(profile) {
129
+ const r = run('aws', ['configure', 'get', 'region', ...(profile ? ['--profile', profile] : [])]);
130
+ return r.ok && r.stdout ? r.stdout.trim() : null;
131
+ }
132
+ /** `aws configure list-profiles`: local config only, no AWS call. */
133
+ export function listProfiles() {
134
+ const r = run('aws', ['configure', 'list-profiles']);
135
+ return r.ok ? r.stdout.split('\n').map((l) => l.trim()).filter(Boolean) : [];
136
+ }
137
+ //# sourceMappingURL=connection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.js","sourceRoot":"","sources":["../../../src/aws/connection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ import { type Finding, type Severity } from '../utils/audit.js';
2
+ import { type PrismResult, type ResultEntry } from '../codewatch/results.js';
3
+ import { type Effort } from './advice.js';
4
+ import { type CheckOptions, type CheckRunDeps } from './run-check.js';
5
+ export declare const RECOMMEND_NOTICE = "No AWS calls (aws recommend): it reads the latest aws check result in .prism/results/. Nothing in AWS is changed.";
6
+ export interface RecommendOptions extends Pick<CheckOptions, 'profile' | 'region' | 'profileSource' | 'connection'> {
7
+ account?: string;
8
+ refresh?: boolean;
9
+ json?: boolean;
10
+ markdown?: boolean;
11
+ }
12
+ /** Why an INDETERMINATE check could not run, as far as its detail tells. */
13
+ export type IndeterminateCause = 'access-denied' | 'no-credential-report' | 'prerequisite' | 'not-integrated' | 'other';
14
+ export interface Recommendation {
15
+ /** fix: one or more FAILs. access: one or more INDETERMINATE checks (could not check). */
16
+ kind: 'fix' | 'access';
17
+ /** The recommendation key; checks that share one fix share it (e.g. "budgets"). */
18
+ id: string;
19
+ /** Every check this item covers, worst first. */
20
+ covers: {
21
+ id: string;
22
+ title: string;
23
+ detail: string;
24
+ }[];
25
+ section: string;
26
+ severity: Severity;
27
+ effort: Effort;
28
+ title: string;
29
+ why: string;
30
+ steps: string[];
31
+ command: string | null;
32
+ doc: string | null;
33
+ /** fix only: its position in the ranked list, 1-based across sections. */
34
+ number?: number;
35
+ /** access only. */
36
+ cause?: IndeterminateCause;
37
+ }
38
+ /** Account and region from the result, filled into the advice's `<account>` and `<region>`. */
39
+ export interface AdviceContext {
40
+ account?: string;
41
+ region?: string;
42
+ }
43
+ export declare const NO_REPORT_STEP = "No credential report exists yet. Run `prism-cli bedrock-protection scan-account` once (it generates one, which is a write) or `aws iam generate-credential-report`, then re-run aws check.";
44
+ /** Only an access-denied detail means "grant"; a missing report or a missing prerequisite says what to do first. */
45
+ export declare function indeterminateCause(f: Finding): IndeterminateCause;
46
+ type Rankable = Pick<Recommendation, 'severity' | 'effort' | 'id'>;
47
+ /** Severity first, then effort (quick wins first), then id. */
48
+ export declare function rank(a: Rankable, b: Rankable): number;
49
+ /** Check ids older results still carry, and the check that replaced them, so a cached result de-duplicates too. */
50
+ export declare const RETIRED_IDS: Record<string, string>;
51
+ export interface SectionAdvice {
52
+ section: string;
53
+ heading: string;
54
+ fixes: Recommendation[];
55
+ access: Recommendation[];
56
+ }
57
+ /**
58
+ * FAILs and INDETERMINATEs as recommendations, grouped by section in aws
59
+ * check's order, each group ranked. Fixes are numbered across sections, so a
60
+ * check that waits on a fix can name it ("item 2").
61
+ */
62
+ export declare function buildRecommendations(checks: Finding[], c?: AdviceContext): SectionAdvice[];
63
+ /** The newest aws-check result, optionally for one account and region. */
64
+ export declare function latestCheck(entries: ResultEntry[], account?: string, region?: string): ResultEntry | null;
65
+ export declare function renderText(r: PrismResult, groups: SectionAdvice[], source: string): string[];
66
+ export declare function renderMarkdown(r: PrismResult, groups: SectionAdvice[], source: string): string;
67
+ /** Runs `aws recommend`. Returns the exit code. */
68
+ export declare function awsRecommend(input: RecommendOptions, d: CheckRunDeps): number;
69
+ export {};
70
+ //# sourceMappingURL=recommend.d.ts.map