camunda-cloud-idac 1.0.0
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/LICENSE +21 -0
- package/README.md +117 -0
- package/dist/camunda/client.js +33 -0
- package/dist/camunda/client.js.map +1 -0
- package/dist/camunda/list-all.js +166 -0
- package/dist/camunda/list-all.js.map +1 -0
- package/dist/camunda/ops.js +63 -0
- package/dist/camunda/ops.js.map +1 -0
- package/dist/cli.js +140 -0
- package/dist/cli.js.map +1 -0
- package/dist/colors.js +19 -0
- package/dist/colors.js.map +1 -0
- package/dist/progress.js +67 -0
- package/dist/progress.js.map +1 -0
- package/dist/reconcile/apply.js +31 -0
- package/dist/reconcile/apply.js.map +1 -0
- package/dist/reconcile/diff.js +280 -0
- package/dist/reconcile/diff.js.map +1 -0
- package/dist/reconcile/format.js +92 -0
- package/dist/reconcile/format.js.map +1 -0
- package/dist/reconcile/order.js +58 -0
- package/dist/reconcile/order.js.map +1 -0
- package/dist/reconcile/protect.js +78 -0
- package/dist/reconcile/protect.js.map +1 -0
- package/dist/reconcile/types.js +18 -0
- package/dist/reconcile/types.js.map +1 -0
- package/dist/spec/load.js +46 -0
- package/dist/spec/load.js.map +1 -0
- package/dist/spec/schema.js +274 -0
- package/dist/spec/schema.js.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export const PROTECTED_ROLE_ID = "admin";
|
|
2
|
+
export const PROTECTED_TENANT_ID = "<default>";
|
|
3
|
+
/**
|
|
4
|
+
* The client this tool itself authenticates as (from CAMUNDA_CLIENT_ID, the same
|
|
5
|
+
* variable createCamundaClientLoose() reads). Its assignment to the admin role is
|
|
6
|
+
* protected from removal so a full reset can never lock the tool itself out.
|
|
7
|
+
* Deliberately NOT self-healing (per explicit product decision): if this client
|
|
8
|
+
* isn't already assigned to the admin role, this tool will not assign it - it
|
|
9
|
+
* only guards an existing assignment from being pruned away.
|
|
10
|
+
*/
|
|
11
|
+
function getGuardianClientId() {
|
|
12
|
+
return process.env.CAMUNDA_CLIENT_ID;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Unconditional safety filter, applied after diffing regardless of spec content.
|
|
16
|
+
* This is deliberately NOT a "skip if the spec doesn't mention admin" heuristic
|
|
17
|
+
* inside diff.ts: if the spec never mentions the admin role at all, the raw diff
|
|
18
|
+
* would otherwise queue every one of its authorizations for deletion in prune
|
|
19
|
+
* mode (they're simply "not in spec" = "extra"). Keeping the guard here, as a
|
|
20
|
+
* pure post-filter over the already-computed action list, means it can't be
|
|
21
|
+
* bypassed by any particular shape of spec and is the one place to audit to
|
|
22
|
+
* trust the invariant holds.
|
|
23
|
+
*
|
|
24
|
+
* Current invariants (narrowed by explicit product decision - the "admin" group,
|
|
25
|
+
* if one exists, is no longer specially protected; only the "admin" role is):
|
|
26
|
+
* 1. The "admin" role itself is never deleted.
|
|
27
|
+
* 2. The "admin" role's authorizations are fully hands-off: never created,
|
|
28
|
+
* updated, or deleted by this tool - not merely protected from deletion.
|
|
29
|
+
* 3. This tool's own client (CAMUNDA_CLIENT_ID) never loses its assignment to
|
|
30
|
+
* the admin role, so a full reset can't lock the tool out of the cluster it
|
|
31
|
+
* just reset. Every other role<->client pair (including other clients
|
|
32
|
+
* assigned to the admin role) is unaffected by this rule.
|
|
33
|
+
* 4. The `<default>` system tenant is never deleted (defense in depth - the API
|
|
34
|
+
* already rejects this server-side).
|
|
35
|
+
* 5. The "admin" role never loses its assignment to the `<default>` tenant, so
|
|
36
|
+
* a full `--prune` reset can never leave the admin role without access to
|
|
37
|
+
* the default tenant. Every other tenant<->role pair (including the admin
|
|
38
|
+
* role's assignment to any other tenant) is unaffected by this rule.
|
|
39
|
+
*
|
|
40
|
+
* Only entity-delete/authorization-mutation/the two guarded unassign edges
|
|
41
|
+
* (unassign-role-client, unassign-tenant-role) are ever blocked. Every other
|
|
42
|
+
* unassign-* action - including removing other roles/members from the admin
|
|
43
|
+
* role, or removing a non-guardian client from it - passes through untouched.
|
|
44
|
+
*/
|
|
45
|
+
export function applyProtections(actions) {
|
|
46
|
+
const warnings = [];
|
|
47
|
+
const guardianClientId = getGuardianClientId();
|
|
48
|
+
const kept = actions.filter((action) => {
|
|
49
|
+
const block = (reason) => {
|
|
50
|
+
warnings.push(`BLOCKED (${reason}): ${action.description}`);
|
|
51
|
+
return false;
|
|
52
|
+
};
|
|
53
|
+
const target = action.target;
|
|
54
|
+
if (target.kind === "delete-role" && target.roleId === PROTECTED_ROLE_ID) {
|
|
55
|
+
return block(`the "${PROTECTED_ROLE_ID}" role must never be deleted`);
|
|
56
|
+
}
|
|
57
|
+
if (target.kind === "delete-tenant" && target.tenantId === PROTECTED_TENANT_ID) {
|
|
58
|
+
return block(`the ${PROTECTED_TENANT_ID} system tenant must never be deleted`);
|
|
59
|
+
}
|
|
60
|
+
if (target.kind === "authorization" && target.ownerType === "ROLE" && target.ownerId === PROTECTED_ROLE_ID) {
|
|
61
|
+
return block(`authorizations of the "${PROTECTED_ROLE_ID}" role must never be created, updated, or deleted`);
|
|
62
|
+
}
|
|
63
|
+
if (target.kind === "unassign-role-client" &&
|
|
64
|
+
target.roleId === PROTECTED_ROLE_ID &&
|
|
65
|
+
guardianClientId !== undefined &&
|
|
66
|
+
target.clientId === guardianClientId) {
|
|
67
|
+
return block(`this tool's own client ("${guardianClientId}") must keep the "${PROTECTED_ROLE_ID}" role, or a full reset would lock the tool out`);
|
|
68
|
+
}
|
|
69
|
+
if (target.kind === "unassign-tenant-role" &&
|
|
70
|
+
target.tenantId === PROTECTED_TENANT_ID &&
|
|
71
|
+
target.roleId === PROTECTED_ROLE_ID) {
|
|
72
|
+
return block(`the "${PROTECTED_ROLE_ID}" role must never be unassigned from the ${PROTECTED_TENANT_ID} tenant`);
|
|
73
|
+
}
|
|
74
|
+
return true;
|
|
75
|
+
});
|
|
76
|
+
return { actions: kept, warnings };
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=protect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protect.js","sourceRoot":"","sources":["../../src/reconcile/protect.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,iBAAiB,GAAG,OAAO,CAAC;AACzC,MAAM,CAAC,MAAM,mBAAmB,GAAG,WAAW,CAAC;AAE/C;;;;;;;GAOG;AACH,SAAS,mBAAmB;IAC1B,OAAO,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;AACvC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAwB;IACvD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,gBAAgB,GAAG,mBAAmB,EAAE,CAAC;IAE/C,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE;QACrC,MAAM,KAAK,GAAG,CAAC,MAAc,EAAE,EAAE;YAC/B,QAAQ,CAAC,IAAI,CAAC,YAAY,MAAM,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;YAC5D,OAAO,KAAK,CAAC;QACf,CAAC,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAE7B,IAAI,MAAM,CAAC,IAAI,KAAK,aAAa,IAAI,MAAM,CAAC,MAAM,KAAK,iBAAiB,EAAE,CAAC;YACzE,OAAO,KAAK,CAAC,QAAQ,iBAAiB,8BAA8B,CAAC,CAAC;QACxE,CAAC;QAED,IAAI,MAAM,CAAC,IAAI,KAAK,eAAe,IAAI,MAAM,CAAC,QAAQ,KAAK,mBAAmB,EAAE,CAAC;YAC/E,OAAO,KAAK,CAAC,OAAO,mBAAmB,sCAAsC,CAAC,CAAC;QACjF,CAAC;QAED,IAAI,MAAM,CAAC,IAAI,KAAK,eAAe,IAAI,MAAM,CAAC,SAAS,KAAK,MAAM,IAAI,MAAM,CAAC,OAAO,KAAK,iBAAiB,EAAE,CAAC;YAC3G,OAAO,KAAK,CAAC,0BAA0B,iBAAiB,mDAAmD,CAAC,CAAC;QAC/G,CAAC;QAED,IACE,MAAM,CAAC,IAAI,KAAK,sBAAsB;YACtC,MAAM,CAAC,MAAM,KAAK,iBAAiB;YACnC,gBAAgB,KAAK,SAAS;YAC9B,MAAM,CAAC,QAAQ,KAAK,gBAAgB,EACpC,CAAC;YACD,OAAO,KAAK,CACV,4BAA4B,gBAAgB,qBAAqB,iBAAiB,iDAAiD,CACpI,CAAC;QACJ,CAAC;QAED,IACE,MAAM,CAAC,IAAI,KAAK,sBAAsB;YACtC,MAAM,CAAC,QAAQ,KAAK,mBAAmB;YACvC,MAAM,CAAC,MAAM,KAAK,iBAAiB,EACnC,CAAC;YACD,OAAO,KAAK,CAAC,QAAQ,iBAAiB,4CAA4C,mBAAmB,SAAS,CAAC,CAAC;QAClH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IAEH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AACrC,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export const DESTRUCTIVE_KINDS = new Set([
|
|
2
|
+
"delete-tenant",
|
|
3
|
+
"delete-role",
|
|
4
|
+
"delete-group",
|
|
5
|
+
"delete-mapping-rule",
|
|
6
|
+
"delete-authorization",
|
|
7
|
+
"unassign-role-mapping-rule",
|
|
8
|
+
"unassign-role-group",
|
|
9
|
+
"unassign-group-mapping-rule",
|
|
10
|
+
"unassign-group-user",
|
|
11
|
+
"unassign-group-client",
|
|
12
|
+
"unassign-role-user",
|
|
13
|
+
"unassign-role-client",
|
|
14
|
+
"unassign-tenant-role",
|
|
15
|
+
"unassign-tenant-group",
|
|
16
|
+
"unassign-tenant-mapping-rule",
|
|
17
|
+
]);
|
|
18
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/reconcile/types.ts"],"names":[],"mappings":"AAiGA,MAAM,CAAC,MAAM,iBAAiB,GAA4B,IAAI,GAAG,CAAa;IAC5E,eAAe;IACf,aAAa;IACb,cAAc;IACd,qBAAqB;IACrB,sBAAsB;IACtB,4BAA4B;IAC5B,qBAAqB;IACrB,6BAA6B;IAC7B,qBAAqB;IACrB,uBAAuB;IACvB,oBAAoB;IACpB,sBAAsB;IACtB,sBAAsB;IACtB,uBAAuB;IACvB,8BAA8B;CAC/B,CAAC,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { parse as parseYaml, YAMLParseError } from "yaml";
|
|
3
|
+
import { Spec } from "./schema.js";
|
|
4
|
+
export class SpecValidationError extends Error {
|
|
5
|
+
filePath;
|
|
6
|
+
issues;
|
|
7
|
+
constructor(filePath, issues) {
|
|
8
|
+
super(`Invalid spec at ${filePath}:\n${issues.map((i) => ` - ${i}`).join("\n")}`);
|
|
9
|
+
this.filePath = filePath;
|
|
10
|
+
this.issues = issues;
|
|
11
|
+
this.name = "SpecValidationError";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function formatZodError(error) {
|
|
15
|
+
return error.issues.map((issue) => {
|
|
16
|
+
const path = issue.path.join(".");
|
|
17
|
+
return path ? `${path}: ${issue.message}` : issue.message;
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
export async function loadSpec(filePath) {
|
|
21
|
+
let raw;
|
|
22
|
+
try {
|
|
23
|
+
raw = await readFile(filePath, "utf-8");
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
throw new SpecValidationError(filePath, [
|
|
27
|
+
err instanceof Error ? err.message : `Could not read file: ${String(err)}`,
|
|
28
|
+
]);
|
|
29
|
+
}
|
|
30
|
+
let parsed;
|
|
31
|
+
try {
|
|
32
|
+
parsed = parseYaml(raw);
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
if (err instanceof YAMLParseError) {
|
|
36
|
+
throw new SpecValidationError(filePath, [err.message]);
|
|
37
|
+
}
|
|
38
|
+
throw err;
|
|
39
|
+
}
|
|
40
|
+
const result = Spec.safeParse(parsed);
|
|
41
|
+
if (!result.success) {
|
|
42
|
+
throw new SpecValidationError(filePath, formatZodError(result.error));
|
|
43
|
+
}
|
|
44
|
+
return result.data;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=load.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load.js","sourceRoot":"","sources":["../../src/spec/load.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAE1D,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAGnC,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAE1B;IACA;IAFlB,YACkB,QAAgB,EAChB,MAAgB;QAEhC,KAAK,CAAC,mBAAmB,QAAQ,MAAM,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAHnE,aAAQ,GAAR,QAAQ,CAAQ;QAChB,WAAM,GAAN,MAAM,CAAU;QAGhC,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED,SAAS,cAAc,CAAC,KAAe;IACrC,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QAChC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,QAAgB;IAC7C,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,mBAAmB,CAAC,QAAQ,EAAE;YACtC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,wBAAwB,MAAM,CAAC,GAAG,CAAC,EAAE;SAC3E,CAAC,CAAC;IACL,CAAC;IAED,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,cAAc,EAAE,CAAC;YAClC,MAAM,IAAI,mBAAmB,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;QACzD,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACtC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,mBAAmB,CAAC,QAAQ,EAAE,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACxE,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// Copied verbatim from node_modules/@camunda8/orchestration-cluster-api's shipped
|
|
3
|
+
// .d.ts (OwnerTypeEnum / ResourceTypeEnum / PermissionTypeEnum). Re-check these
|
|
4
|
+
// against the installed package whenever the pinned SDK version in package.json
|
|
5
|
+
// changes - a drifted enum here would silently accept specs the live API rejects.
|
|
6
|
+
export const OwnerType = z.enum(["USER", "CLIENT", "ROLE", "GROUP", "MAPPING_RULE", "UNSPECIFIED"]);
|
|
7
|
+
export const ResourceType = z.enum([
|
|
8
|
+
"AUDIT_LOG",
|
|
9
|
+
"AUTHORIZATION",
|
|
10
|
+
"BATCH",
|
|
11
|
+
"CLUSTER_VARIABLE",
|
|
12
|
+
"COMPONENT",
|
|
13
|
+
"DECISION_DEFINITION",
|
|
14
|
+
"DECISION_REQUIREMENTS_DEFINITION",
|
|
15
|
+
"DOCUMENT",
|
|
16
|
+
"EXPRESSION",
|
|
17
|
+
"GLOBAL_LISTENER",
|
|
18
|
+
"GROUP",
|
|
19
|
+
"MAPPING_RULE",
|
|
20
|
+
"MESSAGE",
|
|
21
|
+
"PROCESS_DEFINITION",
|
|
22
|
+
"RESOURCE",
|
|
23
|
+
"ROLE",
|
|
24
|
+
"SYSTEM",
|
|
25
|
+
"TENANT",
|
|
26
|
+
"USER",
|
|
27
|
+
"USER_TASK",
|
|
28
|
+
]);
|
|
29
|
+
export const PermissionType = z.enum([
|
|
30
|
+
"ACCESS",
|
|
31
|
+
"CANCEL_PROCESS_INSTANCE",
|
|
32
|
+
"CLAIM",
|
|
33
|
+
"CLAIM_USER_TASK",
|
|
34
|
+
"COMPLETE",
|
|
35
|
+
"COMPLETE_USER_TASK",
|
|
36
|
+
"CREATE",
|
|
37
|
+
"CREATE_BATCH_OPERATION_CANCEL_PROCESS_INSTANCE",
|
|
38
|
+
"CREATE_BATCH_OPERATION_DELETE_DECISION_DEFINITION",
|
|
39
|
+
"CREATE_BATCH_OPERATION_DELETE_DECISION_INSTANCE",
|
|
40
|
+
"CREATE_BATCH_OPERATION_DELETE_PROCESS_DEFINITION",
|
|
41
|
+
"CREATE_BATCH_OPERATION_DELETE_PROCESS_INSTANCE",
|
|
42
|
+
"CREATE_BATCH_OPERATION_MIGRATE_PROCESS_INSTANCE",
|
|
43
|
+
"CREATE_BATCH_OPERATION_MODIFY_PROCESS_INSTANCE",
|
|
44
|
+
"CREATE_BATCH_OPERATION_RESOLVE_INCIDENT",
|
|
45
|
+
"CREATE_DECISION_INSTANCE",
|
|
46
|
+
"CREATE_PROCESS_INSTANCE",
|
|
47
|
+
"CREATE_TASK_LISTENER",
|
|
48
|
+
"DELETE",
|
|
49
|
+
"DELETE_DECISION_INSTANCE",
|
|
50
|
+
"DELETE_DRD",
|
|
51
|
+
"DELETE_FORM",
|
|
52
|
+
"DELETE_PROCESS",
|
|
53
|
+
"DELETE_PROCESS_INSTANCE",
|
|
54
|
+
"DELETE_RESOURCE",
|
|
55
|
+
"DELETE_TASK_LISTENER",
|
|
56
|
+
"EVALUATE",
|
|
57
|
+
"MODIFY_PROCESS_INSTANCE",
|
|
58
|
+
"READ",
|
|
59
|
+
"READ_DECISION_DEFINITION",
|
|
60
|
+
"READ_DECISION_INSTANCE",
|
|
61
|
+
"READ_JOB_METRIC",
|
|
62
|
+
"READ_PROCESS_DEFINITION",
|
|
63
|
+
"READ_PROCESS_INSTANCE",
|
|
64
|
+
"READ_USAGE_METRIC",
|
|
65
|
+
"READ_USER_TASK",
|
|
66
|
+
"READ_TASK_LISTENER",
|
|
67
|
+
"UPDATE",
|
|
68
|
+
"UPDATE_PROCESS_INSTANCE",
|
|
69
|
+
"UPDATE_USER_TASK",
|
|
70
|
+
"UPDATE_TASK_LISTENER",
|
|
71
|
+
]);
|
|
72
|
+
// Entities that can own an authorization and are also declared as first-class
|
|
73
|
+
// entities in this spec (used by the referential-integrity check below).
|
|
74
|
+
const OWNER_TYPES_WITH_DECLARED_ENTITIES = new Set(["ROLE", "GROUP", "MAPPING_RULE"]);
|
|
75
|
+
// .strict() on every object below is deliberate, not incidental: zod's default
|
|
76
|
+
// z.object() silently drops unrecognized keys instead of rejecting them, which
|
|
77
|
+
// would let a typo (e.g. `mappingRuleId: [...]` instead of `mappingRules: [...]`
|
|
78
|
+
// on a group) parse "successfully" while silently doing nothing - exactly the
|
|
79
|
+
// class of error this tool uses zod to prevent in the first place.
|
|
80
|
+
const MappingRuleSpec = z
|
|
81
|
+
.object({
|
|
82
|
+
mappingRuleId: z.string().min(1),
|
|
83
|
+
claimName: z.string().min(1),
|
|
84
|
+
claimValue: z.string().min(1),
|
|
85
|
+
name: z.string().optional(),
|
|
86
|
+
})
|
|
87
|
+
.strict();
|
|
88
|
+
const GroupSpec = z
|
|
89
|
+
.object({
|
|
90
|
+
groupId: z.string().min(1),
|
|
91
|
+
name: z.string().min(1),
|
|
92
|
+
description: z.string().optional(),
|
|
93
|
+
mappingRules: z.array(z.string()).default([]),
|
|
94
|
+
// Direct membership, not modeled via mapping rules/OIDC claims. Usernames and
|
|
95
|
+
// client IDs aren't declared entities elsewhere in this spec (unlike
|
|
96
|
+
// roles/groups/mappingRules), so there's no referential-integrity check for
|
|
97
|
+
// these - any string is accepted, matching how authorization owners of type
|
|
98
|
+
// USER/CLIENT are handled.
|
|
99
|
+
users: z.array(z.string()).default([]),
|
|
100
|
+
clients: z.array(z.string()).default([]),
|
|
101
|
+
})
|
|
102
|
+
.strict();
|
|
103
|
+
const RoleSpec = z
|
|
104
|
+
.object({
|
|
105
|
+
roleId: z.string().min(1),
|
|
106
|
+
name: z.string().min(1),
|
|
107
|
+
description: z.string().optional(),
|
|
108
|
+
mappingRules: z.array(z.string()).default([]),
|
|
109
|
+
groups: z.array(z.string()).default([]),
|
|
110
|
+
// Direct membership - not modeled via mapping rules/OIDC claims, no
|
|
111
|
+
// referential-integrity check (same rationale as GroupSpec.users/clients above).
|
|
112
|
+
users: z.array(z.string()).default([]),
|
|
113
|
+
clients: z.array(z.string()).default([]),
|
|
114
|
+
})
|
|
115
|
+
.strict();
|
|
116
|
+
const TenantSpec = z
|
|
117
|
+
.object({
|
|
118
|
+
tenantId: z.string().min(1),
|
|
119
|
+
name: z.string().min(1),
|
|
120
|
+
description: z.string().optional(),
|
|
121
|
+
roles: z.array(z.string()).default([]),
|
|
122
|
+
groups: z.array(z.string()).default([]),
|
|
123
|
+
mappingRules: z.array(z.string()).default([]),
|
|
124
|
+
})
|
|
125
|
+
.strict();
|
|
126
|
+
const AuthorizationSpec = z
|
|
127
|
+
.object({
|
|
128
|
+
ownerType: OwnerType,
|
|
129
|
+
ownerId: z.string().min(1),
|
|
130
|
+
resourceType: ResourceType,
|
|
131
|
+
resourceId: z.string().min(1),
|
|
132
|
+
permissions: z.array(PermissionType).min(1),
|
|
133
|
+
})
|
|
134
|
+
.strict();
|
|
135
|
+
const RawSpec = z
|
|
136
|
+
.object({
|
|
137
|
+
tenants: z.array(TenantSpec).default([]),
|
|
138
|
+
roles: z.array(RoleSpec).default([]),
|
|
139
|
+
groups: z.array(GroupSpec).default([]),
|
|
140
|
+
mappingRules: z.array(MappingRuleSpec).default([]),
|
|
141
|
+
authorizations: z.array(AuthorizationSpec).default([]),
|
|
142
|
+
})
|
|
143
|
+
.strict();
|
|
144
|
+
function findDuplicates(ids) {
|
|
145
|
+
const seen = new Set();
|
|
146
|
+
const dupes = new Set();
|
|
147
|
+
for (const id of ids) {
|
|
148
|
+
if (seen.has(id))
|
|
149
|
+
dupes.add(id);
|
|
150
|
+
seen.add(id);
|
|
151
|
+
}
|
|
152
|
+
return [...dupes];
|
|
153
|
+
}
|
|
154
|
+
export const Spec = RawSpec.superRefine((spec, ctx) => {
|
|
155
|
+
const mappingRuleIds = new Set(spec.mappingRules.map((m) => m.mappingRuleId));
|
|
156
|
+
const groupIds = new Set(spec.groups.map((g) => g.groupId));
|
|
157
|
+
const roleIds = new Set(spec.roles.map((r) => r.roleId));
|
|
158
|
+
// Rule 7: no duplicate IDs within each entity array.
|
|
159
|
+
for (const [label, ids] of [
|
|
160
|
+
["tenants[].tenantId", spec.tenants.map((t) => t.tenantId)],
|
|
161
|
+
["roles[].roleId", spec.roles.map((r) => r.roleId)],
|
|
162
|
+
["groups[].groupId", spec.groups.map((g) => g.groupId)],
|
|
163
|
+
["mappingRules[].mappingRuleId", spec.mappingRules.map((m) => m.mappingRuleId)],
|
|
164
|
+
]) {
|
|
165
|
+
for (const dupe of findDuplicates(ids)) {
|
|
166
|
+
ctx.addIssue({
|
|
167
|
+
code: "custom",
|
|
168
|
+
path: [label],
|
|
169
|
+
message: `Duplicate ${label} value: "${dupe}"`,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// Rules 1-3: role/group references to mapping rules and groups.
|
|
174
|
+
spec.roles.forEach((role, i) => {
|
|
175
|
+
role.mappingRules.forEach((id, j) => {
|
|
176
|
+
if (!mappingRuleIds.has(id)) {
|
|
177
|
+
ctx.addIssue({
|
|
178
|
+
code: "custom",
|
|
179
|
+
path: ["roles", i, "mappingRules", j],
|
|
180
|
+
message: `roles[${i}] ("${role.roleId}") references unknown mappingRuleId "${id}"`,
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
role.groups.forEach((id, j) => {
|
|
185
|
+
if (!groupIds.has(id)) {
|
|
186
|
+
ctx.addIssue({
|
|
187
|
+
code: "custom",
|
|
188
|
+
path: ["roles", i, "groups", j],
|
|
189
|
+
message: `roles[${i}] ("${role.roleId}") references unknown groupId "${id}"`,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
spec.groups.forEach((group, i) => {
|
|
195
|
+
group.mappingRules.forEach((id, j) => {
|
|
196
|
+
if (!mappingRuleIds.has(id)) {
|
|
197
|
+
ctx.addIssue({
|
|
198
|
+
code: "custom",
|
|
199
|
+
path: ["groups", i, "mappingRules", j],
|
|
200
|
+
message: `groups[${i}] ("${group.groupId}") references unknown mappingRuleId "${id}"`,
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
// Rules 4-5: tenant references to roles and groups.
|
|
206
|
+
spec.tenants.forEach((tenant, i) => {
|
|
207
|
+
tenant.roles.forEach((id, j) => {
|
|
208
|
+
if (!roleIds.has(id)) {
|
|
209
|
+
ctx.addIssue({
|
|
210
|
+
code: "custom",
|
|
211
|
+
path: ["tenants", i, "roles", j],
|
|
212
|
+
message: `tenants[${i}] ("${tenant.tenantId}") references unknown roleId "${id}"`,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
tenant.groups.forEach((id, j) => {
|
|
217
|
+
if (!groupIds.has(id)) {
|
|
218
|
+
ctx.addIssue({
|
|
219
|
+
code: "custom",
|
|
220
|
+
path: ["tenants", i, "groups", j],
|
|
221
|
+
message: `tenants[${i}] ("${tenant.tenantId}") references unknown groupId "${id}"`,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
tenant.mappingRules.forEach((id, j) => {
|
|
226
|
+
if (!mappingRuleIds.has(id)) {
|
|
227
|
+
ctx.addIssue({
|
|
228
|
+
code: "custom",
|
|
229
|
+
path: ["tenants", i, "mappingRules", j],
|
|
230
|
+
message: `tenants[${i}] ("${tenant.tenantId}") references unknown mappingRuleId "${id}"`,
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
// Rule 6: authorization owner must exist among declared entities, when the
|
|
236
|
+
// owner type corresponds to a declared entity type in this spec.
|
|
237
|
+
const idsByOwnerType = {
|
|
238
|
+
ROLE: roleIds,
|
|
239
|
+
GROUP: groupIds,
|
|
240
|
+
MAPPING_RULE: mappingRuleIds,
|
|
241
|
+
};
|
|
242
|
+
spec.authorizations.forEach((auth, i) => {
|
|
243
|
+
if (OWNER_TYPES_WITH_DECLARED_ENTITIES.has(auth.ownerType)) {
|
|
244
|
+
const ids = idsByOwnerType[auth.ownerType];
|
|
245
|
+
if (!ids.has(auth.ownerId)) {
|
|
246
|
+
ctx.addIssue({
|
|
247
|
+
code: "custom",
|
|
248
|
+
path: ["authorizations", i, "ownerId"],
|
|
249
|
+
message: `authorizations[${i}] references unknown ${auth.ownerType} ownerId "${auth.ownerId}"`,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
// Rule 8: no two authorization entries with the same tuple but different permissions.
|
|
255
|
+
const tupleToPermissions = new Map();
|
|
256
|
+
spec.authorizations.forEach((auth, i) => {
|
|
257
|
+
const key = `${auth.ownerType}::${auth.ownerId}::${auth.resourceType}::${auth.resourceId}`;
|
|
258
|
+
const existing = tupleToPermissions.get(key);
|
|
259
|
+
if (!existing) {
|
|
260
|
+
tupleToPermissions.set(key, { index: i, permissions: auth.permissions });
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
const sameSet = existing.permissions.length === auth.permissions.length &&
|
|
264
|
+
new Set(existing.permissions).size === new Set([...existing.permissions, ...auth.permissions]).size;
|
|
265
|
+
if (!sameSet) {
|
|
266
|
+
ctx.addIssue({
|
|
267
|
+
code: "custom",
|
|
268
|
+
path: ["authorizations", i],
|
|
269
|
+
message: `authorizations[${i}] duplicates the tuple (${auth.ownerType}, ${auth.ownerId}, ${auth.resourceType}, ${auth.resourceId}) already declared at authorizations[${existing.index}] with different permissions`,
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/spec/schema.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "camunda-cloud-idac",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Identity-as-code reconciler for Camunda 8 (tenants, roles, groups, mapping rules, authorizations)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Jan Rohwer",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/janhuddel/camunda-cloud-idac.git"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/janhuddel/camunda-cloud-idac#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/janhuddel/camunda-cloud-idac/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"camunda",
|
|
18
|
+
"camunda-8",
|
|
19
|
+
"zeebe",
|
|
20
|
+
"identity-as-code",
|
|
21
|
+
"iac",
|
|
22
|
+
"cli"
|
|
23
|
+
],
|
|
24
|
+
"bin": {
|
|
25
|
+
"camunda-idac": "./dist/cli.js",
|
|
26
|
+
"cci": "./dist/cli.js"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist"
|
|
30
|
+
],
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsc -p tsconfig.json",
|
|
33
|
+
"dev": "tsx src/cli.ts",
|
|
34
|
+
"typecheck": "tsc --noEmit -p tsconfig.typecheck.json",
|
|
35
|
+
"test": "vitest run",
|
|
36
|
+
"prepublishOnly": "npm run typecheck && npm test && npm run build"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@camunda8/orchestration-cluster-api": "9.1.5",
|
|
40
|
+
"commander": "^12.1.0",
|
|
41
|
+
"yaml": "^2.6.1",
|
|
42
|
+
"zod": "^4.0.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/node": "^20.17.0",
|
|
46
|
+
"tsx": "^4.19.2",
|
|
47
|
+
"typescript": "^5.7.2",
|
|
48
|
+
"vitest": "^2.1.8"
|
|
49
|
+
},
|
|
50
|
+
"engines": {
|
|
51
|
+
"node": ">=20.6.0"
|
|
52
|
+
}
|
|
53
|
+
}
|