@calltelemetry/ct-lab-mcp 0.8.98 → 0.8.100

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.
Files changed (68) hide show
  1. package/assets/stig/SHA256SUMS +18 -0
  2. package/assets/stig/files/ct-luks-firstboot.service +13 -0
  3. package/assets/stig/files/ct-luks-firstboot.sh +35 -0
  4. package/assets/stig/guest/keyhash.sh +4 -0
  5. package/assets/stig/guest/read-recovery.sh +2 -0
  6. package/assets/stig/guest/scan-disa.sh +17 -0
  7. package/assets/stig/guest/scan.sh +22 -0
  8. package/assets/stig/guest/shred-recovery.sh +2 -0
  9. package/assets/stig/guest/test-recovery.sh +3 -0
  10. package/assets/stig/guest/trim.sh +3 -0
  11. package/assets/stig/guest/verify-root.sh +9 -0
  12. package/assets/stig/guest/verify-user.sh +9 -0
  13. package/assets/stig/ks.cfg.pkrtpl +95 -0
  14. package/assets/stig/scripts/assess.sh +39 -0
  15. package/assets/stig/scripts/errata.sh +19 -0
  16. package/assets/stig/scripts/remediate.sh +127 -0
  17. package/assets/stig/scripts/seal.sh +46 -0
  18. package/assets/stig/tailoring.xml +16 -0
  19. package/assets/stig/template.pkr.hcl +252 -0
  20. package/dist/src/generated-version.d.ts +1 -1
  21. package/dist/src/generated-version.d.ts.map +1 -1
  22. package/dist/src/generated-version.js +1 -1
  23. package/dist/src/generated-version.js.map +1 -1
  24. package/dist/src/provenance.d.ts.map +1 -1
  25. package/dist/src/provenance.js +18 -1
  26. package/dist/src/provenance.js.map +1 -1
  27. package/dist/src/stig/live.d.ts +116 -0
  28. package/dist/src/stig/live.d.ts.map +1 -0
  29. package/dist/src/stig/live.js +339 -0
  30. package/dist/src/stig/live.js.map +1 -0
  31. package/dist/src/stig/model.d.ts +160 -0
  32. package/dist/src/stig/model.d.ts.map +1 -0
  33. package/dist/src/stig/model.js +384 -0
  34. package/dist/src/stig/model.js.map +1 -0
  35. package/dist/src/stig/ports.d.ts +149 -0
  36. package/dist/src/stig/ports.d.ts.map +1 -0
  37. package/dist/src/stig/ports.js +7 -0
  38. package/dist/src/stig/ports.js.map +1 -0
  39. package/dist/src/stig/receipt.d.ts +35 -0
  40. package/dist/src/stig/receipt.d.ts.map +1 -0
  41. package/dist/src/stig/receipt.js +112 -0
  42. package/dist/src/stig/receipt.js.map +1 -0
  43. package/dist/src/stig/runner.d.ts +109 -0
  44. package/dist/src/stig/runner.d.ts.map +1 -0
  45. package/dist/src/stig/runner.js +471 -0
  46. package/dist/src/stig/runner.js.map +1 -0
  47. package/dist/src/tools/appliance-claim-spec-schema.v1.json +1 -1
  48. package/dist/src/tools/appliance-claim-tools.d.ts +10 -4
  49. package/dist/src/tools/appliance-claim-tools.d.ts.map +1 -1
  50. package/dist/src/tools/appliance-claim-tools.js +10 -2
  51. package/dist/src/tools/appliance-claim-tools.js.map +1 -1
  52. package/dist/src/tools/claim-creation-projection.d.ts +1 -1
  53. package/dist/src/tools/claim-creation-projection.js +1 -1
  54. package/dist/src/tools/claim-custody.d.ts +7 -7
  55. package/dist/src/tools/claimed-import-qcow.d.ts +2 -2
  56. package/dist/src/tools/host-maintenance-shutdown.d.ts +4 -4
  57. package/dist/src/tools/host-migrate-vm.d.ts +4 -4
  58. package/dist/src/tools/index.d.ts.map +1 -1
  59. package/dist/src/tools/index.js +3 -0
  60. package/dist/src/tools/index.js.map +1 -1
  61. package/dist/src/tools/purge-slots.d.ts +1 -1
  62. package/dist/src/tools/sandbox-tools.d.ts +8 -8
  63. package/dist/src/tools/stig-tools.d.ts +47 -0
  64. package/dist/src/tools/stig-tools.d.ts.map +1 -0
  65. package/dist/src/tools/stig-tools.js +125 -0
  66. package/dist/src/tools/stig-tools.js.map +1 -0
  67. package/dist/src/tools/vm-action.d.ts +2 -2
  68. package/package.json +2 -1
