@calltelemetry/ct-lab-mcp 0.8.105 → 0.8.107

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 (63) hide show
  1. package/assets/stig/SHA256SUMS +15 -1
  2. package/assets/stig/guest/collect-fips-state.sh +6 -0
  3. package/assets/stig/guest/collect-hardware.sh +3 -0
  4. package/assets/stig/guest/collect-host-checks.sh +3 -0
  5. package/assets/stig/guest/collect-network-services.sh +15 -0
  6. package/assets/stig/guest/collect-repolist.sh +3 -0
  7. package/assets/stig/guest/collect-rpm-inventory.sh +3 -0
  8. package/assets/stig/guest/collect-rpm-nevra.sh +3 -0
  9. package/assets/stig/guest/collect-rpmlist.sh +3 -0
  10. package/assets/stig/guest/collect-updateinfo-all.sh +3 -0
  11. package/assets/stig/guest/collect-updateinfo-security.sh +3 -0
  12. package/assets/stig/guest/collect-updateinfo-summary.sh +3 -0
  13. package/assets/stig/guest/oval-eval.sh +11 -0
  14. package/assets/stig/guest/oval-prep.sh +4 -0
  15. package/assets/stig/guest/verify-root.sh +13 -0
  16. package/assets/stig/image/verify-image.sh +28 -0
  17. package/dist/src/generated-version.d.ts +1 -1
  18. package/dist/src/generated-version.js +1 -1
  19. package/dist/src/stig/dist.d.ts +121 -0
  20. package/dist/src/stig/dist.d.ts.map +1 -0
  21. package/dist/src/stig/dist.js +234 -0
  22. package/dist/src/stig/dist.js.map +1 -0
  23. package/dist/src/stig/distribution.d.ts +95 -0
  24. package/dist/src/stig/distribution.d.ts.map +1 -0
  25. package/dist/src/stig/distribution.js +398 -0
  26. package/dist/src/stig/distribution.js.map +1 -0
  27. package/dist/src/stig/evidence.d.ts +135 -0
  28. package/dist/src/stig/evidence.d.ts.map +1 -0
  29. package/dist/src/stig/evidence.js +637 -0
  30. package/dist/src/stig/evidence.js.map +1 -0
  31. package/dist/src/stig/live.d.ts +67 -4
  32. package/dist/src/stig/live.d.ts.map +1 -1
  33. package/dist/src/stig/live.js +226 -5
  34. package/dist/src/stig/live.js.map +1 -1
  35. package/dist/src/stig/markers.d.ts +6 -0
  36. package/dist/src/stig/markers.d.ts.map +1 -0
  37. package/dist/src/stig/markers.js +23 -0
  38. package/dist/src/stig/markers.js.map +1 -0
  39. package/dist/src/stig/model.d.ts +2 -1
  40. package/dist/src/stig/model.d.ts.map +1 -1
  41. package/dist/src/stig/model.js +7 -2
  42. package/dist/src/stig/model.js.map +1 -1
  43. package/dist/src/stig/nodes.d.ts +52 -12
  44. package/dist/src/stig/nodes.d.ts.map +1 -1
  45. package/dist/src/stig/nodes.js +90 -11
  46. package/dist/src/stig/nodes.js.map +1 -1
  47. package/dist/src/stig/ports.d.ts +81 -2
  48. package/dist/src/stig/ports.d.ts.map +1 -1
  49. package/dist/src/stig/pve.d.ts +22 -0
  50. package/dist/src/stig/pve.d.ts.map +1 -0
  51. package/dist/src/stig/pve.js +26 -0
  52. package/dist/src/stig/pve.js.map +1 -0
  53. package/dist/src/stig/runner.d.ts +36 -9
  54. package/dist/src/stig/runner.d.ts.map +1 -1
  55. package/dist/src/stig/runner.js +129 -96
  56. package/dist/src/stig/runner.js.map +1 -1
  57. package/dist/src/tools/quick-provision.d.ts +2 -2
  58. package/dist/src/tools/slot-tools.d.ts +4 -4
  59. package/dist/src/tools/stig-tools.d.ts +52 -8
  60. package/dist/src/tools/stig-tools.d.ts.map +1 -1
  61. package/dist/src/tools/stig-tools.js +105 -21
  62. package/dist/src/tools/stig-tools.js.map +1 -1
  63. package/package.json +1 -1
@@ -13,6 +13,20 @@ eb119e742a4791404ca298c962515ffe3492814dfc72aecac16c420ccb3b0ccc guest/keyhash.
13
13
  9abadcf3c9a1334447a6f349c6c78105d090550d6e8c09adb0320fc1a73e5019 guest/shred-recovery.sh
14
14
  0af1b98d2acf8827ac3861a0ec25f507483a3dc902f00ed215ce13b6dc4db0dc guest/test-recovery.sh
15
15
  6a63f43c312eed5941f0b86044ebe8b3457ce9412c5d9a1ceda67316d16a4209 guest/trim.sh
16
- 6b3eab512392c9b68499cb3b4a753377bcc499b810e7259d8ede5e10861bf674 guest/verify-root.sh
16
+ 6155386f59eb807256b9ab5a9f61136821cb43bf629b06304c4279922a4d30f3 guest/verify-root.sh
17
17
  770cbf1c4ea374772d6e80734b1fe4d7d7f5826c8c528a5371f4dfea196479d7 guest/verify-user.sh
18
18
  b4a37a0425369c99dfe9b63086155b7ffaa0ef73f98b158143ecb0cd84d45d94 guest/scan-disa.sh
