@p0security/cli 0.8.1 → 0.8.2

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 (39) hide show
  1. package/dist/commands/scp.d.ts +1 -1
  2. package/dist/commands/scp.js +5 -4
  3. package/dist/commands/shared/index.d.ts +4 -0
  4. package/dist/commands/shared/index.js +67 -0
  5. package/dist/commands/{shared.d.ts → shared/ssh.d.ts} +6 -22
  6. package/dist/commands/{shared.js → shared/ssh.js} +18 -74
  7. package/dist/commands/ssh.d.ts +1 -1
  8. package/dist/commands/ssh.js +3 -3
  9. package/dist/common/retry.d.ts +9 -0
  10. package/dist/common/retry.js +50 -0
  11. package/dist/drivers/auth.d.ts +1 -1
  12. package/dist/drivers/auth.js +7 -3
  13. package/dist/plugins/aws/config.d.ts +1 -1
  14. package/dist/plugins/aws/idc/index.d.ts +16 -0
  15. package/dist/plugins/aws/idc/index.js +150 -0
  16. package/dist/plugins/aws/ssh.d.ts +3 -3
  17. package/dist/plugins/aws/ssh.js +21 -11
  18. package/dist/plugins/aws/types.d.ts +29 -5
  19. package/dist/plugins/google/ssh.d.ts +5 -3
  20. package/dist/plugins/google/ssh.js +26 -10
  21. package/dist/plugins/google/types.d.ts +11 -3
  22. package/dist/plugins/login.d.ts +3 -0
  23. package/dist/plugins/login.js +10 -0
  24. package/dist/plugins/oidc/login.d.ts +33 -2
  25. package/dist/plugins/oidc/login.js +100 -60
  26. package/dist/plugins/okta/aws.d.ts +1 -1
  27. package/dist/plugins/okta/aws.js +2 -2
  28. package/dist/plugins/okta/login.js +11 -1
  29. package/dist/plugins/ping/login.d.ts +2 -1
  30. package/dist/plugins/ping/login.js +11 -1
  31. package/dist/plugins/ssh/index.d.ts +2 -1
  32. package/dist/plugins/ssh/index.js +14 -5
  33. package/dist/types/aws/oidc.d.ts +36 -0
  34. package/dist/types/aws/oidc.js +12 -0
  35. package/dist/types/oidc.d.ts +21 -0
  36. package/dist/types/request.d.ts +2 -7
  37. package/dist/types/ssh.d.ts +27 -0
  38. package/dist/types/ssh.js +5 -0
  39. package/package.json +1 -1
@@ -8,7 +8,8 @@ This file is part of @p0security/cli
8
8
 
9
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
10
  **/
11
- import { CliPermissionSpec, PermissionSpec } from "../../types/request";
11
+ import { PermissionSpec } from "../../types/request";
12
+ import { CliPermissionSpec } from "../../types/ssh";
12
13
  import { CommonSshPermissionSpec } from "../ssh/types";
13
14
  export declare type AwsCredentials = {
14
15
  AWS_ACCESS_KEY_ID: string;
@@ -40,7 +41,7 @@ export declare type AwsFederatedLogin = {
40
41
  };
41
42
  };
42
43
  };
