Skip to main content

Air-Gap Security & Compliance

Purpose: For security officers, provides package signing, SBOM generation, and chain-of-custody documentation.

Overview​

Air-gap artifacts carry all dependencies for a production Kubernetes cluster. This reference documents the security controls applied during build, transfer, and deployment.

Artifact Signing (Cosign)​

Packages are signed using Sigstore Cosign during the build phase in Zone A.

PropertyValue
Signing toolCosign
Key typeECDSA P-256
Signature format.sig file alongside the artifact
Key generationopencenter-airgap keygen

Verification in Zone C:

cosign verify-blob \
--key cosign.pub \
--signature zarf-package-*.tar.zst.sig \
zarf-package-*.tar.zst

The public key must be distributed through a separate trusted channel (not on the same media as the artifact).

SBOM (Software Bill of Materials)​

Zarf generates an SBOM for every package. The SBOM lists:

  • Every container image with tag and digest
  • Every binary with version and download source
  • Every Helm chart with version and repository
  • OS packages and Python wheels

Inspect the SBOM:

zarf package inspect zarf-package-*.tar.zst --sbom

SBOM format: SPDX JSON (Zarf default). Compatible with vulnerability scanners like Grype and Trivy.

Vulnerability Scanning​

The build pipeline runs Trivy against all container images:

SettingValue
ScannerTrivy
Severity thresholdHIGH, CRITICAL
PolicyFail build on HIGH or CRITICAL findings
DatabaseUpdated at build time (Zone A)

Run a manual scan:

trivy image --severity HIGH,CRITICAL <image-ref>

For SBOM-based scanning after build:

trivy sbom sbom.json --severity HIGH,CRITICAL

Checksum Integrity​

ArtifactChecksum methodFile
Zarf packageSHA-256package.sha256
Kubernetes binariesSHA-256 (upstream)*.sha256 from dl.k8s.io
Build manifestSHA-256 (in state file)build/.state.json

Generate and verify:

# Generate (Zone A)
sha256sum dist/zarf-package-*.tar.zst > dist/package.sha256

# Verify (Zone C)
sha256sum -c package.sha256

Chain-of-Custody​

For regulated environments, document the transfer path:

ZoneActionEvidence
Zone ABuild completedBuild log (logs/build-*.log), artifact-manifest.json
Zone APackage signedCosign signature file (.sig)
Zone A → Zone BCopied to mediapackage.sha256 recorded
Zone B → Zone CMedia deliveredChain-of-custody form (organization-specific)
Zone CChecksum verifiedsha256sum -c output
Zone CSignature verifiedcosign verify-blob output
Zone CPackage deployedZarf deploy log

Secrets Handling​

Secret typeStorageNotes
Cosign private keyBuild host only (Zone A)Never transferred to Zone C
SSH keysInjected at deploy timeNot embedded in the Zarf artifact
Registry credentialsNot requiredBastion registry runs without auth (local network only)

Secrets are never committed to Git. The build uses file-based injection from config/.secrets/ (gitignored).

Compliance Mapping​

ControlImplementation
Supply chain integrityCosign signatures + SHA-256 checksums
Software inventorySBOM (SPDX JSON) embedded in every package
Vulnerability managementTrivy scan at build time; fail on HIGH/CRITICAL
Version pinningAll versions in versions.env; no mutable tags
Audit trailBuild logs, state file, artifact manifest
Data-at-restZarf package is compressed but not encrypted; encrypt media if required by policy
Network isolationZone C has zero internet access; all traffic stays on local subnet

Encryption at Rest​

The Zarf package itself is not encrypted — it is a compressed tarball. If your security policy requires encryption of data at rest on transfer media, apply full-disk encryption (e.g., LUKS) to the USB drive or use an encrypted container:

# Example: create encrypted container for transfer
dd if=/dev/zero of=transfer.img bs=1M count=50000
cryptsetup luksFormat transfer.img
cryptsetup open transfer.img transfer
mkfs.ext4 /dev/mapper/transfer
mount /dev/mapper/transfer /mnt/transfer
cp dist/zarf-package-*.tar.zst /mnt/transfer/