19
+ 65e5a3ca041b44d496e81cd961c3fa70ac0bf6804ef9b3f48a9997fa83902d07 image/verify-image.sh
20
+ b16398f652108b9c80f310b98484d23f7f7ac0db9dfd6bb42ca19392ffc2e3d0 guest/collect-fips-state.sh
21
+ f965a01e2010fbdc67418ac65f0b5652fa0a73bd11527930dbbd53b4bf0db31e guest/collect-hardware.sh
22
+ 8c7a455289c18ef63b23c8fead2122db9e31399e8490501e8933f62b5a9c4008 guest/collect-host-checks.sh
23
+ 9a3d629763624d831b945507ba32d2e08f5a41b9d8e00dd7563b9707746aa09e guest/collect-network-services.sh
24
+ 799bedfcce87a51e1b2a82724aae64f2ba0586efbe71b51877e214c6f8396024 guest/collect-repolist.sh
25
+ ed5647566b45fca581e1eed8cfcac3c431ea6d2a6ab405ab2d6aafc7a9eb7af4 guest/collect-rpm-inventory.sh
26
+ 99576ee9e80cb7d2d18c4efb624c69429d67a560f151a22da2b9f12681bdb3a3 guest/collect-rpm-nevra.sh
27
+ 58e22eb71b7e508207acd61719c63a35dffc87973dd540321dc49e4b4f8de46e guest/collect-rpmlist.sh
28
+ 01c34fa475ae254dec8c4a091901406f7f338591a1215cc097206e02249f54b2 guest/collect-updateinfo-all.sh
29
+ 0ad1521d199b7912a2c6490f44ee945b643ea88c33ecae16bb283ab39f22eb9e guest/collect-updateinfo-security.sh
30
+ 48d22a1c247bc1d58fc7d0820c4f045eb4a7e4234721d47094e51db7fd04dcef guest/collect-updateinfo-summary.sh
31
+ b720ee63cac8ff74a68589f23ca57f98aed1ec39a7bc023f93f29e588821ccdc guest/oval-eval.sh
32
+ 10f120dc3ab761227a211c74207ad0ef2f2109e85502413e0b90595fc5794912 guest/oval-prep.sh
@@ -0,0 +1,6 @@
1
+ #!/bin/bash
2
+ # Read-only host facts for fips-state.txt. Run as root; stdout is the evidence file. Faithful to the `do_collect` block of the known-good clone.sh (ct-meta rhel8-stig-template).
3
+ echo "### FIPS"; fips-mode-setup --check; update-crypto-policies --show; cat /proc/sys/crypto/fips_enabled; echo
4
+ echo "### NEVRA"; rpm -q --qf "%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n" kernel kernel-core openssl openssl-libs openssl-pkcs11 libgcrypt gnutls nss nss-softokn nss-softokn-freebl nss-util libkcapi libkcapi-hmaccalc openssh openssh-server nettle gmp dracut-fips 2>&1
5
+ echo; echo "### KCOMP"; rpm -q --qf "%{NAME}-%|EPOCH?{%{EPOCH}}:{(none)}|:%{VERSION}-%{RELEASE}.%{ARCH} %{INSTALLTIME:date} %{RSAHEADER:pgpsig}\n" nss-softokn kernel-core libgcrypt gnutls openssh libkcapi openssl-libs
6
+ echo; echo "### OSREL"; head -3 /etc/os-release
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+ # Read-only host facts for hardware.txt. Run as root; stdout is the evidence file. Faithful to the `do_collect` block of the known-good clone.sh (ct-meta rhel8-stig-template).
3
+ dmidecode -t system 2>&1 | head -20; lscpu; free -b; lsblk -b; ip -br a; uname -r; cat /etc/redhat-release; ls /dev/tpm0 /dev/tpmrm0 2>&1; [ -d /sys/firmware/efi ] && echo EFI-boot || echo BIOS-boot; mokutil --sb-state 2>&1
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+ # Read-only host facts for host-checks.txt. Run as root; stdout is the evidence file. Faithful to the `do_collect` block of the known-good clone.sh (ct-meta rhel8-stig-template).
3
+ getent shadow root | cut -d: -f4,5; rpm -q kernel-core | wc -l; grubby --default-kernel; id -Z; grep -hE "^(deny|fail_interval|unlock_time|even_deny_root|silent|audit)" /etc/security/faillock.conf
@@ -0,0 +1,15 @@
1
+ #!/bin/bash
2
+ # Read-only host facts for network-services.txt. Run as root; stdout is the evidence file. Faithful to the `do_collect` block of the known-good clone.sh (ct-meta rhel8-stig-template).
3
+ echo "### SS"; ss -tulpn; echo; echo "### DEFZONE"; firewall-cmd --get-default-zone; firewall-cmd --get-active-zones; echo; echo "### ZONES"; firewall-cmd --list-all-zones
4
+ echo; echo "### RUNNING"; systemctl list-units --type=service --state=running --no-legend --no-pager
5
+ echo; echo "### ENABLED"; systemctl list-unit-files --state=enabled --no-legend --no-pager
6
+ echo; echo "### SOCKETS"; systemctl list-units --type=socket --no-legend --no-pager
7
+ echo; echo "### RESOLV"; cat /etc/resolv.conf; grep -r . /etc/NetworkManager/conf.d/ 2>/dev/null
8
+ echo; echo "### CHRONY"; grep -vE "^(#|$)" /etc/chrony.conf; chronyc sources 2>&1 | head -12
9
+ echo; echo "### RSYSLOG"; grep -nE "^[^#]*@" /etc/rsyslog.conf
10
+ echo; echo "### REPOS"; ls /etc/yum.repos.d; dnf -C repolist --all 2>&1 | tail -3
11
+ echo; echo "### RHSM"; subscription-manager status 2>&1 | tail -5
12
+ echo; echo "### SSHD"; sshd -T 2>&1 | grep -E "^(port|listenaddress|permitrootlogin|ciphers|macs|banner|kexalgorithms)"
13
+ echo; echo "### SSHD-CRYPTO-POLICY-BACKEND"; cat /etc/crypto-policies/back-ends/opensshserver.config
14
+ echo; echo "### TIMERS"; systemctl list-timers --no-pager --no-legend
15
+ echo; echo "### RSYSLOG-FILE"; grep -n "@@" /etc/rsyslog.conf
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+ # Read-only: dnf repolist, cache only (repolist.txt). Run as root; stdout is the evidence file. Faithful to the `do_collect` block of the known-good clone.sh (ct-meta rhel8-stig-template).
3
+ rc=0; dnf -C repolist --all 2>&1 || rc=$?; echo rc=$rc; head -3 /etc/os-release
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+ # Read-only: rpm inventory rows (rpm-inventory.tsv; the caller writes the header row). Run as root; stdout is the evidence file. Faithful to the `do_collect` block of the known-good clone.sh (ct-meta rhel8-stig-template).
3
+ rpm -qa --qf '%{NAME}\t%|EPOCH?{%{EPOCH}}:{0}|\t%{VERSION}\t%{RELEASE}\t%{ARCH}\t%{VENDOR}\t%{LICENSE}\t%{SOURCERPM}\t%{RSAHEADER:pgpsig}\t%{SIGPGP:pgpsig}\t%{DSAHEADER:pgpsig}\t%{SHA256HEADER}\t%{PACKAGER}\n' | LC_ALL=C sort
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+ # Read-only: rpm NEVRA list (rpm-nevra.txt). Run as root; stdout is the evidence file. Faithful to the `do_collect` block of the known-good clone.sh (ct-meta rhel8-stig-template).
3
+ rpm -qa --qf '%{NAME}-%|EPOCH?{%{EPOCH}}:{0}|:%{VERSION}-%{RELEASE}.%{ARCH}\n' | LC_ALL=C sort
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+ # Read-only: rpm list with vendor (rpmlist.txt). Run as root; stdout is the evidence file. Faithful to the `do_collect` block of the known-good clone.sh (ct-meta rhel8-stig-template).
3
+ rpm -qa --qf '%{NAME}|%|EPOCH?{%{EPOCH}}:{(none)}|%|VERSION?{%{VERSION}}:{(none)}|%{RELEASE}|%|ARCH?{%{ARCH}}:{(none)}|%{VENDOR}\n' | LC_ALL=C sort
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+ # Read-only: dnf updateinfo all, cache only (updateinfo-all.txt). Run as root; stdout is the evidence file. Faithful to the `do_collect` block of the known-good clone.sh (ct-meta rhel8-stig-template).
3
+ rc=0; dnf -C updateinfo list --all --security 2>&1 || rc=$?; echo rc=$rc
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+ # Read-only: dnf updateinfo security, cache only (updateinfo-security.txt). Run as root; stdout is the evidence file. Faithful to the `do_collect` block of the known-good clone.sh (ct-meta rhel8-stig-template).
3
+ rc=0; dnf -C updateinfo list security 2>&1 || rc=$?; echo rc=$rc
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+ # Read-only: dnf updateinfo summary, cache only (updateinfo-summary.txt). Run as root; stdout is the evidence file. Faithful to the `do_collect` block of the known-good clone.sh (ct-meta rhel8-stig-template).
3
+ rc=0; dnf -C updateinfo summary 2>&1 || rc=$?; echo rc=$rc
@@ -0,0 +1,11 @@
1
+ #!/bin/bash
2
+ # Evaluate the uploaded Red Hat OVAL v2 RHEL 8 feed on the clone (oscap oval eval). Run as root.
3
+ # Read-only on the system: oscap reads the RPM database; output stays under /var/tmp/ct-oval.
4
+ # Faithful to the `do_oval` block of the known-good clone.sh (ct-meta rhel8-stig-template).
5
+ e=/var/tmp/ct-oval
6
+ cd $e; rc=0; oscap oval eval --results $e/oval-results.xml --report $e/oval-report.html $e/rhel-8.oval.xml > $e/oval-stdout.txt 2>&1 || rc=$?
7
+ { echo oval_exit=$rc; echo oval_true=$(grep -c ': true$' $e/oval-stdout.txt || true); echo oval_false=$(grep -c ': false$' $e/oval-stdout.txt || true)
8
+ echo oval_other=$(grep '^Definition' $e/oval-stdout.txt | grep -vcE ': (true|false)$' || true); } > $e/oval-summary.txt
9
+ grep ': true$' $e/oval-stdout.txt > $e/oval-true-definitions.txt || true
10
+ rm -f $e/rhel-8.oval.xml; sha256sum $e/oval-results.xml | cut -d' ' -f1 > $e/oval-results.xml.raw.sha256; xz -9e -f $e/oval-results.xml; sha256sum $e/oval-results.xml.xz | cut -d' ' -f1 > $e/oval-results.xml.xz.sha256
11
+ chown -R ctadmin $e
@@ -0,0 +1,4 @@
1
+ #!/bin/bash
2
+ # Scratch directory for the OVAL evaluation (the Red Hat feed is uploaded here by the caller). Run as root.
3
+ # Faithful to the `do_oval` block of the known-good clone.sh (ct-meta rhel8-stig-template).
4
+ install -d -o ctadmin -m 0700 /var/tmp/ct-oval
@@ -7,3 +7,16 @@ echo luks_passphrase_slots=$(cryptsetup luksDump $dev | grep -cE "^ [0-9]+: luk
7
7
  echo clevis_tpm2_tokens=$(cryptsetup luksDump $dev | grep -c "clevis")
8
8
  echo bootstrap_key_file=$(test -e /etc/ct-luks-bootstrap.key && echo present || echo absent)
9
9
  echo tpm_bound=$(clevis luks list -d $dev | grep -c tpm2)
10
+ echo root_min_days=$(getent shadow root | cut -d: -f4)
11
+ echo root_max_days=$(getent shadow root | cut -d: -f5)
12
+ echo kernels_installed=$(rpm -q kernel-core | wc -l)
13
+ echo kernel_packages=$(rpm -qa "kernel*" | sort | paste -sd,)
14
+ echo boot_entries=$(grubby --info=ALL | grep -c ^kernel=)
15
+ echo default_kernel=$(grubby --default-kernel)
16
+ echo bls_entries=$(ls /boot/loader/entries | paste -sd,)
17
+ echo sudo_nopasswd_entries=$(cat /etc/sudoers /etc/sudoers.d/* | grep -v "^#" | grep -c NOPASSWD)
18
+ echo repo_files=$(ls /etc/yum.repos.d | paste -sd,)
19
+ echo ct_offline_repo_enabled=$(sed -n "s/^enabled=//p" /etc/yum.repos.d/ct-offline.repo)
20
+ echo gpgcheck_global=$(sed -n "s/^gpgcheck[ ]*=[ ]*//p" /etc/dnf/dnf.conf)
21
+ echo localpkg_gpgcheck=$(sed -n "s/^localpkg_gpgcheck[ ]*=[ ]*//p" /etc/dnf/dnf.conf)
22
+ echo stale_boot_files=$(ls /boot | grep -c rescue)
@@ -0,0 +1,28 @@
1
+ #!/bin/bash
2
+ # Verify a published STIG image on the host that runs it (read-only; no secrets).
3
+ # Run on a Proxmox node: ssh root@<node> "STORE=/mnt/pve/ct-stig-images TPL=<template> FPR=<fingerprint> bash -s" < verify-image.sh
4
+ # Checks, with the pinned evidence-key fingerprint: public key fingerprint, index.json signature,
5
+ # template.json sha256 + signature, qcow2 sha256 + signature. Exit 0 and VERIFY_OK on success.
6
+ set -euo pipefail
7
+ : "${STORE:?}" "${TPL:?}" "${FPR:?}"
8
+ cd "$STORE/rhel8-stig"
9
+ H="$(mktemp -d /tmp/stgv.XXXXXX)"; chmod 700 "$H"
10
+ trap 'gpgconf --homedir "$H" --kill all >/dev/null 2>&1; rm -rf "$H"' EXIT
11
+ G="gpg --homedir $H --batch --no-tty --yes"
12
+ $G --import stig-evidence-signing.pub.asc >/dev/null 2>&1
13
+ $G --list-keys --with-colons 2>/dev/null | grep -q "^fpr:::::::::$FPR:" || { echo "pubkey fingerprint mismatch" >&2; exit 1; }
14
+ vok() { $G --status-fd 1 --verify "$2" "$1" 2>/dev/null | grep VALIDSIG | grep -q "$FPR" || { echo "BAD signature: $1" >&2; exit 1; }; }
15
+ vok index.json index.json.asc
16
+ read -r QS TS < <(python3 -I - "$TPL" <<'PY'
17
+ import json, sys
18
+ i = json.load(open("index.json"))
19
+ v = [x for x in i["versions"] if x["name"] == sys.argv[1]]
20
+ if not v: sys.exit("template not in index.json")
21
+ print(v[0]["qcow2_sha256"], v[0]["template_json_sha256"])
22
+ PY
23
+ )
24
+ [ "$(sha256sum "$TPL/template.json" | cut -d' ' -f1)" = "$TS" ] || { echo "template.json sha256 mismatch" >&2; exit 1; }
25
+ vok "$TPL/template.json" "$TPL/template.json.asc"
26
+ [ "$(sha256sum "../import/$TPL.qcow2" | cut -d' ' -f1)" = "$QS" ] || { echo "qcow2 sha256 mismatch" >&2; exit 1; }
27
+ vok "../import/$TPL.qcow2" "$TPL/$TPL.qcow2.asc"
28
+ echo "VERIFY_OK qcow2_sha256=$QS template_json_sha256=$TS"
@@ -2,5 +2,5 @@
2
2
  * Auto-synced package version fallback for non-filesystem runtimes (Cloudflare Workers).
3
3
  * Updated automatically during release publication in .github/workflows/publish.yml.
4
4
  */
5
- export declare const PACKAGE_VERSION = "0.8.105";
5
+ export declare const PACKAGE_VERSION = "0.8.107";
6
6
  //# sourceMappingURL=generated-version.d.ts.map
@@ -2,5 +2,5 @@
2
2
  * Auto-synced package version fallback for non-filesystem runtimes (Cloudflare Workers).
3
3
  * Updated automatically during release publication in .github/workflows/publish.yml.
4
4
  */
5
- export const PACKAGE_VERSION = "0.8.105";
5
+ export const PACKAGE_VERSION = "0.8.107";
6
6
  //# sourceMappingURL=generated-version.js.map
@@ -0,0 +1,121 @@
1
+ export declare const TEMPLATE_JSON_SCHEMA = "calltelemetry-rhel8-stig-template/v1";
2
+ export declare const INDEX_SCHEMA = "calltelemetry-rhel8-stig-index/v1";
3
+ export declare const PUBLISH_RECEIPT_SCHEMA = "calltelemetry-rhel8-stig-publish-receipt/v1";
4
+ export declare const SYNC_RECEIPT_SCHEMA = "calltelemetry-rhel8-stig-sync-receipt/v1";
5
+ export declare const EXPORT_DONE = "PUBLISH_EXPORT_DONE";
6
+ export declare const SYNC_DONE = "SYNC_CREATE_DONE";
7
+ export declare const DISK_OPTIONS = "cache=none,discard=on,iothread=1,replicate=0";
8
+ export declare const EFIDISK = "efitype=4m,ms-cert=2023k,pre-enrolled-keys=1";
9
+ export declare const TPM_NOTE = "version=v2.0 (fresh per clone)";
10
+ type Json = Record<string, any>;
11
+ export declare function assertTemplateName(name: string): string;
12
+ /** Python `json.dump(obj, indent=2, sort_keys=True)` plus the trailing newline the scripts add. */
13
+ export declare function pyJson(value: unknown): string;
14
+ /** Python `datetime.now(utc).strftime("%Y-%m-%dT%H:%M:%SZ")`. */
15
+ export declare const utcStamp: (ms: number) => string;
16
+ /** Python `shlex.quote`. */
17
+ export declare function shlexQuote(s: string): string;
18
+ export declare const baseLv: (vmid: number) => string;
19
+ /**
20
+ * The detached export script (publish.sh REMOTE heredoc). The base LV must be read-only; it is activated with -K only
21
+ * when inactive and deactivated afterwards, so it is never made writable.
22
+ */
23
+ export declare function buildExportScript(a: {
24
+ template: string;
25
+ vmid: number;
26
+ store?: string;
27
+ }): string;
28
+ /** `qm config` text to a map (key: value, split on the first ": "). */
29
+ export declare function parseQmConfig(text: string): Record<string, string>;
30
+ /** Python `urllib.parse.unquote` for the percent-encoded description Proxmox stores. */
31
+ export declare function pyUnquote(s: string): string;
32
+ export interface TemplateJsonInput {
33
+ template: string;
34
+ vmid: number;
35
+ qcowSha256: string;
36
+ qcowBytes: number;
37
+ virtualBytes: number;
38
+ qmConfig: string;
39
+ /** keys like result_pass, disa_result_fail */
40
+ scan: Record<string, number>;
41
+ receiptSha256: string | null;
42
+ manifestSha256: string | null;
43
+ publishedMs: number;
44
+ store?: string;
45
+ }
46
+ export declare function buildTemplateJson(i: TemplateJsonInput): Json;
47
+ /** Receipt-summary counts as the summary.txt-style keys the scripts publish (result_pass, disa_result_fail, ...). */
48
+ export declare function scanFromSummary(summary: {
49
+ counts: Record<string, number>;
50
+ disa?: {
51
+ counts: Record<string, number>;
52
+ };
53
+ } | null | undefined): Record<string, number>;
54
+ export interface IndexEntry {
55
+ name: string;
56
+ build_vmid: number;
57
+ qcow2: string;
58
+ qcow2_sha256: string;
59
+ qcow2_bytes: number;
60
+ qcow2_signature: string;
61
+ template_json: string;
62
+ template_json_sha256: string;
63
+ template_json_signature: string;
64
+ published: string;
65
+ }
66
+ export interface StigIndex {
67
+ schema: string;
68
+ signing_key_fpr: string;
69
+ latest: string;
70
+ retention: number;
71
+ versions: IndexEntry[];
72
+ }
73
+ /** The index entry for one published template is verified when it lists the template (the node-side signature check is separate). */
74
+ export declare function indexHas(index: Json | null, template: string): boolean;
75
+ export declare function parseIndex(text: string | null): Json;
76
+ /** Every name in an existing index.json must be a template name before it is copied or reaches `rm -rf`. */
77
+ export declare function assertIndexNames(index: Json): void;
78
+ /** The index position the template would take (0 = newest). */
79
+ export declare function indexRank(old: Json, template: string): number;
80
+ export declare function buildIndex(a: {
81
+ old: Json;
82
+ template: string;
83
+ vmid: number;
84
+ qcowSha256: string;
85
+ qcowBytes: number;
86
+ templateJsonSha256: string;
87
+ publishedMs: number;
88
+ keep?: number;
89
+ }): {
90
+ index: StigIndex;
91
+ dropped: string[];
92
+ };
93
+ export declare function buildPublishReceipt(a: {
94
+ template: Json;
95
+ index: StigIndex;
96
+ buildNode: string;
97
+ pruned: string[];
98
+ }): Json;
99
+ export declare function buildSyncReceipt(a: {
100
+ template: string;
101
+ node: string;
102
+ vmid: number;
103
+ claim: string;
104
+ mode: string;
105
+ qcowSha256: string;
106
+ thin: string;
107
+ lvSizeBytes: number;
108
+ mappedPercent: number;
109
+ syncedMs: number;
110
+ }): Json;
111
+ export declare function validateTemplateJson(t: unknown, template: string): Json;
112
+ /** The detached `qm create` + `qm template` script (sync.sh python heredoc). Bridge has no VLAN tag: the tag belongs to clones. */
113
+ export declare function buildQmCreateScript(a: {
114
+ template: Json;
115
+ vmid: number;
116
+ thin: string;
117
+ bridge: string;
118
+ store?: string;
119
+ }): string;
120
+ export {};
121
+ //# sourceMappingURL=dist.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dist.d.ts","sourceRoot":"","sources":["../../../src/stig/dist.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,234 @@
1
+ /**
2
+ * STIG image distribution: pure builders for the published artifacts (export script, template.json, index.json,
3
+ * `qm create` script, receipts). Every output mirrors the ct-meta `rhel8-stig-template` scripts (publish.sh,
4
+ * sync.sh) and `tools/stig-parity.mjs dist` diffs them against those scripts. No I/O here.
5
+ */
6
+ import { STIG_EVIDENCE_FPR, STIG_STORE, STIG_IMAGE_KEEP_VERSIONS } from "./nodes.js";
7
+ export const TEMPLATE_JSON_SCHEMA = "calltelemetry-rhel8-stig-template/v1";
8
+ export const INDEX_SCHEMA = "calltelemetry-rhel8-stig-index/v1";
9
+ export const PUBLISH_RECEIPT_SCHEMA = "calltelemetry-rhel8-stig-publish-receipt/v1";
10
+ export const SYNC_RECEIPT_SCHEMA = "calltelemetry-rhel8-stig-sync-receipt/v1";
11
+ export const EXPORT_DONE = "PUBLISH_EXPORT_DONE";
12
+ export const SYNC_DONE = "SYNC_CREATE_DONE";
13
+ export const DISK_OPTIONS = "cache=none,discard=on,iothread=1,replicate=0";
14
+ export const EFIDISK = "efitype=4m,ms-cert=2023k,pre-enrolled-keys=1";
15
+ export const TPM_NOTE = "version=v2.0 (fresh per clone)";
16
+ const TEMPLATE_NAME = /^rhel810-stig-\d{8}-\d{4}$/;
17
+ const SHA256 = /^[a-f0-9]{64}$/;
18
+ export function assertTemplateName(name) {
19
+ if (!TEMPLATE_NAME.test(name))
20
+ throw new Error("template name must look like rhel810-stig-YYYYMMDD-VMID");
21
+ return name;
22
+ }
23
+ /** Python `json.dump(obj, indent=2, sort_keys=True)` plus the trailing newline the scripts add. */
24
+ export function pyJson(value) {
25
+ const norm = (v) => (Array.isArray(v) ? v.map(norm) : v && typeof v === "object" ? Object.fromEntries(Object.keys(v).sort().map((k) => [k, norm(v[k])])) : v);
26
+ return `${JSON.stringify(norm(value), null, 2).replace(/[\u0080-\uFFFF]/g, (c) => `\\u${c.charCodeAt(0).toString(16).padStart(4, "0")}`)}\n`;
27
+ }
28
+ /** Python `datetime.now(utc).strftime("%Y-%m-%dT%H:%M:%SZ")`. */
29
+ export const utcStamp = (ms) => new Date(ms).toISOString().replace(/\.\d{3}Z$/, "Z");
30
+ /** Python `shlex.quote`. */
31
+ export function shlexQuote(s) {
32
+ if (s === "")
33
+ return "''";
34
+ return /[^A-Za-z0-9_@%+=:,./-]/.test(s) ? `'${s.replace(/'/g, `'"'"'`)}'` : s;
35
+ }
36
+ /* ------------------------------------------------------------------ export */
37
+ export const baseLv = (vmid) => `pve/base-${vmid}-disk-1`;
38
+ /**
39
+ * The detached export script (publish.sh REMOTE heredoc). The base LV must be read-only; it is activated with -K only
40
+ * when inactive and deactivated afterwards, so it is never made writable.
41
+ */
42
+ export function buildExportScript(a) {
43
+ const store = a.store ?? STIG_STORE.mount;
44
+ const { template: tpl, vmid } = a;
45
+ return [
46
+ "set -euo pipefail",
47
+ `lv=${baseLv(vmid)}`,
48
+ `out=${store}/import/${tpl}.qcow2`,
49
+ `attr_before="$(lvs --noheadings -o lv_attr $lv | tr -d ' ')"`,
50
+ "activated=0",
51
+ `case "$attr_before" in ?r*) ;; *) echo "base LV is not read-only ($attr_before)"; exit 1;; esac`,
52
+ `if [ "$(lvs --noheadings -o lv_active $lv | tr -d ' ')" != active ]; then lvchange -ay -K $lv; activated=1; fi`,
53
+ `rm -f "$out.partial"`,
54
+ `qemu-img convert -f raw -O qcow2 -c -m 4 "/dev/$lv" "$out.partial"`,
55
+ `qemu-img check "$out.partial" >/dev/null`,
56
+ `mv "$out.partial" "$out"`,
57
+ `[ "$activated" = 1 ] && lvchange -an $lv`,
58
+ `attr_after="$(lvs --noheadings -o lv_attr $lv | tr -d ' ')"`,
59
+ `echo "lv_attr before=$attr_before after=$attr_after activated_by_publish=$activated"`,
60
+ `qemu-img info --output=json "$out" > "${store}/rhel8-stig/${tpl}.qemu-img-info.json"`,
61
+ `sha256sum "$out" | cut -d' ' -f1 > "${store}/rhel8-stig/${tpl}.qcow2.sha256"`,
62
+ `echo ${EXPORT_DONE}`,
63
+ "",
64
+ ].join("\n");
65
+ }
66
+ /* ------------------------------------------------------------ template.json */
67
+ /** `qm config` text to a map (key: value, split on the first ": "). */
68
+ export function parseQmConfig(text) {
69
+ const cfg = {};
70
+ for (const line of text.split("\n")) {
71
+ if (line === "")
72
+ continue;
73
+ const i = line.indexOf(": ");
74
+ if (i < 0)
75
+ cfg[line] = "";
76
+ else
77
+ cfg[line.slice(0, i)] = line.slice(i + 2);
78
+ }
79
+ return cfg;
80
+ }
81
+ /** Python `urllib.parse.unquote` for the percent-encoded description Proxmox stores. */
82
+ export function pyUnquote(s) {
83
+ return s.replace(/(?:%[0-9A-Fa-f]{2})+/g, (m) => {
84
+ try {
85
+ return decodeURIComponent(m);
86
+ }
87
+ catch {
88
+ return Buffer.from(m.replace(/%/g, ""), "hex").toString("latin1");
89
+ }
90
+ });
91
+ }
92
+ const need = (cfg, key) => {
93
+ const v = cfg[key];
94
+ if (v === undefined)
95
+ throw new Error(`qm config of the template has no ${key}`);
96
+ return v;
97
+ };
98
+ const intOf = (v, what) => {
99
+ if (!/^\d+$/.test(v))
100
+ throw new Error(`${what} is not an integer`);
101
+ return Number.parseInt(v, 10);
102
+ };
103
+ export function buildTemplateJson(i) {
104
+ const cfg = parseQmConfig(i.qmConfig);
105
+ const hardware = {
106
+ bios: need(cfg, "bios"), machine: need(cfg, "machine"), cpu: need(cfg, "cpu"), cores: intOf(need(cfg, "cores"), "cores"),
107
+ sockets: intOf(cfg.sockets ?? "1", "sockets"), memory_mb: intOf(need(cfg, "memory"), "memory"), scsihw: need(cfg, "scsihw"),
108
+ ostype: need(cfg, "ostype"), agent: cfg.agent ?? "1", numa: cfg.numa ?? "0",
109
+ disk_bytes: i.virtualBytes, disk_options: DISK_OPTIONS, efidisk: EFIDISK, tpm: TPM_NOTE, cloudinit: "ide0",
110
+ tags: cfg.tags ?? "", net0_model: "virtio",
111
+ };
112
+ return {
113
+ schema: TEMPLATE_JSON_SCHEMA, name: i.template, build_vmid: i.vmid, published: utcStamp(i.publishedMs),
114
+ description: pyUnquote(cfg.description ?? ""),
115
+ image: { file: `${i.store ?? STIG_STORE.name}:import/${i.template}.qcow2`, format: "qcow2", compressed: true, sha256: i.qcowSha256, bytes: i.qcowBytes, virtual_bytes: i.virtualBytes },
116
+ hardware, scan: i.scan, receipt_sha256: i.receiptSha256, evidence_manifest_sha256: i.manifestSha256,
117
+ };
118
+ }
119
+ /** Receipt-summary counts as the summary.txt-style keys the scripts publish (result_pass, disa_result_fail, ...). */
120
+ export function scanFromSummary(summary) {
121
+ const scan = {};
122
+ if (!summary)
123
+ return scan;
124
+ for (const [k, v] of Object.entries(summary.counts))
125
+ scan[`result_${k}`] = v;
126
+ if (summary.disa)
127
+ for (const [k, v] of Object.entries(summary.disa.counts))
128
+ scan[`disa_result_${k}`] = v;
129
+ return scan;
130
+ }
131
+ /** The index entry for one published template is verified when it lists the template (the node-side signature check is separate). */
132
+ export function indexHas(index, template) {
133
+ return Array.isArray(index?.versions) && index.versions.some((v) => v?.name === template);
134
+ }
135
+ export function parseIndex(text) {
136
+ if (!text || !text.trim())
137
+ return {};
138
+ const parsed = JSON.parse(text);
139
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
140
+ throw new Error("index.json is not an object");
141
+ return parsed;
142
+ }
143
+ /** Every name in an existing index.json must be a template name before it is copied or reaches `rm -rf`. */
144
+ export function assertIndexNames(index) {
145
+ if (index.versions === undefined)
146
+ return;
147
+ if (!Array.isArray(index.versions))
148
+ throw new Error("index.json versions is not a list");
149
+ for (const v of index.versions) {
150
+ if (typeof v?.name !== "string" || !TEMPLATE_NAME.test(v.name))
151
+ throw new Error(`index.json lists an invalid template name (${JSON.stringify(String(v?.name)).slice(0, 60)}); refusing to rewrite it`);
152
+ }
153
+ }
154
+ /** The index position the template would take (0 = newest). */
155
+ export function indexRank(old, template) {
156
+ const names = new Set([template, ...(Array.isArray(old?.versions) ? old.versions.map((v) => v.name) : [])]);
157
+ return [...names].sort().reverse().indexOf(template);
158
+ }
159
+ export function buildIndex(a) {
160
+ const keep = a.keep ?? STIG_IMAGE_KEEP_VERSIONS;
161
+ const old = Array.isArray(a.old?.versions) ? a.old.versions : [];
162
+ const entry = {
163
+ name: a.template, build_vmid: a.vmid, qcow2: `import/${a.template}.qcow2`, qcow2_sha256: a.qcowSha256, qcow2_bytes: a.qcowBytes,
164
+ qcow2_signature: `rhel8-stig/${a.template}/${a.template}.qcow2.asc`, template_json: `rhel8-stig/${a.template}/template.json`,
165
+ template_json_sha256: a.templateJsonSha256, template_json_signature: `rhel8-stig/${a.template}/template.json.asc`, published: utcStamp(a.publishedMs),
166
+ };
167
+ const versions = [entry, ...old.filter((v) => v.name !== a.template)];
168
+ versions.sort((x, y) => (x.name < y.name ? 1 : x.name > y.name ? -1 : 0)); // reverse by name, as Python's sort(reverse=True)
169
+ const kept = versions.slice(0, keep);
170
+ return {
171
+ index: { schema: INDEX_SCHEMA, signing_key_fpr: STIG_EVIDENCE_FPR, latest: kept[0].name, retention: keep, versions: kept },
172
+ dropped: versions.slice(keep).map((v) => v.name),
173
+ };
174
+ }
175
+ /* ----------------------------------------------------------------- receipts */
176
+ export function buildPublishReceipt(a) {
177
+ const t = a.template;
178
+ const i = a.index;
179
+ return {
180
+ schema: PUBLISH_RECEIPT_SCHEMA, template: t.name, build_node: a.buildNode, published: t.published,
181
+ qcow2_sha256: t.image.sha256, qcow2_bytes: t.image.bytes, virtual_bytes: t.image.virtual_bytes,
182
+ template_json_sha256: i.versions[0].name === t.name ? i.versions[0].template_json_sha256 : null,
183
+ signing_key_fpr: i.signing_key_fpr, latest: i.latest, versions: i.versions.map((v) => v.name), pruned: a.pruned, scan: t.scan,
184
+ };
185
+ }
186
+ export function buildSyncReceipt(a) {
187
+ return {
188
+ schema: SYNC_RECEIPT_SCHEMA, template: a.template, node: a.node, vmid: a.vmid, claim: a.claim, mode: a.mode, qcow2_sha256: a.qcowSha256,
189
+ verified: Object.fromEntries(["index_signature", "template_json_signature", "qcow2_signature", "qcow2_sha256", "template_json_sha256"].map((k) => [k, true])),
190
+ thin_storage: a.thin, disk_virtual_bytes: Math.trunc(a.lvSizeBytes), disk_mapped_bytes: Math.trunc(a.lvSizeBytes * a.mappedPercent / 100),
191
+ disk_mapped_percent: a.mappedPercent, synced: utcStamp(a.syncedMs),
192
+ };
193
+ }
194
+ /* ---------------------------------------------------------------- qm create */
195
+ export function validateTemplateJson(t, template) {
196
+ const bad = (m) => { throw new Error(`template.json refused: ${m}`); };
197
+ if (!t || typeof t !== "object")
198
+ return bad("not an object");
199
+ const j = t;
200
+ if (j.schema !== TEMPLATE_JSON_SCHEMA)
201
+ bad(`schema is not ${TEMPLATE_JSON_SCHEMA}`);
202
+ if (j.name !== template)
203
+ bad("name does not match the requested template");
204
+ const img = j.image;
205
+ if (!img || img.file !== `${STIG_STORE.name}:import/${template}.qcow2` || img.format !== "qcow2" || !SHA256.test(img.sha256))
206
+ bad("image block is not the published qcow2");
207
+ const h = j.hardware;
208
+ if (!h || typeof h !== "object")
209
+ return bad("hardware missing");
210
+ for (const k of ["bios", "machine", "cpu", "scsihw", "ostype", "agent", "numa", "disk_options", "efidisk"])
211
+ if (typeof h[k] !== "string" || h[k] === "")
212
+ bad(`hardware.${k} missing`);
213
+ for (const k of ["cores", "sockets", "memory_mb"])
214
+ if (!Number.isInteger(h[k]) || h[k] < 1)
215
+ bad(`hardware.${k} must be a positive integer`);
216
+ if (typeof h.tags !== "string" || typeof j.description !== "string")
217
+ bad("tags or description missing");
218
+ return j;
219
+ }
220
+ /** The detached `qm create` + `qm template` script (sync.sh python heredoc). Bridge has no VLAN tag: the tag belongs to clones. */
221
+ export function buildQmCreateScript(a) {
222
+ const t = a.template;
223
+ const h = t.hardware;
224
+ const store = a.store ?? STIG_STORE.name;
225
+ const img = String(t.image.file).split(":").slice(1).join(":");
226
+ const args = ["qm", "create", String(a.vmid), "--name", t.name, "--bios", h.bios, "--machine", h.machine, "--cpu", h.cpu,
227
+ "--cores", String(h.cores), "--sockets", String(h.sockets), "--memory", String(h.memory_mb),
228
+ "--scsihw", h.scsihw, "--ostype", h.ostype, "--agent", h.agent, "--numa", h.numa,
229
+ "--net0", `virtio,bridge=${a.bridge}`, "--tags", h.tags, "--description", t.description,
230
+ "--efidisk0", `${a.thin}:1,${h.efidisk}`, "--ide0", `${a.thin}:cloudinit`,
231
+ "--scsi0", `${a.thin}:0,import-from=${store}:${img},${h.disk_options}`, "--boot", "order=scsi0"];
232
+ return `set -euo pipefail\n${args.map(shlexQuote).join(" ")}\nqm template ${a.vmid}\necho ${SYNC_DONE}\n`;
233
+ }
234
+ //# sourceMappingURL=dist.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dist.js","sourceRoot":"","sources":["../../../src/stig/dist.ts"],"names":[],"mappings":"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"}