@homeflare/alchemy 0.6.0 → 0.7.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/README.md +54 -10
- package/dist/caddy/admin-calls.d.ts +48 -0
- package/dist/caddy/admin-calls.d.ts.map +1 -0
- package/dist/caddy/admin-guard.d.ts +40 -0
- package/dist/caddy/admin-guard.d.ts.map +1 -0
- package/dist/caddy/admin.d.ts +73 -0
- package/dist/caddy/admin.d.ts.map +1 -0
- package/dist/caddy/caddyfile-tripwire.d.ts +5 -0
- package/dist/caddy/caddyfile-tripwire.d.ts.map +1 -0
- package/dist/caddy/config-form.d.ts +27 -0
- package/dist/caddy/config-form.d.ts.map +1 -0
- package/dist/caddy/config-lifecycle.d.ts +45 -0
- package/dist/caddy/config-lifecycle.d.ts.map +1 -0
- package/dist/caddy/config.d.ts +30 -0
- package/dist/caddy/config.d.ts.map +1 -0
- package/dist/caddy/digest.d.ts +7 -0
- package/dist/caddy/digest.d.ts.map +1 -0
- package/dist/caddy/fake-caddy.d.ts +43 -0
- package/dist/caddy/fake-caddy.d.ts.map +1 -0
- package/dist/caddy/index.d.ts +21 -0
- package/dist/caddy/index.d.ts.map +1 -0
- package/dist/caddy/index.js +912 -0
- package/dist/caddy/index.js.map +28 -0
- package/dist/caddy/local-admin.d.ts +45 -0
- package/dist/caddy/local-admin.d.ts.map +1 -0
- package/dist/caddy/providers.d.ts +14 -0
- package/dist/caddy/providers.d.ts.map +1 -0
- package/dist/caddy/with-file.d.ts +47 -0
- package/dist/caddy/with-file.d.ts.map +1 -0
- package/dist/cloudflare/fake-mesh.d.ts +58 -0
- package/dist/cloudflare/fake-mesh.d.ts.map +1 -0
- package/dist/cloudflare/index.d.ts +9 -3
- package/dist/cloudflare/index.d.ts.map +1 -1
- package/dist/cloudflare/index.js +218 -7
- package/dist/cloudflare/index.js.map +9 -4
- package/dist/cloudflare/mesh-node-api.d.ts +75 -0
- package/dist/cloudflare/mesh-node-api.d.ts.map +1 -0
- package/dist/cloudflare/mesh-node-form.d.ts +82 -0
- package/dist/cloudflare/mesh-node-form.d.ts.map +1 -0
- package/dist/cloudflare/mesh-node-harness.d.ts +46 -0
- package/dist/cloudflare/mesh-node-harness.d.ts.map +1 -0
- package/dist/cloudflare/mesh-node-lifecycle.d.ts +22 -0
- package/dist/cloudflare/mesh-node-lifecycle.d.ts.map +1 -0
- package/dist/cloudflare/mesh-node-token.d.ts +23 -0
- package/dist/cloudflare/mesh-node-token.d.ts.map +1 -0
- package/dist/cloudflare/mesh-node.d.ts +48 -0
- package/dist/cloudflare/mesh-node.d.ts.map +1 -0
- package/dist/cloudflare/providers.d.ts +1 -12
- package/dist/cloudflare/providers.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/launchd/index.js.map +2 -2
- package/dist/launchd/secret-tripwire.d.ts +1 -0
- package/dist/launchd/secret-tripwire.d.ts.map +1 -1
- package/dist/openbao/cloudflare-role.d.ts.map +1 -1
- package/dist/openbao/fake-engines.d.ts +30 -0
- package/dist/openbao/fake-engines.d.ts.map +1 -0
- package/dist/openbao/fake-stack.d.ts +29 -0
- package/dist/openbao/fake-stack.d.ts.map +1 -0
- package/dist/openbao/index.js +231 -151
- package/dist/openbao/index.js.map +9 -7
- package/dist/openbao/policy.d.ts +2 -0
- package/dist/openbao/policy.d.ts.map +1 -1
- package/dist/openbao/proxmox-role-form.d.ts +18 -8
- package/dist/openbao/proxmox-role-form.d.ts.map +1 -1
- package/dist/openbao/proxmox-role-wire.d.ts +18 -0
- package/dist/openbao/proxmox-role-wire.d.ts.map +1 -0
- package/dist/openbao/proxmox-role.d.ts.map +1 -1
- package/dist/openbao/rename.d.ts +106 -0
- package/dist/openbao/rename.d.ts.map +1 -0
- package/docs/caddy.md +180 -0
- package/docs/mesh-node.md +188 -0
- package/package.json +7 -2
- package/src/caddy/admin-calls.ts +128 -0
- package/src/caddy/admin-guard.ts +170 -0
- package/src/caddy/admin.ts +74 -0
- package/src/caddy/caddyfile-tripwire.ts +133 -0
- package/src/caddy/config-form.ts +64 -0
- package/src/caddy/config-lifecycle.test.ts +218 -0
- package/src/caddy/config-lifecycle.ts +148 -0
- package/src/caddy/config.ts +116 -0
- package/src/caddy/digest.ts +44 -0
- package/src/caddy/fake-caddy.ts +160 -0
- package/src/caddy/guards.test.ts +156 -0
- package/src/caddy/index.ts +25 -0
- package/src/caddy/local-admin.test.ts +160 -0
- package/src/caddy/local-admin.ts +189 -0
- package/src/caddy/providers.test.ts +244 -0
- package/src/caddy/providers.ts +17 -0
- package/src/caddy/with-file.ts +62 -0
- package/src/cloudflare/fake-mesh.ts +181 -0
- package/src/cloudflare/index.ts +9 -3
- package/src/cloudflare/mesh-node-api.ts +127 -0
- package/src/cloudflare/mesh-node-edges.test.ts +103 -0
- package/src/cloudflare/mesh-node-form.test.ts +80 -0
- package/src/cloudflare/mesh-node-form.ts +115 -0
- package/src/cloudflare/mesh-node-harness.ts +124 -0
- package/src/cloudflare/mesh-node-lifecycle.ts +187 -0
- package/src/cloudflare/mesh-node-policy.test.ts +151 -0
- package/src/cloudflare/mesh-node-token.test.ts +117 -0
- package/src/cloudflare/mesh-node-token.ts +125 -0
- package/src/cloudflare/mesh-node.test.ts +172 -0
- package/src/cloudflare/mesh-node.ts +120 -0
- package/src/cloudflare/providers.ts +20 -2
- package/src/index.ts +1 -0
- package/src/launchd/secret-tripwire.ts +1 -1
- package/src/openbao/REPLACE.md +97 -21
- package/src/openbao/cloudflare-role-wire.test.ts +8 -34
- package/src/openbao/cloudflare-role.ts +30 -8
- package/src/openbao/fake-engines.ts +119 -0
- package/src/openbao/fake-stack.ts +112 -0
- package/src/openbao/policy-rename.test.ts +112 -0
- package/src/openbao/policy-wire.test.ts +7 -26
- package/src/openbao/policy.ts +27 -4
- package/src/openbao/proxmox-role-form.ts +27 -8
- package/src/openbao/proxmox-role-wire.ts +24 -0
- package/src/openbao/proxmox-role.ts +62 -37
- package/src/openbao/rename-occupied.test.ts +166 -0
- package/src/openbao/rename.ts +162 -0
- package/src/openbao/role-rename.test.ts +205 -0
package/dist/openbao/index.js
CHANGED
|
@@ -804,7 +804,7 @@ var assertBaoIdentity = (input) => {
|
|
|
804
804
|
import { Resource as Resource3 } from "alchemy";
|
|
805
805
|
import { isResolved as isResolved3 } from "alchemy/Diff";
|
|
806
806
|
import * as Provider3 from "alchemy/Provider";
|
|
807
|
-
import * as
|
|
807
|
+
import * as Effect13 from "effect/Effect";
|
|
808
808
|
|
|
809
809
|
// src/openbao/cloudflare-group-scope.ts
|
|
810
810
|
var zoneResource = (zoneId) => `com.cloudflare.api.account.zone.${zoneId}`;
|
|
@@ -1184,13 +1184,46 @@ var permissionGroupsFromLiveRoles = (declared) => Effect11.gen(function* () {
|
|
|
1184
1184
|
});
|
|
1185
1185
|
});
|
|
1186
1186
|
|
|
1187
|
+
// src/openbao/rename.ts
|
|
1188
|
+
import * as Effect12 from "effect/Effect";
|
|
1189
|
+
var exact = (identity) => identity;
|
|
1190
|
+
var declaredString = (news, key) => {
|
|
1191
|
+
if (typeof news !== "object" || news === null)
|
|
1192
|
+
return;
|
|
1193
|
+
const value = news[key];
|
|
1194
|
+
return typeof value === "string" ? value : undefined;
|
|
1195
|
+
};
|
|
1196
|
+
var isPendingProp = (news, key) => {
|
|
1197
|
+
if (typeof news !== "object" || news === null)
|
|
1198
|
+
return false;
|
|
1199
|
+
const value = news[key];
|
|
1200
|
+
return value !== undefined && typeof value !== "string";
|
|
1201
|
+
};
|
|
1202
|
+
var declaredRolePath = (news, rolePath2) => {
|
|
1203
|
+
const mount = declaredString(news, "mount");
|
|
1204
|
+
const name = declaredString(news, "name");
|
|
1205
|
+
return mount === undefined || name === undefined ? undefined : rolePath2(mount, name);
|
|
1206
|
+
};
|
|
1207
|
+
var policyKey = (name) => name.trim().toLowerCase();
|
|
1208
|
+
var isMoved = (stored, declared, key = exact) => declared === undefined ? undefined : key(stored) !== key(declared);
|
|
1209
|
+
var triedRolePath = (output, olds, rolePath2) => output === undefined ? declaredRolePath(olds, rolePath2) : rolePath2(output.mount, output.name);
|
|
1210
|
+
var judgeMove = (family, tried, declared, pathOf, key = exact) => Effect12.gen(function* () {
|
|
1211
|
+
if (tried === undefined || declared === undefined || key(tried) === key(declared)) {
|
|
1212
|
+
return;
|
|
1213
|
+
}
|
|
1214
|
+
if ((yield* baoRead(pathOf(declared))) === undefined)
|
|
1215
|
+
return { from: tried, to: declared };
|
|
1216
|
+
return yield* Effect12.die(new Error(`${family}: ${tried} → ${declared} would land on an object that already exists at ` + `${declared}. Under RemovalPolicy.destroy() a resource moving off that name (a swap, a ` + "shift, or a reverted move that did not finish) deletes it after this one writes it. " + "Nothing was written. Move through a name nothing holds, in two deploys, or remove " + `${declared} by hand first.`));
|
|
1217
|
+
});
|
|
1218
|
+
var refuseMovedUpdate = (family, from, to) => Effect12.die(new Error(`${family}: planned as an update, but its identity moved from ${from} to ${to}. Writing ` + `${to} now would leave ${from} live with no state record. Nothing was written. Run the ` + "deploy again: once the value resolves at plan time it plans as a replace."));
|
|
1219
|
+
|
|
1187
1220
|
// src/openbao/cloudflare-role.ts
|
|
1188
1221
|
var BaoCloudflareRole = Resource3("Bao.CloudflareRole", {
|
|
1189
1222
|
defaultRemovalPolicy: "retain"
|
|
1190
1223
|
});
|
|
1191
|
-
var BaoCloudflareRoleProvider = () => Provider3.effect(BaoCloudflareRole,
|
|
1224
|
+
var BaoCloudflareRoleProvider = () => Provider3.effect(BaoCloudflareRole, Effect13.gen(function* () {
|
|
1192
1225
|
const groups = yield* CloudflarePermissionGroups;
|
|
1193
|
-
const resolved = (props) =>
|
|
1226
|
+
const resolved = (props) => Effect13.gen(function* () {
|
|
1194
1227
|
const refs = new Map;
|
|
1195
1228
|
for (const policy of props.policies) {
|
|
1196
1229
|
const scope = policy.scope ?? scopeOfResource(policy.resource);
|
|
@@ -1200,18 +1233,25 @@ var BaoCloudflareRoleProvider = () => Provider3.effect(BaoCloudflareRole, Effect
|
|
|
1200
1233
|
const ids = yield* groups.resolve(props.mount, [...refs.values()]);
|
|
1201
1234
|
const { missing, policies } = resolvePolicies(props.policies, ids);
|
|
1202
1235
|
if (missing.length > 0) {
|
|
1203
|
-
return yield*
|
|
1236
|
+
return yield* Effect13.die(new Error(`Bao.CloudflareRole ${rolePath(props.mount, props.name)}: groups ` + `${missing.join(", ")} came back unresolved from a lookup that reported success.`));
|
|
1204
1237
|
}
|
|
1205
1238
|
return policies;
|
|
1206
1239
|
});
|
|
1207
1240
|
return BaoCloudflareRole.Provider.of({
|
|
1208
|
-
list: () =>
|
|
1209
|
-
read:
|
|
1241
|
+
list: () => Effect13.succeed([]),
|
|
1242
|
+
read: Effect13.fn(function* ({ olds }) {
|
|
1210
1243
|
const live = yield* readCloudflareRole(olds.mount, olds.name);
|
|
1211
1244
|
return live === undefined ? undefined : attributesOf4(olds, live);
|
|
1212
1245
|
}),
|
|
1213
|
-
diff:
|
|
1214
|
-
|
|
1246
|
+
diff: Effect13.fn(function* ({ news, olds, output }) {
|
|
1247
|
+
const tried = triedRolePath(output, olds, rolePath);
|
|
1248
|
+
const declared = declaredRolePath(news, rolePath);
|
|
1249
|
+
const move = yield* judgeMove("Bao.CloudflareRole", tried, declared, (path) => path);
|
|
1250
|
+
if (output === undefined)
|
|
1251
|
+
return;
|
|
1252
|
+
if (move !== undefined)
|
|
1253
|
+
return { action: "replace" };
|
|
1254
|
+
if (!isResolved3(news))
|
|
1215
1255
|
return;
|
|
1216
1256
|
if (refusalOf(news) !== undefined)
|
|
1217
1257
|
return { action: "update" };
|
|
@@ -1221,11 +1261,15 @@ var BaoCloudflareRoleProvider = () => Provider3.effect(BaoCloudflareRole, Effect
|
|
|
1221
1261
|
return { action: "update" };
|
|
1222
1262
|
return differences(news, policies, live).length === 0 ? { action: "noop" } : { action: "update" };
|
|
1223
1263
|
}),
|
|
1224
|
-
reconcile:
|
|
1264
|
+
reconcile: Effect13.fn(function* ({ news, output }) {
|
|
1225
1265
|
const path = rolePath(news.mount, news.name);
|
|
1266
|
+
const before = output === undefined ? path : rolePath(output.mount, output.name);
|
|
1267
|
+
if (isMoved(before, path) === true) {
|
|
1268
|
+
return yield* refuseMovedUpdate("Bao.CloudflareRole", before, path);
|
|
1269
|
+
}
|
|
1226
1270
|
const refusal2 = refusalOf(news);
|
|
1227
1271
|
if (refusal2 !== undefined) {
|
|
1228
|
-
return yield*
|
|
1272
|
+
return yield* Effect13.die(new Error(`Bao.CloudflareRole ${path}: ${refusal2}.`));
|
|
1229
1273
|
}
|
|
1230
1274
|
const policies = yield* resolved(news);
|
|
1231
1275
|
const live = yield* readCloudflareRole(news.mount, news.name);
|
|
@@ -1234,15 +1278,15 @@ var BaoCloudflareRoleProvider = () => Provider3.effect(BaoCloudflareRole, Effect
|
|
|
1234
1278
|
}
|
|
1235
1279
|
const after = yield* readCloudflareRole(news.mount, news.name);
|
|
1236
1280
|
if (after === undefined) {
|
|
1237
|
-
return yield*
|
|
1281
|
+
return yield* Effect13.die(new Error(`Bao.CloudflareRole ${path}: the write succeeded but the role is absent.`));
|
|
1238
1282
|
}
|
|
1239
1283
|
const left = differences(news, policies, after);
|
|
1240
1284
|
if (left.length > 0) {
|
|
1241
|
-
return yield*
|
|
1285
|
+
return yield* Effect13.die(new Error(`Bao.CloudflareRole ${path}: wrote cleanly but reads back different in ` + `${left.map((d) => d.field).join(", ")}. Inspect the role before retrying.`));
|
|
1242
1286
|
}
|
|
1243
1287
|
return attributesOf4(news, after);
|
|
1244
1288
|
}),
|
|
1245
|
-
delete:
|
|
1289
|
+
delete: Effect13.fn(function* ({ output }) {
|
|
1246
1290
|
yield* deleteCloudflareRole(output.mount, output.name);
|
|
1247
1291
|
return;
|
|
1248
1292
|
})
|
|
@@ -1492,7 +1536,7 @@ var hostAppRoles = (input) => {
|
|
|
1492
1536
|
import { Resource as Resource4 } from "alchemy";
|
|
1493
1537
|
import { isResolved as isResolved4 } from "alchemy/Diff";
|
|
1494
1538
|
import * as Provider4 from "alchemy/Provider";
|
|
1495
|
-
import * as
|
|
1539
|
+
import * as Effect15 from "effect/Effect";
|
|
1496
1540
|
|
|
1497
1541
|
// src/openbao/jwt-config-form.ts
|
|
1498
1542
|
var text5 = (value) => typeof value === "string" ? value.trim() : "";
|
|
@@ -1582,16 +1626,16 @@ var problems = (props) => {
|
|
|
1582
1626
|
};
|
|
1583
1627
|
|
|
1584
1628
|
// src/openbao/role-reconcile.ts
|
|
1585
|
-
import * as
|
|
1586
|
-
var readRoleAt = (spec) =>
|
|
1587
|
-
var planRole = (spec) =>
|
|
1629
|
+
import * as Effect14 from "effect/Effect";
|
|
1630
|
+
var readRoleAt = (spec) => Effect14.map(baoRead(spec.path), (live) => live === undefined ? undefined : { attributes: spec.attributesOf(live), live });
|
|
1631
|
+
var planRole = (spec) => Effect14.gen(function* () {
|
|
1588
1632
|
if (spec.problems.length > 0)
|
|
1589
1633
|
return "update";
|
|
1590
1634
|
const found = yield* readRoleAt(spec);
|
|
1591
1635
|
return found !== undefined && spec.matches(found.attributes) ? "noop" : "update";
|
|
1592
1636
|
});
|
|
1593
|
-
var refuse2 = (spec, message) =>
|
|
1594
|
-
var reconcileRole = (spec) =>
|
|
1637
|
+
var refuse2 = (spec, message) => Effect14.die(new Error(`${spec.family} ${spec.path}: ${message}`));
|
|
1638
|
+
var reconcileRole = (spec) => Effect14.gen(function* () {
|
|
1595
1639
|
if (spec.problems.length > 0)
|
|
1596
1640
|
return yield* refuse2(spec, spec.problems.join("; "));
|
|
1597
1641
|
const found = yield* readRoleAt(spec);
|
|
@@ -1624,29 +1668,29 @@ var jwtConfigSpec = (props) => ({
|
|
|
1624
1668
|
problems: problems(props),
|
|
1625
1669
|
wouldErase
|
|
1626
1670
|
});
|
|
1627
|
-
var BaoJwtAuthConfigProvider = () => Provider4.effect(BaoJwtAuthConfig,
|
|
1628
|
-
list: () =>
|
|
1629
|
-
read:
|
|
1671
|
+
var BaoJwtAuthConfigProvider = () => Provider4.effect(BaoJwtAuthConfig, Effect15.succeed(BaoJwtAuthConfig.Provider.of({
|
|
1672
|
+
list: () => Effect15.succeed([]),
|
|
1673
|
+
read: Effect15.fn(function* ({ olds }) {
|
|
1630
1674
|
const found = yield* readRoleAt(jwtConfigSpec(olds));
|
|
1631
1675
|
return found?.attributes;
|
|
1632
1676
|
}),
|
|
1633
|
-
diff:
|
|
1677
|
+
diff: Effect15.fn(function* ({ news, output }) {
|
|
1634
1678
|
if (output === undefined || !isResolved4(news))
|
|
1635
1679
|
return;
|
|
1636
1680
|
if (mountOf(news) !== output.mount)
|
|
1637
1681
|
return { action: "replace" };
|
|
1638
1682
|
return { action: yield* planRole(jwtConfigSpec(news)) };
|
|
1639
1683
|
}),
|
|
1640
|
-
reconcile:
|
|
1684
|
+
reconcile: Effect15.fn(function* ({ news }) {
|
|
1641
1685
|
return yield* reconcileRole(jwtConfigSpec(news));
|
|
1642
1686
|
}),
|
|
1643
|
-
delete: () =>
|
|
1687
|
+
delete: () => Effect15.void
|
|
1644
1688
|
})));
|
|
1645
1689
|
// src/openbao/jwt-role.ts
|
|
1646
1690
|
import { Resource as Resource5 } from "alchemy";
|
|
1647
1691
|
import { isResolved as isResolved5 } from "alchemy/Diff";
|
|
1648
1692
|
import * as Provider5 from "alchemy/Provider";
|
|
1649
|
-
import * as
|
|
1693
|
+
import * as Effect16 from "effect/Effect";
|
|
1650
1694
|
|
|
1651
1695
|
// src/openbao/auth-token-form.ts
|
|
1652
1696
|
var sortedSet2 = (values) => [...new Set(values)].sort();
|
|
@@ -1856,13 +1900,13 @@ var jwtRoleSpec = (props) => ({
|
|
|
1856
1900
|
path: rolePath2(props),
|
|
1857
1901
|
problems: problems2(props)
|
|
1858
1902
|
});
|
|
1859
|
-
var BaoJwtRoleProvider = () => Provider5.effect(BaoJwtRole,
|
|
1860
|
-
list: () =>
|
|
1861
|
-
read:
|
|
1903
|
+
var BaoJwtRoleProvider = () => Provider5.effect(BaoJwtRole, Effect16.succeed(BaoJwtRole.Provider.of({
|
|
1904
|
+
list: () => Effect16.succeed([]),
|
|
1905
|
+
read: Effect16.fn(function* ({ olds }) {
|
|
1862
1906
|
const found = yield* readRoleAt(jwtRoleSpec(olds));
|
|
1863
1907
|
return found?.attributes;
|
|
1864
1908
|
}),
|
|
1865
|
-
diff:
|
|
1909
|
+
diff: Effect16.fn(function* ({ news, output }) {
|
|
1866
1910
|
if (output === undefined || !isResolved5(news))
|
|
1867
1911
|
return;
|
|
1868
1912
|
if (mountOf2(news) !== output.mount || news.name !== output.name) {
|
|
@@ -1870,10 +1914,10 @@ var BaoJwtRoleProvider = () => Provider5.effect(BaoJwtRole, Effect15.succeed(Bao
|
|
|
1870
1914
|
}
|
|
1871
1915
|
return { action: yield* planRole(jwtRoleSpec(news)) };
|
|
1872
1916
|
}),
|
|
1873
|
-
reconcile:
|
|
1917
|
+
reconcile: Effect16.fn(function* ({ news }) {
|
|
1874
1918
|
return yield* reconcileRole(jwtRoleSpec(news));
|
|
1875
1919
|
}),
|
|
1876
|
-
delete:
|
|
1920
|
+
delete: Effect16.fn(function* ({ output }) {
|
|
1877
1921
|
yield* baoDelete(rolePath2(output));
|
|
1878
1922
|
return;
|
|
1879
1923
|
})
|
|
@@ -1882,7 +1926,7 @@ var BaoJwtRoleProvider = () => Provider5.effect(BaoJwtRole, Effect15.succeed(Bao
|
|
|
1882
1926
|
import { Resource as Resource6 } from "alchemy";
|
|
1883
1927
|
import { isResolved as isResolved6 } from "alchemy/Diff";
|
|
1884
1928
|
import * as Provider6 from "alchemy/Provider";
|
|
1885
|
-
import * as
|
|
1929
|
+
import * as Effect17 from "effect/Effect";
|
|
1886
1930
|
|
|
1887
1931
|
// src/openbao/kubernetes-role-form.ts
|
|
1888
1932
|
var sortedSet4 = (values) => [...new Set(values)].sort();
|
|
@@ -1959,13 +2003,13 @@ var kubernetesRoleSpec = (props) => ({
|
|
|
1959
2003
|
path: rolePath3(props),
|
|
1960
2004
|
problems: problems3(props)
|
|
1961
2005
|
});
|
|
1962
|
-
var BaoKubernetesRoleProvider = () => Provider6.effect(BaoKubernetesRole,
|
|
1963
|
-
list: () =>
|
|
1964
|
-
read:
|
|
2006
|
+
var BaoKubernetesRoleProvider = () => Provider6.effect(BaoKubernetesRole, Effect17.succeed(BaoKubernetesRole.Provider.of({
|
|
2007
|
+
list: () => Effect17.succeed([]),
|
|
2008
|
+
read: Effect17.fn(function* ({ olds }) {
|
|
1965
2009
|
const found = yield* readRoleAt(kubernetesRoleSpec(olds));
|
|
1966
2010
|
return found?.attributes;
|
|
1967
2011
|
}),
|
|
1968
|
-
diff:
|
|
2012
|
+
diff: Effect17.fn(function* ({ news, output }) {
|
|
1969
2013
|
if (output === undefined || !isResolved6(news))
|
|
1970
2014
|
return;
|
|
1971
2015
|
if (mountOf3(news) !== output.mount || news.name !== output.name) {
|
|
@@ -1973,10 +2017,10 @@ var BaoKubernetesRoleProvider = () => Provider6.effect(BaoKubernetesRole, Effect
|
|
|
1973
2017
|
}
|
|
1974
2018
|
return { action: yield* planRole(kubernetesRoleSpec(news)) };
|
|
1975
2019
|
}),
|
|
1976
|
-
reconcile:
|
|
2020
|
+
reconcile: Effect17.fn(function* ({ news }) {
|
|
1977
2021
|
return yield* reconcileRole(kubernetesRoleSpec(news));
|
|
1978
2022
|
}),
|
|
1979
|
-
delete:
|
|
2023
|
+
delete: Effect17.fn(function* ({ output }) {
|
|
1980
2024
|
yield* baoDelete(rolePath3(output));
|
|
1981
2025
|
return;
|
|
1982
2026
|
})
|
|
@@ -1985,7 +2029,7 @@ var BaoKubernetesRoleProvider = () => Provider6.effect(BaoKubernetesRole, Effect
|
|
|
1985
2029
|
import { Resource as Resource7 } from "alchemy";
|
|
1986
2030
|
import { isResolved as isResolved7 } from "alchemy/Diff";
|
|
1987
2031
|
import * as Provider7 from "alchemy/Provider";
|
|
1988
|
-
import * as
|
|
2032
|
+
import * as Effect19 from "effect/Effect";
|
|
1989
2033
|
|
|
1990
2034
|
// src/openbao/mfa-enforcement-form.ts
|
|
1991
2035
|
var sortedSet5 = (values) => [...new Set(values.map((value) => value.trim()))].filter((value) => value !== "").sort();
|
|
@@ -2053,16 +2097,16 @@ var problems4 = (props, missingPaths) => {
|
|
|
2053
2097
|
};
|
|
2054
2098
|
|
|
2055
2099
|
// src/openbao/mfa-wire.ts
|
|
2056
|
-
import * as
|
|
2100
|
+
import * as Effect18 from "effect/Effect";
|
|
2057
2101
|
var TOTP_PATH = "identity/mfa/method/totp";
|
|
2058
2102
|
var METHODS_PATH = "identity/mfa/method";
|
|
2059
2103
|
var enforcementPath = (name) => `identity/mfa/login-enforcement/${name}`;
|
|
2060
2104
|
var record4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
|
|
2061
|
-
var ownNamespacePath =
|
|
2105
|
+
var ownNamespacePath = Effect18.gen(function* () {
|
|
2062
2106
|
const env = yield* BaoEnv;
|
|
2063
2107
|
return namespacePath(envNamespace(env));
|
|
2064
2108
|
});
|
|
2065
|
-
var findTotp = (name) =>
|
|
2109
|
+
var findTotp = (name) => Effect18.gen(function* () {
|
|
2066
2110
|
const listing = yield* baoRead(`${METHODS_PATH}?list=true`);
|
|
2067
2111
|
const info = record4(listing?.["key_info"]) ?? {};
|
|
2068
2112
|
const own = yield* ownNamespacePath;
|
|
@@ -2071,17 +2115,17 @@ var findTotp = (name) => Effect17.gen(function* () {
|
|
|
2071
2115
|
if (live === undefined || live["name"] !== name || live["namespace_path"] !== own)
|
|
2072
2116
|
continue;
|
|
2073
2117
|
if (live["type"] !== "totp") {
|
|
2074
|
-
return yield*
|
|
2118
|
+
return yield* Effect18.die(new Error(`Bao.MfaTotpMethod ${name}: that name belongs to a ${String(live["type"])} method ` + `(${id}) in this namespace, and a TOTP write would convert it. Pick another name.`));
|
|
2075
2119
|
}
|
|
2076
2120
|
return { id, live };
|
|
2077
2121
|
}
|
|
2078
2122
|
return;
|
|
2079
2123
|
});
|
|
2080
|
-
var writeTotp = (body) =>
|
|
2124
|
+
var writeTotp = (body) => Effect18.asVoid(baoCall("write", "POST", TOTP_PATH, body));
|
|
2081
2125
|
var deleteTotp = (id) => baoDelete(`${TOTP_PATH}/${id}`);
|
|
2082
2126
|
var readEnforcement = (name) => baoRead(enforcementPath(name));
|
|
2083
|
-
var writeEnforcement = (name, body) =>
|
|
2084
|
-
var authAccessors = (paths) =>
|
|
2127
|
+
var writeEnforcement = (name, body) => Effect18.asVoid(baoCall("write", "POST", enforcementPath(name), body));
|
|
2128
|
+
var authAccessors = (paths) => Effect18.gen(function* () {
|
|
2085
2129
|
if (paths.length === 0)
|
|
2086
2130
|
return { accessors: [], missing: [] };
|
|
2087
2131
|
const table = (yield* baoRead("sys/auth")) ?? {};
|
|
@@ -2101,20 +2145,20 @@ var authAccessors = (paths) => Effect17.gen(function* () {
|
|
|
2101
2145
|
var BaoMfaLoginEnforcement = Resource7("Bao.MfaLoginEnforcement", {
|
|
2102
2146
|
defaultRemovalPolicy: "retain"
|
|
2103
2147
|
});
|
|
2104
|
-
var refuse3 = (name, message) =>
|
|
2105
|
-
var resolveTargets = (props) =>
|
|
2148
|
+
var refuse3 = (name, message) => Effect19.die(new Error(`Bao.MfaLoginEnforcement ${name}: ${message}`));
|
|
2149
|
+
var resolveTargets = (props) => Effect19.map(authAccessors(props.authMethodPaths ?? []), ({ accessors, missing }) => ({
|
|
2106
2150
|
bad: problems4(props, missing),
|
|
2107
2151
|
resolved: accessors
|
|
2108
2152
|
}));
|
|
2109
|
-
var readLive = (name) =>
|
|
2110
|
-
var planEnforcement = (props) =>
|
|
2153
|
+
var readLive = (name) => Effect19.map(readEnforcement(name), (live) => live === undefined ? undefined : attributesOf8(name, live));
|
|
2154
|
+
var planEnforcement = (props) => Effect19.gen(function* () {
|
|
2111
2155
|
const { bad, resolved } = yield* resolveTargets(props);
|
|
2112
2156
|
if (bad.length > 0)
|
|
2113
2157
|
return "update";
|
|
2114
2158
|
const live = yield* readLive(props.name);
|
|
2115
2159
|
return live !== undefined && matches7(live, props, resolved) ? "noop" : "update";
|
|
2116
2160
|
});
|
|
2117
|
-
var reconcileEnforcement = (props) =>
|
|
2161
|
+
var reconcileEnforcement = (props) => Effect19.gen(function* () {
|
|
2118
2162
|
const { bad, resolved } = yield* resolveTargets(props);
|
|
2119
2163
|
if (bad.length > 0)
|
|
2120
2164
|
return yield* refuse3(props.name, bad.join("; "));
|
|
@@ -2130,22 +2174,22 @@ var reconcileEnforcement = (props) => Effect18.gen(function* () {
|
|
|
2130
2174
|
}
|
|
2131
2175
|
return after;
|
|
2132
2176
|
});
|
|
2133
|
-
var BaoMfaLoginEnforcementProvider = () => Provider7.effect(BaoMfaLoginEnforcement,
|
|
2134
|
-
list: () =>
|
|
2135
|
-
read:
|
|
2177
|
+
var BaoMfaLoginEnforcementProvider = () => Provider7.effect(BaoMfaLoginEnforcement, Effect19.succeed(BaoMfaLoginEnforcement.Provider.of({
|
|
2178
|
+
list: () => Effect19.succeed([]),
|
|
2179
|
+
read: Effect19.fn(function* ({ olds }) {
|
|
2136
2180
|
return yield* readLive(olds.name);
|
|
2137
2181
|
}),
|
|
2138
|
-
diff:
|
|
2182
|
+
diff: Effect19.fn(function* ({ news, output }) {
|
|
2139
2183
|
if (output === undefined || !isResolved7(news))
|
|
2140
2184
|
return;
|
|
2141
2185
|
if (news.name !== output.name)
|
|
2142
2186
|
return { action: "replace" };
|
|
2143
2187
|
return { action: yield* planEnforcement(news) };
|
|
2144
2188
|
}),
|
|
2145
|
-
reconcile:
|
|
2189
|
+
reconcile: Effect19.fn(function* ({ news }) {
|
|
2146
2190
|
return yield* reconcileEnforcement(news);
|
|
2147
2191
|
}),
|
|
2148
|
-
delete:
|
|
2192
|
+
delete: Effect19.fn(function* ({ output }) {
|
|
2149
2193
|
return yield* refuse3(output.name, "REFUSING to delete: OpenBao 2.6.2 drops a login enforcement from memory only, and it " + "returns on the next unseal (openbao/openbao#4030). Set this resource back to " + "retain to drop it from state; remove it for good only once the server is fixed.");
|
|
2150
2194
|
})
|
|
2151
2195
|
})));
|
|
@@ -2153,7 +2197,7 @@ var BaoMfaLoginEnforcementProvider = () => Provider7.effect(BaoMfaLoginEnforceme
|
|
|
2153
2197
|
import { Resource as Resource8 } from "alchemy";
|
|
2154
2198
|
import { isResolved as isResolved8 } from "alchemy/Diff";
|
|
2155
2199
|
import * as Provider8 from "alchemy/Provider";
|
|
2156
|
-
import * as
|
|
2200
|
+
import * as Effect20 from "effect/Effect";
|
|
2157
2201
|
|
|
2158
2202
|
// src/openbao/mfa-totp-form.ts
|
|
2159
2203
|
var canonical6 = (input) => ({
|
|
@@ -2234,15 +2278,15 @@ var problems5 = (props) => {
|
|
|
2234
2278
|
var BaoMfaTotpMethod = Resource8("Bao.MfaTotpMethod", {
|
|
2235
2279
|
defaultRemovalPolicy: "retain"
|
|
2236
2280
|
});
|
|
2237
|
-
var refuse4 = (props, message) =>
|
|
2238
|
-
var readTotp = (props) =>
|
|
2239
|
-
var planTotp = (props) =>
|
|
2281
|
+
var refuse4 = (props, message) => Effect20.die(new Error(`Bao.MfaTotpMethod ${props.name}: ${message}`));
|
|
2282
|
+
var readTotp = (props) => Effect20.map(findTotp(props.name), (found) => found === undefined ? undefined : attributesOf9(found.id, found.live));
|
|
2283
|
+
var planTotp = (props) => Effect20.gen(function* () {
|
|
2240
2284
|
if (problems5(props).length > 0)
|
|
2241
2285
|
return "update";
|
|
2242
2286
|
const live = yield* readTotp(props);
|
|
2243
2287
|
return live !== undefined && matches8(live, props) ? "noop" : "update";
|
|
2244
2288
|
});
|
|
2245
|
-
var reconcileTotp = (props) =>
|
|
2289
|
+
var reconcileTotp = (props) => Effect20.gen(function* () {
|
|
2246
2290
|
const bad = problems5(props);
|
|
2247
2291
|
if (bad.length > 0)
|
|
2248
2292
|
return yield* refuse4(props, bad.join("; "));
|
|
@@ -2256,12 +2300,12 @@ var reconcileTotp = (props) => Effect19.gen(function* () {
|
|
|
2256
2300
|
return yield* refuse4(props, "the method read back different.");
|
|
2257
2301
|
return after;
|
|
2258
2302
|
});
|
|
2259
|
-
var BaoMfaTotpMethodProvider = () => Provider8.effect(BaoMfaTotpMethod,
|
|
2260
|
-
list: () =>
|
|
2261
|
-
read:
|
|
2303
|
+
var BaoMfaTotpMethodProvider = () => Provider8.effect(BaoMfaTotpMethod, Effect20.succeed(BaoMfaTotpMethod.Provider.of({
|
|
2304
|
+
list: () => Effect20.succeed([]),
|
|
2305
|
+
read: Effect20.fn(function* ({ olds }) {
|
|
2262
2306
|
return yield* readTotp(olds);
|
|
2263
2307
|
}),
|
|
2264
|
-
diff:
|
|
2308
|
+
diff: Effect20.fn(function* ({ news, output }) {
|
|
2265
2309
|
if (output === undefined || !isResolved8(news))
|
|
2266
2310
|
return;
|
|
2267
2311
|
const rename = renameProblem(output.name, news.name);
|
|
@@ -2269,10 +2313,10 @@ var BaoMfaTotpMethodProvider = () => Provider8.effect(BaoMfaTotpMethod, Effect19
|
|
|
2269
2313
|
return yield* refuse4(news, rename);
|
|
2270
2314
|
return { action: yield* planTotp(news) };
|
|
2271
2315
|
}),
|
|
2272
|
-
reconcile:
|
|
2316
|
+
reconcile: Effect20.fn(function* ({ news }) {
|
|
2273
2317
|
return yield* reconcileTotp(news);
|
|
2274
2318
|
}),
|
|
2275
|
-
delete:
|
|
2319
|
+
delete: Effect20.fn(function* ({ output }) {
|
|
2276
2320
|
yield* deleteTotp(output.methodId);
|
|
2277
2321
|
return;
|
|
2278
2322
|
})
|
|
@@ -2281,24 +2325,24 @@ var BaoMfaTotpMethodProvider = () => Provider8.effect(BaoMfaTotpMethod, Effect19
|
|
|
2281
2325
|
import { Resource as Resource9 } from "alchemy";
|
|
2282
2326
|
import { isResolved as isResolved9 } from "alchemy/Diff";
|
|
2283
2327
|
import * as Provider9 from "alchemy/Provider";
|
|
2284
|
-
import * as
|
|
2328
|
+
import * as Effect23 from "effect/Effect";
|
|
2285
2329
|
|
|
2286
2330
|
// src/openbao/mount-reconcile.ts
|
|
2287
|
-
import * as
|
|
2331
|
+
import * as Effect22 from "effect/Effect";
|
|
2288
2332
|
|
|
2289
2333
|
// src/openbao/mount-wire.ts
|
|
2290
|
-
import * as
|
|
2291
|
-
var absentFromTable2 = (path, asked) => baoRead("sys/mounts").pipe(
|
|
2334
|
+
import * as Effect21 from "effect/Effect";
|
|
2335
|
+
var absentFromTable2 = (path, asked) => baoRead("sys/mounts").pipe(Effect21.mapError((listing) => new BaoError(asked.status, asked.method, asked.path, [
|
|
2292
2336
|
...asked.errors,
|
|
2293
2337
|
`sys/mounts could not confirm the mount is absent: ${listing.message}`
|
|
2294
|
-
])),
|
|
2295
|
-
var readMountData = (path) => baoRead(readPath(path)).pipe(
|
|
2338
|
+
])), Effect21.flatMap((table) => table !== undefined && !Object.hasOwn(table, `${mountPath(path)}/`) ? Effect21.succeed(undefined) : Effect21.fail(asked)));
|
|
2339
|
+
var readMountData = (path) => baoRead(readPath(path)).pipe(Effect21.catchIf((error) => error.status === 400, (error) => absentFromTable2(path, error)));
|
|
2296
2340
|
var enableMount = (props) => baoWrite("POST", readPath(props.path), enableBody(props));
|
|
2297
2341
|
var tuneMount = (props) => baoWrite("POST", tunePath(props.path), tuneBody(props));
|
|
2298
2342
|
var disableMount = (path) => baoDelete(readPath(path));
|
|
2299
2343
|
|
|
2300
2344
|
// src/openbao/mount-reconcile.ts
|
|
2301
|
-
var readMount = (props) =>
|
|
2345
|
+
var readMount = (props) => Effect22.gen(function* () {
|
|
2302
2346
|
const live = yield* readMountData(props.path);
|
|
2303
2347
|
if (live === undefined)
|
|
2304
2348
|
return;
|
|
@@ -2311,10 +2355,10 @@ var moveTarget2 = (props) => ({
|
|
|
2311
2355
|
type: props.type,
|
|
2312
2356
|
wire: mountPath
|
|
2313
2357
|
});
|
|
2314
|
-
var reconcileMount = (news, stated, options) =>
|
|
2358
|
+
var reconcileMount = (news, stated, options) => Effect22.gen(function* () {
|
|
2315
2359
|
const move = planMove("Bao.Mount", stated, news.path, news.remountFrom);
|
|
2316
2360
|
if (move.kind === "refuse")
|
|
2317
|
-
return yield*
|
|
2361
|
+
return yield* Effect22.die(new Error(move.message));
|
|
2318
2362
|
if (move.kind === "move")
|
|
2319
2363
|
yield* performMove(moveTarget2(news), move.from, options);
|
|
2320
2364
|
let live = yield* readMount(news);
|
|
@@ -2324,13 +2368,13 @@ var reconcileMount = (news, stated, options) => Effect21.gen(function* () {
|
|
|
2324
2368
|
yield* tuneMount(news);
|
|
2325
2369
|
} else if (!matches(live, news)) {
|
|
2326
2370
|
if (live.type !== news.type) {
|
|
2327
|
-
return yield*
|
|
2371
|
+
return yield* Effect22.die(new Error(`Bao.Mount ${mountPath(news.path)}: live type ${live.type} != ${news.type}. ` + "Secrets engine type is immutable — replace manually."));
|
|
2328
2372
|
}
|
|
2329
2373
|
yield* tuneMount(news);
|
|
2330
2374
|
}
|
|
2331
2375
|
live = yield* readMount(news);
|
|
2332
2376
|
if (live === undefined) {
|
|
2333
|
-
return yield*
|
|
2377
|
+
return yield* Effect22.die(new Error(`Bao.Mount ${mountPath(news.path)}: write returned no error but the mount is still absent.`));
|
|
2334
2378
|
}
|
|
2335
2379
|
return live;
|
|
2336
2380
|
});
|
|
@@ -2339,17 +2383,17 @@ var reconcileMount = (news, stated, options) => Effect21.gen(function* () {
|
|
|
2339
2383
|
var BaoMount = Resource9("Bao.Mount", {
|
|
2340
2384
|
defaultRemovalPolicy: "retain"
|
|
2341
2385
|
});
|
|
2342
|
-
var BaoMountProvider = () => Provider9.effect(BaoMount,
|
|
2343
|
-
list: () =>
|
|
2344
|
-
read:
|
|
2386
|
+
var BaoMountProvider = () => Provider9.effect(BaoMount, Effect23.succeed(BaoMount.Provider.of({
|
|
2387
|
+
list: () => Effect23.succeed([]),
|
|
2388
|
+
read: Effect23.fn(function* ({ olds }) {
|
|
2345
2389
|
return yield* readMount(olds);
|
|
2346
2390
|
}),
|
|
2347
|
-
diff:
|
|
2391
|
+
diff: Effect23.fn(function* ({ news, output }) {
|
|
2348
2392
|
if (output === undefined || !isResolved9(news))
|
|
2349
2393
|
return;
|
|
2350
2394
|
const move = planMove("Bao.Mount", output.path, news.path, news.remountFrom);
|
|
2351
2395
|
if (move.kind === "refuse")
|
|
2352
|
-
return yield*
|
|
2396
|
+
return yield* Effect23.die(new Error(move.message));
|
|
2353
2397
|
if (move.kind === "move")
|
|
2354
2398
|
return { action: "update" };
|
|
2355
2399
|
const live = yield* readMount(news);
|
|
@@ -2361,10 +2405,10 @@ var BaoMountProvider = () => Provider9.effect(BaoMount, Effect22.succeed(BaoMoun
|
|
|
2361
2405
|
return { action: "noop" };
|
|
2362
2406
|
return { action: "update" };
|
|
2363
2407
|
}),
|
|
2364
|
-
reconcile:
|
|
2408
|
+
reconcile: Effect23.fn(function* ({ news, output }) {
|
|
2365
2409
|
return yield* reconcileMount(news, output?.path);
|
|
2366
2410
|
}),
|
|
2367
|
-
delete:
|
|
2411
|
+
delete: Effect23.fn(function* ({ output }) {
|
|
2368
2412
|
yield* disableMount(output.path);
|
|
2369
2413
|
return;
|
|
2370
2414
|
})
|
|
@@ -2373,7 +2417,7 @@ var BaoMountProvider = () => Provider9.effect(BaoMount, Effect22.succeed(BaoMoun
|
|
|
2373
2417
|
import { Resource as Resource10 } from "alchemy";
|
|
2374
2418
|
import { isResolved as isResolved10 } from "alchemy/Diff";
|
|
2375
2419
|
import * as Provider10 from "alchemy/Provider";
|
|
2376
|
-
import * as
|
|
2420
|
+
import * as Effect24 from "effect/Effect";
|
|
2377
2421
|
|
|
2378
2422
|
// src/openbao/pki-role-canonical.ts
|
|
2379
2423
|
var DEFAULT_KEY_USAGE = [
|
|
@@ -2539,18 +2583,18 @@ var problems6 = (props) => {
|
|
|
2539
2583
|
var BaoPkiRole = Resource10("Bao.PkiRole", {
|
|
2540
2584
|
defaultRemovalPolicy: "retain"
|
|
2541
2585
|
});
|
|
2542
|
-
var readRole2 = (props) =>
|
|
2586
|
+
var readRole2 = (props) => Effect24.gen(function* () {
|
|
2543
2587
|
const live = yield* baoRead(rolePath4(props));
|
|
2544
2588
|
if (live === undefined)
|
|
2545
2589
|
return;
|
|
2546
2590
|
return attributesOf10(props, live);
|
|
2547
2591
|
});
|
|
2548
|
-
var BaoPkiRoleProvider = () => Provider10.effect(BaoPkiRole,
|
|
2549
|
-
list: () =>
|
|
2550
|
-
read:
|
|
2592
|
+
var BaoPkiRoleProvider = () => Provider10.effect(BaoPkiRole, Effect24.succeed(BaoPkiRole.Provider.of({
|
|
2593
|
+
list: () => Effect24.succeed([]),
|
|
2594
|
+
read: Effect24.fn(function* ({ olds }) {
|
|
2551
2595
|
return yield* readRole2(olds);
|
|
2552
2596
|
}),
|
|
2553
|
-
diff:
|
|
2597
|
+
diff: Effect24.fn(function* ({ news, output }) {
|
|
2554
2598
|
if (output === undefined || !isResolved10(news))
|
|
2555
2599
|
return;
|
|
2556
2600
|
if (mountPath(news.mount ?? "pki") !== output.mount || news.name !== output.name)
|
|
@@ -2562,11 +2606,11 @@ var BaoPkiRoleProvider = () => Provider10.effect(BaoPkiRole, Effect23.succeed(Ba
|
|
|
2562
2606
|
return { action: "update" };
|
|
2563
2607
|
return matches9(live, news) ? { action: "noop" } : { action: "update" };
|
|
2564
2608
|
}),
|
|
2565
|
-
reconcile:
|
|
2609
|
+
reconcile: Effect24.fn(function* ({ news }) {
|
|
2566
2610
|
const path = rolePath4(news);
|
|
2567
2611
|
const bad = problems6(news);
|
|
2568
2612
|
if (bad.length > 0) {
|
|
2569
|
-
return yield*
|
|
2613
|
+
return yield* Effect24.die(new Error(`Bao.PkiRole ${path}: ${bad.join(" ")}`));
|
|
2570
2614
|
}
|
|
2571
2615
|
const live = yield* readRole2(news);
|
|
2572
2616
|
if (live === undefined || !matches9(live, news)) {
|
|
@@ -2574,14 +2618,14 @@ var BaoPkiRoleProvider = () => Provider10.effect(BaoPkiRole, Effect23.succeed(Ba
|
|
|
2574
2618
|
}
|
|
2575
2619
|
const after = yield* readRole2(news);
|
|
2576
2620
|
if (after === undefined) {
|
|
2577
|
-
return yield*
|
|
2621
|
+
return yield* Effect24.die(new Error(`Bao.PkiRole ${path}: write reported success but the role is absent.`));
|
|
2578
2622
|
}
|
|
2579
2623
|
if (!matches9(after, news)) {
|
|
2580
|
-
return yield*
|
|
2624
|
+
return yield* Effect24.die(new Error(`Bao.PkiRole ${path}: wrote cleanly but the role read back different. ` + "OpenBao stored something other than what was declared — inspect with " + `\`bao read ${path}\` before retrying.`));
|
|
2581
2625
|
}
|
|
2582
2626
|
return after;
|
|
2583
2627
|
}),
|
|
2584
|
-
delete:
|
|
2628
|
+
delete: Effect24.fn(function* ({ output }) {
|
|
2585
2629
|
yield* baoDelete(rolePath4(output));
|
|
2586
2630
|
return;
|
|
2587
2631
|
})
|
|
@@ -2590,7 +2634,7 @@ var BaoPkiRoleProvider = () => Provider10.effect(BaoPkiRole, Effect23.succeed(Ba
|
|
|
2590
2634
|
import { Resource as Resource11 } from "alchemy";
|
|
2591
2635
|
import { isResolved as isResolved11 } from "alchemy/Diff";
|
|
2592
2636
|
import * as Provider11 from "alchemy/Provider";
|
|
2593
|
-
import * as
|
|
2637
|
+
import * as Effect26 from "effect/Effect";
|
|
2594
2638
|
|
|
2595
2639
|
// src/openbao/plugin-form.ts
|
|
2596
2640
|
var resolve = (props) => ({
|
|
@@ -2646,7 +2690,7 @@ var sameArgs = (want, have) => want.length === have.length && want.every((entry,
|
|
|
2646
2690
|
var matches10 = (attributes, form) => !attributes.builtin && attributes.version === form.version && attributes.sha256 === form.sha256 && attributes.command === form.command && sameArgs(form.args, attributes.args);
|
|
2647
2691
|
|
|
2648
2692
|
// src/openbao/plugin-reconcile.ts
|
|
2649
|
-
import * as
|
|
2693
|
+
import * as Effect25 from "effect/Effect";
|
|
2650
2694
|
|
|
2651
2695
|
// src/openbao/plugin-wire.ts
|
|
2652
2696
|
var readPluginData = (form) => baoRead(versionedPath(form.type, form.name, form.version));
|
|
@@ -2654,10 +2698,10 @@ var registerPlugin = (form) => baoWrite("PUT", catalogPath(form.type, form.name)
|
|
|
2654
2698
|
var deregisterPlugin = (type, name, version) => baoDelete(versionedPath(type, name, version));
|
|
2655
2699
|
|
|
2656
2700
|
// src/openbao/plugin-reconcile.ts
|
|
2657
|
-
var readEntry = (form) =>
|
|
2658
|
-
var refuse5 = (form, message) =>
|
|
2701
|
+
var readEntry = (form) => Effect25.map(readPluginData(form), (live) => live === undefined ? undefined : { attributes: attributesOf11(form, live), live });
|
|
2702
|
+
var refuse5 = (form, message) => Effect25.die(new Error(`Bao.Plugin ${versionedPath(form.type, form.name, form.version)}: ${message}`));
|
|
2659
2703
|
var SELF_REPORTED = "the write succeeded but the read-back does not match. If the binary reports its own version, " + "OpenBao filed the registration under it (plugin_catalog.go setInternal) — declare `version` " + "as exactly the version the binary reports; that adopts the entry this write just made.";
|
|
2660
|
-
var reconcilePlugin = (props) =>
|
|
2704
|
+
var reconcilePlugin = (props) => Effect25.gen(function* () {
|
|
2661
2705
|
const form = resolve(props);
|
|
2662
2706
|
const bad = problems7(form);
|
|
2663
2707
|
if (bad.length > 0)
|
|
@@ -2684,13 +2728,13 @@ var reconcilePlugin = (props) => Effect24.gen(function* () {
|
|
|
2684
2728
|
var BaoPlugin = Resource11("Bao.Plugin", {
|
|
2685
2729
|
defaultRemovalPolicy: "retain"
|
|
2686
2730
|
});
|
|
2687
|
-
var BaoPluginProvider = () => Provider11.effect(BaoPlugin,
|
|
2688
|
-
list: () =>
|
|
2689
|
-
read:
|
|
2731
|
+
var BaoPluginProvider = () => Provider11.effect(BaoPlugin, Effect26.succeed(BaoPlugin.Provider.of({
|
|
2732
|
+
list: () => Effect26.succeed([]),
|
|
2733
|
+
read: Effect26.fn(function* ({ olds }) {
|
|
2690
2734
|
const found = yield* readEntry(resolve(olds));
|
|
2691
2735
|
return found?.attributes;
|
|
2692
2736
|
}),
|
|
2693
|
-
diff:
|
|
2737
|
+
diff: Effect26.fn(function* ({ news, output }) {
|
|
2694
2738
|
if (output === undefined || !isResolved11(news))
|
|
2695
2739
|
return;
|
|
2696
2740
|
const form = resolve(news);
|
|
@@ -2702,10 +2746,10 @@ var BaoPluginProvider = () => Provider11.effect(BaoPlugin, Effect25.succeed(BaoP
|
|
|
2702
2746
|
return { action: "update" };
|
|
2703
2747
|
return matches10(found.attributes, form) ? { action: "noop" } : { action: "update" };
|
|
2704
2748
|
}),
|
|
2705
|
-
reconcile:
|
|
2749
|
+
reconcile: Effect26.fn(function* ({ news }) {
|
|
2706
2750
|
return yield* reconcilePlugin(news);
|
|
2707
2751
|
}),
|
|
2708
|
-
delete:
|
|
2752
|
+
delete: Effect26.fn(function* ({ output }) {
|
|
2709
2753
|
yield* deregisterPlugin(output.type, output.name, output.version);
|
|
2710
2754
|
return;
|
|
2711
2755
|
})
|
|
@@ -2714,7 +2758,7 @@ var BaoPluginProvider = () => Provider11.effect(BaoPlugin, Effect25.succeed(BaoP
|
|
|
2714
2758
|
import { Resource as Resource12 } from "alchemy";
|
|
2715
2759
|
import { isResolved as isResolved12 } from "alchemy/Diff";
|
|
2716
2760
|
import * as Provider12 from "alchemy/Provider";
|
|
2717
|
-
import * as
|
|
2761
|
+
import * as Effect28 from "effect/Effect";
|
|
2718
2762
|
import * as FileSystem from "effect/FileSystem";
|
|
2719
2763
|
import * as Path from "effect/Path";
|
|
2720
2764
|
|
|
@@ -2722,13 +2766,13 @@ import * as Path from "effect/Path";
|
|
|
2722
2766
|
var isEmptyAssembly = (parts, joined) => parts === 0 || !/^\s*path\s+"/m.test(joined);
|
|
2723
2767
|
|
|
2724
2768
|
// src/openbao/policy-wire.ts
|
|
2725
|
-
import * as
|
|
2769
|
+
import * as Effect27 from "effect/Effect";
|
|
2726
2770
|
var policyPath = (name) => `sys/policies/acl/${name}`;
|
|
2727
|
-
var readPolicy = (name) =>
|
|
2771
|
+
var readPolicy = (name) => Effect27.flatMap(baoRead(policyPath(name)), (data) => {
|
|
2728
2772
|
if (data === undefined)
|
|
2729
|
-
return
|
|
2773
|
+
return Effect27.succeed("");
|
|
2730
2774
|
const text11 = data["policy"];
|
|
2731
|
-
return typeof text11 === "string" ?
|
|
2775
|
+
return typeof text11 === "string" ? Effect27.succeed(text11) : Effect27.fail(new BaoError(200, "GET", policyPath(name), ["no data.policy in the response"]));
|
|
2732
2776
|
});
|
|
2733
2777
|
var writePolicy = (name, hcl) => baoWrite("PUT", policyPath(name), { policy: hcl });
|
|
2734
2778
|
var deletePolicy = (name) => baoDelete(policyPath(name));
|
|
@@ -2744,10 +2788,10 @@ var attributesOf12 = (name, hcl, parts) => ({
|
|
|
2744
2788
|
grants: grantsOf(hcl),
|
|
2745
2789
|
parts
|
|
2746
2790
|
});
|
|
2747
|
-
var BaoPolicyProvider = () => Provider12.effect(BaoPolicy,
|
|
2791
|
+
var BaoPolicyProvider = () => Provider12.effect(BaoPolicy, Effect28.gen(function* () {
|
|
2748
2792
|
const fs = yield* FileSystem.FileSystem;
|
|
2749
2793
|
const path = yield* Path.Path;
|
|
2750
|
-
const assemble = (dir) =>
|
|
2794
|
+
const assemble = (dir) => Effect28.gen(function* () {
|
|
2751
2795
|
const entries2 = (yield* fs.readDirectory(dir)).filter((f) => f.endsWith(".hcl")).sort();
|
|
2752
2796
|
let joined = "";
|
|
2753
2797
|
for (const f of entries2)
|
|
@@ -2756,23 +2800,33 @@ var BaoPolicyProvider = () => Provider12.effect(BaoPolicy, Effect27.gen(function
|
|
|
2756
2800
|
return { joined, parts: entries2.length };
|
|
2757
2801
|
});
|
|
2758
2802
|
return BaoPolicy.Provider.of({
|
|
2759
|
-
list: () =>
|
|
2760
|
-
read:
|
|
2803
|
+
list: () => Effect28.succeed([]),
|
|
2804
|
+
read: Effect28.fn(function* ({ olds }) {
|
|
2761
2805
|
const live = yield* readPolicy(olds.name);
|
|
2762
2806
|
return live.length === 0 ? undefined : attributesOf12(olds.name, live, 0);
|
|
2763
2807
|
}),
|
|
2764
|
-
diff:
|
|
2765
|
-
|
|
2808
|
+
diff: Effect28.fn(function* ({ news, olds, output }) {
|
|
2809
|
+
const tried = output?.name ?? declaredString(olds, "name");
|
|
2810
|
+
const declared = declaredString(news, "name");
|
|
2811
|
+
const move = yield* judgeMove("Bao.Policy", tried, declared, policyPath, policyKey);
|
|
2812
|
+
if (output === undefined)
|
|
2813
|
+
return;
|
|
2814
|
+
if (move !== undefined)
|
|
2815
|
+
return { action: "replace" };
|
|
2816
|
+
if (!isResolved12(news))
|
|
2766
2817
|
return;
|
|
2767
2818
|
const { joined } = yield* assemble(news.fragments);
|
|
2768
2819
|
const live = yield* readPolicy(news.name);
|
|
2769
2820
|
return live.length > 0 && sha256(live) === sha256(joined) ? { action: "noop" } : { action: "update" };
|
|
2770
2821
|
}),
|
|
2771
|
-
reconcile:
|
|
2822
|
+
reconcile: Effect28.fn(function* ({ news, output }) {
|
|
2772
2823
|
const name = news.name;
|
|
2824
|
+
if (output !== undefined && isMoved(output.name, name, policyKey) === true) {
|
|
2825
|
+
return yield* refuseMovedUpdate(`Bao.Policy ${name}`, output.name, name);
|
|
2826
|
+
}
|
|
2773
2827
|
const { joined, parts } = yield* assemble(news.fragments);
|
|
2774
2828
|
if (isEmptyAssembly(parts, joined))
|
|
2775
|
-
return yield*
|
|
2829
|
+
return yield* Effect28.die(new Error(`Bao.Policy ${name}: the fragments under ${news.fragments} carry no path grant ` + `(${String(parts)} file(s)). Writing it would revoke every grant the policy carries.`));
|
|
2776
2830
|
const current = yield* readPolicy(name);
|
|
2777
2831
|
if (current.length > 0 && sha256(current) === sha256(joined)) {
|
|
2778
2832
|
return attributesOf12(name, joined, parts);
|
|
@@ -2780,7 +2834,7 @@ var BaoPolicyProvider = () => Provider12.effect(BaoPolicy, Effect27.gen(function
|
|
|
2780
2834
|
yield* writePolicy(name, joined);
|
|
2781
2835
|
return attributesOf12(name, joined, parts);
|
|
2782
2836
|
}),
|
|
2783
|
-
delete:
|
|
2837
|
+
delete: Effect28.fn(function* ({ output }) {
|
|
2784
2838
|
yield* deletePolicy(output.name);
|
|
2785
2839
|
return;
|
|
2786
2840
|
})
|
|
@@ -2790,7 +2844,7 @@ var BaoPolicyProvider = () => Provider12.effect(BaoPolicy, Effect27.gen(function
|
|
|
2790
2844
|
import { Resource as Resource13 } from "alchemy";
|
|
2791
2845
|
import { isResolved as isResolved13 } from "alchemy/Diff";
|
|
2792
2846
|
import * as Provider13 from "alchemy/Provider";
|
|
2793
|
-
import * as
|
|
2847
|
+
import * as Effect30 from "effect/Effect";
|
|
2794
2848
|
|
|
2795
2849
|
// src/openbao/proxmox-role-form.ts
|
|
2796
2850
|
var text11 = (value) => typeof value === "string" ? value : "";
|
|
@@ -2836,25 +2890,45 @@ var sameTtl5 = (want, have) => {
|
|
|
2836
2890
|
const haveSeconds = ttlSeconds(have);
|
|
2837
2891
|
return wantSeconds !== undefined && wantSeconds === haveSeconds;
|
|
2838
2892
|
};
|
|
2893
|
+
var rescopeRefusal = (before, mintUser, allowMintUserChange) => before === mintUser || allowMintUserChange === before ? undefined : `re-scopes mint_user ${before} → ${mintUser}. Every token this role mints inherits ` + `the ACL of that PVE user. To re-scope deliberately, declare allowMintUserChange: '${before}'.`;
|
|
2839
2894
|
var matches11 = (attributes, props) => attributes.mintUser === props.mintUser && sameTtl5(props.ttl, attributes.ttl) && sameTtl5(props.maxTtl, attributes.maxTtl);
|
|
2840
2895
|
|
|
2841
|
-
// src/openbao/proxmox-role.ts
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
});
|
|
2845
|
-
var readRole3 = (props) => Effect28.gen(function* () {
|
|
2896
|
+
// src/openbao/proxmox-role-wire.ts
|
|
2897
|
+
import * as Effect29 from "effect/Effect";
|
|
2898
|
+
var readRole3 = (props) => Effect29.gen(function* () {
|
|
2846
2899
|
const live = yield* baoRead(rolePath5(props.mount, props.name));
|
|
2847
2900
|
if (live === undefined)
|
|
2848
2901
|
return;
|
|
2849
2902
|
return attributesOf13(props, live);
|
|
2850
2903
|
});
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2904
|
+
|
|
2905
|
+
// src/openbao/proxmox-role.ts
|
|
2906
|
+
var BaoProxmoxRole = Resource13("Bao.ProxmoxRole", {
|
|
2907
|
+
defaultRemovalPolicy: "retain"
|
|
2908
|
+
});
|
|
2909
|
+
var BaoProxmoxRoleProvider = () => Provider13.effect(BaoProxmoxRole, Effect30.succeed(BaoProxmoxRole.Provider.of({
|
|
2910
|
+
list: () => Effect30.succeed([]),
|
|
2911
|
+
read: Effect30.fn(function* ({ olds }) {
|
|
2854
2912
|
return yield* readRole3(olds);
|
|
2855
2913
|
}),
|
|
2856
|
-
diff:
|
|
2857
|
-
|
|
2914
|
+
diff: Effect30.fn(function* ({ news, olds, output }) {
|
|
2915
|
+
const tried = triedRolePath(output, olds, rolePath5);
|
|
2916
|
+
const declared = declaredRolePath(news, rolePath5);
|
|
2917
|
+
const move = yield* judgeMove("Bao.ProxmoxRole", tried, declared, (path) => path);
|
|
2918
|
+
if (output === undefined)
|
|
2919
|
+
return;
|
|
2920
|
+
if (move !== undefined) {
|
|
2921
|
+
const mintUser = declaredString(news, "mintUser");
|
|
2922
|
+
if (mintUser === undefined || isPendingProp(news, "allowMintUserChange"))
|
|
2923
|
+
return;
|
|
2924
|
+
const from = (yield* readRole3(output))?.mintUser ?? output.mintUser;
|
|
2925
|
+
const allow = declaredString(news, "allowMintUserChange");
|
|
2926
|
+
const refusal2 = rescopeRefusal(from, mintUser, allow);
|
|
2927
|
+
if (refusal2 === undefined)
|
|
2928
|
+
return { action: "replace" };
|
|
2929
|
+
return yield* Effect30.die(new Error(`Bao.ProxmoxRole ${move.from} → ${move.to}: the rename ${refusal2}`));
|
|
2930
|
+
}
|
|
2931
|
+
if (!isResolved13(news))
|
|
2858
2932
|
return;
|
|
2859
2933
|
const live = yield* readRole3(news);
|
|
2860
2934
|
if (live === undefined)
|
|
@@ -2863,25 +2937,31 @@ var BaoProxmoxRoleProvider = () => Provider13.effect(BaoProxmoxRole, Effect28.su
|
|
|
2863
2937
|
return { action: "noop" };
|
|
2864
2938
|
return { action: "update" };
|
|
2865
2939
|
}),
|
|
2866
|
-
reconcile:
|
|
2940
|
+
reconcile: Effect30.fn(function* ({ news, output }) {
|
|
2941
|
+
const path = rolePath5(news.mount, news.name);
|
|
2942
|
+
const before = output === undefined ? path : rolePath5(output.mount, output.name);
|
|
2943
|
+
if (isMoved(before, path) === true) {
|
|
2944
|
+
return yield* refuseMovedUpdate("Bao.ProxmoxRole", before, path);
|
|
2945
|
+
}
|
|
2867
2946
|
const live = yield* readRole3(news);
|
|
2868
|
-
|
|
2869
|
-
|
|
2947
|
+
const rescope = live === undefined ? undefined : rescopeRefusal(live.mintUser, news.mintUser, news.allowMintUserChange);
|
|
2948
|
+
if (rescope !== undefined) {
|
|
2949
|
+
return yield* Effect30.die(new Error(`Bao.ProxmoxRole ${path}: ${rescope}`));
|
|
2870
2950
|
}
|
|
2871
2951
|
if (live === undefined || !matches11(live, news)) {
|
|
2872
2952
|
const write = writeBody9(news);
|
|
2873
2953
|
if (!write.ok) {
|
|
2874
|
-
return yield*
|
|
2954
|
+
return yield* Effect30.die(new Error(`Bao.ProxmoxRole ${path}: unparseable duration ` + `${write.bad.join(", ")}. Use 30s / 5m / 1h / 1d, or 0.`));
|
|
2875
2955
|
}
|
|
2876
|
-
yield* baoWrite("PUT",
|
|
2956
|
+
yield* baoWrite("PUT", path, write.body);
|
|
2877
2957
|
}
|
|
2878
2958
|
const after = yield* readRole3(news);
|
|
2879
2959
|
if (after === undefined) {
|
|
2880
|
-
return yield*
|
|
2960
|
+
return yield* Effect30.die(new Error(`Bao.ProxmoxRole ${path}: write returned no error ` + "but the role is still absent."));
|
|
2881
2961
|
}
|
|
2882
2962
|
return after;
|
|
2883
2963
|
}),
|
|
2884
|
-
delete:
|
|
2964
|
+
delete: Effect30.fn(function* ({ output }) {
|
|
2885
2965
|
yield* baoDelete(rolePath5(output.mount, output.name));
|
|
2886
2966
|
return;
|
|
2887
2967
|
})
|
|
@@ -2890,7 +2970,7 @@ var BaoProxmoxRoleProvider = () => Provider13.effect(BaoProxmoxRole, Effect28.su
|
|
|
2890
2970
|
import { Resource as Resource14 } from "alchemy";
|
|
2891
2971
|
import { isResolved as isResolved14 } from "alchemy/Diff";
|
|
2892
2972
|
import * as Provider14 from "alchemy/Provider";
|
|
2893
|
-
import * as
|
|
2973
|
+
import * as Effect31 from "effect/Effect";
|
|
2894
2974
|
|
|
2895
2975
|
// src/openbao/ssh-role-form.ts
|
|
2896
2976
|
var readPath4 = (mount, name) => `${sshMountOf(mount)}/roles/${name}`;
|
|
@@ -2982,7 +3062,7 @@ var matches12 = (attributes, form) => attributes.keyType === "ca" && sameList2(f
|
|
|
2982
3062
|
var BaoSshRole = Resource14("Bao.SshRole", {
|
|
2983
3063
|
defaultRemovalPolicy: "retain"
|
|
2984
3064
|
});
|
|
2985
|
-
var readRole4 = (form) =>
|
|
3065
|
+
var readRole4 = (form) => Effect31.gen(function* () {
|
|
2986
3066
|
const live = yield* baoRead(readPath4(form.mount, form.name));
|
|
2987
3067
|
if (live === undefined)
|
|
2988
3068
|
return;
|
|
@@ -3008,14 +3088,14 @@ var wouldErase2 = (live) => {
|
|
|
3008
3088
|
}
|
|
3009
3089
|
return lost.sort();
|
|
3010
3090
|
};
|
|
3011
|
-
var refuse6 = (message) =>
|
|
3012
|
-
var BaoSshRoleProvider = () => Provider14.effect(BaoSshRole,
|
|
3013
|
-
list: () =>
|
|
3014
|
-
read:
|
|
3091
|
+
var refuse6 = (message) => Effect31.die(new Error(message));
|
|
3092
|
+
var BaoSshRoleProvider = () => Provider14.effect(BaoSshRole, Effect31.succeed(BaoSshRole.Provider.of({
|
|
3093
|
+
list: () => Effect31.succeed([]),
|
|
3094
|
+
read: Effect31.fn(function* ({ olds }) {
|
|
3015
3095
|
const found = yield* readRole4(resolve2(olds));
|
|
3016
3096
|
return found?.attributes;
|
|
3017
3097
|
}),
|
|
3018
|
-
diff:
|
|
3098
|
+
diff: Effect31.fn(function* ({ news, output }) {
|
|
3019
3099
|
if (output === undefined || !isResolved14(news))
|
|
3020
3100
|
return;
|
|
3021
3101
|
const form = resolve2(news);
|
|
@@ -3027,7 +3107,7 @@ var BaoSshRoleProvider = () => Provider14.effect(BaoSshRole, Effect29.succeed(Ba
|
|
|
3027
3107
|
return { action: "update" };
|
|
3028
3108
|
return matches12(found.attributes, form) ? { action: "noop" } : { action: "update" };
|
|
3029
3109
|
}),
|
|
3030
|
-
reconcile:
|
|
3110
|
+
reconcile: Effect31.fn(function* ({ news }) {
|
|
3031
3111
|
const form = resolve2(news);
|
|
3032
3112
|
const path = readPath4(form.mount, form.name);
|
|
3033
3113
|
const bad = badDurations(form);
|
|
@@ -3053,7 +3133,7 @@ var BaoSshRoleProvider = () => Provider14.effect(BaoSshRole, Effect29.succeed(Ba
|
|
|
3053
3133
|
}
|
|
3054
3134
|
return after.attributes;
|
|
3055
3135
|
}),
|
|
3056
|
-
delete:
|
|
3136
|
+
delete: Effect31.fn(function* ({ output }) {
|
|
3057
3137
|
yield* baoDelete(readPath4(output.mount, output.name));
|
|
3058
3138
|
return;
|
|
3059
3139
|
})
|
|
@@ -3107,5 +3187,5 @@ export {
|
|
|
3107
3187
|
revokeSelfEffect
|
|
3108
3188
|
};
|
|
3109
3189
|
|
|
3110
|
-
//# debugId=
|
|
3190
|
+
//# debugId=81D869587FC0B7AF64756E2164756E21
|
|
3111
3191
|
//# sourceMappingURL=index.js.map
|