@calltelemetry/ct-lab-mcp 0.8.97 → 0.8.99
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 +22 -0
- package/assets/stig/SHA256SUMS +18 -0
- package/assets/stig/files/ct-luks-firstboot.service +13 -0
- package/assets/stig/files/ct-luks-firstboot.sh +35 -0
- package/assets/stig/guest/keyhash.sh +4 -0
- package/assets/stig/guest/read-recovery.sh +2 -0
- package/assets/stig/guest/scan-disa.sh +17 -0
- package/assets/stig/guest/scan.sh +22 -0
- package/assets/stig/guest/shred-recovery.sh +2 -0
- package/assets/stig/guest/test-recovery.sh +3 -0
- package/assets/stig/guest/trim.sh +3 -0
- package/assets/stig/guest/verify-root.sh +9 -0
- package/assets/stig/guest/verify-user.sh +9 -0
- package/assets/stig/ks.cfg.pkrtpl +95 -0
- package/assets/stig/scripts/assess.sh +39 -0
- package/assets/stig/scripts/errata.sh +19 -0
- package/assets/stig/scripts/remediate.sh +127 -0
- package/assets/stig/scripts/seal.sh +46 -0
- package/assets/stig/tailoring.xml +16 -0
- package/assets/stig/template.pkr.hcl +252 -0
- package/dist/src/credentials/index.d.ts +1 -0
- package/dist/src/credentials/index.d.ts.map +1 -1
- package/dist/src/credentials/index.js +1 -0
- package/dist/src/credentials/index.js.map +1 -1
- package/dist/src/credentials/remediation.d.ts +33 -0
- package/dist/src/credentials/remediation.d.ts.map +1 -0
- package/dist/src/credentials/remediation.js +105 -0
- package/dist/src/credentials/remediation.js.map +1 -0
- package/dist/src/generated-version.d.ts +1 -1
- package/dist/src/generated-version.js +1 -1
- package/dist/src/stig/live.d.ts +116 -0
- package/dist/src/stig/live.d.ts.map +1 -0
- package/dist/src/stig/live.js +339 -0
- package/dist/src/stig/live.js.map +1 -0
- package/dist/src/stig/model.d.ts +160 -0
- package/dist/src/stig/model.d.ts.map +1 -0
- package/dist/src/stig/model.js +384 -0
- package/dist/src/stig/model.js.map +1 -0
- package/dist/src/stig/ports.d.ts +149 -0
- package/dist/src/stig/ports.d.ts.map +1 -0
- package/dist/src/stig/ports.js +7 -0
- package/dist/src/stig/ports.js.map +1 -0
- package/dist/src/stig/receipt.d.ts +35 -0
- package/dist/src/stig/receipt.d.ts.map +1 -0
- package/dist/src/stig/receipt.js +112 -0
- package/dist/src/stig/receipt.js.map +1 -0
- package/dist/src/stig/runner.d.ts +109 -0
- package/dist/src/stig/runner.d.ts.map +1 -0
- package/dist/src/stig/runner.js +471 -0
- package/dist/src/stig/runner.js.map +1 -0
- package/dist/src/tools/appliance-claim-spec-schema.v1.json +1 -1
- package/dist/src/tools/appliance-claim-tools.d.ts +10 -4
- package/dist/src/tools/appliance-claim-tools.d.ts.map +1 -1
- package/dist/src/tools/appliance-claim-tools.js +10 -2
- package/dist/src/tools/appliance-claim-tools.js.map +1 -1
- package/dist/src/tools/claim-creation-projection.d.ts +1 -1
- package/dist/src/tools/claim-creation-projection.js +1 -1
- package/dist/src/tools/claim-custody.d.ts +7 -7
- package/dist/src/tools/claimed-import-qcow.d.ts +2 -2
- package/dist/src/tools/credential-status.d.ts.map +1 -1
- package/dist/src/tools/credential-status.js +19 -0
- package/dist/src/tools/credential-status.js.map +1 -1
- package/dist/src/tools/host-maintenance-shutdown.d.ts +4 -4
- package/dist/src/tools/host-migrate-vm.d.ts +4 -4
- package/dist/src/tools/index.d.ts.map +1 -1
- package/dist/src/tools/index.js +6 -1
- package/dist/src/tools/index.js.map +1 -1
- package/dist/src/tools/purge-slots.d.ts +1 -1
- package/dist/src/tools/sandbox-tools.d.ts +8 -8
- package/dist/src/tools/stig-tools.d.ts +47 -0
- package/dist/src/tools/stig-tools.d.ts.map +1 -0
- package/dist/src/tools/stig-tools.js +125 -0
- package/dist/src/tools/stig-tools.js.map +1 -0
- package/dist/src/tools/vm-action.d.ts +2 -2
- 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"}
|