43
- declare type AwsLogin = AwsFederatedLogin | AwsIamLogin | AwsIdcLogin;
44
+ export declare type AwsLogin = AwsFederatedLogin | AwsIamLogin | AwsIdcLogin;
44
45
  export declare type AwsItemConfig = {
45
46
  label?: string;
46
47
  state: string;
@@ -66,7 +67,30 @@ export declare type AwsSshGenerated = {
66
67
  ssh: {
67
68
  linuxUserName: string;
68
69
  };
70
+ idc?: {
71
+ region: string;
72
+ id: string;
73
+ };
74
+ };
75
+ export declare type AwsSshPermissionSpec = PermissionSpec<"ssh", AwsSshPermission, AwsSshGenerated>;
76
+ export declare type AwsSsh = CliPermissionSpec<AwsSshPermissionSpec, undefined>;
77
+ export declare type BaseAwsSshRequest = {
78
+ linuxUserName: string;
79
+ accountId: string;
80
+ region: string;
81
+ id: string;
82
+ type: "aws";
83
+ };
84
+ export declare type AwsSshRoleRequest = BaseAwsSshRequest & {
85
+ role: string;
86
+ access: "role";
87
+ };
88
+ export declare type AwsSshIdcRequest = BaseAwsSshRequest & {
89
+ permissionSet: string;
90
+ idc: {
91
+ id: string;
92
+ region: string;
93
+ };
94
+ access: "idc";
69
95
  };
70
- export declare type AwsPermissionSpec = PermissionSpec<"ssh", AwsSshPermission, AwsSshGenerated>;
71
- export declare type AwsSsh = CliPermissionSpec<AwsPermissionSpec>;
72
- export {};
96
+ export declare type AwsSshRequest = AwsSshIdcRequest | AwsSshRoleRequest;
@@ -8,6 +8,8 @@ This file is part of @p0security/cli
8
8
 
9
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
10
  **/
11
- import { SshRequest } from "../../commands/shared";
12
- import { GcpSsh } from "./types";
13
- export declare const gcpRequestToSsh: (request: GcpSsh) => SshRequest;
11
+ import { SshProvider } from "../../types/ssh";
12
+ import { GcpSshPermissionSpec, GcpSshRequest } from "./types";
13
+ export declare const gcpSshProvider: SshProvider<GcpSshPermissionSpec, {
14
+ linuxUserName: string;
15
+ }, GcpSshRequest>;
@@ -1,13 +1,29 @@
1
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
+ };
2
11
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.gcpRequestToSsh = void 0;
4
- const gcpRequestToSsh = (request) => {
5
- return {
6
- id: request.permission.spec.instanceName,
7
- projectId: request.permission.spec.projectId,
8
- zone: request.permission.spec.zone,
9
- linuxUserName: request.cliLocalData.linuxUserName,
10
- type: "gcloud",
11
- };
12
+ exports.gcpSshProvider = void 0;
13
+ const ssh_key_1 = require("./ssh-key");
14
+ exports.gcpSshProvider = {
15
+ requestToSsh: (request) => {
16
+ return {
17
+ id: request.permission.spec.instanceName,
18
+ projectId: request.permission.spec.projectId,
19
+ zone: request.permission.spec.zone,
20
+ linuxUserName: request.cliLocalData.linuxUserName,
21
+ type: "gcloud",
22
+ };
23
+ },
24
+ toCliRequest: (request, options) => __awaiter(void 0, void 0, void 0, function* () {
25
+ return (Object.assign(Object.assign({}, request), { cliLocalData: {
26
+ linuxUserName: yield (0, ssh_key_1.importSshKey)(request.permission.spec.publicKey, options),
27
+ } }));
28
+ }),
12
29
  };
13
- exports.gcpRequestToSsh = gcpRequestToSsh;
@@ -8,7 +8,8 @@ This file is part of @p0security/cli
8
8
 
9
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
10
  **/
11
- import { CliPermissionSpec, PermissionSpec } from "../../types/request";
11
+ import { PermissionSpec } from "../../types/request";
12
+ import { CliPermissionSpec } from "../../types/ssh";
12
13
  import { CommonSshPermissionSpec } from "../ssh/types";
13
14
  export declare type GcpSshPermission = {
14
15
  spec: CommonSshPermissionSpec & {
@@ -19,10 +20,17 @@ export declare type GcpSshPermission = {
19
20
  };
20
21
  type: "session";
21
22
  };
22
- export declare type GcpPermissionSpec = PermissionSpec<"ssh", GcpSshPermission>;
23
- export declare type GcpSsh = CliPermissionSpec<GcpPermissionSpec, {
23
+ export declare type GcpSshPermissionSpec = PermissionSpec<"ssh", GcpSshPermission>;
24
+ export declare type GcpSsh = CliPermissionSpec<GcpSshPermissionSpec, {
24
25
  linuxUserName: string;
25
26
  }>;
27
+ export declare type GcpSshRequest = {
28
+ linuxUserName: string;
29
+ projectId: string;
30
+ zone: string;
31
+ id: string;
32
+ type: "gcloud";
33
+ };
26
34
  declare type PosixAccount = {
27
35
  username: string;
28
36
  uid: string;
@@ -10,4 +10,7 @@ You should have received a copy of the GNU General Public License along with @p0
10
10
  **/
11
11
  import { TokenResponse } from "../types/oidc";
12
12
  import { OrgData } from "../types/org";
13
+ declare const loginPlugins: readonly ["google", "okta", "ping", "oidc-pkce", "microsoft", "azure-oidc", "google-oidc", "aws-oidc"];
14
+ export declare type LoginPluginType = (typeof loginPlugins)[number];
13
15
  export declare const pluginLoginMap: Record<string, (org: OrgData) => Promise<TokenResponse>>;
16
+ export {};
@@ -13,6 +13,16 @@ exports.pluginLoginMap = void 0;
13
13
  const login_1 = require("./google/login");
14
14
  const login_2 = require("./okta/login");
15
15
  const login_3 = require("./ping/login");
16
+ const loginPlugins = [
17
+ "google",
18
+ "okta",
19
+ "ping",
20
+ "oidc-pkce",
21
+ "microsoft",
22
+ "azure-oidc",
23
+ "google-oidc",
24
+ "aws-oidc",
25
+ ];
16
26
  exports.pluginLoginMap = {
17
27
  google: login_1.googleLogin,
18
28
  okta: login_2.oktaLogin,
@@ -1,5 +1,36 @@
1
- import { TokenResponse } from "../../types/oidc";
1
+ import { AuthorizeResponse, OidcLoginSteps } from "../../types/oidc";
2
2
  import { OrgData } from "../../types/org";
3
+ export declare const DEVICE_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code";
3
4
  export declare const validateProviderDomain: (org: OrgData) => void;
5
+ /** Executes the first step of a device-authorization grant flow */
6
+ export declare const authorize: <T>(request: {
7
+ url: string;
8
+ init: RequestInit;
9
+ }, validateResponse: (response: Response) => Promise<Response>) => Promise<T>;
10
+ /** Attempts to fetch this device's OIDC token
11
+ *
12
+ * The authorization may or may not be granted at this stage. If it is not, the
13
+ * authorization server will return "authorization_pending", in which case this
14
+ * function will return undefined.
15
+ */
16
+ export declare const fetchOidcToken: <T>(request: {
17
+ url: string;
18
+ init: RequestInit;
19
+ }) => Promise<T | undefined>;
20
+ /** Waits until user device authorization is complete
21
+ *
22
+ * Returns the OIDC token after completion.
23
+ */
24
+ export declare const waitForActivation: <A, T>(authorize: A, extractExpiryInterval: (authorize: A) => {
25
+ expires_in: number;
26
+ interval: number;
27
+ }, tokenRequest: {
28
+ url: string;
29
+ init: RequestInit;
30
+ }) => Promise<NonNullable<Awaited<T>>>;
31
+ export declare const oidcLoginSteps: (org: OrgData, scope: string, urls: () => {
32
+ deviceAuthorizationUrl: string;
33
+ tokenUrl: string;
34
+ }) => OidcLoginSteps<AuthorizeResponse>;
4
35
  /** Logs in to an Identity Provider via OIDC */
5
- export declare const oidcLogin: (org: OrgData, scope: string) => Promise<TokenResponse>;
36
+ export declare const oidcLogin: <A, T>(steps: OidcLoginSteps<A>) => Promise<NonNullable<Awaited<T>>>;
@@ -12,7 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.oidcLogin = exports.validateProviderDomain = void 0;
15
+ exports.oidcLogin = exports.oidcLoginSteps = exports.waitForActivation = exports.fetchOidcToken = exports.authorize = exports.validateProviderDomain = exports.DEVICE_GRANT_TYPE = void 0;
16
16
  /** Copyright © 2024-present P0 Security
17
17
 
18
18
  This file is part of @p0security/cli
@@ -27,107 +27,147 @@ const oidc_1 = require("../../common/auth/oidc");
27
27
  const fetch_1 = require("../../common/fetch");
28
28
  const stdio_1 = require("../../drivers/stdio");
29
29
  const util_1 = require("../../util");
30
- const lodash_1 = require("lodash");
31
30
  const open_1 = __importDefault(require("open"));
32
- const DEVICE_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code";
31
+ exports.DEVICE_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code";
33
32
  const validateProviderDomain = (org) => {
34
33
  if (!org.providerDomain)
35
34
  throw "Login requires a configured provider domain.";
36
35
  };
37
36
  exports.validateProviderDomain = validateProviderDomain;
37
+ const oidcProviderLabels = (providerType) => {
38
+ switch (providerType) {
39
+ case "okta":
40
+ return "Okta";
41
+ case "ping":
42
+ return "PingOne";
43
+ case "google":
44
+ case "google-oidc":
45
+ return "Google";
46
+ case "oidc-pkce":
47
+ return "OIDC";
48
+ case "aws-oidc":
49
+ return "AWS";
50
+ case "azure-oidc":
51
+ case "microsoft":
52
+ return "Entra ID";
53
+ default:
54
+ (0, util_1.throwAssertNever)(providerType);
55
+ }
56
+ throw "Invalid provider type";
57
+ };
38
58
  /** Executes the first step of a device-authorization grant flow */
39
59
  // cf. https://developer.okta.com/docs/guides/device-authorization-grant/main/
40
- const authorize = (org, scope) => __awaiter(void 0, void 0, void 0, function* () {
41
- if (org.providerType === undefined) {
42
- throw "Login requires a configured provider type.";
43
- }
44
- const init = {
45
- method: "POST",
46
- headers: oidc_1.OIDC_HEADERS,
47
- body: (0, fetch_1.urlEncode)({
48
- client_id: org.clientId,
49
- scope,
50
- }),
51
- };
52
- (0, exports.validateProviderDomain)(org);
53
- // This is the "org" authorization server; the okta.apps.* scopes are not
54
- // available with custom authorization servers
55
- const url = org.providerType === "okta"
56
- ? `https:${org.providerDomain}/oauth2/v1/device/authorize`
57
- : org.providerType === "ping"
58
- ? `https://${org.providerDomain}/${org.environmentId}/as/device_authorization`
59
- : (0, util_1.throwAssertNever)(org.providerType);
60
+ const authorize = (request, validateResponse) => __awaiter(void 0, void 0, void 0, function* () {
61
+ const { url, init } = request;
60
62
  const response = yield fetch(url, init);
61
- yield (0, fetch_1.validateResponse)(response);
63
+ yield validateResponse(response);
62
64
  return (yield response.json());
63
65
  });
66
+ exports.authorize = authorize;
64
67
  /** Attempts to fetch this device's OIDC token
65
68
  *
66
69
  * The authorization may or may not be granted at this stage. If it is not, the
67
70
  * authorization server will return "authorization_pending", in which case this
68
71
  * function will return undefined.
69
72
  */
70
- const fetchOidcToken = (org, authorize) => __awaiter(void 0, void 0, void 0, function* () {
71
- if (org.providerType === undefined) {
72
- throw "Login requires a configured provider type.";
73
- }
74
- const init = {
75
- method: "POST",
76
- headers: oidc_1.OIDC_HEADERS,
77
- body: (0, fetch_1.urlEncode)({
78
- client_id: org.clientId,
79
- device_code: authorize.device_code,
80
- grant_type: DEVICE_GRANT_TYPE,
81
- }),
82
- };
83
- (0, exports.validateProviderDomain)(org);
84
- const url = org.providerType === "okta"
85
- ? `https:${org.providerDomain}/oauth2/v1/token`
86
- : org.providerType === "ping"
87
- ? `https://${org.providerDomain}/${org.environmentId}/as/token`
88
- : (0, util_1.throwAssertNever)(org.providerType);
73
+ const fetchOidcToken = (request) => __awaiter(void 0, void 0, void 0, function* () {
74
+ const { url, init } = request;
89
75
  const response = yield fetch(url, init);
90
76
  if (!response.ok) {
91
77
  if (response.status === 400) {
92
78
  const data = yield response.json();
93
79
  if (data.error === "authorization_pending")
94
80
  return undefined;
81
+ if (data.error === "access_denied")
82
+ throw "Access denied, try again";
95
83
  }
96
84
  yield (0, fetch_1.validateResponse)(response);
97
85
  }
98
86
  return (yield response.json());
99
87
  });
88
+ exports.fetchOidcToken = fetchOidcToken;
100
89
  /** Waits until user device authorization is complete
101
90
  *
102
91
  * Returns the OIDC token after completion.
103
92
  */
104
- const waitForActivation = (org, authorize) => __awaiter(void 0, void 0, void 0, function* () {
93
+ const waitForActivation = (authorize, extractExpiryInterval, // Aws implementation differs from standard OIDC response, need function to extract expiry
94
+ tokenRequest) => __awaiter(void 0, void 0, void 0, function* () {
105
95
  const start = Date.now();
106
- while (Date.now() - start <= authorize.expires_in * 1e3) {
107
- const response = yield fetchOidcToken(org, authorize);
96
+ const { expires_in, interval } = extractExpiryInterval(authorize);
97
+ while (Date.now() - start <= expires_in * 1e3) {
98
+ const response = yield (0, exports.fetchOidcToken)(tokenRequest);
108
99
  if (!response)
109
- yield (0, util_1.sleep)(authorize.interval * 1e3);
100
+ yield (0, util_1.sleep)(interval * 1e3);
110
101
  else
111
102
  return response;
112
103
  }
113
104
  throw "Expired awaiting in-browser authorization.";
114
105
  });
115
- /** Logs in to an Identity Provider via OIDC */
116
- const oidcLogin = (org, scope) => __awaiter(void 0, void 0, void 0, function* () {
106
+ exports.waitForActivation = waitForActivation;
107
+ const oidcLoginSteps = (org, scope, urls) => {
108
+ const { deviceAuthorizationUrl, tokenUrl } = urls();
117
109
  if (org.providerType === undefined) {
118
- throw "Login requires a configured provider type.";
110
+ throw "Your organization's login configuration does not support this access. Your P0 admin will need to install a supported OIDC provider in order for you to use this command.";
119
111
  }
120
- const authorizeResponse = yield authorize(org, scope);
112
+ const buildOidcAuthorizeRequest = () => {
113
+ (0, exports.validateProviderDomain)(org);
114
+ return {
115
+ init: {
116
+ method: "POST",
117
+ headers: oidc_1.OIDC_HEADERS,
118
+ body: (0, fetch_1.urlEncode)({
119
+ client_id: org.clientId,
120
+ scope,
121
+ }),
122
+ },
123
+ url: deviceAuthorizationUrl,
124
+ };
125
+ };
126
+ const buildOidcTokenRequest = (authorize) => {
127
+ (0, exports.validateProviderDomain)(org);
128
+ return {
129
+ url: tokenUrl,
130
+ init: {
131
+ method: "POST",
132
+ headers: oidc_1.OIDC_HEADERS,
133
+ body: (0, fetch_1.urlEncode)({
134
+ client_id: org.clientId,
135
+ device_code: authorize.device_code,
136
+ grant_type: exports.DEVICE_GRANT_TYPE,
137
+ }),
138
+ },
139
+ };
140
+ };
141
+ return {
142
+ providerType: org.providerType,
143
+ validateResponse: fetch_1.validateResponse,
144
+ buildAuthorizeRequest: buildOidcAuthorizeRequest,
145
+ buildTokenRequest: buildOidcTokenRequest,
146
+ processAuthzExpiry: (authorize) => ({
147
+ expires_in: authorize.expires_in,
148
+ interval: authorize.interval,
149
+ }),
150
+ processAuthzResponse: (authorize) => ({
151
+ user_code: authorize.user_code,
152
+ verification_uri_complete: authorize.verification_uri_complete,
153
+ }),
154
+ };
155
+ };
156
+ exports.oidcLoginSteps = oidcLoginSteps;
157
+ /** Logs in to an Identity Provider via OIDC */
158
+ const oidcLogin = (steps) => __awaiter(void 0, void 0, void 0, function* () {
159
+ const { providerType, buildAuthorizeRequest, buildTokenRequest, processAuthzExpiry, processAuthzResponse, validateResponse, } = steps;
160
+ const deviceAuthorizationResponse = yield (0, exports.authorize)(buildAuthorizeRequest(), validateResponse);
161
+ const { user_code, verification_uri_complete } = processAuthzResponse(deviceAuthorizationResponse);
121
162
  (0, stdio_1.print2)(`Please use the opened browser window to continue your P0 login.
122
-
123
- When prompted, confirm that ${(0, lodash_1.capitalize)(org.providerType)} displays this code:
124
-
125
- ${authorizeResponse.user_code}
126
163
 
127
- Waiting for authorization...
128
- `);
129
- void (0, open_1.default)(authorizeResponse.verification_uri_complete);
130
- const oidcResponse = yield waitForActivation(org, authorizeResponse);
131
- return oidcResponse;
164
+ When prompted, confirm that ${oidcProviderLabels(providerType)} displays this code:
165
+
166
+ ${user_code}
167
+
168
+ Waiting for authorization...
169
+ `);
170
+ void (0, open_1.default)(verification_uri_complete);
171
+ return yield (0, exports.waitForActivation)(deviceAuthorizationResponse, processAuthzExpiry, buildTokenRequest(deviceAuthorizationResponse));
132
172
  });
133
173
  exports.oidcLogin = oidcLogin;
@@ -1,5 +1,5 @@
1
1
  import { Authn } from "../../types/identity";
2
2
  export declare const assumeRoleWithOktaSaml: (authn: Authn, args: {
3
- account?: string;
3
+ accountId?: string;
4
4
  role: string;
5
5
  }) => Promise<import("../aws/types").AwsCredentials>;
@@ -24,8 +24,8 @@ const role_1 = require("../../commands/aws/role");
24
24
  const auth_1 = require("../../drivers/auth");
25
25
  const assumeRole_1 = require("../aws/assumeRole");
26
26
  const assumeRoleWithOktaSaml = (authn, args) => __awaiter(void 0, void 0, void 0, function* () {
27
- return yield (0, auth_1.cached)(`aws-okta-${args.account}-${args.role}`, () => __awaiter(void 0, void 0, void 0, function* () {
28
- const { account, config, samlResponse } = yield (0, role_1.initOktaSaml)(authn, args.account);
27
+ return yield (0, auth_1.cached)(`aws-okta-${args.accountId}-${args.role}`, () => __awaiter(void 0, void 0, void 0, function* () {
28
+ const { account, config, samlResponse } = yield (0, role_1.initOktaSaml)(authn, args.accountId);
29
29
  const { roles } = (0, role_1.rolesFromSaml)(account, samlResponse);
30
30
  if (!roles.includes(args.role))
31
31
  throw `Role not available. Available roles:\n${roles.map((r) => ` ${r}`).join("\n")}`;
@@ -66,7 +66,17 @@ const fetchSamlResponse = (org, { access_token }) => __awaiter(void 0, void 0, v
66
66
  return samlInput === null || samlInput === void 0 ? void 0 : samlInput.value;
67
67
  });
68
68
  /** Logs in to Okta via OIDC */
69
- const oktaLogin = (org) => __awaiter(void 0, void 0, void 0, function* () { return (0, login_1.oidcLogin)(org, "openid email profile okta.apps.sso"); });
69
+ const oktaLogin = (org) => __awaiter(void 0, void 0, void 0, function* () {
70
+ return (0, login_1.oidcLogin)((0, login_1.oidcLoginSteps)(org, "openid email profile okta.apps.sso", () => {
71
+ if (org.providerType !== "okta") {
72
+ throw `Invalid provider type ${org.providerType} (expected "okta")`;
73
+ }
74
+ return {
75
+ deviceAuthorizationUrl: `https://${org.providerDomain}/oauth2/v1/device/authorize`,
76
+ tokenUrl: `https://${org.providerDomain}/oauth2/v1/token`,
77
+ };
78
+ }));
79
+ });
70
80
  exports.oktaLogin = oktaLogin;
71
81
  /** Retrieves a SAML response for an okta app */
72
82
  // TODO: Inject Okta app
@@ -8,6 +8,7 @@ This file is part of @p0security/cli
8
8
 
9
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
10
  **/
11
+ import { TokenResponse } from "../../types/oidc";
11
12
  import { OrgData } from "../../types/org";
12
13
  /** Logs in to PingOne via OIDC */
13
- export declare const pingLogin: (org: OrgData) => Promise<import("../../types/oidc").TokenResponse>;
14
+ export declare const pingLogin: (org: OrgData) => Promise<TokenResponse>;
@@ -12,5 +12,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.pingLogin = void 0;
13
13
  const login_1 = require("../oidc/login");
14
14
  /** Logs in to PingOne via OIDC */
15
- const pingLogin = (org) => __awaiter(void 0, void 0, void 0, function* () { return (0, login_1.oidcLogin)(org, "openid email profile"); });
15
+ const pingLogin = (org) => __awaiter(void 0, void 0, void 0, function* () {
16
+ return (0, login_1.oidcLogin)((0, login_1.oidcLoginSteps)(org, "openid email profile", () => {
17
+ if (org.providerType !== "ping" || org.providerType === undefined) {
18
+ throw `Invalid provider type ${org.providerType} (expected "ping")`;
19
+ }
20
+ return {
21
+ deviceAuthorizationUrl: `https://${org.providerDomain}/${org.environmentId}/as/device_authorization`,
22
+ tokenUrl: `https://${org.providerDomain}/${org.environmentId}/as/token`,
23
+ };
24
+ }));
25
+ });
16
26
  exports.pingLogin = pingLogin;
@@ -8,6 +8,7 @@ This file is part of @p0security/cli
8
8
 
9
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
10
  **/
11
- import { ScpCommandArgs, SshCommandArgs, SshRequest } from "../../commands/shared";
11
+ import { ScpCommandArgs, SshCommandArgs } from "../../commands/shared/ssh";
12
12
  import { Authn } from "../../types/identity";
13
+ import { SshRequest } from "../../types/ssh";
13
14
  export declare const sshOrScp: (authn: Authn, data: SshRequest, cmdArgs: ScpCommandArgs | SshCommandArgs, privateKey: string) => Promise<number | null>;
@@ -13,6 +13,8 @@ exports.sshOrScp = void 0;
13
13
  const keys_1 = require("../../common/keys");
14
14
  const stdio_1 = require("../../drivers/stdio");
15
15
  const util_1 = require("../../util");
16
+ const config_1 = require("../aws/config");
17
+ const idc_1 = require("../aws/idc");
16
18
  const install_1 = require("../aws/ssm/install");
17
19
  const aws_1 = require("../okta/aws");
18
20
  const ssh_agent_1 = require("../ssh-agent");
@@ -256,13 +258,19 @@ const transformForShell = (args) => {
256
258
  });
257
259
  };
258
260
  const awsLogin = (authn, data) => __awaiter(void 0, void 0, void 0, function* () {
261
+ var _a, _b, _c, _d;
259
262
  if (!(yield (0, install_1.ensureSsmInstall)())) {
260
263
  throw "Please try again after installing the required AWS utilities";
261
264
  }
262
- return yield (0, aws_1.assumeRoleWithOktaSaml)(authn, {
263
- account: data.accountId,
264
- role: data.role,
265
- });
265
+ const { config } = yield (0, config_1.getAwsConfig)(authn, data.accountId);
266
+ if (!((_a = config.login) === null || _a === void 0 ? void 0 : _a.type) || ((_b = config.login) === null || _b === void 0 ? void 0 : _b.type) === "iam") {
267
+ throw "This account is not configured for SSH access via the P0 CLI";
268
+ }
269
+ return ((_c = config.login) === null || _c === void 0 ? void 0 : _c.type) === "idc"
270
+ ? yield (0, idc_1.assumeRoleWithIdc)(data)
271
+ : ((_d = config.login) === null || _d === void 0 ? void 0 : _d.type) === "federated"
272
+ ? yield (0, aws_1.assumeRoleWithOktaSaml)(authn, data)
273
+ : (0, util_1.throwAssertNever)(config.login);
266
274
  });
267
275
  const sshOrScp = (authn, data, cmdArgs, privateKey) => __awaiter(void 0, void 0, void 0, function* () {
268
276
  if (!privateKey) {
@@ -277,7 +285,8 @@ const sshOrScp = (authn, data, cmdArgs, privateKey) => __awaiter(void 0, void 0,
277
285
  `eval $(ssh-agent)`,
278
286
  `ssh-add "${keys_1.PRIVATE_KEY_PATH}"`,
279
287
  // TODO ENG-2284 support login with Google Cloud
280
- ...(data.type === "aws"
288
+ // TODO: Modify commands to add the ability to get permission set commands
289
+ ...(data.type === "aws" && data.access !== "idc"
281
290
  ? [
282
291
  `eval $(p0 aws role assume ${data.role} --account ${data.accountId})`,
283
292
  ]
@@ -0,0 +1,36 @@
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
+ export declare type AWSClientInformation = {
12
+ authorizationEndpoint: string;
13
+ clientId: string;
14
+ clientIdIssuedAt: number;
15
+ clientSecret: string;
16
+ clientSecretExpiresAt: number;
17
+ tokenEndpoint: string;
18
+ };
19
+ /**
20
+ * AWS OIDC token response uses camelCase instead of snake_case
21
+ */
22
+ export declare type AWSTokenResponse = {
23
+ accessToken: string;
24
+ expiresIn: number;
25
+ idToken: string;
26
+ refreshToken: string;
27
+ tokenType: string;
28
+ };
29
+ export declare type AWSAuthorizeResponse = {
30
+ deviceCode: string;
31
+ expiresIn: number;
32
+ interval: number;
33
+ userCode: string;
34
+ verificationUri: string;
35
+ verificationUriComplete: string;
36
+ };
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ /** Copyright © 2024-present P0 Security
3
+
4
+ This file is part of @p0security/cli
5
+
6
+ @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.
7
+
8
+ @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.
9
+
10
+ You should have received a copy of the GNU General Public License along with @p0security/cli. If not, see <https://www.gnu.org/licenses/>.
11
+ **/
12
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,3 +1,4 @@
1
+ import { LoginPluginType } from "../plugins/login";
1
2
  /** Copyright © 2024-present P0 Security
2
3
 
3
4
  This file is part of @p0security/cli
@@ -39,3 +40,23 @@ export declare type TokenResponse = {
39
40
  export declare type TokenErrorResponse = {
40
41
  error: "access_denied" | "authorization_pending" | "bad grant type" | "expired_token" | "missing parameter" | "not found" | "slow_down";
41
42
  };
43
+ export declare type OidcLoginSteps<A> = {
44
+ providerType: LoginPluginType;
45
+ validateResponse: (response: Response) => Promise<Response>;
46
+ buildAuthorizeRequest: () => {
47
+ url: string;
48
+ init: RequestInit;
49
+ };
50
+ buildTokenRequest: (authorize: A) => {
51
+ url: string;
52
+ init: RequestInit;
53
+ };
54
+ processAuthzResponse: (authorize: A) => {
55
+ user_code: string;
56
+ verification_uri_complete: string;
57
+ };
58
+ processAuthzExpiry: (authorize: A) => {
59
+ expires_in: number;
60
+ interval: number;
61
+ };
62
+ };
@@ -8,16 +8,10 @@ This file is part of @p0security/cli
8
8
 
9
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
10
  **/
11
- import { AwsPermissionSpec, AwsSsh } from "../plugins/aws/types";
12
- import { GcpPermissionSpec, GcpSsh } from "../plugins/google/types";
11
+ import { PluginSshRequest } from "./ssh";
13
12
  export declare const DONE_STATUSES: readonly ["DONE", "DONE_NOTIFIED"];
14
13
  export declare const DENIED_STATUSES: readonly ["DENIED", "DENIED_NOTIFIED"];
15
14
  export declare const ERROR_STATUSES: readonly ["ERRORED", "ERRORED", "ERRORED_NOTIFIED"];
16
- export declare type CliRequest = AwsSsh | GcpSsh;
17
- export declare type PluginRequest = AwsPermissionSpec | GcpPermissionSpec;
18
- export declare type CliPermissionSpec<P extends PluginRequest, C extends object | undefined = undefined> = P & {
19
- cliLocalData: C;
20
- };
21
15
  export declare type PermissionSpec<K extends string, P extends {
22
16
  type: string;
23
17
  }, G extends object | undefined = undefined> = {
@@ -25,6 +19,7 @@ export declare type PermissionSpec<K extends string, P extends {
25
19
  permission: P;
26
20
  generated: G;
27
21
  };
22
+ export declare type PluginRequest = PluginSshRequest;
28
23
  export declare type Request<P extends PluginRequest> = P & {
29
24
  status: string;
30
25
  principal: string;