docs consolidation and others
This commit is contained in:
60
docs/modules/airgap/runbooks/av-scan.md
Normal file
60
docs/modules/airgap/runbooks/av-scan.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# AV/YARA Scan Runbook (AIRGAP-AV-510-011)
|
||||
|
||||
Purpose: ensure every offline-kit bundle is scanned pre-publish and post-ingest, with deterministic reports and optional signatures.
|
||||
|
||||
## Inputs
|
||||
- Bundle directory containing `manifest.json` and payload files.
|
||||
- AV scanner (e.g., ClamAV) and optional YARA rule set available locally (no network).
|
||||
|
||||
## Steps (offline)
|
||||
1. Scan all bundle files:
|
||||
```bash
|
||||
clamscan -r --max-filesize=2G --max-scansize=4G --no-summary bundle/ > reports/av-scan.txt
|
||||
```
|
||||
2. Convert to structured report:
|
||||
```bash
|
||||
python - <<'PY'
|
||||
import hashlib, json, pathlib, sys
|
||||
root = pathlib.Path("bundle")
|
||||
report = {
|
||||
"scanner": "clamav",
|
||||
"scannerVersion": "1.4.1",
|
||||
"startedAt": "2025-12-02T00:02:00Z",
|
||||
"completedAt": "2025-12-02T00:04:30Z",
|
||||
"status": "clean",
|
||||
"artifacts": [],
|
||||
"errors": []
|
||||
}
|
||||
for path in root.glob("**/*"):
|
||||
if path.is_file():
|
||||
h = hashlib.sha256(path.read_bytes()).hexdigest()
|
||||
report["artifacts"].append({
|
||||
"path": str(path.relative_to(root)),
|
||||
"sha256": h,
|
||||
"result": "clean",
|
||||
"yaraRules": []
|
||||
})
|
||||
json.dump(report, sys.stdout, indent=2)
|
||||
PY
|
||||
```
|
||||
3. Validate report against schema:
|
||||
```bash
|
||||
jq empty --argfile schema docs/modules/airgap/schemas/av-report.schema.json 'input' < docs/modules/airgap/samples/av-report.sample.json >/dev/null
|
||||
```
|
||||
4. Optionally sign report (detached):
|
||||
```bash
|
||||
openssl dgst -sha256 -sign airgap-av-key.pem reports/av-report.json > reports/av-report.sig
|
||||
```
|
||||
5. Update `manifest.json`:
|
||||
- Set `avScan.status` to `clean` or `findings`.
|
||||
- `avScan.reportPath` and `avScan.reportSha256` must match the generated report.
|
||||
|
||||
## Acceptance checks
|
||||
- Report validates against `docs/modules/airgap/schemas/av-report.schema.json`.
|
||||
- `manifest.json` hashes updated and verified via `src/AirGap/scripts/verify-manifest.sh`.
|
||||
- If any artifact result is `malicious`/`suspicious`, bundle must be rejected and re-scanned after remediation.
|
||||
|
||||
## References
|
||||
- Manifest schema: `docs/modules/airgap/schemas/manifest.schema.json`
|
||||
- Sample report: `docs/modules/airgap/samples/av-report.sample.json`
|
||||
- Manifest verifier: `src/AirGap/scripts/verify-manifest.sh`
|
||||
57
docs/modules/airgap/runbooks/import-verify.md
Normal file
57
docs/modules/airgap/runbooks/import-verify.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Offline Kit Import Verification Runbook
|
||||
|
||||
This runbook supports AIRGAP-MANIFEST-510-010, AIRGAP-REPLAY-510-013, and AIRGAP-VERIFY-510-014. It validates bundles fully offline and enforces replay depth.
|
||||
|
||||
## Replay depth levels (manifest `replayPolicy`)
|
||||
- `hash-only`: verify manifest/bundle digests, staleness window, optional signature.
|
||||
- `full-recompute`: hash-only + every chunk hash + AV report hash.
|
||||
- `policy-freeze`: full-recompute + manifest policies must include the sealed policy hash (prevents imports with drifting policy/graph material).
|
||||
|
||||
## Quick steps
|
||||
|
||||
```bash
|
||||
src/AirGap/scripts/verify-kit.sh \
|
||||
--manifest offline-kit/manifest.json \
|
||||
--bundle offline-kit/bundle.tar.gz \
|
||||
--signature offline-kit/manifest.sig --pubkey offline-kit/manifest.pub.pem \
|
||||
--av-report offline-kit/reports/av-report.json \
|
||||
--receipt offline-kit/receipts/ingress.json \
|
||||
--sealed-policy-hash "aa55..." \
|
||||
--depth policy-freeze
|
||||
```
|
||||
|
||||
## What the script enforces
|
||||
1) Manifest & bundle digests match (`hashes.*`).
|
||||
2) Optional manifest signature is valid (OpenSSL).
|
||||
3) Staleness: `createdAt` must be within `stalenessWindowHours` of `--now` (defaults to UTC now).
|
||||
4) AV: `avScan.status` must not be `findings`; if `reportSha256` is present, the provided report hash must match.
|
||||
5) Chunks (full-recompute/policy-freeze): every `chunks[].path` exists relative to the manifest and matches its recorded SHA-256.
|
||||
6) Policy-freeze: `--sealed-policy-hash` must appear in `policies[].sha256`.
|
||||
7) Optional: `--expected-graph-sha` checks the graph chunk hash; `--receipt` reuses `verify-receipt.sh` to bind the receipt to the manifest/bundle hashes.
|
||||
|
||||
Exit codes: hash mismatch (3/4), staleness (5), AV issues (6–8), chunk drift (9–10), graph mismatch (11), policy drift (12–13), bad depth (14).
|
||||
|
||||
## Controller verify endpoint (server-side guard)
|
||||
|
||||
`POST /system/airgap/verify` (scope `airgap:verify`) expects `VerifyRequest`:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"depth": "PolicyFreeze",
|
||||
"manifestSha256": "...",
|
||||
"bundleSha256": "...",
|
||||
"computedManifestSha256": "...", // from offline verifier
|
||||
"computedBundleSha256": "...",
|
||||
"manifestCreatedAt": "2025-12-02T00:00:00Z",
|
||||
"stalenessWindowHours": 168,
|
||||
"bundlePolicyHash": "aa55...",
|
||||
"sealedPolicyHash": "aa55..." // optional, controller fills from state if omitted
|
||||
}
|
||||
```
|
||||
|
||||
The controller applies the same replay rules and returns `{ "valid": true|false, "reason": "..." }`.
|
||||
|
||||
## References
|
||||
- Schema: `docs/modules/airgap/schemas/manifest.schema.json`
|
||||
- Samples: `docs/modules/airgap/samples/offline-kit-manifest.sample.json`, `docs/modules/airgap/samples/av-report.sample.json`, `docs/modules/airgap/samples/receipt.sample.json`
|
||||
- Scripts: `src/AirGap/scripts/verify-kit.sh`, `src/AirGap/scripts/verify-manifest.sh`, `src/AirGap/scripts/verify-receipt.sh`
|
||||
39
docs/modules/airgap/runbooks/quarantine-investigation.md
Normal file
39
docs/modules/airgap/runbooks/quarantine-investigation.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# AirGap Quarantine Investigation Runbook
|
||||
|
||||
## Purpose
|
||||
Quarantine preserves failed bundle imports for offline forensic analysis. It keeps the original bundle and the verification context (reason + logs) so operators can diagnose tampering, trust-root drift, or packaging issues without re-running in an online environment.
|
||||
|
||||
## Location & Structure
|
||||
Default root: `/updates/quarantine`
|
||||
|
||||
Per-tenant layout:
|
||||
`/updates/quarantine/<tenantId>/<timestamp>-<reason>-<id>/`
|
||||
|
||||
Removal staging:
|
||||
`/updates/quarantine/<tenantId>/.removed/<quarantineId>/`
|
||||
|
||||
## Files in a quarantine entry
|
||||
- `bundle.tar.zst` - the original bundle as provided
|
||||
- `manifest.json` - bundle manifest (when available)
|
||||
- `verification.log` - validation step output (TUF/DSSE/Merkle/rotation/monotonicity, etc.)
|
||||
- `failure-reason.txt` - human-readable failure summary (reason + timestamp + metadata)
|
||||
- `quarantine.json` - structured metadata for listing/automation
|
||||
|
||||
## Investigation steps (offline)
|
||||
1. Identify the tenant and locate the quarantine root on the importer host.
|
||||
2. Pick the newest quarantine entry for the tenant (timestamp prefix).
|
||||
3. Read `failure-reason.txt` first to capture the top-level reason and metadata.
|
||||
4. Review `verification.log` for the precise failing step.
|
||||
5. If needed, extract and inspect `bundle.tar.zst` in an isolated workspace (no network).
|
||||
6. Decide whether the entry should be retained (for audit) or removed after investigation.
|
||||
|
||||
## Removal & Retention
|
||||
- Removal requires a human-provided reason (audit trail). Implementations should use the quarantine service’s remove operation which moves entries under `.removed/`.
|
||||
- Retention and quota controls are configured via `AirGap:Quarantine` settings (root, TTL, max size); TTL cleanup can remove entries older than the retention period.
|
||||
|
||||
## Common failure categories
|
||||
- `tuf:*` - invalid/expired metadata or snapshot hash mismatch
|
||||
- `dsse:*` - signature invalid or trust root mismatch
|
||||
- `merkle-*` - payload entry set invalid or empty
|
||||
- `rotation:*` - root rotation policy failure (dual approval, no-op rotation, etc.)
|
||||
- `version-non-monotonic:*` - rollback prevention triggered (force activation requires a justification)
|
||||
Reference in New Issue
Block a user