@@ -0,0 +1,471 @@
1
+ /**
2
+ * STIG runner: build a template, create a clone, validate it, release a template.
3
+ *
4
+ * Mirrors the known-good shell recipe (ct-meta rhel8-stig-template: build.sh / clone.sh / receipt.sh) step for
5
+ * step, but every side effect crosses a port (./ports.ts) and every apply is claim-first:
6
+ * claim create -> operator reconciles Ready -> only then any Proxmox mutation.
7
+ * Plans are pure. Applies need the digest of the plan they were shown.
8
+ */
9
+ import { createHash } from "node:crypto";
10
+ import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
11
+ import { join } from "node:path";
12
+ import { STIG_RECEIPT_ANNOTATION, STIG_STEP_ANNOTATION, STIG_STEPS, STIG_PINS, STIG_DATASTREAM_SHA256, STIG_TAILORING_SHA256, STIG_DVD_ISO, STIG_TEMPLATE_PREFIX, STIG_ANNOTATION_MAX_BYTES, STIG_POOL_LIMIT_PERCENT, COUNT_KEYS, assertPoolBelow, assertSingleReencrypt, disaCountsFromKv, DISA_PROFILE_ID, assertTemplateReleaseAllowed, buildReceiptSummary, capTtl, countsFromKv, defaultDescriptor, parseKv, planTemplateRenewal, receiptGate, redact, stigDescriptor, stigStatusPreview, validateReceiptSummary, } from "./model.js";
13
+ import { sha256File } from "./receipt.js";
14
+ export const BUILD_CLAIM_TTL_HOURS = 6;
15
+ export const DEFAULT_CLONE_TTL_HOURS = 48;
16
+ export const VMID_RANGE = { min: 8100, max: 8899 };
17
+ const CI_USER = "ctadmin";
18
+ const VLAN = 126;
19
+ const DEFAULT_DNS = ["192.168.126.1", "192.168.68.125"];
20
+ const digest = (value) => createHash("sha256").update(JSON.stringify(value)).digest("hex");
21
+ const shq = (s) => `'${s.replace(/'/g, `'\\''`)}'`;
22
+ const dopplerKeyFor = (cloneName) => `LAB_RHEL8_RECOVERY_${cloneName.toUpperCase().replace(/-/g, "_")}`;
23
+ export class StigRunner {
24
+ d;
25
+ static reencrypting = false;
26
+ constructor(d) {
27
+ this.d = d;
28
+ }
29
+ log(line) { this.d.log.info(redact(line)); }
30
+ /* ------------------------------------------------------------ helpers */
31
+ async listGuests() {
32
+ const r = await this.d.pve.run("pvesh get /cluster/resources --type vm --output-format json");
33
+ if (r.code !== 0)
34
+ throw new Error("could not list Proxmox guests");
35
+ return JSON.parse(r.stdout);
36
+ }
37
+ async pickVmid(guests) {
38
+ const live = guests ?? (await this.listGuests());
39
+ const used = new Set(live.map((g) => g.vmid));
40
+ for (const c of await this.d.claims.list())
41
+ if (Number.isInteger(c.spec?.vmid))
42
+ used.add(c.spec.vmid);
43
+ for (let v = VMID_RANGE.min; v <= VMID_RANGE.max; v++)
44
+ if (!used.has(v))
45
+ return v;
46
+ throw new Error(`no free VMID in ${VMID_RANGE.min}-${VMID_RANGE.max}`);
47
+ }
48
+ async poolPercent() {
49
+ const r = await this.d.pve.run("pvesm status --storage local-lvm");
50
+ const row = r.stdout.split("\n")[1] ?? "";
51
+ const last = row.trim().split(/\s+/).pop() ?? "";
52
+ const n = Number.parseFloat(last.replace("%", ""));
53
+ return Number.isFinite(n) ? Math.floor(n) : Number.NaN;
54
+ }
55
+ newestTemplate(guests) {
56
+ return guests.filter((g) => g.template === 1 && g.name.startsWith(STIG_TEMPLATE_PREFIX)).sort((a, b) => (a.name < b.name ? -1 : 1)).pop();
57
+ }
58
+ async step(claim, step) {
59
+ await this.d.claims.annotate(claim, { [STIG_STEP_ANNOTATION]: step });
60
+ }
61
+ ensureDir(path) { mkdirSync(path, { recursive: true, mode: 0o700 }); chmodSync(path, 0o700); return path; }
62
+ writeSecretFile(path, content) { writeFileSync(path, content, { mode: 0o600 }); chmodSync(path, 0o600); }
63
+ /* ------------------------------------------------------------ clone */
64
+ async planClone(i) {
65
+ if (!/^[a-z0-9]([a-z0-9-]{0,40}[a-z0-9])?$/.test(i.cloneName))
66
+ throw new Error("cloneName must be a lowercase DNS label (a-z, 0-9, -)");
67
+ const ttlHours = capTtl(i.ttlHours ?? DEFAULT_CLONE_TTL_HOURS);
68
+ const claim = `clone-${i.cloneName}`;
69
+ if (await this.d.claims.get(claim))
70
+ throw new Error(`claim ${claim} already exists; renew, delete or choose another cloneName`);
71
+ const guests = await this.listGuests();
72
+ const tpl = i.templateRef ? guests.find((g) => g.template === 1 && g.name === i.templateRef) : this.newestTemplate(guests);
73
+ if (!tpl)
74
+ throw new Error(i.templateRef ? `template ${i.templateRef} not found` : `no ${STIG_TEMPLATE_PREFIX}* template found`);
75
+ const vmid = await this.pickVmid(guests);
76
+ const poolPercent = await this.poolPercent();
77
+ const poolMaxPercent = i.poolMaxPercent ?? STIG_POOL_LIMIT_PERCENT;
78
+ if (!Number.isInteger(poolMaxPercent) || poolMaxPercent < 10 || poolMaxPercent > STIG_POOL_LIMIT_PERCENT)
79
+ throw new Error(`poolMaxPercent must be 10-${STIG_POOL_LIMIT_PERCENT}`);
80
+ let blockedBy = null;
81
+ try {
82
+ assertPoolBelow(poolPercent, poolMaxPercent);
83
+ }
84
+ catch (e) {
85
+ blockedBy = e.message;
86
+ }
87
+ if (!blockedBy) {
88
+ try {
89
+ assertSingleReencrypt(await this.d.claims.list(), claim);
90
+ }
91
+ catch (e) {
92
+ blockedBy = e.message;
93
+ }
94
+ }
95
+ const base = { cloneName: i.cloneName, claim, vmid, template: { ref: tpl.name, vmid: tpl.vmid }, ttlHours, dns: i.dns ?? DEFAULT_DNS, ntp: i.ntp ?? [], poolMaxPercent };
96
+ return {
97
+ mode: "plan", cloneName: i.cloneName, claim, vmid, template: base.template, ttlHours, poolPercent, poolMaxPercent, poolOk: blockedBy === null, blockedBy,
98
+ escrowKey: dopplerKeyFor(i.cloneName), steps: STIG_STEPS.clone, planDigest: digest({ kind: "clone", ...base }),
99
+ };
100
+ }
101
+ async createClone(i) {
102
+ const plan = await this.planClone(i);
103
+ if (!i.apply)
104
+ return plan;
105
+ if (!i.planDigest || i.planDigest !== plan.planDigest)
106
+ throw new Error("plan digest missing or stale; re-run the plan and apply with its planDigest");
107
+ // Guards run before anything is created: a refused request leaves no claim and no guest.
108
+ assertPoolBelow(plan.poolPercent, plan.poolMaxPercent);
109
+ assertSingleReencrypt(await this.d.claims.list(), plan.claim);
110
+ if (StigRunner.reencrypting)
111
+ throw new Error("another clone is re-encrypting in this process; only one at a time");
112
+ StigRunner.reencrypting = true;
113
+ try {
114
+ return await this.applyClone(plan, i);
115
+ }
116
+ finally {
117
+ StigRunner.reencrypting = false;
118
+ }
119
+ }
120
+ async applyClone(plan, i) {
121
+ const { cloneName, claim, vmid, template, ttlHours, escrowKey } = plan;
122
+ const state = this.ensureDir(join(this.d.baseDir, `clone-${cloneName}`));
123
+ this.ensureDir(join(state, "evidence"));
124
+ const keys = await this.d.materials.sshKeypair(state, `claim-${claim}`);
125
+ const adminPassword = this.d.materials.randomAlnum(32);
126
+ const adminHash = await this.d.materials.sha512Crypt(adminPassword);
127
+ this.writeSecretFile(join(state, "ctadmin_password"), adminPassword);
128
+ writeFileSync(join(state, "vmid"), `${vmid}\n`);
129
+ writeFileSync(join(state, "template"), `${template.ref}\n`);
130
+ const knownHosts = join(state, "known_hosts");
131
+ this.d.guest.configure({ user: CI_USER, keyFile: keys.privateKeyFile, knownHostsFile: knownHosts });
132
+ const sudoStdin = (extra = "") => `${adminPassword}\n${extra}`;
133
+ // 1. claim first, wait for the operator, then (and only then) touch Proxmox.
134
+ this.log(`claim ${claim}: creating (vmid ${vmid}, ${ttlHours}h)`);
135
+ // The descriptor is spec.stig, set at creation: immutable and part of the claim's custody request.
136
+ const descriptor = defaultDescriptor("clone", { template, adminKeyRef: `doppler:${escrowKey}`, dns: i.dns ?? DEFAULT_DNS, ntp: i.ntp ?? [], tailoringSha256: STIG_TAILORING_SHA256 });
137
+ await this.d.claims.create({ name: claim, vmid, vmName: cloneName, ttlHours, stig: descriptor });
138
+ await this.d.claims.waitReady(claim);
139
+ await this.d.claims.annotate(claim, { [STIG_STEP_ANNOTATION]: "claim" });
140
+ await this.step(claim, "pool-guard");
141
+ // 2. clone, fresh TPM, cloud-init, VLAN126 (the canonical lab-inventory verb, or root-SSH qm as the fallback)
142
+ await this.step(claim, "clone");
143
+ this.log(`proxmox: full clone of ${template.ref} (${template.vmid}) to ${vmid}`);
144
+ if (this.d.provider) {
145
+ const others = (await this.d.claims.list()).filter((c) => c.metadata.name !== claim).map((c) => c.spec?.vmid).filter((v) => Number.isInteger(v));
146
+ await this.d.provider.clone({ operationId: `stig-clone-${claim}-${this.d.clock.now()}`, name: cloneName, templateName: template.ref, vmid, claimedVmids: others, sshPublicKey: keys.publicKey, passwordHash: adminHash, dns: i.dns ?? DEFAULT_DNS });
147
+ await this.step(claim, "tpm");
148
+ await this.step(claim, "cloud-init");
149
+ }
150
+ else {
151
+ await this.pveOk(`set -e\nqm clone ${template.vmid} ${vmid} --name ${cloneName} --full 1 --storage local-lvm --description ${shq(`Claim ${claim}; clone of ${template.ref} (RHEL 8.10 STIG)`)}`);
152
+ await this.step(claim, "tpm");
153
+ // Never shared with the template or another clone.
154
+ await this.pveOk(`set -e\nif qm config ${vmid} | grep -q '^tpmstate0'; then qm set ${vmid} --delete tpmstate0; fi\nqm set ${vmid} --tpmstate0 local-lvm:1,version=v2.0`);
155
+ await this.step(claim, "cloud-init");
156
+ const dns = (i.dns ?? DEFAULT_DNS).join(" ");
157
+ // The password hash and the public key arrive on stdin; PVE would otherwise hash with sha256-crypt (STIG wants sha512).
158
+ await this.pveOk(`set -e\numask 077\nP=/tmp/${claim}.pub; W=/tmp/${claim}.pw\ncat > "$P" <<'KEY'\n${keys.publicKey}\nKEY\nIFS= read -r HASH\nprintf '%s' "$HASH" > "$W"\n` +
159
+ `qm set ${vmid} --ciuser ${CI_USER} --cipassword "$(cat "$W")" --sshkeys "$P" --ipconfig0 ip=dhcp --nameserver ${shq(dns)} --agent 1 --tags rhel8-stig-clone >/dev/null\n` +
160
+ `qm set ${vmid} --net0 "$(qm config ${vmid} | sed -n 's/^net0: \\([^,]*\\),.*/\\1/p'),bridge=vmbr0,tag=${VLAN}"\nrm -f "$P" "$W"`, { stdin: `${adminHash}\n` });
161
+ }
162
+ // 3. boot, first-boot re-key, TPM bind
163
+ await this.step(claim, "boot");
164
+ if (!this.d.provider)
165
+ await this.pveOk(`qm start ${vmid}`);
166
+ let ip = "";
167
+ for (let n = 0; n < 60 && !ip; n++) {
168
+ if (this.d.provider) {
169
+ try {
170
+ ip = await this.d.provider.guestIp(vmid);
171
+ }
172
+ catch {
173
+ ip = "";
174
+ }
175
+ }
176
+ else {
177
+ const r = await this.d.pve.run(`qm guest cmd ${vmid} network-get-interfaces`);
178
+ if (r.code === 0)
179
+ ip = guestIp(r.stdout);
180
+ }
181
+ if (!ip)
182
+ await this.d.clock.sleep(10_000);
183
+ }
184
+ if (!ip)
185
+ throw new Error("no guest IP via qemu-guest-agent after 10m");
186
+ writeFileSync(join(state, "ip"), `${ip}\n`);
187
+ this.d.guest.setTarget(ip);
188
+ if (!(await this.d.guest.waitSsh("accept-new", 40)))
189
+ throw new Error("ssh not reachable");
190
+ await this.step(claim, "reencrypt");
191
+ this.log(`ssh up at ${ip}; waiting for first-boot LUKS re-encryption and TPM bind (reboots once)`);
192
+ let done = false;
193
+ for (let n = 0; n < 240 && !done; n++) {
194
+ done = await this.d.guest.fileExists("/var/lib/ct-luks-firstboot.done");
195
+ if (!done)
196
+ await this.d.clock.sleep(15_000);
197
+ }
198
+ if (!done)
199
+ throw new Error("first boot did not finish in 60m");
200
+ if (!(await this.d.guest.waitSsh("yes", 60)))
201
+ throw new Error("guest did not return after the TPM-unlock reboot");
202
+ // 4. escrow the recovery passphrase by name, then shred the guest copy
203
+ await this.step(claim, "escrow");
204
+ const rec = await this.d.guest.runScript(this.d.readAsset("guest/read-recovery.sh"), { sudo: true, stdin: sudoStdin() });
205
+ const recovery = rec.stdout.trim();
206
+ if (recovery) {
207
+ await this.d.secrets.set(escrowKey, recovery);
208
+ if ((await this.d.secrets.get(escrowKey)) !== recovery)
209
+ throw new Error("escrow verification failed; recovery file left on guest");
210
+ await this.d.guest.runScript(this.d.readAsset("guest/shred-recovery.sh"), { sudo: true, stdin: sudoStdin() });
211
+ this.log(`recovery passphrase escrowed to Doppler key ${escrowKey}`);
212
+ }
213
+ else
214
+ this.log("recovery file missing (already escrowed?)");
215
+ // 5. verify
216
+ await this.step(claim, "verify");
217
+ const verify = await this.verifyGuest(escrowKey, sudoStdin);
218
+ writeFileSync(join(state, "verify.txt"), verify.text);
219
+ // 6. fstrim: re-encryption fully allocates the thin disk
220
+ await this.step(claim, "trim");
221
+ const before = await this.poolPercent();
222
+ await this.d.guest.runScript(this.d.readAsset("guest/trim.sh"), { sudo: true, stdin: sudoStdin() });
223
+ const after = await this.poolPercent();
224
+ this.log(`pool before trim ${before}%, after ${after}%`);
225
+ await this.step(claim, "complete");
226
+ return { ok: true, claim, vmid, name: cloneName, ip, template: template.ref, escrowKey, verify: verify.kv, poolBefore: before, poolAfter: after, stateDir: state };
227
+ }
228
+ async pveOk(script, opts) {
229
+ const r = await this.d.pve.run(script, opts);
230
+ if (r.code !== 0)
231
+ throw new Error(`proxmox command failed (exit ${r.code}): ${redact(r.stderr).slice(0, 200)}`);
232
+ return r;
233
+ }
234
+ async verifyGuest(escrowKey, sudoStdin) {
235
+ const user = await this.d.guest.runScript(this.d.readAsset("guest/verify-user.sh"));
236
+ const root = await this.d.guest.runScript(this.d.readAsset("guest/verify-root.sh"), { sudo: true, stdin: sudoStdin() });
237
+ let text = `${user.stdout.trim()}\n${root.stdout.trim()}`;
238
+ const rec = await this.d.secrets.get(escrowKey);
239
+ if (rec) {
240
+ const t = await this.d.guest.runScript(this.d.readAsset("guest/test-recovery.sh"), { sudo: true, stdin: sudoStdin(rec) });
241
+ text += `\nrecovery_passphrase_test=${t.stdout.trim().split("\n").pop() ?? ""}`;
242
+ }
243
+ text += "\n";
244
+ const kv = parseKv(text);
245
+ const okGate = kv.fips_enabled === "1" && kv.selinux === "Enforcing" && kv.tpm_bound === "1" && kv.bootstrap_key_file === "absent";
246
+ if (!okGate)
247
+ throw new Error("VERIFY FAILED: fips/selinux/tpm/bootstrap-key checks did not all pass");
248
+ return { kv, text };
249
+ }
250
+ /* ------------------------------------------------------------ build */
251
+ async planBuild(i) {
252
+ const packer = await this.d.packer.version();
253
+ if (packer !== STIG_PINS.packer)
254
+ throw new Error(`packer ${packer} is not the pinned ${STIG_PINS.packer}`);
255
+ if (i.ssgDatastreamSha256 !== STIG_DATASTREAM_SHA256)
256
+ throw new Error(`SSG datastream sha256 ${i.ssgDatastreamSha256.slice(0, 12)}... is not the pinned ${STIG_PINS.ssg} datastream`);
257
+ const iso = await this.d.pve.run(`pvesm list ${STIG_DVD_ISO.split(":")[0]} --content iso`);
258
+ const dvd = iso.code === 0 && iso.stdout.includes(STIG_DVD_ISO.split("/").pop());
259
+ if (!dvd)
260
+ throw new Error(`RHEL 8.10 DVD ${STIG_DVD_ISO} is not present on Proxmox storage`);
261
+ const vmid = await this.pickVmid();
262
+ const date = (i.now ?? new Date(this.d.clock.now()).toISOString().slice(0, 10)).replace(/-/g, "");
263
+ const name = i.name ?? `${STIG_TEMPLATE_PREFIX}${date}-${vmid}`;
264
+ if (!/^rhel810-stig-\d{8}-\d{4}$/.test(name))
265
+ throw new Error("template name must look like rhel810-stig-YYYYMMDD-VMID");
266
+ const claim = `tpl-${name}`;
267
+ if (await this.d.claims.get(claim))
268
+ throw new Error(`claim ${claim} already exists`);
269
+ const base = { kind: "build", name, vmid, claim, ttl: BUILD_CLAIM_TTL_HOURS, ds: i.ssgDatastreamSha256 };
270
+ return { mode: "plan", name, claim, vmid, claimTtlHours: BUILD_CLAIM_TTL_HOURS, steps: STIG_STEPS["build-template"], preflight: { packer, dvd, datastreamSha256: i.ssgDatastreamSha256 }, planDigest: digest(base) };
271
+ }
272
+ async build(i) {
273
+ const plan = await this.planBuild(i);
274
+ if (!i.apply)
275
+ return plan;
276
+ if (!i.planDigest || i.planDigest !== plan.planDigest)
277
+ throw new Error("plan digest missing or stale; re-run the plan and apply with its planDigest");
278
+ const { name, claim, vmid } = plan;
279
+ const runRoot = this.ensureDir(join(this.d.baseDir, "runs"));
280
+ const runDir = join(runRoot, name);
281
+ if (existsSync(runDir))
282
+ renameSync(runDir, `${runDir}.prev-${new Date(this.d.clock.now()).toISOString().slice(11, 19).replace(/:/g, "")}`);
283
+ this.ensureDir(runDir);
284
+ this.ensureDir(join(runDir, "evidence"));
285
+ // claim first
286
+ this.log(`claim ${claim}: creating (vmid ${vmid}, ${BUILD_CLAIM_TTL_HOURS}h)`);
287
+ const descriptor = defaultDescriptor("build-template", { adminKeyRef: "doppler:LAB_PROXMOX_MINIS_API_TOKEN", tailoringSha256: STIG_TAILORING_SHA256, dns: i.dns, ntp: i.ntp });
288
+ await this.d.claims.create({ name: claim, vmid, vmName: name, ttlHours: BUILD_CLAIM_TTL_HOURS, stig: descriptor });
289
+ await this.d.claims.waitReady(claim);
290
+ await this.d.claims.annotate(claim, { [STIG_STEP_ANNOTATION]: "claim" });
291
+ // secrets by NAME, straight into the Packer environment
292
+ const names = ["LAB_PROXMOX_MINIS_API_TOKEN", "LAB_PROXMOX_MINIS_URL", "RHEL_ORG_ID", "RHEL_ACTIVATION_KEY"];
293
+ const got = {};
294
+ for (const n of names) {
295
+ const v = await this.d.secrets.get(n);
296
+ if (!v)
297
+ throw new Error(`Doppler secret ${n} is missing`);
298
+ got[n] = v;
299
+ }
300
+ const tokenFull = got.LAB_PROXMOX_MINIS_API_TOKEN;
301
+ const eq = tokenFull.indexOf("=");
302
+ if (eq < 1)
303
+ throw new Error("LAB_PROXMOX_MINIS_API_TOKEN is not user@realm!id=secret");
304
+ const mat = await this.d.materials.buildMaterial(runDir, name);
305
+ const env = {
306
+ PKR_VAR_proxmox_url: got.LAB_PROXMOX_MINIS_URL, PKR_VAR_proxmox_username: tokenFull.slice(0, eq), PKR_VAR_proxmox_token: tokenFull.slice(eq + 1),
307
+ PKR_VAR_rhsm_org: got.RHEL_ORG_ID, PKR_VAR_rhsm_key: got.RHEL_ACTIVATION_KEY, PKR_VAR_luks_bootstrap: mat.luksBootstrap,
308
+ PKR_VAR_build_password: mat.buildPassword, PKR_VAR_build_password_hash: mat.buildPasswordHash, PKR_VAR_grub_pbkdf2: mat.grubPbkdf2,
309
+ };
310
+ const vars = {
311
+ vm_id: String(vmid), template_name: name, ssh_private_key_file: mat.sshPrivateKeyFile, ssh_public_key: mat.sshPublicKey,
312
+ ssg_datastream: i.ssgDatastream, evidence_dir: join(runDir, "evidence"), tailoring_file: join(this.d.assetsDir, "tailoring.xml"),
313
+ dns_servers: (i.dns ?? DEFAULT_DNS).join(","), ...(i.ntp && i.ntp.length ? { ntp_servers: i.ntp.join(",") } : {}),
314
+ };
315
+ await this.step(claim, "packer");
316
+ this.log(`packer build ${name} (vmid ${vmid})`);
317
+ const rc = await this.d.packer.build({ vars, env, logFile: join(runDir, "packer.log") });
318
+ if (rc !== 0)
319
+ throw new Error(`BUILD FAILED rc=${rc}; claim ${claim} left to expire in <=${BUILD_CLAIM_TTL_HOURS}h; evidence kept in ${runDir}`);
320
+ for (const s of ["errata", "remediate", "scan", "seal"])
321
+ await this.step(claim, s);
322
+ // gate, then verify the live template, then make the claim long-lived
323
+ const ev = join(runDir, "evidence", "stig-report");
324
+ const summ = parseKv(readFileSync(join(ev, "summary.txt"), "utf8"));
325
+ const counts = countsFromKv(summ);
326
+ const gate = receiptGate(counts);
327
+ if (!gate.failZero)
328
+ throw new Error(`STIG scan gate failed: fail=${counts.fail} error=${counts.error} pass=${counts.pass}; claim ${claim} left to expire`);
329
+ await this.step(claim, "verify-template");
330
+ const cfg = await this.pveOk(`qm config ${vmid}`);
331
+ if (!/^template: 1$/m.test(cfg.stdout))
332
+ throw new Error(`VM ${vmid} is not a Proxmox template after the build`);
333
+ writeFileSync(join(runDir, "evidence", "template-qm-config.txt"), cfg.stdout);
334
+ await this.step(claim, "renew");
335
+ const live = (await this.d.claims.get(claim));
336
+ const renewal = planTemplateRenewal(live, this.d.clock.now());
337
+ if (!renewal.ok)
338
+ throw new Error(renewal.error);
339
+ await this.d.claims.renew(claim, renewal.extendHours);
340
+ const openscap = (/^openscap-scanner-(\S+?)\.[A-Za-z0-9_]+$/m.exec(readFileSync(join(ev, "summary.txt"), "utf8"))?.[1] ?? "").replace(/\.el\d.*$/, "").replace(/-\d+$/, "");
341
+ const receiptLike = {
342
+ template: { name }, os: { release: (summ.VERSION_ID ?? "").replace(/^"|"$/g, ""), kernel: summ.kernel },
343
+ stig: { version: STIG_PINS.stig, ssg_datastream_version: STIG_PINS.ssg, datastream_sha256: summ.ds_sha256, tailoring_sha256: summ.tailoring_sha256 },
344
+ template_scan: Object.fromEntries(COUNT_KEYS.map((k) => [`result_${k}`, counts[k]])),
345
+ artifacts_sha256: { template_arf: sha256File(join(ev, "final-arf.xml")), template_report_html: sha256File(join(ev, "final-report.html")) },
346
+ };
347
+ const summary = buildReceiptSummary(receiptLike, { mode: "build-template", ...(openscap ? { openscap } : {}), validatedAt: new Date(this.d.clock.now()).toISOString() });
348
+ await this.annotateSummary(claim, summary);
349
+ await this.step(claim, "complete");
350
+ this.log(`TEMPLATE READY name=${name} vmid=${vmid} claim=${claim}`);
351
+ return { ok: true, name, vmid, claim, counts, gate, renewedExtendHours: renewal.extendHours, runDir, summary };
352
+ }
353
+ async annotateSummary(claim, summary) {
354
+ const json = JSON.stringify(summary);
355
+ if (Buffer.byteLength(json) > STIG_ANNOTATION_MAX_BYTES)
356
+ throw new Error("receipt summary exceeds the annotation budget");
357
+ if (!validateReceiptSummary(summary))
358
+ throw new Error("receipt summary failed validation; not annotating");
359
+ await this.d.claims.annotate(claim, { [STIG_RECEIPT_ANNOTATION]: json });
360
+ }
361
+ /* --------------------------------------------------------- validate */
362
+ async validate(i) {
363
+ const claim = `clone-${i.cloneName}`;
364
+ const state = join(this.d.baseDir, `clone-${i.cloneName}`);
365
+ if (!existsSync(join(state, "ctadmin_password")) || !existsSync(join(state, "ip")))
366
+ throw new Error(`no runner state for clone ${i.cloneName}; it must be created by create_stig_claim on this host`);
367
+ const rec = await this.d.claims.get(claim);
368
+ if (!rec)
369
+ throw new Error(`claim ${claim} not found`);
370
+ const pw = readFileSync(join(state, "ctadmin_password"), "utf8");
371
+ const ip = readFileSync(join(state, "ip"), "utf8").trim();
372
+ const tpl = readFileSync(join(state, "template"), "utf8").trim();
373
+ this.d.guest.configure({ user: CI_USER, keyFile: join(state, "id_key"), knownHostsFile: join(state, "known_hosts") });
374
+ this.d.guest.setTarget(ip);
375
+ if (!(await this.d.guest.waitSsh("yes", 3)))
376
+ throw new Error("clone is not reachable over ssh");
377
+ const sudoStdin = (extra = "") => `${pw}\n${extra}`;
378
+ await this.step(claim, "scan");
379
+ this.log(`oscap scan on ${i.cloneName}`);
380
+ await this.d.guest.runScript(this.d.readAsset("guest/scan.sh"), { sudo: true, stdin: sudoStdin(), timeoutMs: 30 * 60_000 });
381
+ this.log(`oscap DISA V2R8 benchmark scan on ${i.cloneName} (skipped on templates that predate the dual-scan recipe)`);
382
+ await this.d.guest.runScript(this.d.readAsset("guest/scan-disa.sh"), { sudo: true, stdin: sudoStdin(), timeoutMs: 30 * 60_000 });
383
+ const evDir = join(state, "evidence");
384
+ await this.d.guest.fetchDir("/var/tmp/ct-scan", evDir);
385
+ await this.d.guest.runScript("rm -rf /var/tmp/ct-scan\n", { sudo: true, stdin: sudoStdin() });
386
+ const counts = countsFromKv(parseKv(readFileSync(join(evDir, "clone-summary.txt"), "utf8")));
387
+ let disa;
388
+ if (!existsSync(join(evDir, "clone-disa-absent")) && existsSync(join(evDir, "clone-disa-summary.txt"))) {
389
+ disa = {
390
+ profile: DISA_PROFILE_ID, benchmarkSha256: readFileSync(join(evDir, "clone-disa-benchmark.sha256"), "utf8").trim(),
391
+ counts: disaCountsFromKv(parseKv(readFileSync(join(evDir, "clone-disa-summary.txt"), "utf8"))),
392
+ };
393
+ }
394
+ const gate = receiptGate(counts, disa?.counts);
395
+ const disaMissing = !disa;
396
+ const escrowKey = dopplerKeyFor(i.cloneName);
397
+ let keyDigest;
398
+ const recovery = await this.d.secrets.get(escrowKey);
399
+ if (recovery) {
400
+ const out = await this.d.guest.runScript(this.d.readAsset("guest/keyhash.sh"), { sudo: true, stdin: sudoStdin(recovery) });
401
+ const hex = out.stdout.trim().split("\n").pop() ?? "";
402
+ if (/^[a-f0-9]{64}$/.test(hex))
403
+ keyDigest = hex;
404
+ }
405
+ if (keyDigest)
406
+ writeFileSync(join(state, "keyhash.txt"), `${keyDigest}\n`, { mode: 0o600 });
407
+ const verifyKv = existsSync(join(state, "verify.txt")) ? parseKv(readFileSync(join(state, "verify.txt"), "utf8")) : {};
408
+ const rhel = /(\d+\.\d+) \(/.exec(verifyKv.PRETTY_NAME ?? "")?.[1] ?? "8.10";
409
+ const summary = buildReceiptSummary({
410
+ template: { name: tpl }, os: { release: rhel, kernel: verifyKv.kernel ?? "unknown" },
411
+ stig: { version: STIG_PINS.stig, ssg_datastream_version: STIG_PINS.ssg, datastream_sha256: STIG_DATASTREAM_SHA256, tailoring_sha256: STIG_TAILORING_SHA256 },
412
+ clone_scan: Object.fromEntries(COUNT_KEYS.map((k) => [`result_${k}`, counts[k]])),
413
+ artifacts_sha256: { clone_arf: sha256File(join(evDir, "clone-arf.xml")), clone_report_html: sha256File(join(evDir, "clone-report.html")) },
414
+ }, { mode: "validate", ...(disa ? { disa } : {}), ...(keyDigest ? { keyDigest } : {}), validatedAt: new Date(this.d.clock.now()).toISOString() });
415
+ await this.annotateSummary(claim, summary);
416
+ await this.step(claim, "complete");
417
+ const ok = gate.failZero && !(i.requireDisa && disaMissing);
418
+ return { ok, claim, counts, gate, disa: disa ?? null, disaScan: disa ? "ran" : "unavailable (template predates the DISA dual-scan recipe)", keyDigest, summary, evidenceDir: evDir };
419
+ }
420
+ async getReceipt(i) {
421
+ const rec = await this.d.claims.get(i.claim);
422
+ if (!rec)
423
+ throw new Error(`claim ${i.claim} not found`);
424
+ const raw = rec.metadata.annotations?.[STIG_RECEIPT_ANNOTATION];
425
+ let summary = null;
426
+ if (raw) {
427
+ try {
428
+ summary = validateReceiptSummary(JSON.parse(raw));
429
+ }
430
+ catch {
431
+ summary = null;
432
+ }
433
+ }
434
+ return { claim: i.claim, descriptor: stigDescriptor(rec), summary, statusPreview: stigStatusPreview(rec) };
435
+ }
436
+ /* ---------------------------------------------------------- release */
437
+ async releaseTemplate(i) {
438
+ const rec = await this.d.claims.get(i.claim);
439
+ if (!rec)
440
+ throw new Error(`claim ${i.claim} not found`);
441
+ const vmid = rec.spec?.vmid;
442
+ const guest = (await this.listGuests()).find((g) => g.vmid === vmid);
443
+ if (!guest)
444
+ throw new Error(`no Proxmox guest ${vmid} for claim ${i.claim}`);
445
+ assertTemplateReleaseAllowed({ guest: guest, claim: rec, destroyConfirmed: i.confirmDestroy });
446
+ this.log(`destroying template ${guest.name} (${guest.vmid}) before releasing claim ${i.claim}`);
447
+ if (this.d.provider)
448
+ await this.d.provider.destroyTemplate({ operationId: `stig-destroy-${i.claim}-${this.d.clock.now()}`, name: guest.name, vmid: guest.vmid });
449
+ else
450
+ await this.pveOk(`qm destroy ${guest.vmid} --purge 1 --destroy-unreferenced-disks 1`);
451
+ if ((await this.listGuests()).some((g) => g.vmid === guest.vmid))
452
+ throw new Error(`template ${guest.vmid} still exists after destroy; claim retained`);
453
+ await this.d.claims.delete(i.claim, rec.metadata.uid);
454
+ return { ok: true, destroyed: { vmid: guest.vmid, name: guest.name }, claimDeleted: i.claim };
455
+ }
456
+ }
457
+ function guestIp(stdout) {
458
+ try {
459
+ const ifaces = JSON.parse(stdout);
460
+ for (const f of ifaces) {
461
+ if (f.name === "lo")
462
+ continue;
463
+ const v4 = f["ip-addresses"]?.find((a) => a["ip-address-type"] === "ipv4");
464
+ if (v4)
465
+ return v4["ip-address"];
466
+ }
467
+ }
468
+ catch { /* not ready yet */ }
469
+ return "";
470
+ }
471
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../../src/stig/runner.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"properties":{"adminEmail":{"default":"demo@calltelemetry.com","type":"string"},"adminPassword":{"type":"string"},"adminPasswordSecretRef":{"properties":{"key":{"default":"password","type":"string"},"name":{"type":"string"}},"type":"object"},"applianceId":{"type":"string"},"claimType":{"default":"dynamic","enum":["dynamic","fixture"],"type":"string"},"closed":{"type":"boolean"},"containerOverrides":{"properties":{"jtapi":{"type":"string"},"media":{"type":"string"},"syslog":{"type":"string"},"vue":{"type":"string"},"web":{"type":"string"}},"type":"object"},"cubes":{"items":{"properties":{"dialpeers":{"items":{"properties":{"codec":{"default":"g711ulaw","enum":["g711ulaw","g711alaw","g729","g729r8"],"type":"string"},"destinationPattern":{"type":"string"},"dtmfRelay":{"default":"rtp-nte","enum":["rtp-nte","cisco-rtp","sip-notify","sip-kpml"],"type":"string"},"incomingCalledNumber":{"type":"string"},"preference":{"default":0,"maximum":10,"minimum":0,"type":"integer"},"sessionTarget":{"type":"string"},"tag":{"maximum":2147483647,"minimum":1,"type":"integer"},"type":{"default":"voip","enum":["voip","pots"],"type":"string"}},"required":["tag"],"type":"object"},"type":"array"},"gatewayIp":{"pattern":"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$","type":"string"},"ip":{"pattern":"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$","type":"string"},"mode":{"default":"dynamic_vm","enum":["dynamic_vm","dynamic_mock","claim_fixture","in_guest_emulator"],"type":"string"},"name":{"type":"string"},"node":{"default":"proxmox","type":"string"},"role":{"enum":["cucm-edge","att-pstn","internal","external","standalone"],"type":"string"},"templateVmid":{"default":200,"type":"integer"},"vlan":{"default":125,"maximum":4094,"minimum":1,"type":"integer"},"vmid":{"maximum":299,"minimum":200,"type":"integer"},"xcc":{"properties":{"applianceUrl":{"type":"string"},"enabled":{"default":true,"type":"boolean"},"heartbeatIntervalSeconds":{"default":15,"maximum":300,"minimum":1,"type":"integer"},"remoteUrl":{"type":"string"}},"type":"object"}},"required":["name","role","mode","ip"],"type":"object"},"type":"array"},"cucmEmulator":{"properties":{"axlVersion":{"default":"14.0","enum":["11.5","12.0","12.5","14.0","15.0"],"type":"string"},"cdrPublisher":{"properties":{"enabled":{"default":true,"type":"boolean"},"intervalSeconds":{"default":60,"maximum":3600,"minimum":5,"type":"integer"},"sftpDestination":{"properties":{"host":{"type":"string"},"passwordSecretRef":{"properties":{"key":{"default":"password","type":"string"},"name":{"type":"string"}},"type":"object"},"path":{"default":"/var/spool/calltelemetry/cdr","type":"string"},"port":{"default":2222,"maximum":65535,"minimum":1,"type":"integer"},"username":{"default":"calltelemetry","type":"string"}},"type":"object"}},"type":"object"},"enabled":{"default":false,"type":"boolean"},"mockPhonesCount":{"default":10,"maximum":1000,"minimum":0,"type":"integer"},"mode":{"default":"dynamic_pod","enum":["dynamic_pod","in_guest","external"],"type":"string"},"profile":{"default":"standard-lab","type":"string"},"scenario":{"type":"string"}},"type":"object"},"enableCallManagers":{"default":true,"type":"boolean"},"enableCubes":{"default":true,"type":"boolean"},"licenseDays":{"default":90,"maximum":3650,"minimum":1,"type":"integer"},"licenseTier":{"default":"Demo","enum":["Demo","Community","Standard","Enterprise"],"type":"string"},"loadTesting":{"properties":{"calledNumberPattern":{"default":"+1555200XXXX","type":"string"},"callerIdPattern":{"default":"+1555100XXXX","type":"string"},"chaosErrorRate":{"default":0,"maximum":100,"minimum":0,"type":"number"},"codec":{"default":"g711ulaw","enum":["g711ulaw","g711alaw","g729"],"type":"string"},"concurrency":{"default":5,"maximum":500,"minimum":1,"type":"integer"},"cps":{"default":1,"maximum":500,"minimum":0.1,"type":"number"},"durationSeconds":{"default":60,"maximum":86400,"minimum":1,"type":"integer"},"enabled":{"default":false,"type":"boolean"},"target":{"default":"external_cube","enum":["external_cube","internal_cube","appliance"],"type":"string"}},"type":"object"},"mockPstn":{"properties":{"autoAnswer":{"default":true,"type":"boolean"},"callRateCps":{"default":2,"maximum":500,"minimum":0.1,"type":"number"},"destinationPrefix":{"default":"1...","type":"string"},"enabled":{"default":false,"type":"boolean"},"ip":{"pattern":"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$","type":"string"},"sipPort":{"default":5060,"maximum":65535,"minimum":1,"type":"integer"},"vlan":{"default":123,"maximum":4094,"minimum":1,"type":"integer"}},"type":"object"},"node":{"default":"minis","type":"string"},"orgName":{"default":"CallTelemetry Demo","type":"string"},"paused":{"default":false,"type":"boolean"},"pausedReason":{"maxLength":500,"type":"string"},"phoneEmulator":{"properties":{"autoAnswer":{"default":true,"type":"boolean"},"bibAudioStreaming":{"default":true,"type":"boolean"},"bibStreaming":{"default":true,"type":"boolean"},"controlPlanePort":{"default":8080,"maximum":65535,"minimum":1024,"type":"integer"},"count":{"default":2,"maximum":500,"minimum":1,"type":"integer"},"cucmHost":{"type":"string"},"devicePrefix":{"default":"SEP","type":"string"},"enabled":{"default":false,"type":"boolean"},"mode":{"default":"dynamic_pod","enum":["dynamic_pod","in_guest"],"type":"string"},"model":{"default":"CP-7965G","type":"string"},"phoneCount":{"maximum":500,"minimum":1,"type":"integer"},"phoneWebXmlAccess":{"default":true,"type":"boolean"},"protocol":{"default":"SCCP","enum":["SCCP","SIP","sccp","sip"],"type":"string"},"webXmlAccess":{"default":true,"type":"boolean"}},"type":"object"},"preset":{"default":"comprehensive_demo","enum":["comprehensive_demo","standard_demo","minimal_demo","empty"],"type":"string"},"profile":{"default":"demo","enum":["demo","bare"],"type":"string"},"role":{"enum":["runner","gate","cucm","gateway","infra","harness"],"type":"string"},"sftp":{"properties":{"enabled":{"default":false,"type":"boolean"},"mode":{"default":"appliance_builtin","enum":["appliance_builtin","dynamic_pod"],"type":"string"},"passwordSecretRef":{"properties":{"key":{"default":"password","type":"string"},"name":{"type":"string"}},"type":"object"},"port":{"default":2222,"maximum":65535,"minimum":1,"type":"integer"},"stagingPath":{"default":"/opt/calltelemetry/cdr_staging","type":"string"},"user":{"default":"calltelemetry","type":"string"}},"type":"object"},"sideloadLicense":{"type":"string"},"sshUser":{"default":"calltelemetry","type":"string"},"state":{"enum":["Active","Closed"],"type":"string"},"targetIp":{"pattern":"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$","type":"string"},"targetPort":{"default":2222,"maximum":65535,"minimum":1,"type":"integer"},"train":{"default":"stable","enum":["stable","beta","rc","candidate","dev","edge"],"type":"string"},"ttlHours":{"default":24,"maximum":8760,"minimum":0,"type":"integer"},"version":{"default":"0.8.6.27","type":"string"},"vmName":{"type":"string"},"vmid":{"maximum":8999,"minimum":100,"type":"integer"}},"type":"object"}
1
+ {"properties":{"adminEmail":{"default":"demo@calltelemetry.com","type":"string"},"adminPassword":{"type":"string"},"adminPasswordSecretRef":{"properties":{"key":{"default":"password","type":"string"},"name":{"type":"string"}},"type":"object"},"applianceId":{"type":"string"},"claimType":{"default":"dynamic","enum":["dynamic","fixture"],"type":"string"},"closed":{"type":"boolean"},"containerOverrides":{"properties":{"jtapi":{"type":"string"},"media":{"type":"string"},"syslog":{"type":"string"},"vue":{"type":"string"},"web":{"type":"string"}},"type":"object"},"cubes":{"items":{"properties":{"dialpeers":{"items":{"properties":{"codec":{"default":"g711ulaw","enum":["g711ulaw","g711alaw","g729","g729r8"],"type":"string"},"destinationPattern":{"type":"string"},"dtmfRelay":{"default":"rtp-nte","enum":["rtp-nte","cisco-rtp","sip-notify","sip-kpml"],"type":"string"},"incomingCalledNumber":{"type":"string"},"preference":{"default":0,"maximum":10,"minimum":0,"type":"integer"},"sessionTarget":{"type":"string"},"tag":{"maximum":2147483647,"minimum":1,"type":"integer"},"type":{"default":"voip","enum":["voip","pots"],"type":"string"}},"required":["tag"],"type":"object"},"type":"array"},"gatewayIp":{"pattern":"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$","type":"string"},"ip":{"pattern":"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$","type":"string"},"mode":{"default":"dynamic_vm","enum":["dynamic_vm","dynamic_mock","claim_fixture","in_guest_emulator"],"type":"string"},"name":{"type":"string"},"node":{"default":"proxmox","type":"string"},"role":{"enum":["cucm-edge","att-pstn","internal","external","standalone"],"type":"string"},"templateVmid":{"default":200,"type":"integer"},"vlan":{"default":125,"maximum":4094,"minimum":1,"type":"integer"},"vmid":{"maximum":299,"minimum":200,"type":"integer"},"xcc":{"properties":{"applianceUrl":{"type":"string"},"enabled":{"default":true,"type":"boolean"},"heartbeatIntervalSeconds":{"default":15,"maximum":300,"minimum":1,"type":"integer"},"remoteUrl":{"type":"string"}},"type":"object"}},"required":["name","role","mode","ip"],"type":"object"},"type":"array"},"cucmEmulator":{"properties":{"axlVersion":{"default":"14.0","enum":["11.5","12.0","12.5","14.0","15.0"],"type":"string"},"cdrPublisher":{"properties":{"enabled":{"default":true,"type":"boolean"},"intervalSeconds":{"default":60,"maximum":3600,"minimum":5,"type":"integer"},"sftpDestination":{"properties":{"host":{"type":"string"},"passwordSecretRef":{"properties":{"key":{"default":"password","type":"string"},"name":{"type":"string"}},"type":"object"},"path":{"default":"/var/spool/calltelemetry/cdr","type":"string"},"port":{"default":2222,"maximum":65535,"minimum":1,"type":"integer"},"username":{"default":"calltelemetry","type":"string"}},"type":"object"}},"type":"object"},"enabled":{"default":false,"type":"boolean"},"mockPhonesCount":{"default":10,"maximum":1000,"minimum":0,"type":"integer"},"mode":{"default":"dynamic_pod","enum":["dynamic_pod","in_guest","external"],"type":"string"},"profile":{"default":"standard-lab","type":"string"},"scenario":{"type":"string"}},"type":"object"},"enableCallManagers":{"default":true,"type":"boolean"},"enableCubes":{"default":true,"type":"boolean"},"licenseDays":{"default":90,"maximum":3650,"minimum":1,"type":"integer"},"licenseTier":{"default":"Demo","enum":["Demo","Community","Standard","Enterprise"],"type":"string"},"loadTesting":{"properties":{"calledNumberPattern":{"default":"+1555200XXXX","type":"string"},"callerIdPattern":{"default":"+1555100XXXX","type":"string"},"chaosErrorRate":{"default":0,"maximum":100,"minimum":0,"type":"number"},"codec":{"default":"g711ulaw","enum":["g711ulaw","g711alaw","g729"],"type":"string"},"concurrency":{"default":5,"maximum":500,"minimum":1,"type":"integer"},"cps":{"default":1,"maximum":500,"minimum":0.1,"type":"number"},"durationSeconds":{"default":60,"maximum":86400,"minimum":1,"type":"integer"},"enabled":{"default":false,"type":"boolean"},"target":{"default":"external_cube","enum":["external_cube","internal_cube","appliance"],"type":"string"}},"type":"object"},"mockPstn":{"properties":{"autoAnswer":{"default":true,"type":"boolean"},"callRateCps":{"default":2,"maximum":500,"minimum":0.1,"type":"number"},"destinationPrefix":{"default":"1...","type":"string"},"enabled":{"default":false,"type":"boolean"},"ip":{"pattern":"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$","type":"string"},"sipPort":{"default":5060,"maximum":65535,"minimum":1,"type":"integer"},"vlan":{"default":123,"maximum":4094,"minimum":1,"type":"integer"}},"type":"object"},"node":{"default":"minis","type":"string"},"orgName":{"default":"CallTelemetry Demo","type":"string"},"paused":{"default":false,"type":"boolean"},"pausedReason":{"maxLength":500,"type":"string"},"phoneEmulator":{"properties":{"autoAnswer":{"default":true,"type":"boolean"},"bibAudioStreaming":{"default":true,"type":"boolean"},"bibStreaming":{"default":true,"type":"boolean"},"controlPlanePort":{"default":8080,"maximum":65535,"minimum":1024,"type":"integer"},"count":{"default":2,"maximum":500,"minimum":1,"type":"integer"},"cucmHost":{"type":"string"},"devicePrefix":{"default":"SEP","type":"string"},"enabled":{"default":false,"type":"boolean"},"mode":{"default":"dynamic_pod","enum":["dynamic_pod","in_guest"],"type":"string"},"model":{"default":"CP-7965G","type":"string"},"phoneCount":{"maximum":500,"minimum":1,"type":"integer"},"phoneWebXmlAccess":{"default":true,"type":"boolean"},"protocol":{"default":"SCCP","enum":["SCCP","SIP","sccp","sip"],"type":"string"},"webXmlAccess":{"default":true,"type":"boolean"}},"type":"object"},"preset":{"default":"comprehensive_demo","enum":["comprehensive_demo","standard_demo","minimal_demo","empty"],"type":"string"},"profile":{"default":"demo","enum":["demo","bare"],"type":"string"},"role":{"enum":["runner","gate","cucm","gateway","infra","harness"],"type":"string"},"sftp":{"properties":{"enabled":{"default":false,"type":"boolean"},"mode":{"default":"appliance_builtin","enum":["appliance_builtin","dynamic_pod"],"type":"string"},"passwordSecretRef":{"properties":{"key":{"default":"password","type":"string"},"name":{"type":"string"}},"type":"object"},"port":{"default":2222,"maximum":65535,"minimum":1,"type":"integer"},"stagingPath":{"default":"/opt/calltelemetry/cdr_staging","type":"string"},"user":{"default":"calltelemetry","type":"string"}},"type":"object"},"sideloadLicense":{"type":"string"},"sshUser":{"default":"calltelemetry","type":"string"},"state":{"enum":["Active","Closed"],"type":"string"},"stig":{"properties":{"mode":{"enum":["build-template","clone","validate"],"type":"string"},"pins":{"properties":{"packer":{"pattern":"^\\d+\\.\\d+\\.\\d+$","type":"string"},"packerProxmoxPlugin":{"pattern":"^\\d+\\.\\d+\\.\\d+$","type":"string"},"ssg":{"pattern":"^\\d+\\.\\d+\\.\\d+$","type":"string"},"stig":{"pattern":"^V\\d+R\\d+$","type":"string"}},"required":["ssg","stig","packer","packerProxmoxPlugin"],"type":"object"},"profile":{"enum":["rhel8-stig"],"type":"string"},"schema":{"enum":["calltelemetry-stig-claim/v1"],"type":"string"},"site":{"properties":{"adminKeyRef":{"pattern":"^doppler:[A-Z][A-Z0-9_]{2,127}$","type":"string"},"dns":{"items":{"pattern":"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$","type":"string"},"maxItems":4,"minItems":1,"type":"array"},"ntp":{"items":{"maxLength":253,"type":"string"},"maxItems":4,"type":"array"}},"required":["dns","ntp","adminKeyRef"],"type":"object"},"tailoring":{"properties":{"ref":{"maxLength":120,"pattern":"^xccdf_[A-Za-z0-9._-]+_profile_[A-Za-z0-9._-]+$","type":"string"},"sha256":{"pattern":"^[a-f0-9]{64}$","type":"string"}},"required":["ref"],"type":"object"},"template":{"properties":{"ref":{"maxLength":40,"pattern":"^rhel810-stig-\\d{8}-\\d{4}$","type":"string"},"vmid":{"maximum":8999,"minimum":100,"type":"integer"}},"required":["ref","vmid"],"type":"object"}},"required":["schema","mode","profile","tailoring","site","pins"],"type":"object"},"targetIp":{"pattern":"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$","type":"string"},"targetPort":{"default":2222,"maximum":65535,"minimum":1,"type":"integer"},"train":{"default":"stable","enum":["stable","beta","rc","candidate","dev","edge"],"type":"string"},"ttlHours":{"default":24,"maximum":8760,"minimum":0,"type":"integer"},"version":{"default":"0.8.6.27","type":"string"},"vmName":{"type":"string"},"vmid":{"maximum":8999,"minimum":100,"type":"integer"}},"type":"object"}