-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathpolicies.ts
More file actions
238 lines (223 loc) · 8.71 KB
/
Copy pathpolicies.ts
File metadata and controls
238 lines (223 loc) · 8.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
import type { Command } from "commander";
import { withErrorHandler, createClient, getFormat, outputResponse } from "../../helpers.js";
import { parseJsonInput } from "../../input.js";
import { printSuccess } from "../../output.js";
import { addExamples } from "../help.js";
export function registerPoliciesCommand(parent: Command): void {
const policies = parent
.command("policies")
.description("Manage XACML access control policies");
// policies list
const list = policies
.command("list")
.description("List all access control policies, showing their status and priority")
.action(
withErrorHandler(async (_opts: unknown, cmd: Command) => {
const client = createClient(cmd);
const format = getFormat(cmd);
const response = await client.rawRequest("GET", "/admin/policies");
outputResponse(response, format);
}),
);
addExamples(list, [
{
description: "List all policies",
command: "geonic admin policies list",
},
{
description: "List policies in table format for an overview",
command: "geonic admin policies list --format table",
},
]);
// policies get
const get = policies
.command("get <id>")
.description("Get a policy's full details — target rules, effect, priority, and status")
.action(
withErrorHandler(async (id: unknown, _opts: unknown, cmd: Command) => {
const client = createClient(cmd);
const format = getFormat(cmd);
const response = await client.rawRequest(
"GET",
`/admin/policies/${encodeURIComponent(String(id))}`,
);
outputResponse(response, format);
}),
);
addExamples(get, [
{
description: "Inspect a policy's rules and target configuration",
command: "geonic admin policies get <policy-id>",
},
]);
// policies create
const create = policies
.command("create [json]")
.summary("Create a new policy")
.description(
"Create a new policy\n\n" +
"JSON payload examples:\n\n" +
" Allow all entities:\n" +
" {\n" +
' "description": "Allow all entities",\n' +
' "rules": [{"ruleId": "allow-all", "effect": "Permit"}]\n' +
" }\n\n" +
" Allow GET access to a specific entity type:\n" +
" {\n" +
' "description": "Allow GET access to Landmark entities",\n' +
' "target": {\n' +
' "resources": [{"attributeId": "entityType", "matchValue": "Landmark"}],\n' +
' "actions": [{"attributeId": "method", "matchValue": "GET"}]\n' +
" },\n" +
' "rules": [{"ruleId": "permit-get", "effect": "Permit"}]\n' +
" }\n\n" +
"Target fields:\n" +
" subjects — attributeId: role, userId, email, tenantId\n" +
" resources — attributeId: path, entityType, entityId, entityOwner, tenantService, servicePath\n" +
" actions — attributeId: method (GET, POST, PATCH, DELETE)\n\n" +
"Each element: {attributeId, matchValue, matchFunction?}\n" +
" matchFunction: \"string-equal\" (default) | \"string-regexp\" | \"glob\"\n\n" +
"Priority: smaller value = higher precedence (e.g. priority 10 overrides user default at 100).\n" +
" tenant_admin: minimum priority 10. user self-service (/me/policies): fixed at 100.\n\n" +
"Default role policies (priority 100):\n" +
" user → /v2/** and /ngsi-ld/** all methods Permit; other data APIs GET only\n" +
" api_key → all Deny, anonymous → all Deny",
)
.action(
withErrorHandler(async (json: unknown, _opts: unknown, cmd: Command) => {
const body = await parseJsonInput(json as string | undefined);
const client = createClient(cmd);
const format = getFormat(cmd);
const response = await client.rawRequest("POST", "/admin/policies", {
body,
});
outputResponse(response, format);
printSuccess("Policy created.");
}),
);
addExamples(create, [
{
description: "Create with inline JSON",
command: `geonic admin policies create '{"description":"Allow all entities","rules":[{"ruleId":"allow-all","effect":"Permit"}]}'`,
},
{
description: "Create with target (entity type + method)",
command: `geonic admin policies create '{"description":"Allow GET Landmark","target":{"resources":[{"attributeId":"entityType","matchValue":"Landmark"}],"actions":[{"attributeId":"method","matchValue":"GET"}]},"rules":[{"ruleId":"permit-get","effect":"Permit"}]}'`,
},
{
description: "Create anonymous access policy",
command: `geonic admin policies create '{"policyId":"public-read","target":{"subjects":[{"attributeId":"role","matchValue":"anonymous"}],"resources":[{"attributeId":"entityType","matchValue":"WeatherObserved"}],"actions":[{"attributeId":"method","matchValue":"GET"}]},"rules":[{"effect":"Permit"}]}'`,
},
{
description: "Create servicePath-based policy (glob match)",
command: `geonic admin policies create '{"description":"Allow read on /opendata/**","priority":100,"target":{"resources":[{"attributeId":"servicePath","matchValue":"/opendata/**","matchFunction":"glob"}],"actions":[{"attributeId":"method","matchValue":"GET"}]},"rules":[{"effect":"Permit"}]}'`,
},
{
description: "Create from a JSON file",
command: "geonic admin policies create @policy.json",
},
{
description: "Create from stdin pipe",
command: "cat policy.json | geonic admin policies create",
},
]);
// policies update
const update = policies
.command("update <id> [json]")
.summary("Update a policy")
.description(
"Update a policy\n\n" +
"JSON payload: only specified fields are updated.\n" +
' e.g. {"description": "Updated policy"}',
)
.action(
withErrorHandler(
async (id: unknown, json: unknown, _opts: unknown, cmd: Command) => {
const body = await parseJsonInput(json as string | undefined);
const client = createClient(cmd);
const format = getFormat(cmd);
const response = await client.rawRequest(
"PATCH",
`/admin/policies/${encodeURIComponent(String(id))}`,
{ body },
);
outputResponse(response, format);
printSuccess("Policy updated.");
},
),
);
addExamples(update, [
{
description: "Update description",
command: `geonic admin policies update <policy-id> '{"description":"Updated policy"}'`,
},
{
description: "Update from a JSON file",
command: "geonic admin policies update <policy-id> @policy.json",
},
{
description: "Update from stdin pipe",
command: "cat policy.json | geonic admin policies update <policy-id>",
},
]);
// policies delete
const del = policies
.command("delete <id>")
.description("Delete a policy. Users or API keys referencing this policy will lose the access it granted")
.action(
withErrorHandler(async (id: unknown, _opts: unknown, cmd: Command) => {
const client = createClient(cmd);
await client.rawRequest(
"DELETE",
`/admin/policies/${encodeURIComponent(String(id))}`,
);
printSuccess("Policy deleted.");
}),
);
addExamples(del, [
{
description: "Delete a policy by ID",
command: "geonic admin policies delete <policy-id>",
},
]);
// policies activate
const activate = policies
.command("activate <id>")
.description("Activate a policy so its access control rules are enforced")
.action(
withErrorHandler(async (id: unknown, _opts: unknown, cmd: Command) => {
const client = createClient(cmd);
await client.rawRequest(
"POST",
`/admin/policies/${encodeURIComponent(String(id))}/activate`,
);
printSuccess("Policy activated.");
}),
);
addExamples(activate, [
{
description: "Enable a policy to start enforcing its rules",
command: "geonic admin policies activate <policy-id>",
},
]);
// policies deactivate
const deactivate = policies
.command("deactivate <id>")
.description("Deactivate a policy, suspending its rules without deleting it")
.action(
withErrorHandler(async (id: unknown, _opts: unknown, cmd: Command) => {
const client = createClient(cmd);
await client.rawRequest(
"POST",
`/admin/policies/${encodeURIComponent(String(id))}/deactivate`,
);
printSuccess("Policy deactivated.");
}),
);
addExamples(deactivate, [
{
description: "Temporarily disable a policy without deleting it",
command: "geonic admin policies deactivate <policy-id>",
},
]);
}