@p0security/cli 0.11.2 → 0.11.4

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 (63) hide show
  1. package/dist/commands/__tests__/login.test.js +4 -2
  2. package/dist/commands/__tests__/login.test.js.map +1 -1
  3. package/dist/commands/allow.js +1 -1
  4. package/dist/commands/allow.js.map +1 -1
  5. package/dist/commands/aws/role.js +2 -2
  6. package/dist/commands/aws/role.js.map +1 -1
  7. package/dist/commands/grant.js +1 -1
  8. package/dist/commands/grant.js.map +1 -1
  9. package/dist/commands/index.js +2 -0
  10. package/dist/commands/index.js.map +1 -1
  11. package/dist/commands/kubeconfig.js +9 -14
  12. package/dist/commands/kubeconfig.js.map +1 -1
  13. package/dist/commands/login.js +10 -5
  14. package/dist/commands/login.js.map +1 -1
  15. package/dist/commands/ls.js +1 -1
  16. package/dist/commands/ls.js.map +1 -1
  17. package/dist/commands/request.js +1 -1
  18. package/dist/commands/request.js.map +1 -1
  19. package/dist/commands/scp.js +1 -1
  20. package/dist/commands/scp.js.map +1 -1
  21. package/dist/commands/ssh-keygen.d.ts +2 -0
  22. package/dist/commands/ssh-keygen.js +28 -0
  23. package/dist/commands/ssh-keygen.js.map +1 -0
  24. package/dist/commands/ssh.js +1 -1
  25. package/dist/commands/ssh.js.map +1 -1
  26. package/dist/common/keys.d.ts +1 -0
  27. package/dist/common/keys.js +4 -3
  28. package/dist/common/keys.js.map +1 -1
  29. package/dist/drivers/api.d.ts +10 -0
  30. package/dist/drivers/api.js +2 -12
  31. package/dist/drivers/api.js.map +1 -1
  32. package/dist/drivers/auth.js +4 -16
  33. package/dist/drivers/auth.js.map +1 -1
  34. package/dist/drivers/config.d.ts +15 -0
  35. package/dist/drivers/config.js +43 -0
  36. package/dist/drivers/config.js.map +1 -0
  37. package/dist/drivers/env.d.ts +1 -1
  38. package/dist/drivers/env.js +2 -2
  39. package/dist/drivers/env.js.map +1 -1
  40. package/dist/drivers/firestore.d.ts +15 -3
  41. package/dist/drivers/firestore.js +47 -22
  42. package/dist/drivers/firestore.js.map +1 -1
  43. package/dist/plugins/aws/__tests__/utils.test.d.ts +1 -0
  44. package/dist/plugins/aws/__tests__/utils.test.js +82 -0
  45. package/dist/plugins/aws/__tests__/utils.test.js.map +1 -0
  46. package/dist/plugins/aws/utils.d.ts +20 -0
  47. package/dist/plugins/aws/utils.js +54 -0
  48. package/dist/plugins/aws/utils.js.map +1 -0
  49. package/dist/plugins/google/login.js +6 -4
  50. package/dist/plugins/google/login.js.map +1 -1
  51. package/dist/plugins/kubeconfig/index.d.ts +2 -2
  52. package/dist/plugins/kubeconfig/index.js +17 -14
  53. package/dist/plugins/kubeconfig/index.js.map +1 -1
  54. package/dist/plugins/kubeconfig/types.d.ts +9 -8
  55. package/dist/plugins/ssh/index.js +2 -7
  56. package/dist/plugins/ssh/index.js.map +1 -1
  57. package/dist/public/favicon.ico +0 -0
  58. package/dist/types/org.d.ts +3 -0
  59. package/dist/types/org.js +0 -10
  60. package/dist/types/org.js.map +1 -1
  61. package/dist/util.js +3 -1
  62. package/dist/util.js.map +1 -1
  63. package/package.json +2 -1
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.loadConfig = exports.saveConfig = exports.getTenantConfig = exports.CONFIG_FILE_PATH = void 0;
16
+ const util_1 = require("../util");
17
+ const stdio_1 = require("./stdio");
18
+ const promises_1 = __importDefault(require("fs/promises"));
19
+ const path_1 = __importDefault(require("path"));
20
+ exports.CONFIG_FILE_PATH = path_1.default.join(util_1.P0_PATH, "config.json");
21
+ let tenantConfig;
22
+ function getTenantConfig() {
23
+ return tenantConfig;
24
+ }
25
+ exports.getTenantConfig = getTenantConfig;
26
+ function saveConfig(config) {
27
+ return __awaiter(this, void 0, void 0, function* () {
28
+ (0, stdio_1.print2)(`Saving config to ${exports.CONFIG_FILE_PATH}.`);
29
+ const dir = path_1.default.dirname(exports.CONFIG_FILE_PATH);
30
+ yield promises_1.default.mkdir(dir, { recursive: true });
31
+ yield promises_1.default.writeFile(exports.CONFIG_FILE_PATH, JSON.stringify(config), { mode: "600" });
32
+ tenantConfig = config;
33
+ });
34
+ }
35
+ exports.saveConfig = saveConfig;
36
+ function loadConfig() {
37
+ return __awaiter(this, void 0, void 0, function* () {
38
+ const buffer = yield promises_1.default.readFile(exports.CONFIG_FILE_PATH);
39
+ tenantConfig = JSON.parse(buffer.toString());
40
+ });
41
+ }
42
+ exports.loadConfig = loadConfig;
43
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/drivers/config.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAWA,kCAAkC;AAClC,mCAAiC;AACjC,2DAA6B;AAC7B,gDAAwB;AAEX,QAAA,gBAAgB,GAAG,cAAI,CAAC,IAAI,CAAC,cAAO,EAAE,aAAa,CAAC,CAAC;AAElE,IAAI,YAAoB,CAAC;AAEzB,SAAgB,eAAe;IAC7B,OAAO,YAAY,CAAC;AACtB,CAAC;AAFD,0CAEC;AAED,SAAsB,UAAU,CAAC,MAAc;;QAC7C,IAAA,cAAM,EAAC,oBAAoB,wBAAgB,GAAG,CAAC,CAAC;QAChD,MAAM,GAAG,GAAG,cAAI,CAAC,OAAO,CAAC,wBAAgB,CAAC,CAAC;QAC3C,MAAM,kBAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzC,MAAM,kBAAE,CAAC,SAAS,CAAC,wBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC9E,YAAY,GAAG,MAAM,CAAC;IACxB,CAAC;CAAA;AAND,gCAMC;AAED,SAAsB,UAAU;;QAC9B,MAAM,MAAM,GAAG,MAAM,kBAAE,CAAC,QAAQ,CAAC,wBAAgB,CAAC,CAAC;QACnD,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC/C,CAAC;CAAA;AAHD,gCAGC"}
@@ -1,4 +1,4 @@
1
- export declare const config: {
1
+ export declare const bootstrapConfig: {
2
2
  fs: {
3
3
  apiKey: string;
4
4
  authDomain: string;
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.config = void 0;
7
+ exports.bootstrapConfig = void 0;
8
8
  /** Copyright © 2024-present P0 Security
9
9
 
10
10
  This file is part of @p0security/cli
@@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License along with @p0
18
18
  const dotenv_1 = __importDefault(require("dotenv"));
19
19
  dotenv_1.default.config();
20
20
  const { env } = process;
21
- exports.config = {
21
+ exports.bootstrapConfig = {
22
22
  fs: {
23
23
  // Falls back to public production Firestore credentials
24
24
  apiKey: (_a = env.P0_FS_API_KEY) !== null && _a !== void 0 ? _a : "AIzaSyCaL-Ik_l_5tdmgNUNZ4Nv6NuR4o5_PPfs",
@@ -1 +1 @@
1
- {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/drivers/env.ts"],"names":[],"mappings":";;;;;;;AAAA;;;;;;;;;GASG;AACH,oDAA4B;AAE5B,gBAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;AAEX,QAAA,MAAM,GAAG;IACpB,EAAE,EAAE;QACF,wDAAwD;QACxD,MAAM,EAAE,MAAA,GAAG,CAAC,aAAa,mCAAI,yCAAyC;QACtE,UAAU,EAAE,MAAA,GAAG,CAAC,iBAAiB,mCAAI,yBAAyB;QAC9D,SAAS,EAAE,MAAA,GAAG,CAAC,gBAAgB,mCAAI,SAAS;QAC5C,aAAa,EAAE,MAAA,GAAG,CAAC,oBAAoB,mCAAI,qBAAqB;QAChE,iBAAiB,EAAE,MAAA,GAAG,CAAC,yBAAyB,mCAAI,cAAc;QAClE,KAAK,EAAE,MAAA,GAAG,CAAC,YAAY,mCAAI,2CAA2C;KACvE;IACD,MAAM,EAAE;QACN,QAAQ,EACN,MAAA,GAAG,CAAC,wBAAwB,mCAC5B,0EAA0E;QAC5E,4EAA4E;QAC5E,qFAAqF;QACrF,YAAY,EACV,MAAA,GAAG,CAAC,4BAA4B,mCAAI,qCAAqC;KAC5E;IACD,MAAM,EAAE,MAAA,GAAG,CAAC,UAAU,mCAAI,oBAAoB;IAC9C,WAAW,EAAE,MAAA,GAAG,CAAC,MAAM,mCAAI,YAAY;CACxC,CAAC"}
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/drivers/env.ts"],"names":[],"mappings":";;;;;;;AAAA;;;;;;;;;GASG;AACH,oDAA4B;AAE5B,gBAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;AAEX,QAAA,eAAe,GAAG;IAC7B,EAAE,EAAE;QACF,wDAAwD;QACxD,MAAM,EAAE,MAAA,GAAG,CAAC,aAAa,mCAAI,yCAAyC;QACtE,UAAU,EAAE,MAAA,GAAG,CAAC,iBAAiB,mCAAI,yBAAyB;QAC9D,SAAS,EAAE,MAAA,GAAG,CAAC,gBAAgB,mCAAI,SAAS;QAC5C,aAAa,EAAE,MAAA,GAAG,CAAC,oBAAoB,mCAAI,qBAAqB;QAChE,iBAAiB,EAAE,MAAA,GAAG,CAAC,yBAAyB,mCAAI,cAAc;QAClE,KAAK,EAAE,MAAA,GAAG,CAAC,YAAY,mCAAI,2CAA2C;KACvE;IACD,MAAM,EAAE;QACN,QAAQ,EACN,MAAA,GAAG,CAAC,wBAAwB,mCAC5B,0EAA0E;QAC5E,4EAA4E;QAC5E,qFAAqF;QACrF,YAAY,EACV,MAAA,GAAG,CAAC,4BAA4B,mCAAI,qCAAqC;KAC5E;IACD,MAAM,EAAE,MAAA,GAAG,CAAC,UAAU,mCAAI,oBAAoB;IAC9C,WAAW,EAAE,MAAA,GAAG,CAAC,MAAM,mCAAI,YAAY;CACxC,CAAC"}
@@ -1,10 +1,22 @@
1
+ /** Copyright © 2024-present P0 Security
2
+
3
+ This file is part of @p0security/cli
4
+
5
+ @p0security/cli is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
6
+
7
+ @p0security/cli is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
8
+
9
+ You should have received a copy of the GNU General Public License along with @p0security/cli. If not, see <https://www.gnu.org/licenses/>.
10
+ **/
11
+ import { Identity } from "../types/identity";
1
12
  import { CollectionReference, DocumentReference } from "firebase/firestore";
2
- export declare const FIRESTORE: import("@firebase/firestore").Firestore;
3
- export declare const auth: import("@firebase/auth").Auth;
13
+ export declare function initializeFirebase(): void;
14
+ export declare function authenticateToFirebase(identity: Identity): Promise<import("@firebase/auth").UserCredential>;
4
15
  export declare const collection: <T>(path: string, ...pathSegments: string[]) => CollectionReference<T, import("@firebase/firestore").DocumentData>;
5
16
  export declare const doc: <T>(path: string) => DocumentReference<T, import("@firebase/firestore").DocumentData>;
17
+ export declare const publicDoc: <T>(path: string) => DocumentReference<T, import("@firebase/firestore").DocumentData>;
6
18
  /** Ensures that Firestore is shutdown at command termination
7
19
  *
8
20
  * This prevents Firestore from holding the command on execution completion or failure.
9
21
  */
10
- export declare const guard: <P, T>(cb: (args: P) => Promise<T>) => (args: P) => Promise<void>;
22
+ export declare const fsShutdownGuard: <P, T>(cb: (args: P) => Promise<T>) => (args: P) => Promise<void>;
@@ -9,46 +9,71 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.guard = exports.doc = exports.collection = exports.auth = exports.FIRESTORE = void 0;
13
- /** Copyright © 2024-present P0 Security
14
-
15
- This file is part of @p0security/cli
16
-
17
- @p0security/cli is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
18
-
19
- @p0security/cli is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
20
-
21
- You should have received a copy of the GNU General Public License along with @p0security/cli. If not, see <https://www.gnu.org/licenses/>.
22
- **/
12
+ exports.fsShutdownGuard = exports.publicDoc = exports.doc = exports.collection = exports.authenticateToFirebase = exports.initializeFirebase = void 0;
13
+ const config_1 = require("./config");
23
14
  const env_1 = require("./env");
24
15
  const app_1 = require("firebase/app");
25
16
  const auth_1 = require("firebase/auth");
26
17
  const firestore_1 = require("firebase/firestore");
27
- // Your web app's Firebase configuration
28
- const firebaseConfig = env_1.config.fs;
29
- // Initialize Firebase
30
- const app = (0, app_1.initializeApp)(firebaseConfig);
31
- exports.FIRESTORE = (0, firestore_1.getFirestore)(app);
32
- exports.auth = (0, auth_1.getAuth)();
18
+ const bootstrapApp = (0, app_1.initializeApp)(env_1.bootstrapConfig.fs, "bootstrapApp");
19
+ const bootstrapFirestore = (0, firestore_1.getFirestore)(bootstrapApp);
20
+ let app;
21
+ let firestore;
22
+ function initializeFirebase() {
23
+ const tenantConfig = (0, config_1.getTenantConfig)();
24
+ app = (0, app_1.initializeApp)(tenantConfig.fs, "authFirebase");
25
+ firestore = (0, firestore_1.getFirestore)(app);
26
+ }
27
+ exports.initializeFirebase = initializeFirebase;
28
+ function authenticateToFirebase(identity) {
29
+ var _a;
30
+ return __awaiter(this, void 0, void 0, function* () {
31
+ const { credential } = identity;
32
+ const tenantId = identity.org.tenantId;
33
+ // TODO: Move to map lookup
34
+ const provider = new auth_1.OAuthProvider(identity.org.ssoProvider === "google"
35
+ ? auth_1.SignInMethod.GOOGLE
36
+ : identity.org.providerId);
37
+ const firebaseCredential = provider.credential({
38
+ accessToken: credential.access_token,
39
+ idToken: credential.id_token,
40
+ });
41
+ const auth = (0, auth_1.getAuth)(app);
42
+ auth.tenantId = tenantId;
43
+ const userCredential = yield (0, auth_1.signInWithCredential)(auth, firebaseCredential);
44
+ if (!((_a = userCredential === null || userCredential === void 0 ? void 0 : userCredential.user) === null || _a === void 0 ? void 0 : _a.email)) {
45
+ throw "Can not sign in: this user has previously signed in with a different identity provider.\nPlease contact support@p0.dev to enable this user.";
46
+ }
47
+ return userCredential;
48
+ });
49
+ }
50
+ exports.authenticateToFirebase = authenticateToFirebase;
33
51
  const collection = (path, ...pathSegments) => {
34
- return (0, firestore_1.collection)(exports.FIRESTORE, path, ...pathSegments);
52
+ return (0, firestore_1.collection)(firestore, path, ...pathSegments);
35
53
  };
36
54
  exports.collection = collection;
37
55
  const doc = (path) => {
38
- return (0, firestore_1.doc)(exports.FIRESTORE, path);
56
+ return (0, firestore_1.doc)(firestore, path);
39
57
  };
40
58
  exports.doc = doc;
59
+ const publicDoc = (path) => {
60
+ return (0, firestore_1.doc)(bootstrapFirestore, path);
61
+ };
62
+ exports.publicDoc = publicDoc;
41
63
  /** Ensures that Firestore is shutdown at command termination
42
64
  *
43
65
  * This prevents Firestore from holding the command on execution completion or failure.
44
66
  */
45
- const guard = (cb) => (args) => __awaiter(void 0, void 0, void 0, function* () {
67
+ const fsShutdownGuard = (cb) => (args) => __awaiter(void 0, void 0, void 0, function* () {
46
68
  try {
47
69
  yield cb(args);
48
70
  }
49
71
  finally {
50
- void (0, firestore_1.terminate)(exports.FIRESTORE);
72
+ if (bootstrapFirestore)
73
+ void (0, firestore_1.terminate)(bootstrapFirestore);
74
+ if (firestore)
75
+ void (0, firestore_1.terminate)(firestore);
51
76
  }
52
77
  });
53
- exports.guard = guard;
78
+ exports.fsShutdownGuard = fsShutdownGuard;
54
79
  //# sourceMappingURL=firestore.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"firestore.js","sourceRoot":"","sources":["../../src/drivers/firestore.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA;;;;;;;;;GASG;AACH,+BAA+B;AAC/B,sCAA6C;AAC7C,wCAAwC;AACxC,kDAO4B;AAE5B,wCAAwC;AACxC,MAAM,cAAc,GAAG,YAAM,CAAC,EAAE,CAAC;AAEjC,sBAAsB;AACtB,MAAM,GAAG,GAAG,IAAA,mBAAa,EAAC,cAAc,CAAC,CAAC;AAC7B,QAAA,SAAS,GAAG,IAAA,wBAAY,EAAC,GAAG,CAAC,CAAC;AAC9B,QAAA,IAAI,GAAG,IAAA,cAAO,GAAE,CAAC;AAEvB,MAAM,UAAU,GAAG,CAAI,IAAY,EAAE,GAAG,YAAsB,EAAE,EAAE;IACvE,OAAO,IAAA,sBAAY,EACjB,iBAAS,EACT,IAAI,EACJ,GAAG,YAAY,CACU,CAAC;AAC9B,CAAC,CAAC;AANW,QAAA,UAAU,cAMrB;AACK,MAAM,GAAG,GAAG,CAAI,IAAY,EAAE,EAAE;IACrC,OAAO,IAAA,eAAK,EAAC,iBAAS,EAAE,IAAI,CAAyB,CAAC;AACxD,CAAC,CAAC;AAFW,QAAA,GAAG,OAEd;AAEF;;;GAGG;AACI,MAAM,KAAK,GAChB,CAAO,EAA2B,EAAE,EAAE,CACtC,CAAO,IAAO,EAAE,EAAE;IAChB,IAAI;QACF,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC;KAChB;YAAS;QACR,KAAK,IAAA,qBAAS,EAAC,iBAAS,CAAC,CAAC;KAC3B;AACH,CAAC,CAAA,CAAC;AARS,QAAA,KAAK,SAQd"}
1
+ {"version":3,"file":"firestore.js","sourceRoot":"","sources":["../../src/drivers/firestore.ts"],"names":[],"mappings":";;;;;;;;;;;;AAWA,qCAA2C;AAC3C,+BAAwC;AACxC,sCAA0D;AAC1D,wCAKuB;AACvB,kDAQ4B;AAE5B,MAAM,YAAY,GAAG,IAAA,mBAAa,EAAC,qBAAe,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC;AACvE,MAAM,kBAAkB,GAAG,IAAA,wBAAY,EAAC,YAAY,CAAC,CAAC;AAEtD,IAAI,GAAgB,CAAC;AACrB,IAAI,SAAoB,CAAC;AAEzB,SAAgB,kBAAkB;IAChC,MAAM,YAAY,GAAG,IAAA,wBAAe,GAAE,CAAC;IACvC,GAAG,GAAG,IAAA,mBAAa,EAAC,YAAY,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC;IACrD,SAAS,GAAG,IAAA,wBAAY,EAAC,GAAG,CAAC,CAAC;AAChC,CAAC;AAJD,gDAIC;AAED,SAAsB,sBAAsB,CAAC,QAAkB;;;QAC7D,MAAM,EAAE,UAAU,EAAE,GAAG,QAAQ,CAAC;QAChC,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC;QAEvC,2BAA2B;QAC3B,MAAM,QAAQ,GAAG,IAAI,oBAAa,CAChC,QAAQ,CAAC,GAAG,CAAC,WAAW,KAAK,QAAQ;YACnC,CAAC,CAAC,mBAAY,CAAC,MAAM;YACrB,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAC5B,CAAC;QAEF,MAAM,kBAAkB,GAAG,QAAQ,CAAC,UAAU,CAAC;YAC7C,WAAW,EAAE,UAAU,CAAC,YAAY;YACpC,OAAO,EAAE,UAAU,CAAC,QAAQ;SAC7B,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,IAAA,cAAO,EAAC,GAAG,CAAC,CAAC;QAC1B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAEzB,MAAM,cAAc,GAAG,MAAM,IAAA,2BAAoB,EAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;QAE5E,IAAI,CAAC,CAAA,MAAA,cAAc,aAAd,cAAc,uBAAd,cAAc,CAAE,IAAI,0CAAE,KAAK,CAAA,EAAE;YAChC,MAAM,6IAA6I,CAAC;SACrJ;QAED,OAAO,cAAc,CAAC;;CACvB;AA1BD,wDA0BC;AAEM,MAAM,UAAU,GAAG,CAAI,IAAY,EAAE,GAAG,YAAsB,EAAE,EAAE;IACvE,OAAO,IAAA,sBAAY,EACjB,SAAS,EACT,IAAI,EACJ,GAAG,YAAY,CACU,CAAC;AAC9B,CAAC,CAAC;AANW,QAAA,UAAU,cAMrB;AAEK,MAAM,GAAG,GAAG,CAAI,IAAY,EAAE,EAAE;IACrC,OAAO,IAAA,eAAK,EAAC,SAAS,EAAE,IAAI,CAAyB,CAAC;AACxD,CAAC,CAAC;AAFW,QAAA,GAAG,OAEd;AAEK,MAAM,SAAS,GAAG,CAAI,IAAY,EAAE,EAAE;IAC3C,OAAO,IAAA,eAAK,EAAC,kBAAkB,EAAE,IAAI,CAAyB,CAAC;AACjE,CAAC,CAAC;AAFW,QAAA,SAAS,aAEpB;AAEF;;;GAGG;AACI,MAAM,eAAe,GAC1B,CAAO,EAA2B,EAAE,EAAE,CACtC,CAAO,IAAO,EAAE,EAAE;IAChB,IAAI;QACF,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC;KAChB;YAAS;QACR,IAAI,kBAAkB;YAAE,KAAK,IAAA,qBAAS,EAAC,kBAAkB,CAAC,CAAC;QAC3D,IAAI,SAAS;YAAE,KAAK,IAAA,qBAAS,EAAC,SAAS,CAAC,CAAC;KAC1C;AACH,CAAC,CAAA,CAAC;AATS,QAAA,eAAe,mBASxB"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /** Copyright © 2024-present P0 Security
4
+
5
+ This file is part of @p0security/cli
6
+
7
+ @p0security/cli is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
8
+
9
+ @p0security/cli is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
10
+
11
+ You should have received a copy of the GNU General Public License along with @p0security/cli. If not, see <https://www.gnu.org/licenses/>.
12
+ **/
13
+ const utils_1 = require("../utils");
14
+ describe("parseArn() function", () => {
15
+ it.each([
16
+ "badarn:aws:ec2:us-east-1:123456789012:vpc/vpc-0e9801d129EXAMPLE",
17
+ ":aws:ec2:us-east-1:123456789012:vpc/vpc-0e9801d129EXAMPLE",
18
+ "arn:aws:ec2:us-east-1:123456789012", // Too few elements
19
+ ])('Raises an "Invalid ARN" error', (arn) => {
20
+ expect(() => (0, utils_1.parseArn)(arn)).toThrow("Invalid AWS ARN");
21
+ });
22
+ it("Parses a valid ARN with all fields correctly", () => {
23
+ const arn = "arn:aws:ec2:us-east-1:123456789012:vpc/vpc-0e9801d129EXAMPLE";
24
+ const parsed = (0, utils_1.parseArn)(arn);
25
+ expect(parsed).toEqual({
26
+ partition: "aws",
27
+ service: "ec2",
28
+ region: "us-east-1",
29
+ accountId: "123456789012",
30
+ resource: "vpc/vpc-0e9801d129EXAMPLE",
31
+ });
32
+ });
33
+ it("Parses a valid ARN with colons in the resource correctly", () => {
34
+ // Note: This is not the format we would expect an EKS ARN to actually be in (it should
35
+ // use a / instead of a : in the resource); this is just for unit testing purposes.
36
+ const arn = "arn:aws:eks:us-west-2:123456789012:cluster:my-testing-cluster";
37
+ const parsed = (0, utils_1.parseArn)(arn);
38
+ expect(parsed).toEqual({
39
+ partition: "aws",
40
+ service: "eks",
41
+ region: "us-west-2",
42
+ accountId: "123456789012",
43
+ resource: "cluster:my-testing-cluster",
44
+ });
45
+ });
46
+ it("Parses a valid ARN with no region correctly", () => {
47
+ const arn = "arn:aws:iam::123456789012:user/johndoe";
48
+ const parsed = (0, utils_1.parseArn)(arn);
49
+ expect(parsed).toEqual({
50
+ partition: "aws",
51
+ service: "iam",
52
+ region: "",
53
+ accountId: "123456789012",
54
+ resource: "user/johndoe",
55
+ });
56
+ });
57
+ it("Parses a valid ARN with no account ID correctly", () => {
58
+ // Note: This is not a valid SNS ARN; they would ordinarily have an account ID. This is
59
+ // just for unit testing purposes.
60
+ const arn = "arn:aws-us-gov:sns:us-east-1::example-sns-topic-name";
61
+ const parsed = (0, utils_1.parseArn)(arn);
62
+ expect(parsed).toEqual({
63
+ partition: "aws-us-gov",
64
+ service: "sns",
65
+ region: "us-east-1",
66
+ accountId: "",
67
+ resource: "example-sns-topic-name",
68
+ });
69
+ });
70
+ it("Parses a valid ARN with no region or account ID correctly", () => {
71
+ const arn = "arn:aws-cn:s3:::my-corporate-bucket";
72
+ const parsed = (0, utils_1.parseArn)(arn);
73
+ expect(parsed).toEqual({
74
+ partition: "aws-cn",
75
+ service: "s3",
76
+ region: "",
77
+ accountId: "",
78
+ resource: "my-corporate-bucket",
79
+ });
80
+ });
81
+ });
82
+ //# sourceMappingURL=utils.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.test.js","sourceRoot":"","sources":["../../../../src/plugins/aws/__tests__/utils.test.ts"],"names":[],"mappings":";;AAAA;;;;;;;;;GASG;AACH,oCAAoC;AAEpC,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,IAAI,CAAC;QACN,iEAAiE;QACjE,2DAA2D;QAC3D,oCAAoC,EAAE,mBAAmB;KAC1D,CAAC,CAAC,+BAA+B,EAAE,CAAC,GAAG,EAAE,EAAE;QAC1C,MAAM,CAAC,GAAG,EAAE,CAAC,IAAA,gBAAQ,EAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,GAAG,GAAG,8DAA8D,CAAC;QAE3E,MAAM,MAAM,GAAG,IAAA,gBAAQ,EAAC,GAAG,CAAC,CAAC;QAE7B,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB,SAAS,EAAE,KAAK;YAChB,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,WAAW;YACnB,SAAS,EAAE,cAAc;YACzB,QAAQ,EAAE,2BAA2B;SACtC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,uFAAuF;QACvF,mFAAmF;QACnF,MAAM,GAAG,GAAG,+DAA+D,CAAC;QAE5E,MAAM,MAAM,GAAG,IAAA,gBAAQ,EAAC,GAAG,CAAC,CAAC;QAE7B,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB,SAAS,EAAE,KAAK;YAChB,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,WAAW;YACnB,SAAS,EAAE,cAAc;YACzB,QAAQ,EAAE,4BAA4B;SACvC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,GAAG,GAAG,wCAAwC,CAAC;QAErD,MAAM,MAAM,GAAG,IAAA,gBAAQ,EAAC,GAAG,CAAC,CAAC;QAE7B,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB,SAAS,EAAE,KAAK;YAChB,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,EAAE;YACV,SAAS,EAAE,cAAc;YACzB,QAAQ,EAAE,cAAc;SACzB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,uFAAuF;QACvF,kCAAkC;QAClC,MAAM,GAAG,GAAG,sDAAsD,CAAC;QAEnE,MAAM,MAAM,GAAG,IAAA,gBAAQ,EAAC,GAAG,CAAC,CAAC;QAE7B,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB,SAAS,EAAE,YAAY;YACvB,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,WAAW;YACnB,SAAS,EAAE,EAAE;YACb,QAAQ,EAAE,wBAAwB;SACnC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,GAAG,GAAG,qCAAqC,CAAC;QAElD,MAAM,MAAM,GAAG,IAAA,gBAAQ,EAAC,GAAG,CAAC,CAAC;QAE7B,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB,SAAS,EAAE,QAAQ;YACnB,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,EAAE;YACV,SAAS,EAAE,EAAE;YACb,QAAQ,EAAE,qBAAqB;SAChC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Parses out Amazon Resource Names (ARNs) from AWS into their components. Note
3
+ * that not all components are present in all ARNs (depending on the service;
4
+ * for example, S3 ARNs don't have a region or account ID), and the final
5
+ * component of the ARN (`resource`) may contain its own internal structure that
6
+ * is also service-dependent and which may also include colons. In particular,
7
+ * quoting the Amazon docs: "Be aware that the ARNs for some resources omit the
8
+ * Region, the account ID, or both the Region and the account ID."
9
+ *
10
+ * @param arn The ARN to parse as a string.
11
+ * @return A structure representing the components of the ARN. All fields will
12
+ * be defined, but some may be empty strings if they are not present in the ARN.
13
+ */
14
+ export declare const parseArn: (arn: string) => {
15
+ partition: string;
16
+ service: string;
17
+ region: string;
18
+ accountId: string;
19
+ resource: string;
20
+ };
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseArn = void 0;
4
+ /** Copyright © 2024-present P0 Security
5
+
6
+ This file is part of @p0security/cli
7
+
8
+ @p0security/cli is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
9
+
10
+ @p0security/cli is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
11
+
12
+ You should have received a copy of the GNU General Public License along with @p0security/cli. If not, see <https://www.gnu.org/licenses/>.
13
+ **/
14
+ const ARN_PATTERN = /^arn:(aws|aws-us-gov|aws-cn|aws-iso|aws-iso-b):([^:]*):([^:]*):([^:]*):(.*)$/;
15
+ /**
16
+ * Parses out Amazon Resource Names (ARNs) from AWS into their components. Note
17
+ * that not all components are present in all ARNs (depending on the service;
18
+ * for example, S3 ARNs don't have a region or account ID), and the final
19
+ * component of the ARN (`resource`) may contain its own internal structure that
20
+ * is also service-dependent and which may also include colons. In particular,
21
+ * quoting the Amazon docs: "Be aware that the ARNs for some resources omit the
22
+ * Region, the account ID, or both the Region and the account ID."
23
+ *
24
+ * @param arn The ARN to parse as a string.
25
+ * @return A structure representing the components of the ARN. All fields will
26
+ * be defined, but some may be empty strings if they are not present in the ARN.
27
+ */
28
+ const parseArn = (arn) => {
29
+ // Reference: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference-arns.html
30
+ const invalidArnMsg = `Invalid AWS ARN: ${arn}`;
31
+ const match = arn.match(ARN_PATTERN);
32
+ if (!match) {
33
+ throw invalidArnMsg;
34
+ }
35
+ const [_, partition, service, region, accountId, resource] = match;
36
+ // We know these are all defined based on the regex, but TypeScript doesn't.
37
+ // Empty string is okay, so explicitly check for undefined.
38
+ if (partition === undefined ||
39
+ service === undefined ||
40
+ accountId === undefined ||
41
+ region === undefined ||
42
+ resource === undefined) {
43
+ throw invalidArnMsg;
44
+ }
45
+ return {
46
+ partition,
47
+ service,
48
+ region,
49
+ accountId,
50
+ resource,
51
+ };
52
+ };
53
+ exports.parseArn = parseArn;
54
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/plugins/aws/utils.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;GASG;AACH,MAAM,WAAW,GACf,8EAA8E,CAAC;AAEjF;;;;;;;;;;;;GAYG;AACI,MAAM,QAAQ,GAAG,CACtB,GAAW,EAOX,EAAE;IACF,kFAAkF;IAClF,MAAM,aAAa,GAAG,oBAAoB,GAAG,EAAE,CAAC;IAChD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAErC,IAAI,CAAC,KAAK,EAAE;QACV,MAAM,aAAa,CAAC;KACrB;IAED,MAAM,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC;IAEnE,4EAA4E;IAC5E,2DAA2D;IAC3D,IACE,SAAS,KAAK,SAAS;QACvB,OAAO,KAAK,SAAS;QACrB,SAAS,KAAK,SAAS;QACvB,MAAM,KAAK,SAAS;QACpB,QAAQ,KAAK,SAAS,EACtB;QACA,MAAM,aAAa,CAAC;KACrB;IAED,OAAO;QACL,SAAS;QACT,OAAO;QACP,MAAM;QACN,SAAS;QACT,QAAQ;KACT,CAAC;AACJ,CAAC,CAAC;AAtCW,QAAA,QAAQ,YAsCnB"}
@@ -26,7 +26,7 @@ You should have received a copy of the GNU General Public License along with @p0
26
26
  const oidc_1 = require("../../common/auth/oidc");
27
27
  const server_1 = require("../../common/auth/server");
28
28
  const fetch_1 = require("../../common/fetch");
29
- const env_1 = require("../../drivers/env");
29
+ const config_1 = require("../../drivers/config");
30
30
  const stdio_1 = require("../../drivers/stdio");
31
31
  const open_1 = __importDefault(require("open"));
32
32
  const GOOGLE_OIDC_URL = "https://accounts.google.com/o/oauth2/v2/auth";
@@ -35,10 +35,11 @@ const GOOGLE_OIDC_REDIRECT_PORT = 52700;
35
35
  const GOOGLE_OIDC_REDIRECT_URL = `http://127.0.0.1:${GOOGLE_OIDC_REDIRECT_PORT}`;
36
36
  const PKCE_LENGTH = 128;
37
37
  const requestAuth = () => __awaiter(void 0, void 0, void 0, function* () {
38
+ const tenantConfig = (0, config_1.getTenantConfig)();
38
39
  const pkceChallenge = (yield import("pkce-challenge")).default;
39
40
  const pkce = yield pkceChallenge(PKCE_LENGTH);
40
41
  const authBody = {
41
- client_id: env_1.config.google.clientId,
42
+ client_id: tenantConfig.google.clientId,
42
43
  code_challenge: pkce.code_challenge,
43
44
  code_challenge_method: "S256",
44
45
  redirect_uri: GOOGLE_OIDC_REDIRECT_URL,
@@ -54,9 +55,10 @@ ${url}`);
54
55
  return pkce;
55
56
  });
56
57
  const requestToken = (code, pkce) => __awaiter(void 0, void 0, void 0, function* () {
58
+ const tenantConfig = (0, config_1.getTenantConfig)();
57
59
  const body = {
58
- client_id: env_1.config.google.clientId,
59
- client_secret: env_1.config.google.clientSecret,
60
+ client_id: tenantConfig.google.clientId,
61
+ client_secret: tenantConfig.google.clientSecret,
60
62
  code,
61
63
  code_verifier: pkce.code_verifier,
62
64
  grant_type: "authorization_code",
@@ -1 +1 @@
1
- {"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/plugins/google/login.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA;;;;;;;;;GASG;AACH,iDAAsD;AACtD,qDAA8D;AAC9D,8CAAiE;AACjE,2CAA2C;AAC3C,+CAA6C;AAE7C,gDAAwB;AAOxB,MAAM,eAAe,GAAG,8CAA8C,CAAC;AACvE,MAAM,wBAAwB,GAAG,qCAAqC,CAAC;AACvE,MAAM,yBAAyB,GAAG,KAAK,CAAC;AACxC,MAAM,wBAAwB,GAAG,oBAAoB,yBAAyB,EAAE,CAAC;AACjF,MAAM,WAAW,GAAG,GAAG,CAAC;AAExB,MAAM,WAAW,GAAG,GAAS,EAAE;IAC7B,MAAM,aAAa,GAAG,CAAC,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,OAAc,CAAC;IACtE,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,WAAW,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAqB;QACjC,SAAS,EAAE,YAAM,CAAC,MAAM,CAAC,QAAQ;QACjC,cAAc,EAAE,IAAI,CAAC,cAAc;QACnC,qBAAqB,EAAE,MAAM;QAC7B,YAAY,EAAE,wBAAwB;QACtC,aAAa,EAAE,MAAM;QACrB,KAAK,EAAE,QAAQ;KAChB,CAAC;IACF,MAAM,GAAG,GAAG,GAAG,eAAe,IAAI,IAAA,iBAAS,EAAC,QAAQ,CAAC,EAAE,CAAC;IACxD,IAAA,cAAI,EAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;QACnB,IAAA,cAAM,EAAC;;EAET,GAAG,EAAE,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IACH,OAAO,IAAI,CAAC;AACd,CAAC,CAAA,CAAC;AAEF,MAAM,YAAY,GAAG,CACnB,IAAY,EACZ,IAAuD,EACvD,EAAE;IACF,MAAM,IAAI,GAAG;QACX,SAAS,EAAE,YAAM,CAAC,MAAM,CAAC,QAAQ;QACjC,aAAa,EAAE,YAAM,CAAC,MAAM,CAAC,YAAY;QACzC,IAAI;QACJ,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,UAAU,EAAE,oBAAoB;QAChC,YAAY,EAAE,wBAAwB;KACvC,CAAC;IACF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,wBAAwB,EAAE;QACrD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,mBAAY;QACrB,IAAI,EAAE,IAAA,iBAAS,EAAC,IAAI,CAAC;KACtB,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,MAAM,IAAA,wBAAgB,EAAC,QAAQ,CAAC,CAAC;IAC/C,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,EAAE,CAAkB,CAAC;AAC/C,CAAC,CAAA,CAAC;AAEK,MAAM,WAAW,GAAG,GAAS,EAAE;IACpC,OAAO,MAAM,IAAA,2BAAkB,EAC7B,GAAS,EAAE,kDAAC,OAAA,MAAM,WAAW,EAAE,CAAA,GAAA,EAC/B,CAAO,IAAI,EAAE,KAAK,EAAE,EAAE,kDAAC,OAAA,MAAM,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA,GAAA,EAC3D,EAAE,IAAI,EAAE,yBAAyB,EAAE,CACpC,CAAC;AACJ,CAAC,CAAA,CAAC;AANW,QAAA,WAAW,eAMtB"}
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/plugins/google/login.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA;;;;;;;;;GASG;AACH,iDAAsD;AACtD,qDAA8D;AAC9D,8CAAiE;AACjE,iDAAuD;AACvD,+CAA6C;AAE7C,gDAAwB;AAOxB,MAAM,eAAe,GAAG,8CAA8C,CAAC;AACvE,MAAM,wBAAwB,GAAG,qCAAqC,CAAC;AACvE,MAAM,yBAAyB,GAAG,KAAK,CAAC;AACxC,MAAM,wBAAwB,GAAG,oBAAoB,yBAAyB,EAAE,CAAC;AACjF,MAAM,WAAW,GAAG,GAAG,CAAC;AAExB,MAAM,WAAW,GAAG,GAAS,EAAE;IAC7B,MAAM,YAAY,GAAG,IAAA,wBAAe,GAAE,CAAC;IACvC,MAAM,aAAa,GAAG,CAAC,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,OAAc,CAAC;IACtE,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,WAAW,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAqB;QACjC,SAAS,EAAE,YAAY,CAAC,MAAM,CAAC,QAAQ;QACvC,cAAc,EAAE,IAAI,CAAC,cAAc;QACnC,qBAAqB,EAAE,MAAM;QAC7B,YAAY,EAAE,wBAAwB;QACtC,aAAa,EAAE,MAAM;QACrB,KAAK,EAAE,QAAQ;KAChB,CAAC;IACF,MAAM,GAAG,GAAG,GAAG,eAAe,IAAI,IAAA,iBAAS,EAAC,QAAQ,CAAC,EAAE,CAAC;IACxD,IAAA,cAAI,EAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;QACnB,IAAA,cAAM,EAAC;;EAET,GAAG,EAAE,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IACH,OAAO,IAAI,CAAC;AACd,CAAC,CAAA,CAAC;AAEF,MAAM,YAAY,GAAG,CACnB,IAAY,EACZ,IAAuD,EACvD,EAAE;IACF,MAAM,YAAY,GAAG,IAAA,wBAAe,GAAE,CAAC;IACvC,MAAM,IAAI,GAAG;QACX,SAAS,EAAE,YAAY,CAAC,MAAM,CAAC,QAAQ;QACvC,aAAa,EAAE,YAAY,CAAC,MAAM,CAAC,YAAY;QAC/C,IAAI;QACJ,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,UAAU,EAAE,oBAAoB;QAChC,YAAY,EAAE,wBAAwB;KACvC,CAAC;IACF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,wBAAwB,EAAE;QACrD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,mBAAY;QACrB,IAAI,EAAE,IAAA,iBAAS,EAAC,IAAI,CAAC;KACtB,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,MAAM,IAAA,wBAAgB,EAAC,QAAQ,CAAC,CAAC;IAC/C,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,EAAE,CAAkB,CAAC;AAC/C,CAAC,CAAA,CAAC;AAEK,MAAM,WAAW,GAAG,GAAS,EAAE;IACpC,OAAO,MAAM,IAAA,2BAAkB,EAC7B,GAAS,EAAE,kDAAC,OAAA,MAAM,WAAW,EAAE,CAAA,GAAA,EAC/B,CAAO,IAAI,EAAE,KAAK,EAAE,EAAE,kDAAC,OAAA,MAAM,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA,GAAA,EAC3D,EAAE,IAAI,EAAE,yBAAyB,EAAE,CACpC,CAAC;AACJ,CAAC,CAAA,CAAC;AANW,QAAA,WAAW,eAMtB"}
@@ -12,7 +12,7 @@ import { KubeconfigCommandArgs } from "../../commands/kubeconfig";
12
12
  import { Authn } from "../../types/identity";
13
13
  import { Request } from "../../types/request";
14
14
  import { AwsCredentials } from "../aws/types";
15
- import { K8sGenerated, K8sPermissionSpec } from "./types";
15
+ import { K8sPermissionSpec } from "./types";
16
16
  import yargs from "yargs";
17
17
  export declare const getAndValidateK8sIntegration: (authn: Authn, clusterId: string) => Promise<{
18
18
  clusterConfig: {
@@ -24,4 +24,4 @@ export declare const getAndValidateK8sIntegration: (authn: Authn, clusterId: str
24
24
  }>;
25
25
  export declare const requestAccessToCluster: (authn: Authn, args: yargs.ArgumentsCamelCase<KubeconfigCommandArgs>, clusterId: string, role: string) => Promise<Request<K8sPermissionSpec>>;
26
26
  export declare const profileName: (eksCluterName: string) => string;
27
- export declare const awsCloudAuth: (authn: Authn, awsAccountId: string, generated: K8sGenerated, loginType: "federated" | "idc") => Promise<AwsCredentials>;
27
+ export declare const awsCloudAuth: (authn: Authn, awsAccountId: string, request: Request<K8sPermissionSpec>, loginType: "federated" | "idc") => Promise<AwsCredentials>;
@@ -17,6 +17,7 @@ const stdio_1 = require("../../drivers/stdio");
17
17
  const util_1 = require("../../util");
18
18
  const config_1 = require("../aws/config");
19
19
  const idc_1 = require("../aws/idc");
20
+ const utils_1 = require("../aws/utils");
20
21
  const aws_1 = require("../okta/aws");
21
22
  const firestore_2 = require("firebase/firestore");
22
23
  const lodash_1 = require("lodash");
@@ -28,15 +29,16 @@ const getAndValidateK8sIntegration = (authn, clusterId) => __awaiter(void 0, voi
28
29
  if (!config) {
29
30
  throw `Cluster with ID ${clusterId} not found`;
30
31
  }
31
- if (config.state !== "installed" || config.provider.type !== "aws") {
32
+ if (config.state !== "installed") {
32
33
  throw `Cluster with ID ${clusterId} is not installed`;
33
34
  }
34
- const { provider } = config;
35
- const { accountId: awsAccountId, clusterArn: awsClusterArn } = provider;
36
- if (!awsAccountId || !awsClusterArn) {
35
+ const { hosting } = config;
36
+ if (hosting.type !== "aws") {
37
37
  throw (`This command currently only supports AWS EKS clusters, and ${clusterId} is not configured as one.\n` +
38
38
  "You can request access to the cluster using the `p0 request k8s` command.");
39
39
  }
40
+ const { arn: awsClusterArn } = hosting;
41
+ const { accountId: awsAccountId } = (0, utils_1.parseArn)(awsClusterArn);
40
42
  const { config: awsConfig } = yield (0, config_1.getAwsConfig)(authn, awsAccountId);
41
43
  const { login: awsLogin } = awsConfig;
42
44
  // Verify that the AWS auth type is supported before issuing the requests
@@ -70,28 +72,29 @@ const requestAccessToCluster = (authn, args, clusterId, role) => __awaiter(void
70
72
  if (!response) {
71
73
  throw "Did not receive access ID from server";
72
74
  }
73
- const { id, isPreexisting } = response;
74
- if (!isPreexisting) {
75
- (0, stdio_1.print2)("Waiting for access to be provisioned. This may take up to a minute.");
76
- }
77
- return yield (0, shared_1.waitForProvisioning)(authn, id);
75
+ const { id } = response;
76
+ return yield (0, stdio_1.spinUntil)("Waiting for access to be provisioned. This may take up to a minute.", (0, shared_1.waitForProvisioning)(authn, id));
78
77
  });
79
78
  exports.requestAccessToCluster = requestAccessToCluster;
80
79
  const profileName = (eksCluterName) => `p0cli-managed-eks-${eksCluterName}`;
81
80
  exports.profileName = profileName;
82
- const awsCloudAuth = (authn, awsAccountId, generated, loginType) => __awaiter(void 0, void 0, void 0, function* () {
81
+ const awsCloudAuth = (authn, awsAccountId, request, loginType) => __awaiter(void 0, void 0, void 0, function* () {
82
+ var _c;
83
+ const { permission, generated } = request;
83
84
  const { eksGenerated } = generated;
84
- const { name, idc } = eksGenerated;
85
+ const { name } = eksGenerated;
85
86
  switch (loginType) {
86
- case "idc":
87
- if (!idc) {
87
+ case "idc": {
88
+ const { idcId, idcRegion } = (_c = permission.awsResourcePermission) !== null && _c !== void 0 ? _c : {};
89
+ if (!idcId || !idcRegion) {
88
90
  throw "AWS is configured to use Identity Center, but IDC information wasn't received in the request.";
89
91
  }
90
92
  return yield (0, idc_1.assumeRoleWithIdc)({
91
93
  accountId: awsAccountId,
92
94
  permissionSet: name,
93
- idc,
95
+ idc: { id: idcId, region: idcRegion },
94
96
  });
97
+ }
95
98
  case "federated":
96
99
  return yield (0, aws_1.assumeRoleWithOktaSaml)(authn, {
97
100
  accountId: awsAccountId,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/plugins/kubeconfig/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/plugins/kubeconfig/index.ts"],"names":[],"mappings":"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"}
@@ -16,12 +16,13 @@ export type K8sClusterConfig = {
16
16
  isProxy: boolean;
17
17
  token: string;
18
18
  publicJwk?: string;
19
- provider: {
19
+ hosting: {
20
20
  type: "aws";
21
- clusterArn: string;
22
- accountId: string;
21
+ arn: string;
23
22
  } | {
24
- type: "email";
23
+ type: "azure";
24
+ } | {
25
+ type: "gcp";
25
26
  };
26
27
  state: string;
27
28
  };
@@ -38,14 +39,14 @@ export type K8sResourcePermission = {
38
39
  role: string;
39
40
  clusterId: string;
40
41
  type: "resource";
42
+ awsResourcePermission?: {
43
+ idcRegion?: string;
44
+ idcId?: string;
45
+ };
41
46
  };
42
47
  export type K8sGenerated = {
43
48
  eksGenerated: {
44
49
  name: string;
45
- idc?: {
46
- id: string;
47
- region: string;
48
- };
49
50
  };
50
51
  role: string;
51
52
  };
@@ -136,12 +136,8 @@ function spawnSshNode(options) {
136
136
  return;
137
137
  }
138
138
  (_b = options.abortController) === null || _b === void 0 ? void 0 : _b.abort(code);
139
- if (code && code !== 0) {
140
- (0, stdio_1.print2)(`Failed to establish an SSH session.${!options.debug ? " Use the --debug option to see additional details." : ""}`);
141
- }
142
- else if (!options.isAccessPropagationPreTest) {
139
+ if (!options.isAccessPropagationPreTest)
143
140
  (0, stdio_1.print2)(`SSH session terminated`);
144
- }
145
141
  resolve(code);
146
142
  });
147
143
  });
@@ -274,9 +270,8 @@ const sshOrScp = (args) => __awaiter(void 0, void 0, void 0, function* () {
274
270
  }
275
271
  const endTime = Date.now() + sshProvider.propagationTimeoutMs;
276
272
  const exitCode = yield preTestAccessPropagationIfNeeded(sshProvider, request, cmdArgs, proxyCommand, credential, endTime);
277
- // Only exit if there was an error when pre-testing
278
273
  if (exitCode && exitCode !== 0) {
279
- return exitCode;
274
+ return exitCode; // Only exit if there was an error when pre-testing
280
275
  }
281
276
  return spawnSshNode({
282
277
  credential,