opal-security 3.2.1 → 3.2.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.
- package/README.md +28 -25
- package/lib/commands/login.js +8 -1
- package/lib/commands/request/create.d.ts +2 -0
- package/lib/commands/request/create.js +41 -20
- package/lib/commands/request/get.js +5 -57
- package/lib/commands/request/list.js +3 -60
- package/lib/graphql/gql.d.ts +35 -15
- package/lib/graphql/gql.js +9 -5
- package/lib/graphql/graphql.d.ts +286 -228
- package/lib/graphql/graphql.js +1674 -1095
- package/lib/labels.d.ts +3 -0
- package/lib/labels.js +37 -0
- package/lib/lib/request/api/index.d.ts +6 -0
- package/lib/lib/request/api/index.js +20 -0
- package/lib/lib/request/api/mutations/create-request.d.ts +8 -0
- package/lib/lib/request/api/mutations/create-request.js +159 -0
- package/lib/lib/request/api/queries/apps.d.ts +4 -0
- package/lib/lib/request/api/queries/apps.js +73 -0
- package/lib/lib/request/api/queries/assets.d.ts +6 -0
- package/lib/lib/request/api/queries/assets.js +136 -0
- package/lib/lib/request/api/queries/request-defaults.d.ts +5 -0
- package/lib/lib/request/api/queries/request-defaults.js +51 -0
- package/lib/lib/request/api/queries/requests.d.ts +4 -0
- package/lib/lib/request/api/queries/requests.js +163 -0
- package/lib/lib/request/api/queries/roles.d.ts +5 -0
- package/lib/lib/request/api/queries/roles.js +239 -0
- package/lib/{utils → lib/request}/displays.d.ts +4 -2
- package/lib/{utils → lib/request}/displays.js +41 -19
- package/lib/lib/request/prompts/apps-prompt.d.ts +4 -0
- package/lib/lib/request/prompts/apps-prompt.js +35 -0
- package/lib/lib/request/prompts/asset-prompt.d.ts +5 -0
- package/lib/lib/request/prompts/asset-prompt.js +81 -0
- package/lib/lib/request/prompts/duration-prompt.d.ts +2 -0
- package/lib/lib/request/prompts/duration-prompt.js +122 -0
- package/lib/lib/request/prompts/index.d.ts +8 -0
- package/lib/lib/request/prompts/index.js +20 -0
- package/lib/lib/request/prompts/reason-prompt.d.ts +2 -0
- package/lib/lib/request/prompts/reason-prompt.js +20 -0
- package/lib/lib/request/prompts/role-prompt.d.ts +4 -0
- package/lib/lib/request/prompts/role-prompt.js +44 -0
- package/lib/lib/request/prompts/validate-prompt.d.ts +4 -0
- package/lib/lib/request/prompts/validate-prompt.js +29 -0
- package/lib/lib/request/request-utils.d.ts +15 -0
- package/lib/lib/request/request-utils.js +467 -0
- package/lib/lib/request/types.d.ts +55 -0
- package/lib/lib/request/types.js +15 -0
- package/lib/lib/util.d.ts +1 -0
- package/lib/lib/util.js +16 -0
- package/lib/types.d.ts +19 -3
- package/lib/types.js +18 -2
- package/oclif.manifest.json +54 -38
- package/package.json +1 -1
- package/lib/lib/requests.d.ts +0 -54
- package/lib/lib/requests.js +0 -1160
- package/lib/utils/utils.d.ts +0 -1
- package/lib/utils/utils.js +0 -18
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.queryBundle = exports.queryRequests = exports.queryRequest = void 0;
|
|
4
|
+
const graphql_1 = require("../../../../graphql");
|
|
5
|
+
const RESOURCE_FRAGMENT = (0, graphql_1.graphql)(`
|
|
6
|
+
fragment ResourceFields on Resource {
|
|
7
|
+
displayName
|
|
8
|
+
id
|
|
9
|
+
connectionId
|
|
10
|
+
connection {
|
|
11
|
+
name
|
|
12
|
+
connectionType
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
`);
|
|
16
|
+
const GROUP_FRAGMENT = (0, graphql_1.graphql)(`
|
|
17
|
+
fragment GroupFields on Group {
|
|
18
|
+
name
|
|
19
|
+
id
|
|
20
|
+
connectionId
|
|
21
|
+
connection {
|
|
22
|
+
name
|
|
23
|
+
connectionType
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
`);
|
|
27
|
+
const REQUEST_FIELDS_FRAGMENT = (0, graphql_1.graphql)(`
|
|
28
|
+
fragment RequestFields on Request {
|
|
29
|
+
id
|
|
30
|
+
createdAt
|
|
31
|
+
status
|
|
32
|
+
durationInMinutes
|
|
33
|
+
reason
|
|
34
|
+
requester {
|
|
35
|
+
displayName
|
|
36
|
+
}
|
|
37
|
+
targetUser {
|
|
38
|
+
displayName
|
|
39
|
+
}
|
|
40
|
+
requestedResources {
|
|
41
|
+
resource {
|
|
42
|
+
...ResourceFields
|
|
43
|
+
}
|
|
44
|
+
accessLevel {
|
|
45
|
+
accessLevelName
|
|
46
|
+
accessLevelRemoteId
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
requestedGroups {
|
|
50
|
+
group {
|
|
51
|
+
...GroupFields
|
|
52
|
+
}
|
|
53
|
+
accessLevel {
|
|
54
|
+
accessLevelName
|
|
55
|
+
accessLevelRemoteId
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
`);
|
|
60
|
+
const GET_REQUEST = (0, graphql_1.graphql)(`
|
|
61
|
+
query GetRequest(
|
|
62
|
+
$id: RequestId!
|
|
63
|
+
) {
|
|
64
|
+
request(input: {id: $id}) {
|
|
65
|
+
__typename
|
|
66
|
+
... on RequestResult {
|
|
67
|
+
request {
|
|
68
|
+
...RequestFields
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
... on RequestNotFoundError {
|
|
72
|
+
message
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
`);
|
|
77
|
+
const queryRequest = async (client, requestId) => {
|
|
78
|
+
const resp = await client.query({
|
|
79
|
+
query: GET_REQUEST,
|
|
80
|
+
variables: {
|
|
81
|
+
id: requestId,
|
|
82
|
+
},
|
|
83
|
+
fetchPolicy: "network-only", // to avoid caching
|
|
84
|
+
});
|
|
85
|
+
return resp;
|
|
86
|
+
};
|
|
87
|
+
exports.queryRequest = queryRequest;
|
|
88
|
+
// TODO: Add date filters, search query,
|
|
89
|
+
const GET_OUTGOING_REQUESTS = (0, graphql_1.graphql)(`
|
|
90
|
+
query GetRequests($showPendingOnly: Boolean!, $pageSize: Int) {
|
|
91
|
+
requests(input: {
|
|
92
|
+
requestType: OUTGOING
|
|
93
|
+
maxNumEntries: $pageSize
|
|
94
|
+
filters: {
|
|
95
|
+
showPendingOnly: $showPendingOnly
|
|
96
|
+
}
|
|
97
|
+
}) {
|
|
98
|
+
__typename
|
|
99
|
+
... on RequestsResult {
|
|
100
|
+
requestType
|
|
101
|
+
requests {
|
|
102
|
+
...RequestFields
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
}
|
|
108
|
+
}`);
|
|
109
|
+
const queryRequests = async (client, pageSize, showPendingOnly) => {
|
|
110
|
+
const resp = await client.query({
|
|
111
|
+
query: GET_OUTGOING_REQUESTS,
|
|
112
|
+
variables: {
|
|
113
|
+
pageSize: pageSize,
|
|
114
|
+
showPendingOnly: showPendingOnly,
|
|
115
|
+
},
|
|
116
|
+
fetchPolicy: "network-only", // to avoid caching
|
|
117
|
+
});
|
|
118
|
+
return resp;
|
|
119
|
+
};
|
|
120
|
+
exports.queryRequests = queryRequests;
|
|
121
|
+
const GET_BUNDLE = (0, graphql_1.graphql)(`query GetBundle($id: BundleId!) {
|
|
122
|
+
bundle(input: { id: $id }) {
|
|
123
|
+
__typename
|
|
124
|
+
... on BundleResult {
|
|
125
|
+
bundle {
|
|
126
|
+
name
|
|
127
|
+
id
|
|
128
|
+
items {
|
|
129
|
+
edges {
|
|
130
|
+
accessLevel {
|
|
131
|
+
accessLevelName
|
|
132
|
+
accessLevelRemoteId
|
|
133
|
+
}
|
|
134
|
+
node {
|
|
135
|
+
... on Resource {
|
|
136
|
+
...ResourceFields
|
|
137
|
+
isRequestable
|
|
138
|
+
}
|
|
139
|
+
... on Group {
|
|
140
|
+
...GroupFields
|
|
141
|
+
isRequestable
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
... on BundleNotFoundError {
|
|
149
|
+
message
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}`);
|
|
153
|
+
const queryBundle = async (client, bundleId) => {
|
|
154
|
+
const resp = await client.query({
|
|
155
|
+
query: GET_BUNDLE,
|
|
156
|
+
variables: {
|
|
157
|
+
id: bundleId,
|
|
158
|
+
},
|
|
159
|
+
fetchPolicy: "network-only", // to avoid caching
|
|
160
|
+
});
|
|
161
|
+
return resp;
|
|
162
|
+
};
|
|
163
|
+
exports.queryBundle = queryBundle;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ApolloClient, NormalizedCacheObject } from "@apollo/client";
|
|
2
|
+
import type { Command } from "@oclif/core";
|
|
3
|
+
import type { PromptChoice } from "../../types";
|
|
4
|
+
export declare function queryAssetRoles(cmd: Command, client: ApolloClient<NormalizedCacheObject>, assetType: string, assetId: string): Promise<PromptChoice[] | undefined>;
|
|
5
|
+
export declare function queryAssociatedItems(cmd: Command, client: ApolloClient<NormalizedCacheObject>, id: string, input: string | undefined): Promise<PromptChoice[] | undefined>;
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.queryAssetRoles = queryAssetRoles;
|
|
4
|
+
exports.queryAssociatedItems = queryAssociatedItems;
|
|
5
|
+
const graphql_1 = require("../../../../graphql");
|
|
6
|
+
const graphql_2 = require("../../../../graphql/graphql");
|
|
7
|
+
const labels_1 = require("../../../../labels");
|
|
8
|
+
const RESOURCE_ROLES_QUERY = (0, graphql_1.graphql)(`
|
|
9
|
+
query ResourceAccessLevels($resourceId: ResourceId!) {
|
|
10
|
+
accessLevels(input: {
|
|
11
|
+
resourceId: $resourceId,
|
|
12
|
+
onlyMine: false,
|
|
13
|
+
}) {
|
|
14
|
+
__typename
|
|
15
|
+
... on ResourceAccessLevelsResult {
|
|
16
|
+
accessLevels {
|
|
17
|
+
... on ResourceAccessLevel {
|
|
18
|
+
accessLevelName
|
|
19
|
+
accessLevelRemoteId
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
... on ResourceNotFoundError {
|
|
24
|
+
message
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
`);
|
|
29
|
+
const GROUP_ROLES_QUERY = (0, graphql_1.graphql)(`
|
|
30
|
+
query GroupAccessLevels($groupId: GroupId!) {
|
|
31
|
+
groupAccessLevels(
|
|
32
|
+
input: { groupId: $groupId }
|
|
33
|
+
) {
|
|
34
|
+
... on GroupAccessLevelsResult {
|
|
35
|
+
groupId
|
|
36
|
+
accessLevels {
|
|
37
|
+
... on GroupAccessLevel {
|
|
38
|
+
accessLevelName
|
|
39
|
+
accessLevelRemoteId
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
`);
|
|
46
|
+
async function queryAssetRoles(cmd, client, assetType, assetId) {
|
|
47
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
48
|
+
try {
|
|
49
|
+
switch (assetType) {
|
|
50
|
+
case graphql_2.EntityType.Resource: {
|
|
51
|
+
const resp = await client.query({
|
|
52
|
+
query: RESOURCE_ROLES_QUERY,
|
|
53
|
+
variables: {
|
|
54
|
+
resourceId: assetId,
|
|
55
|
+
},
|
|
56
|
+
fetchPolicy: "network-only", // to avoid caching
|
|
57
|
+
});
|
|
58
|
+
// no fall through doesn't consider process.exit();
|
|
59
|
+
let x;
|
|
60
|
+
switch (resp.data.accessLevels.__typename) {
|
|
61
|
+
case "ResourceAccessLevelsResult":
|
|
62
|
+
return (_c = (_b = (_a = resp.data) === null || _a === void 0 ? void 0 : _a.accessLevels) === null || _b === void 0 ? void 0 : _b.accessLevels) === null || _c === void 0 ? void 0 : _c.map((role) => {
|
|
63
|
+
return {
|
|
64
|
+
message: role.accessLevelName || "",
|
|
65
|
+
value: {
|
|
66
|
+
name: role.accessLevelName || "",
|
|
67
|
+
id: role.accessLevelRemoteId || "",
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
case "ResourceNotFoundError":
|
|
72
|
+
x = cmd.error((_e = (_d = resp.data) === null || _d === void 0 ? void 0 : _d.accessLevels) === null || _e === void 0 ? void 0 : _e.message);
|
|
73
|
+
break;
|
|
74
|
+
default:
|
|
75
|
+
cmd.error(resp.error || "Unknown error occurred.");
|
|
76
|
+
}
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
case graphql_2.EntityType.Group: {
|
|
80
|
+
const resp = await client.query({
|
|
81
|
+
query: GROUP_ROLES_QUERY,
|
|
82
|
+
variables: {
|
|
83
|
+
groupId: assetId,
|
|
84
|
+
},
|
|
85
|
+
fetchPolicy: "network-only", // to avoid caching
|
|
86
|
+
});
|
|
87
|
+
// no fall through doesn't consider process.exit();
|
|
88
|
+
let x;
|
|
89
|
+
switch (resp.data.groupAccessLevels.__typename) {
|
|
90
|
+
case "GroupAccessLevelsResult":
|
|
91
|
+
return (_h = (_g = (_f = resp.data) === null || _f === void 0 ? void 0 : _f.groupAccessLevels) === null || _g === void 0 ? void 0 : _g.accessLevels) === null || _h === void 0 ? void 0 : _h.map((role) => {
|
|
92
|
+
return {
|
|
93
|
+
message: role.accessLevelName,
|
|
94
|
+
value: {
|
|
95
|
+
name: role.accessLevelName,
|
|
96
|
+
id: role.accessLevelRemoteId,
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
});
|
|
100
|
+
default:
|
|
101
|
+
x = cmd.error(resp.error || "Unknown error occurred.");
|
|
102
|
+
}
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
if (error instanceof Error || typeof error === "string") {
|
|
109
|
+
cmd.error(error);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const ASSOCIATED_ITEMS_QUERY = (0, graphql_1.graphql)(`
|
|
114
|
+
query GetAssociatedItems($resourceId: ResourceId!, $searchQuery: String) {
|
|
115
|
+
resource(input: {
|
|
116
|
+
id: $resourceId
|
|
117
|
+
}) {
|
|
118
|
+
__typename
|
|
119
|
+
... on ResourceResult {
|
|
120
|
+
__typename
|
|
121
|
+
resource {
|
|
122
|
+
associatedItems(
|
|
123
|
+
first: 200
|
|
124
|
+
filters: {
|
|
125
|
+
searchQuery: {
|
|
126
|
+
contains: $searchQuery
|
|
127
|
+
}
|
|
128
|
+
access: REQUESTABLE
|
|
129
|
+
endUserVisible: true
|
|
130
|
+
entityType: {
|
|
131
|
+
in: [GROUP, RESOURCE]
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
) {
|
|
135
|
+
edges {
|
|
136
|
+
__typename
|
|
137
|
+
... on ResourceAssociatedItemEdge {
|
|
138
|
+
alias
|
|
139
|
+
node {
|
|
140
|
+
__typename
|
|
141
|
+
id
|
|
142
|
+
name
|
|
143
|
+
... on Resource {
|
|
144
|
+
accessLevels(
|
|
145
|
+
filters: {
|
|
146
|
+
skipRemoteAccessLevels: false # azure app roles are remote
|
|
147
|
+
}
|
|
148
|
+
) {
|
|
149
|
+
__typename
|
|
150
|
+
accessLevelName
|
|
151
|
+
accessLevelRemoteId
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
... on ResourceNotFoundError {
|
|
161
|
+
message
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
`);
|
|
166
|
+
function appRolesFromEdge(edge) {
|
|
167
|
+
var _a, _b, _c, _d;
|
|
168
|
+
switch (edge.node.__typename) {
|
|
169
|
+
case "Resource": {
|
|
170
|
+
if (edge.node.accessLevels && edge.node.accessLevels.length > 0) {
|
|
171
|
+
return edge.node.accessLevels.map((accessLevel) => ({
|
|
172
|
+
message: accessLevel.accessLevelName || "No Role (Direct access)",
|
|
173
|
+
value: {
|
|
174
|
+
id: edge.node.id + accessLevel.accessLevelRemoteId,
|
|
175
|
+
name: accessLevel.accessLevelName,
|
|
176
|
+
type: labels_1.DisplayLabels[graphql_2.EntityType.Resource],
|
|
177
|
+
toString: () => accessLevel.accessLevelName,
|
|
178
|
+
},
|
|
179
|
+
}));
|
|
180
|
+
}
|
|
181
|
+
return [
|
|
182
|
+
{
|
|
183
|
+
message: (_a = edge.alias) !== null && _a !== void 0 ? _a : edge.node.name,
|
|
184
|
+
value: {
|
|
185
|
+
id: edge.node.id,
|
|
186
|
+
name: (_b = edge.alias) !== null && _b !== void 0 ? _b : edge.node.name,
|
|
187
|
+
type: labels_1.DisplayLabels[graphql_2.EntityType.Resource],
|
|
188
|
+
toString: () => { var _a; return (_a = edge.alias) !== null && _a !== void 0 ? _a : edge.node.name; },
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
];
|
|
192
|
+
}
|
|
193
|
+
case "Group":
|
|
194
|
+
return [
|
|
195
|
+
{
|
|
196
|
+
message: `${(_c = edge.alias) !== null && _c !== void 0 ? _c : edge.node.name} ${graphql_2.EntityType.Group}`,
|
|
197
|
+
value: {
|
|
198
|
+
id: edge.node.id,
|
|
199
|
+
name: (_d = edge.alias) !== null && _d !== void 0 ? _d : edge.node.name,
|
|
200
|
+
type: labels_1.DisplayLabels[graphql_2.EntityType.Group],
|
|
201
|
+
toString: () => { var _a; return (_a = edge.alias) !== null && _a !== void 0 ? _a : edge.node.name; },
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
];
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
async function queryAssociatedItems(cmd, client, id, input) {
|
|
208
|
+
var _a, _b;
|
|
209
|
+
try {
|
|
210
|
+
const resp = await client.query({
|
|
211
|
+
query: ASSOCIATED_ITEMS_QUERY,
|
|
212
|
+
variables: {
|
|
213
|
+
resourceId: id || "",
|
|
214
|
+
searchQuery: input || "",
|
|
215
|
+
},
|
|
216
|
+
fetchPolicy: "network-only", // to avoid caching
|
|
217
|
+
});
|
|
218
|
+
switch (resp.data.resource.__typename) {
|
|
219
|
+
case "ResourceResult": {
|
|
220
|
+
const associatedItems = resp.data.resource.resource.associatedItems.edges.filter((edge) => edge.__typename === "ResourceAssociatedItemEdge");
|
|
221
|
+
const initial = [];
|
|
222
|
+
for (const edge of associatedItems) {
|
|
223
|
+
initial.push(...appRolesFromEdge(edge));
|
|
224
|
+
}
|
|
225
|
+
return initial;
|
|
226
|
+
}
|
|
227
|
+
case "ResourceNotFoundError":
|
|
228
|
+
cmd.log((_b = (_a = resp.data) === null || _a === void 0 ? void 0 : _a.resource) === null || _b === void 0 ? void 0 : _b.message);
|
|
229
|
+
break;
|
|
230
|
+
default:
|
|
231
|
+
cmd.error(resp.error || "Unknown error occurred.");
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
if (error instanceof Error || typeof error === "string") {
|
|
236
|
+
cmd.error(error);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { ApolloQueryResult } from "@apollo/client";
|
|
2
2
|
import type { Command } from "@oclif/core/lib/command";
|
|
3
|
-
import type { GetRequestQuery, GetRequestsQuery } from "
|
|
4
|
-
import {
|
|
3
|
+
import type { GetRequestQuery, GetRequestsQuery } from "../../graphql/graphql";
|
|
4
|
+
import type { RequestMap, RequestMetadata } from "./types";
|
|
5
5
|
export declare function headerMessage(cmd: Command): void;
|
|
6
6
|
export declare function treeifyRequestMap(cmd: Command, requestMap: RequestMap): void;
|
|
7
7
|
export declare function displayFinalRequestSummary(cmd: Command, metadata: RequestMetadata): void;
|
|
8
8
|
export declare function getStyledStatus(status: string): string;
|
|
9
9
|
export declare function displayRequestDetails(cmd: Command, requestResp: ApolloQueryResult<GetRequestQuery>): void;
|
|
10
10
|
export declare function displayRequestListTable(cmd: Command, requestResp: ApolloQueryResult<GetRequestsQuery>): void;
|
|
11
|
+
export declare function formatDuration(durationInMinutes: number): string;
|
|
12
|
+
export declare function displayRequestAgain(cmd: Command, id: string): void;
|
|
@@ -6,8 +6,10 @@ exports.displayFinalRequestSummary = displayFinalRequestSummary;
|
|
|
6
6
|
exports.getStyledStatus = getStyledStatus;
|
|
7
7
|
exports.displayRequestDetails = displayRequestDetails;
|
|
8
8
|
exports.displayRequestListTable = displayRequestListTable;
|
|
9
|
+
exports.formatDuration = formatDuration;
|
|
10
|
+
exports.displayRequestAgain = displayRequestAgain;
|
|
9
11
|
const chalk_1 = require("chalk");
|
|
10
|
-
const
|
|
12
|
+
const labels_1 = require("../../labels");
|
|
11
13
|
const Table = require("cli-table3");
|
|
12
14
|
function headerMessage(cmd) {
|
|
13
15
|
console.clear();
|
|
@@ -15,6 +17,16 @@ function headerMessage(cmd) {
|
|
|
15
17
|
cmd.log("Opal Access Request ✏️");
|
|
16
18
|
cmd.log("Press Ctrl+C to cancel at any time.\n");
|
|
17
19
|
}
|
|
20
|
+
/*
|
|
21
|
+
Example treeified output:
|
|
22
|
+
|
|
23
|
+
Opal [App]
|
|
24
|
+
└── Infosec Group [Group]
|
|
25
|
+
└── Infosec Prod Databases [Group]
|
|
26
|
+
MongoDB Atlas Test [App]
|
|
27
|
+
└── my-mongo-db-atlas [Resource]
|
|
28
|
+
└── admin:test [Role]
|
|
29
|
+
*/
|
|
18
30
|
function treeifyRequestMap(cmd, requestMap) {
|
|
19
31
|
for (const [_appId, appNode] of Object.entries(requestMap)) {
|
|
20
32
|
// Print App title first (without tree lines)
|
|
@@ -22,7 +34,7 @@ function treeifyRequestMap(cmd, requestMap) {
|
|
|
22
34
|
for (const [_assetId, assetNode] of Object.entries(appNode.assets)) {
|
|
23
35
|
// If okta/azure asset with no role, change asset name
|
|
24
36
|
const assetName = assetNode.assetName || "No Role (Direct access)";
|
|
25
|
-
cmd.log(`└── ${assetName} ${chalk_1.default.dim(`[${
|
|
37
|
+
cmd.log(`└── ${assetName} ${chalk_1.default.dim(`[${labels_1.DisplayLabels[assetNode.type]}]`)}`);
|
|
26
38
|
if (assetNode.roles !== undefined) {
|
|
27
39
|
for (const [_roleId, roleNode] of Object.entries(assetNode.roles)) {
|
|
28
40
|
const roleName = roleNode.roleName;
|
|
@@ -75,34 +87,37 @@ function displayRequestDetails(cmd, requestResp) {
|
|
|
75
87
|
var _a, _b, _c, _d, _e, _f;
|
|
76
88
|
switch (requestResp.data.request.__typename) {
|
|
77
89
|
case "RequestResult": {
|
|
90
|
+
const request = requestResp.data.request.request;
|
|
78
91
|
cmd.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
|
79
|
-
cmd.log(`Request Details ${chalk_1.default.cyan(
|
|
92
|
+
cmd.log(`Request Details ${chalk_1.default.cyan(request.id)}`);
|
|
80
93
|
cmd.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
|
81
|
-
const status =
|
|
94
|
+
const status = request.status;
|
|
82
95
|
cmd.log(getStyledStatus(status));
|
|
83
96
|
// Request users "Requested by: <requester> -> Requested for: <targetUser>"
|
|
84
|
-
const requester = (_a =
|
|
85
|
-
const targetUser = (_b =
|
|
97
|
+
const requester = (_a = request.requester) === null || _a === void 0 ? void 0 : _a.displayName;
|
|
98
|
+
const targetUser = (_b = request.targetUser) === null || _b === void 0 ? void 0 : _b.displayName;
|
|
86
99
|
if (requester && targetUser) {
|
|
87
100
|
cmd.log(`${chalk_1.default.bold("Requested by:")} ${requester} ${chalk_1.default.gray("->")} ${chalk_1.default.bold("Requested for:")} ${targetUser}`);
|
|
88
101
|
}
|
|
89
|
-
const durationInMinutes =
|
|
102
|
+
const durationInMinutes = request.durationInMinutes;
|
|
90
103
|
cmd.log(`${chalk_1.default.bold("Duration:")} ${durationInMinutes ? formatDuration(durationInMinutes) : "Permanent"}`);
|
|
91
|
-
const reason =
|
|
104
|
+
const reason = request.reason;
|
|
92
105
|
if (reason) {
|
|
93
106
|
cmd.log(`${chalk_1.default.bold("Reason:")} "${chalk_1.default.italic(reason)}"`);
|
|
94
107
|
}
|
|
95
108
|
// Requested resources
|
|
96
|
-
const requestedResources = (_d = (_c =
|
|
97
|
-
var _a, _b
|
|
109
|
+
const requestedResources = (_d = (_c = request.requestedResources) === null || _c === void 0 ? void 0 : _c.map((resource) => {
|
|
110
|
+
var _a, _b;
|
|
98
111
|
if (((_a = resource.resource) === null || _a === void 0 ? void 0 : _a.__typename) === "Resource") {
|
|
99
|
-
|
|
112
|
+
const requestedResource = resource.resource;
|
|
113
|
+
return formatAssetName(requestedResource.displayName, ((_b = resource.accessLevel) === null || _b === void 0 ? void 0 : _b.accessLevelName) || "");
|
|
100
114
|
}
|
|
101
115
|
})) !== null && _d !== void 0 ? _d : [];
|
|
102
|
-
const requestedGroups = (_f = (_e =
|
|
103
|
-
var _a, _b
|
|
116
|
+
const requestedGroups = (_f = (_e = request.requestedGroups) === null || _e === void 0 ? void 0 : _e.map((group) => {
|
|
117
|
+
var _a, _b;
|
|
104
118
|
if (((_a = group.group) === null || _a === void 0 ? void 0 : _a.__typename) === "Group") {
|
|
105
|
-
|
|
119
|
+
const requestedGroup = group.group;
|
|
120
|
+
return formatAssetName(requestedGroup.name, ((_b = group.accessLevel) === null || _b === void 0 ? void 0 : _b.accessLevelName) || "");
|
|
106
121
|
}
|
|
107
122
|
})) !== null && _f !== void 0 ? _f : [];
|
|
108
123
|
const requestedItems = [...requestedResources, ...requestedGroups].join(", ");
|
|
@@ -131,7 +146,8 @@ function displayRequestListTable(cmd, requestResp) {
|
|
|
131
146
|
wordWrap: true,
|
|
132
147
|
wrapOnWordBoundary: false,
|
|
133
148
|
});
|
|
134
|
-
for (const
|
|
149
|
+
for (const req of requests) {
|
|
150
|
+
const request = req;
|
|
135
151
|
const targetUser = (_a = request.targetUser) === null || _a === void 0 ? void 0 : _a.displayName;
|
|
136
152
|
const reason = request.reason;
|
|
137
153
|
const status = request.status;
|
|
@@ -139,15 +155,17 @@ function displayRequestListTable(cmd, requestResp) {
|
|
|
139
155
|
? formatDuration(request.durationInMinutes)
|
|
140
156
|
: "Permanent";
|
|
141
157
|
const requestedResources = (_c = (_b = request.requestedResources) === null || _b === void 0 ? void 0 : _b.map((resource) => {
|
|
142
|
-
var _a, _b
|
|
158
|
+
var _a, _b;
|
|
143
159
|
if (((_a = resource.resource) === null || _a === void 0 ? void 0 : _a.__typename) === "Resource") {
|
|
144
|
-
|
|
160
|
+
const requestedResource = resource.resource;
|
|
161
|
+
return formatAssetName(requestedResource.displayName, ((_b = resource.accessLevel) === null || _b === void 0 ? void 0 : _b.accessLevelName) || "");
|
|
145
162
|
}
|
|
146
163
|
})) !== null && _c !== void 0 ? _c : [];
|
|
147
164
|
const requestedGroups = (_e = (_d = request.requestedGroups) === null || _d === void 0 ? void 0 : _d.map((group) => {
|
|
148
|
-
var _a, _b
|
|
165
|
+
var _a, _b;
|
|
149
166
|
if (((_a = group.group) === null || _a === void 0 ? void 0 : _a.__typename) === "Group") {
|
|
150
|
-
|
|
167
|
+
const requestedGroup = group.group;
|
|
168
|
+
return formatAssetName(requestedGroup.name, ((_b = group.accessLevel) === null || _b === void 0 ? void 0 : _b.accessLevelName) || "");
|
|
151
169
|
}
|
|
152
170
|
})) !== null && _e !== void 0 ? _e : [];
|
|
153
171
|
const requestedItems = [
|
|
@@ -199,3 +217,7 @@ function formatAssetName(assetName, roleName) {
|
|
|
199
217
|
}
|
|
200
218
|
return str;
|
|
201
219
|
}
|
|
220
|
+
function displayRequestAgain(cmd, id) {
|
|
221
|
+
cmd.log(chalk_1.default.bold("\nTo request this again, run:"));
|
|
222
|
+
cmd.log(chalk_1.default.italic(` opal request create --template ${id}\n`));
|
|
223
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ApolloClient, NormalizedCacheObject } from "@apollo/client";
|
|
2
|
+
import type { Command } from "@oclif/core";
|
|
3
|
+
import type { RequestMap } from "../types";
|
|
4
|
+
export declare function selectRequestableItems(cmd: Command, client: ApolloClient<NormalizedCacheObject>, requestMap: RequestMap): Promise<void>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.selectRequestableItems = selectRequestableItems;
|
|
4
|
+
const _1 = require(".");
|
|
5
|
+
const api_1 = require("../api");
|
|
6
|
+
const { AutoComplete } = require("enquirer");
|
|
7
|
+
async function selectRequestableItems(cmd, client, requestMap) {
|
|
8
|
+
const initial = (await (0, api_1.queryRequestableApps)(cmd, client, "")) || [];
|
|
9
|
+
const appPrompt = new AutoComplete({
|
|
10
|
+
name: "App",
|
|
11
|
+
message: "Select an app",
|
|
12
|
+
hint: _1.selectInstructions,
|
|
13
|
+
limit: 15,
|
|
14
|
+
choices: initial,
|
|
15
|
+
async suggest(input) {
|
|
16
|
+
const filteredChoices = await (0, api_1.queryRequestableApps)(cmd, client, input || "");
|
|
17
|
+
return filteredChoices || initial;
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
const App = await appPrompt.run();
|
|
21
|
+
// Set the app in the requestMap and call choose assets step
|
|
22
|
+
if (!(App.id in requestMap)) {
|
|
23
|
+
requestMap[App.id] = {
|
|
24
|
+
appId: App.id,
|
|
25
|
+
appType: App.type,
|
|
26
|
+
appName: App.name,
|
|
27
|
+
assets: {},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
if (App.type === "OKTA_APP" || App.type === "AZURE_ENTERPRISE_APP") {
|
|
31
|
+
await (0, _1.chooseOktaAzureRoles)(cmd, client, App, requestMap);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
await (0, _1.chooseAssets)(cmd, client, App.id, requestMap);
|
|
35
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ApolloClient, NormalizedCacheObject } from "@apollo/client";
|
|
2
|
+
import type { Command } from "@oclif/core";
|
|
3
|
+
import { type EntityValue, type RequestMap } from "../types";
|
|
4
|
+
export declare function chooseOktaAzureRoles(cmd: Command, client: ApolloClient<NormalizedCacheObject>, app: EntityValue, requestMap: RequestMap): Promise<void>;
|
|
5
|
+
export declare function chooseAssets(cmd: Command, client: ApolloClient<NormalizedCacheObject>, appId: string, requestMap: RequestMap): Promise<void>;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.chooseOktaAzureRoles = chooseOktaAzureRoles;
|
|
4
|
+
exports.chooseAssets = chooseAssets;
|
|
5
|
+
const _1 = require(".");
|
|
6
|
+
const api_1 = require("../api");
|
|
7
|
+
const types_1 = require("../types");
|
|
8
|
+
const { AutoComplete } = require("enquirer");
|
|
9
|
+
async function chooseOktaAzureRoles(cmd, client, app, requestMap) {
|
|
10
|
+
const associatedItems = (await (0, api_1.queryAssociatedItems)(cmd, client, app.id, "")) || [];
|
|
11
|
+
const rolePrompt = new AutoComplete({
|
|
12
|
+
name: "Roles",
|
|
13
|
+
message: `Select a role for ${app.name}:`,
|
|
14
|
+
hint: _1.multiSelectInstructions,
|
|
15
|
+
limit: 15,
|
|
16
|
+
multiple: true,
|
|
17
|
+
async choices(input) {
|
|
18
|
+
if (!input)
|
|
19
|
+
return associatedItems;
|
|
20
|
+
const filteredChoices = await (0, api_1.queryAssociatedItems)(cmd, client, app.id, input);
|
|
21
|
+
return filteredChoices || associatedItems;
|
|
22
|
+
},
|
|
23
|
+
validate: (answer) => {
|
|
24
|
+
if (answer.length !== 1) {
|
|
25
|
+
return "Only one role is allowed to be requested for on Okta or Azure apps.";
|
|
26
|
+
}
|
|
27
|
+
return true;
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
const Roles = await rolePrompt.run();
|
|
31
|
+
const entry = requestMap[app.id];
|
|
32
|
+
for (const role of Roles) {
|
|
33
|
+
if (!(role.id in entry.assets)) {
|
|
34
|
+
entry.assets[role.id] = {
|
|
35
|
+
assetId: role.id,
|
|
36
|
+
assetName: role.name,
|
|
37
|
+
type: (0, types_1.entityTypeFromString)(role.type),
|
|
38
|
+
roles: {},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async function chooseAssets(cmd, client, appId, requestMap) {
|
|
44
|
+
const initial = (await (0, api_1.queryRequestableAssets)(cmd, client, appId, "")) || [];
|
|
45
|
+
const assetPrompt = new AutoComplete({
|
|
46
|
+
name: "Assets",
|
|
47
|
+
message: "Select one or more assets:",
|
|
48
|
+
hint: _1.multiSelectInstructions,
|
|
49
|
+
limit: 15,
|
|
50
|
+
multiple: true,
|
|
51
|
+
async choices(input) {
|
|
52
|
+
if (!input) {
|
|
53
|
+
return initial;
|
|
54
|
+
}
|
|
55
|
+
const filteredChoices = await (0, api_1.queryRequestableAssets)(cmd, client, appId, input);
|
|
56
|
+
return filteredChoices || initial;
|
|
57
|
+
},
|
|
58
|
+
validate: (answer) => {
|
|
59
|
+
if (answer.length < 1) {
|
|
60
|
+
return "You must select at least one item.";
|
|
61
|
+
}
|
|
62
|
+
return true;
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
const Assets = await assetPrompt.run();
|
|
66
|
+
const entry = requestMap[appId];
|
|
67
|
+
for (const asset of Assets) {
|
|
68
|
+
if (entry === undefined) {
|
|
69
|
+
throw new Error(`Error formatting app ${appId} in request`);
|
|
70
|
+
}
|
|
71
|
+
if (!(asset.id in entry.assets)) {
|
|
72
|
+
entry.assets[asset.id] = {
|
|
73
|
+
assetId: asset.id,
|
|
74
|
+
assetName: asset.name,
|
|
75
|
+
type: asset.type,
|
|
76
|
+
roles: {},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
await (0, _1.chooseRoles)(cmd, client, appId, asset.id, requestMap);
|
|
80
|
+
}
|
|
81
|
+
}
|