@flowcore/cli-plugin-iam 1.1.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/README.md +51 -3
- package/dist/commands/delete/policy.d.ts +17 -0
- package/dist/commands/delete/policy.js +84 -0
- package/dist/commands/delete/role.d.ts +17 -0
- package/dist/commands/delete/role.js +84 -0
- package/dist/commands/get/policy.js +41 -0
- package/dist/commands/get/role.js +115 -70
- package/oclif.manifest.json +123 -1
- package/package.json +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.2.1](https://github.com/flowcore-io/cli-plugin-iam/compare/v1.2.0...v1.2.1) (2024-10-22)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **configuration:** :bug: changed from prompt to enquirer import ([172ae77](https://github.com/flowcore-io/cli-plugin-iam/commit/172ae77e0a96f61786f334da1de8d2f388c10463))
|
|
9
|
+
|
|
10
|
+
## [1.2.0](https://github.com/flowcore-io/cli-plugin-iam/compare/v1.1.0...v1.2.0) (2024-10-22)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* :sparkles: added delete and updated get for policies and roles ([22fe717](https://github.com/flowcore-io/cli-plugin-iam/commit/22fe71767c39f4a234583ae637d5204c7732900c))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* **configuration:** :bug: switched from jsr to npm for obj-diff ([141d75e](https://github.com/flowcore-io/cli-plugin-iam/commit/141d75e1b9efb1c5c851dfbfc466e03c58c8fcfa))
|
|
21
|
+
|
|
3
22
|
## [1.1.0](https://github.com/flowcore-io/cli-plugin-iam/compare/v1.0.0...v1.1.0) (2024-10-21)
|
|
4
23
|
|
|
5
24
|
|
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ $ npm install -g @flowcore/cli-plugin-iam
|
|
|
18
18
|
$ iam COMMAND
|
|
19
19
|
running command...
|
|
20
20
|
$ iam (--version)
|
|
21
|
-
@flowcore/cli-plugin-iam/1.1
|
|
21
|
+
@flowcore/cli-plugin-iam/1.2.1 linux-x64 node-v20.18.0
|
|
22
22
|
$ iam --help [COMMAND]
|
|
23
23
|
USAGE
|
|
24
24
|
$ iam COMMAND
|
|
@@ -27,9 +27,57 @@ USAGE
|
|
|
27
27
|
<!-- usagestop -->
|
|
28
28
|
# Commands
|
|
29
29
|
<!-- commands -->
|
|
30
|
+
* [`iam delete policy NAME`](#iam-delete-policy-name)
|
|
31
|
+
* [`iam delete role NAME`](#iam-delete-role-name)
|
|
30
32
|
* [`iam get policy [NAME]`](#iam-get-policy-name)
|
|
31
33
|
* [`iam get role [NAME]`](#iam-get-role-name)
|
|
32
34
|
|
|
35
|
+
## `iam delete policy NAME`
|
|
36
|
+
|
|
37
|
+
Delete a policy
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
USAGE
|
|
41
|
+
$ iam delete policy NAME -t <value> [--profile <value>] [-j] [-y]
|
|
42
|
+
|
|
43
|
+
ARGUMENTS
|
|
44
|
+
NAME name
|
|
45
|
+
|
|
46
|
+
FLAGS
|
|
47
|
+
-j, --json json output
|
|
48
|
+
-t, --tenant=<value> (required) tenant
|
|
49
|
+
-y, --yes yes to all
|
|
50
|
+
--profile=<value> Specify the configuration profile to use
|
|
51
|
+
|
|
52
|
+
DESCRIPTION
|
|
53
|
+
Delete a policy
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
_See code: [src/commands/delete/policy.ts](https://github.com/flowcore-io/cli-plugin-iam/blob/v1.2.1/src/commands/delete/policy.ts)_
|
|
57
|
+
|
|
58
|
+
## `iam delete role NAME`
|
|
59
|
+
|
|
60
|
+
Delete a role
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
USAGE
|
|
64
|
+
$ iam delete role NAME -t <value> [--profile <value>] [-j] [-y]
|
|
65
|
+
|
|
66
|
+
ARGUMENTS
|
|
67
|
+
NAME name
|
|
68
|
+
|
|
69
|
+
FLAGS
|
|
70
|
+
-j, --json json output
|
|
71
|
+
-t, --tenant=<value> (required) tenant
|
|
72
|
+
-y, --yes yes to all
|
|
73
|
+
--profile=<value> Specify the configuration profile to use
|
|
74
|
+
|
|
75
|
+
DESCRIPTION
|
|
76
|
+
Delete a role
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
_See code: [src/commands/delete/role.ts](https://github.com/flowcore-io/cli-plugin-iam/blob/v1.2.1/src/commands/delete/role.ts)_
|
|
80
|
+
|
|
33
81
|
## `iam get policy [NAME]`
|
|
34
82
|
|
|
35
83
|
Get a policy
|
|
@@ -51,7 +99,7 @@ DESCRIPTION
|
|
|
51
99
|
Get a policy
|
|
52
100
|
```
|
|
53
101
|
|
|
54
|
-
_See code: [src/commands/get/policy.ts](https://github.com/flowcore-io/cli-plugin-iam/blob/v1.1
|
|
102
|
+
_See code: [src/commands/get/policy.ts](https://github.com/flowcore-io/cli-plugin-iam/blob/v1.2.1/src/commands/get/policy.ts)_
|
|
55
103
|
|
|
56
104
|
## `iam get role [NAME]`
|
|
57
105
|
|
|
@@ -74,5 +122,5 @@ DESCRIPTION
|
|
|
74
122
|
Get a role
|
|
75
123
|
```
|
|
76
124
|
|
|
77
|
-
_See code: [src/commands/get/role.ts](https://github.com/flowcore-io/cli-plugin-iam/blob/v1.1
|
|
125
|
+
_See code: [src/commands/get/role.ts](https://github.com/flowcore-io/cli-plugin-iam/blob/v1.2.1/src/commands/get/role.ts)_
|
|
78
126
|
<!-- commandsstop -->
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { BaseCommand } from "@flowcore/cli-plugin-config";
|
|
2
|
+
export declare const DELETE_POLICY_ARGS: {
|
|
3
|
+
NAME: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
4
|
+
};
|
|
5
|
+
export default class DeletePolicy extends BaseCommand<typeof DeletePolicy> {
|
|
6
|
+
static args: {
|
|
7
|
+
NAME: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
8
|
+
};
|
|
9
|
+
static description: string;
|
|
10
|
+
static examples: never[];
|
|
11
|
+
static flags: {
|
|
12
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
|
+
tenant: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
|
+
};
|
|
16
|
+
run(): Promise<void>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { BaseCommand, ValidateLogin } from "@flowcore/cli-plugin-config";
|
|
2
|
+
import { ClientFactory } from "@flowcore/cli-plugin-core";
|
|
3
|
+
import { Args, Flags, ux } from "@oclif/core";
|
|
4
|
+
import enquirer from "enquirer";
|
|
5
|
+
import { tryit } from "radash";
|
|
6
|
+
import { OrganizationService } from "../../services/organization.service.js";
|
|
7
|
+
import { Api as IamApi } from "../../utils/clients/iam/Api.js";
|
|
8
|
+
export const DELETE_POLICY_ARGS = {
|
|
9
|
+
NAME: Args.string({ description: "name", required: true }),
|
|
10
|
+
};
|
|
11
|
+
export default class DeletePolicy extends BaseCommand {
|
|
12
|
+
static args = DELETE_POLICY_ARGS;
|
|
13
|
+
static description = "Delete a policy";
|
|
14
|
+
static examples = [];
|
|
15
|
+
static flags = {
|
|
16
|
+
json: Flags.boolean({
|
|
17
|
+
char: "j",
|
|
18
|
+
description: "json output",
|
|
19
|
+
required: false,
|
|
20
|
+
}),
|
|
21
|
+
tenant: Flags.string({
|
|
22
|
+
char: "t",
|
|
23
|
+
description: "tenant",
|
|
24
|
+
required: true,
|
|
25
|
+
}),
|
|
26
|
+
yes: Flags.boolean({
|
|
27
|
+
char: "y",
|
|
28
|
+
description: "yes to all",
|
|
29
|
+
required: false,
|
|
30
|
+
}),
|
|
31
|
+
};
|
|
32
|
+
async run() {
|
|
33
|
+
const { args, flags } = await this.parse(DeletePolicy);
|
|
34
|
+
const graphqlClient = await ClientFactory.create(this.cliConfiguration, this.logger, flags.json);
|
|
35
|
+
const organizationService = new OrganizationService(graphqlClient);
|
|
36
|
+
const organizations = await organizationService.getMyOrganizations();
|
|
37
|
+
const iamClient = new IamApi();
|
|
38
|
+
const config = this.cliConfiguration.getConfig();
|
|
39
|
+
const login = new ValidateLogin(config.login.url);
|
|
40
|
+
await login.validate(config, this.cliConfiguration, !flags.json);
|
|
41
|
+
const { auth } = config;
|
|
42
|
+
if (!auth?.accessToken) {
|
|
43
|
+
this.logger.fatal("Not logged in, run 'flowcore login'");
|
|
44
|
+
}
|
|
45
|
+
const organization = organizations.me.organizations.find((org) => org.organization.org === flags.tenant);
|
|
46
|
+
if (!organization) {
|
|
47
|
+
this.logger.fatal(`Organization ${flags.tenant} not found, or you are not a member`);
|
|
48
|
+
}
|
|
49
|
+
const [policiesErr, policies] = await tryit(iamClient.getApiV1PolicyAssociationsOrganizationByOrganizationId)(organization.organization.id, {
|
|
50
|
+
headers: {
|
|
51
|
+
Authorization: `Bearer ${auth?.accessToken}`,
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
if (policiesErr) {
|
|
55
|
+
this.logger.fatal(`Failed to get policies: ${policiesErr.message}`);
|
|
56
|
+
}
|
|
57
|
+
const policy = policies.data.find((policy) => policy.name === args.NAME);
|
|
58
|
+
if (!policy) {
|
|
59
|
+
this.logger.fatal(`Policy ${args.NAME} not found in tenant: ${flags.tenant}`);
|
|
60
|
+
}
|
|
61
|
+
if (!flags.yes) {
|
|
62
|
+
const { confirm } = await enquirer.prompt([
|
|
63
|
+
{
|
|
64
|
+
message: `Are you sure you want to delete policy ${ux.colorize("cyan", policy.name)} in tenant: ${ux.colorize("cyan", flags.tenant)}?`,
|
|
65
|
+
name: "confirm",
|
|
66
|
+
type: "confirm",
|
|
67
|
+
},
|
|
68
|
+
]);
|
|
69
|
+
if (!confirm) {
|
|
70
|
+
this.logger.info("Aborted");
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const [err] = await tryit(iamClient.deleteApiV1PoliciesById)(policy.id, {
|
|
75
|
+
headers: {
|
|
76
|
+
Authorization: `Bearer ${auth?.accessToken}`,
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
if (err) {
|
|
80
|
+
this.logger.fatal(`Failed to delete policy: ${err.message}`);
|
|
81
|
+
}
|
|
82
|
+
this.logger.info(`Policy ${policy.name} deleted`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { BaseCommand } from "@flowcore/cli-plugin-config";
|
|
2
|
+
export declare const DELETE_ROLE_ARGS: {
|
|
3
|
+
NAME: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
4
|
+
};
|
|
5
|
+
export default class DeleteRole extends BaseCommand<typeof DeleteRole> {
|
|
6
|
+
static args: {
|
|
7
|
+
NAME: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
8
|
+
};
|
|
9
|
+
static description: string;
|
|
10
|
+
static examples: never[];
|
|
11
|
+
static flags: {
|
|
12
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
|
+
tenant: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
|
+
};
|
|
16
|
+
run(): Promise<void>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { BaseCommand, ValidateLogin } from "@flowcore/cli-plugin-config";
|
|
2
|
+
import { ClientFactory } from "@flowcore/cli-plugin-core";
|
|
3
|
+
import { Args, Flags, ux } from "@oclif/core";
|
|
4
|
+
import enquirer from "enquirer";
|
|
5
|
+
import { tryit } from "radash";
|
|
6
|
+
import { OrganizationService } from "../../services/organization.service.js";
|
|
7
|
+
import { Api as IamApi } from "../../utils/clients/iam/Api.js";
|
|
8
|
+
export const DELETE_ROLE_ARGS = {
|
|
9
|
+
NAME: Args.string({ description: "name", required: true }),
|
|
10
|
+
};
|
|
11
|
+
export default class DeleteRole extends BaseCommand {
|
|
12
|
+
static args = DELETE_ROLE_ARGS;
|
|
13
|
+
static description = "Delete a role";
|
|
14
|
+
static examples = [];
|
|
15
|
+
static flags = {
|
|
16
|
+
json: Flags.boolean({
|
|
17
|
+
char: "j",
|
|
18
|
+
description: "json output",
|
|
19
|
+
required: false,
|
|
20
|
+
}),
|
|
21
|
+
tenant: Flags.string({
|
|
22
|
+
char: "t",
|
|
23
|
+
description: "tenant",
|
|
24
|
+
required: true,
|
|
25
|
+
}),
|
|
26
|
+
yes: Flags.boolean({
|
|
27
|
+
char: "y",
|
|
28
|
+
description: "yes to all",
|
|
29
|
+
required: false,
|
|
30
|
+
}),
|
|
31
|
+
};
|
|
32
|
+
async run() {
|
|
33
|
+
const { args, flags } = await this.parse(DeleteRole);
|
|
34
|
+
const graphqlClient = await ClientFactory.create(this.cliConfiguration, this.logger, flags.json);
|
|
35
|
+
const organizationService = new OrganizationService(graphqlClient);
|
|
36
|
+
const organizations = await organizationService.getMyOrganizations();
|
|
37
|
+
const iamClient = new IamApi();
|
|
38
|
+
const config = this.cliConfiguration.getConfig();
|
|
39
|
+
const login = new ValidateLogin(config.login.url);
|
|
40
|
+
await login.validate(config, this.cliConfiguration, !flags.json);
|
|
41
|
+
const { auth } = config;
|
|
42
|
+
if (!auth?.accessToken) {
|
|
43
|
+
this.logger.fatal("Not logged in, run 'flowcore login'");
|
|
44
|
+
}
|
|
45
|
+
const organization = organizations.me.organizations.find((org) => org.organization.org === flags.tenant);
|
|
46
|
+
if (!organization) {
|
|
47
|
+
this.logger.fatal(`Organization ${flags.tenant} not found, or you are not a member`);
|
|
48
|
+
}
|
|
49
|
+
const [rolesErr, roles] = await tryit(iamClient.getApiV1RoleAssociationsOrganizationByOrganizationId)(organization.organization.id, {
|
|
50
|
+
headers: {
|
|
51
|
+
Authorization: `Bearer ${auth?.accessToken}`,
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
if (rolesErr) {
|
|
55
|
+
this.logger.fatal(`Failed to get roles: ${rolesErr.message}`);
|
|
56
|
+
}
|
|
57
|
+
const role = roles.data.find((role) => role.name === args.NAME);
|
|
58
|
+
if (!role) {
|
|
59
|
+
this.logger.fatal(`Role ${args.NAME} not found in tenant: ${flags.tenant}`);
|
|
60
|
+
}
|
|
61
|
+
if (!flags.yes) {
|
|
62
|
+
const { confirm } = await enquirer.prompt([
|
|
63
|
+
{
|
|
64
|
+
message: `Are you sure you want to delete role ${ux.colorize("cyan", role.name)} in tenant: ${ux.colorize("cyan", flags.tenant)}?`,
|
|
65
|
+
name: "confirm",
|
|
66
|
+
type: "confirm",
|
|
67
|
+
},
|
|
68
|
+
]);
|
|
69
|
+
if (!confirm) {
|
|
70
|
+
this.logger.info("Aborted");
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const [err] = await tryit(iamClient.deleteApiV1RolesById)(role.id, {
|
|
75
|
+
headers: {
|
|
76
|
+
Authorization: `Bearer ${auth?.accessToken}`,
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
if (err) {
|
|
80
|
+
this.logger.fatal(`Failed to delete role: ${err.message}`);
|
|
81
|
+
}
|
|
82
|
+
this.logger.info(`Role ${role.name} deleted`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -126,6 +126,47 @@ export default class GetPolicy extends BaseCommand {
|
|
|
126
126
|
documentTable = documentTable.row(row);
|
|
127
127
|
}
|
|
128
128
|
documentTable.render();
|
|
129
|
+
this.logger.info("");
|
|
130
|
+
const [associationsErr, associations] = await tryit(iamClient.getApiV1PolicyAssociationsByPolicyId)(policy.id, {
|
|
131
|
+
headers: {
|
|
132
|
+
Authorization: `Bearer ${auth?.accessToken}`,
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
if (associationsErr) {
|
|
136
|
+
this.logger.fatal(`Failed to get associations: ${associationsErr.message}`);
|
|
137
|
+
}
|
|
138
|
+
const userAssociationHeaders = ["User ID"];
|
|
139
|
+
const keyAssociationHeaders = ["Key ID"];
|
|
140
|
+
const roleAssociationHeaders = ["Role ID"];
|
|
141
|
+
const userAssociationTable = this.ui
|
|
142
|
+
.table()
|
|
143
|
+
.head(userAssociationHeaders);
|
|
144
|
+
const keyAssociationTable = this.ui.table().head(keyAssociationHeaders);
|
|
145
|
+
const roleAssociationTable = this.ui.table().head(roleAssociationHeaders);
|
|
146
|
+
for (const association of associations.data.keys) {
|
|
147
|
+
keyAssociationTable.row([association.keyId]);
|
|
148
|
+
}
|
|
149
|
+
for (const association of associations.data.users) {
|
|
150
|
+
userAssociationTable.row([association.userId]);
|
|
151
|
+
}
|
|
152
|
+
for (const association of associations.data.roles) {
|
|
153
|
+
roleAssociationTable.row([association.roleId]);
|
|
154
|
+
}
|
|
155
|
+
this.logger.info("");
|
|
156
|
+
this.logger.info("Key Associations:");
|
|
157
|
+
associations.data.keys.length > 0 && !flags.json
|
|
158
|
+
? keyAssociationTable.render()
|
|
159
|
+
: this.logger.info("No key associations");
|
|
160
|
+
this.logger.info("");
|
|
161
|
+
this.logger.info("User Associations:");
|
|
162
|
+
associations.data.users.length > 0 && !flags.json
|
|
163
|
+
? userAssociationTable.render()
|
|
164
|
+
: this.logger.info("No user associations");
|
|
165
|
+
this.logger.info("");
|
|
166
|
+
this.logger.info("Role Associations:");
|
|
167
|
+
associations.data.roles.length > 0 && !flags.json
|
|
168
|
+
? roleAssociationTable.render()
|
|
169
|
+
: this.logger.info("No role associations");
|
|
129
170
|
}
|
|
130
171
|
}
|
|
131
172
|
else if (flags.json) {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { BaseCommand, ValidateLogin } from "@flowcore/cli-plugin-config";
|
|
2
2
|
import { ClientFactory } from "@flowcore/cli-plugin-core";
|
|
3
3
|
import { Args, Flags } from "@oclif/core";
|
|
4
|
-
import _ from "lodash";
|
|
5
4
|
import { tryit } from "radash";
|
|
6
5
|
import { OrganizationService } from "../../services/organization.service.js";
|
|
7
6
|
import { Api as IamApi } from "../../utils/clients/iam/Api.js";
|
|
@@ -47,55 +46,39 @@ export default class GetRole extends BaseCommand {
|
|
|
47
46
|
if (!auth?.accessToken) {
|
|
48
47
|
this.logger.fatal("Not logged in, run 'flowcore login'");
|
|
49
48
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
});
|
|
55
|
-
if (err) {
|
|
56
|
-
this.logger.fatal(`Failed to get roles: ${err.message}`);
|
|
57
|
-
}
|
|
58
|
-
const roles = rolesResponse.data
|
|
59
|
-
.map((role) => {
|
|
60
|
-
const organizationLink = organizations.me.organizations.find((organization) => organization.organization.id === role.organizationId);
|
|
61
|
-
if (!organizationLink) {
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
return {
|
|
65
|
-
description: role.description,
|
|
66
|
-
id: role.id,
|
|
67
|
-
name: role.name,
|
|
68
|
-
organization: organizationLink,
|
|
69
|
-
organizationId: role.organizationId,
|
|
70
|
-
};
|
|
71
|
-
})
|
|
72
|
-
.filter((role) => role !== undefined)
|
|
73
|
-
.filter((role) => {
|
|
74
|
-
if (flags.tenant) {
|
|
75
|
-
return role.organization.organization.org === flags.tenant;
|
|
76
|
-
}
|
|
77
|
-
return true;
|
|
78
|
-
});
|
|
79
|
-
if (args.NAME) {
|
|
80
|
-
const role = roles.find((role) => role.name === args.NAME);
|
|
81
|
-
if (!role) {
|
|
82
|
-
this.logger.fatal(`Role ${args.NAME} not found`);
|
|
49
|
+
if (flags.tenant) {
|
|
50
|
+
const organization = organizations.me.organizations.find((organization) => flags.tenant ? organization.organization.org === flags.tenant : true);
|
|
51
|
+
if (!organization) {
|
|
52
|
+
this.logger.fatal(`Organization ${flags.tenant} not found, or not accessible`);
|
|
83
53
|
}
|
|
84
|
-
|
|
85
|
-
|
|
54
|
+
this.logger.info(`Roles for ${flags.tenant}:`);
|
|
55
|
+
const [err, roles] = await tryit(iamClient.getApiV1RoleAssociationsOrganizationByOrganizationId)(organization.organization.id, {
|
|
56
|
+
headers: {
|
|
57
|
+
Authorization: `Bearer ${auth?.accessToken}`,
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
if (err) {
|
|
61
|
+
this.logger.fatal(`Failed to get roles: ${err.message}`);
|
|
86
62
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
.
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
63
|
+
if (args.NAME && flags.tenant) {
|
|
64
|
+
const role = roles.data.find((role) => role.name === args.NAME);
|
|
65
|
+
if (!role) {
|
|
66
|
+
this.logger.fatal(`Role ${args.NAME} not found`);
|
|
67
|
+
}
|
|
68
|
+
!flags.json &&
|
|
69
|
+
this.ui
|
|
70
|
+
.sticker()
|
|
71
|
+
.add(`Role ${this.ui.colors.green(role.name)}`)
|
|
72
|
+
.add("")
|
|
73
|
+
.add(`ID: ${this.ui.colors.green(role.id)}`)
|
|
74
|
+
.add(`Description: ${this.ui.colors.green(role.description ?? "")}`)
|
|
75
|
+
.add(`Organization: ${this.ui.colors.green(organization.organization.displayName === ""
|
|
76
|
+
? organization.organization.org
|
|
77
|
+
: organization.organization.displayName)}`)
|
|
78
|
+
.render();
|
|
96
79
|
this.logger.info("");
|
|
97
80
|
this.logger.info("Policies:");
|
|
98
|
-
const [err, policies] = await tryit(iamClient.
|
|
81
|
+
const [err, policies] = await tryit(iamClient.getApiV1PolicyAssociationsRoleByRoleId)(role.id, {
|
|
99
82
|
headers: {
|
|
100
83
|
Authorization: `Bearer ${auth?.accessToken}`,
|
|
101
84
|
},
|
|
@@ -123,35 +106,97 @@ export default class GetRole extends BaseCommand {
|
|
|
123
106
|
];
|
|
124
107
|
policyTable = policyTable.row(row);
|
|
125
108
|
}
|
|
126
|
-
policyTable.render();
|
|
109
|
+
!flags.json && policyTable.render();
|
|
127
110
|
this.logger.info("");
|
|
111
|
+
const [associationsErr, associations] = await tryit(iamClient.getApiV1RoleAssociationsByRoleId)(role.id, {
|
|
112
|
+
headers: {
|
|
113
|
+
Authorization: `Bearer ${auth?.accessToken}`,
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
if (associationsErr) {
|
|
117
|
+
this.logger.fatal(`Failed to get associations: ${associationsErr.message}`);
|
|
118
|
+
}
|
|
119
|
+
const userAssociationHeaders = ["User ID"];
|
|
120
|
+
const keyAssociationHeaders = ["Key ID"];
|
|
121
|
+
const userAssociationTable = this.ui
|
|
122
|
+
.table()
|
|
123
|
+
.head(userAssociationHeaders);
|
|
124
|
+
const keyAssociationTable = this.ui.table().head(keyAssociationHeaders);
|
|
125
|
+
for (const association of associations.data.keys) {
|
|
126
|
+
keyAssociationTable.row([association.keyId]);
|
|
127
|
+
}
|
|
128
|
+
for (const association of associations.data.users) {
|
|
129
|
+
userAssociationTable.row([association.userId]);
|
|
130
|
+
}
|
|
131
|
+
this.logger.info("");
|
|
132
|
+
this.logger.info("Key Associations:");
|
|
133
|
+
associations.data.keys.length > 0 && !flags.json
|
|
134
|
+
? keyAssociationTable.render()
|
|
135
|
+
: this.logger.info("No key associations");
|
|
136
|
+
this.logger.info("");
|
|
137
|
+
this.logger.info("User Associations:");
|
|
138
|
+
associations.data.users.length > 0 && !flags.json
|
|
139
|
+
? userAssociationTable.render()
|
|
140
|
+
: this.logger.info("No user associations");
|
|
141
|
+
if (flags.json) {
|
|
142
|
+
console.log(JSON.stringify({
|
|
143
|
+
associations: associations.data,
|
|
144
|
+
policies: policies.data,
|
|
145
|
+
role: roles.data,
|
|
146
|
+
}, null, 2));
|
|
147
|
+
}
|
|
128
148
|
}
|
|
149
|
+
else if (!args.NAME && flags.tenant) {
|
|
150
|
+
const roleHeaders = ["Role ID", "Name", "Description"];
|
|
151
|
+
let roleTable = this.ui.table().head(roleHeaders);
|
|
152
|
+
for (const role of roles.data) {
|
|
153
|
+
const row = [role.id, role.name, role.description ?? ""];
|
|
154
|
+
roleTable = roleTable.row(row);
|
|
155
|
+
}
|
|
156
|
+
!flags.json && roleTable.render();
|
|
157
|
+
this.logger.info("");
|
|
158
|
+
if (flags.json) {
|
|
159
|
+
console.log(JSON.stringify({ role: roles.data }, null, 2));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return;
|
|
129
163
|
}
|
|
130
|
-
|
|
131
|
-
|
|
164
|
+
const [err, userRoles] = await tryit(iamClient.getApiV1Roles)({
|
|
165
|
+
headers: {
|
|
166
|
+
Authorization: `Bearer ${auth?.accessToken}`,
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
if (err) {
|
|
170
|
+
this.logger.fatal(`Failed to get roles: ${err.message}`);
|
|
132
171
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
role.description ?? "",
|
|
147
|
-
role.organization.organization.displayName === ""
|
|
148
|
-
? role.organization.organization.org
|
|
149
|
-
: role.organization.organization.displayName,
|
|
150
|
-
...(flags.wide ? [role.organization.organization.id] : []),
|
|
151
|
-
];
|
|
152
|
-
listTable = listTable.row(row);
|
|
172
|
+
console.log(userRoles.data);
|
|
173
|
+
const headers = [
|
|
174
|
+
"Role ID",
|
|
175
|
+
"Name",
|
|
176
|
+
"Description",
|
|
177
|
+
"Organization Name",
|
|
178
|
+
...(flags.wide ? ["Organization ID"] : []),
|
|
179
|
+
];
|
|
180
|
+
const listTable = this.ui.table().head(headers);
|
|
181
|
+
for (const role of userRoles.data) {
|
|
182
|
+
const organization = organizations.me.organizations.find((organization) => organization.organization.id === role.organizationId);
|
|
183
|
+
if (!organization) {
|
|
184
|
+
continue;
|
|
153
185
|
}
|
|
154
|
-
|
|
186
|
+
const row = [
|
|
187
|
+
role.id,
|
|
188
|
+
role.name,
|
|
189
|
+
role.description ?? "",
|
|
190
|
+
organization.organization.displayName === ""
|
|
191
|
+
? organization.organization.org
|
|
192
|
+
: organization.organization.displayName,
|
|
193
|
+
...(flags.wide ? [organization.organization.id] : []),
|
|
194
|
+
];
|
|
195
|
+
listTable.row(row);
|
|
196
|
+
}
|
|
197
|
+
!flags.json && listTable.render();
|
|
198
|
+
if (flags.json) {
|
|
199
|
+
console.log(JSON.stringify({ role: userRoles.data }, null, 2));
|
|
155
200
|
}
|
|
156
201
|
}
|
|
157
202
|
}
|
package/oclif.manifest.json
CHANGED
|
@@ -1,5 +1,127 @@
|
|
|
1
1
|
{
|
|
2
2
|
"commands": {
|
|
3
|
+
"delete:policy": {
|
|
4
|
+
"aliases": [],
|
|
5
|
+
"args": {
|
|
6
|
+
"NAME": {
|
|
7
|
+
"description": "name",
|
|
8
|
+
"name": "NAME",
|
|
9
|
+
"required": true
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"description": "Delete a policy",
|
|
13
|
+
"examples": [],
|
|
14
|
+
"flags": {
|
|
15
|
+
"profile": {
|
|
16
|
+
"description": "Specify the configuration profile to use",
|
|
17
|
+
"name": "profile",
|
|
18
|
+
"hasDynamicHelp": false,
|
|
19
|
+
"multiple": false,
|
|
20
|
+
"type": "option"
|
|
21
|
+
},
|
|
22
|
+
"json": {
|
|
23
|
+
"char": "j",
|
|
24
|
+
"description": "json output",
|
|
25
|
+
"name": "json",
|
|
26
|
+
"required": false,
|
|
27
|
+
"allowNo": false,
|
|
28
|
+
"type": "boolean"
|
|
29
|
+
},
|
|
30
|
+
"tenant": {
|
|
31
|
+
"char": "t",
|
|
32
|
+
"description": "tenant",
|
|
33
|
+
"name": "tenant",
|
|
34
|
+
"required": true,
|
|
35
|
+
"hasDynamicHelp": false,
|
|
36
|
+
"multiple": false,
|
|
37
|
+
"type": "option"
|
|
38
|
+
},
|
|
39
|
+
"yes": {
|
|
40
|
+
"char": "y",
|
|
41
|
+
"description": "yes to all",
|
|
42
|
+
"name": "yes",
|
|
43
|
+
"required": false,
|
|
44
|
+
"allowNo": false,
|
|
45
|
+
"type": "boolean"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"hasDynamicHelp": false,
|
|
49
|
+
"hiddenAliases": [],
|
|
50
|
+
"id": "delete:policy",
|
|
51
|
+
"pluginAlias": "@flowcore/cli-plugin-iam",
|
|
52
|
+
"pluginName": "@flowcore/cli-plugin-iam",
|
|
53
|
+
"pluginType": "core",
|
|
54
|
+
"strict": true,
|
|
55
|
+
"enableJsonFlag": false,
|
|
56
|
+
"isESM": true,
|
|
57
|
+
"relativePath": [
|
|
58
|
+
"dist",
|
|
59
|
+
"commands",
|
|
60
|
+
"delete",
|
|
61
|
+
"policy.js"
|
|
62
|
+
]
|
|
63
|
+
},
|
|
64
|
+
"delete:role": {
|
|
65
|
+
"aliases": [],
|
|
66
|
+
"args": {
|
|
67
|
+
"NAME": {
|
|
68
|
+
"description": "name",
|
|
69
|
+
"name": "NAME",
|
|
70
|
+
"required": true
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
"description": "Delete a role",
|
|
74
|
+
"examples": [],
|
|
75
|
+
"flags": {
|
|
76
|
+
"profile": {
|
|
77
|
+
"description": "Specify the configuration profile to use",
|
|
78
|
+
"name": "profile",
|
|
79
|
+
"hasDynamicHelp": false,
|
|
80
|
+
"multiple": false,
|
|
81
|
+
"type": "option"
|
|
82
|
+
},
|
|
83
|
+
"json": {
|
|
84
|
+
"char": "j",
|
|
85
|
+
"description": "json output",
|
|
86
|
+
"name": "json",
|
|
87
|
+
"required": false,
|
|
88
|
+
"allowNo": false,
|
|
89
|
+
"type": "boolean"
|
|
90
|
+
},
|
|
91
|
+
"tenant": {
|
|
92
|
+
"char": "t",
|
|
93
|
+
"description": "tenant",
|
|
94
|
+
"name": "tenant",
|
|
95
|
+
"required": true,
|
|
96
|
+
"hasDynamicHelp": false,
|
|
97
|
+
"multiple": false,
|
|
98
|
+
"type": "option"
|
|
99
|
+
},
|
|
100
|
+
"yes": {
|
|
101
|
+
"char": "y",
|
|
102
|
+
"description": "yes to all",
|
|
103
|
+
"name": "yes",
|
|
104
|
+
"required": false,
|
|
105
|
+
"allowNo": false,
|
|
106
|
+
"type": "boolean"
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
"hasDynamicHelp": false,
|
|
110
|
+
"hiddenAliases": [],
|
|
111
|
+
"id": "delete:role",
|
|
112
|
+
"pluginAlias": "@flowcore/cli-plugin-iam",
|
|
113
|
+
"pluginName": "@flowcore/cli-plugin-iam",
|
|
114
|
+
"pluginType": "core",
|
|
115
|
+
"strict": true,
|
|
116
|
+
"enableJsonFlag": false,
|
|
117
|
+
"isESM": true,
|
|
118
|
+
"relativePath": [
|
|
119
|
+
"dist",
|
|
120
|
+
"commands",
|
|
121
|
+
"delete",
|
|
122
|
+
"role.js"
|
|
123
|
+
]
|
|
124
|
+
},
|
|
3
125
|
"get:policy": {
|
|
4
126
|
"aliases": [],
|
|
5
127
|
"args": {
|
|
@@ -123,5 +245,5 @@
|
|
|
123
245
|
]
|
|
124
246
|
}
|
|
125
247
|
},
|
|
126
|
-
"version": "1.1
|
|
248
|
+
"version": "1.2.1"
|
|
127
249
|
}
|
package/package.json
CHANGED
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"@oclif/core": "^4.0.21",
|
|
10
10
|
"@oclif/plugin-help": "^6",
|
|
11
11
|
"@oclif/plugin-plugins": "^5.4.7",
|
|
12
|
-
"@opentf/obj-diff": "
|
|
12
|
+
"@opentf/obj-diff": "^0.12.0",
|
|
13
|
+
"add": "^2.0.6",
|
|
13
14
|
"dayjs": "^1.11.10",
|
|
14
15
|
"deepmerge": "^4.3.1",
|
|
15
16
|
"enquirer": "^2.4.1",
|
|
@@ -20,6 +21,7 @@
|
|
|
20
21
|
"lodash": "^4.17.21",
|
|
21
22
|
"radash": "^12.1.0",
|
|
22
23
|
"uuid": "^9.0.1",
|
|
24
|
+
"yarn": "^1.22.22",
|
|
23
25
|
"zod": "^3.22.4"
|
|
24
26
|
},
|
|
25
27
|
"description": "Flowcore CLI plugin for managing the IAM of the Flowcore Platform",
|
|
@@ -88,7 +90,7 @@
|
|
|
88
90
|
"version": "oclif readme && git add README.md",
|
|
89
91
|
"update-schema": "rover graph introspect https://graph.api.flowcore.io/graphql -o schema.gql"
|
|
90
92
|
},
|
|
91
|
-
"version": "1.1
|
|
93
|
+
"version": "1.2.1",
|
|
92
94
|
"bugs": "https://github.com/flowcore-io/cli-plugin-iam/issues",
|
|
93
95
|
"keywords": [
|
|
94
96
|
"oclif"
|