Skip to content

Repeatable container compliance

Indian Hill Labs treats control application and control assessment as two halves of one versioned container profile. The scope is the image artifact: this process does not scan or make claims about the host, container runtime, orchestrator, or consuming information system.

Control-pack contract

The controlled catalog is compliance/container-compliance/catalog.json. Each profile records:

  • the security standard and container-image scope;
  • how controls are realized in reviewed build source;
  • the exact OpenSCAP content release, archive checksum, data stream, and XCCDF profile;
  • whether findings are report-only or enforced; and
  • which XCCDF result states block an enforced profile.

Each container binding records its operating-system family, Secure/Hardened/Validated Dockerfiles, pipeline image variable, output prefix, and ordered compliance profiles. The pipeline converts that binding into a digest-bound compliance plan. The plan hashes the Dockerfile that applied the controls and names the immutable scanner and target image digests.

For Chiseled images, controls are applied through base-image selection, Dockerfiles, and copied configuration. OpenSCAP remediation scripts are not executed in the final image: they generally assume a mutable host with a shell, package manager, services, and kernel.

Pipeline evaluation

The pipeline builds a pipeline-scoped external scanner from tools/openscap/Dockerfile. During that build, tools/openscap/install_content.py installs every data stream registered in the catalog and rejects any source whose SHA-512 does not match. The image includes OpenSCAP, Skopeo, and Umoci. The scan job then performs this operation for every catalog entry:

  1. Resolve the image only as repository@sha256:digest.
  2. Generate the catalogued compliance plan.
  3. Copy the exact image into an OCI layout without executing it.
  4. Unpack its filesystem with Umoci.
  5. Run every registered XCCDF profile through oscap-chroot.
  6. Retain XCCDF results, ARF, HTML, and normalized JSON.
  7. Bind those files into the assurance evidence manifest.

Each standard has two assessments. The raw assessment permanently retains the complete upstream server profile for visibility. The tailored assessment uses a versioned XCCDF Tailoring file and a reviewed applicability matrix to select only controls that OpenSCAP can truthfully evaluate in the immutable image filesystem. The upstream data stream is never edited.

The first reviewed Ubuntu 24.04 Chiseled matrices reconcile every upstream-selected rule:

Standard Upstream selections Tailored filesystem selections Explicit exclusions
ComplianceAsCode Ubuntu STIG 240 18 222
ComplianceAsCode CIS Level 1 Server 408 63 345

The matrices retain the two raw image results, references, severity, disposition, and rationale for every rule. Exclusions distinguish host inheritance, runtime inheritance, organization responsibility, absent components, compensating container controls, and content drift. A rule is never treated as passing merely because it was excluded.

The pinned ComplianceAsCode 0.1.81 Ubuntu STIG profile identifies itself as V1R1. The IHL control source of record remains the separately hashed DISA Ubuntu 24.04 V1R6 baseline and reviewed applicability profile. The matrix explicitly records the two non-one-to-one STIG identifier mappings instead of silently normalizing them.

Raw assessments remain in report-only mode for continuing upstream visibility. Tailored assessment mode is materialized from the selected candidate tier in the digest-bound plan:

Candidate tier Tailored CIS Level 1 Tailored STIG
Secure Report only Report only
Hardened Enforce Report only
Validated Enforce Enforce

Every profile still runs for every candidate. The mode controls the qualification boundary, not evidence collection. Scanner failures, missing or modified policy files, incomplete tailoring, missing evidence, fail, error, unknown, notchecked, and any result outside the reviewed expectation block an enforced profile. The exporter rejects evidence whose recorded mode does not match the selected tier.

Applying and reviewing controls

The applicability matrix is the review record; the generated XML is the executable delta. For each content or image-family revision:

  1. Run the raw upstream profile against each digest-bound candidate image.
  2. Reconcile every selected rule against the image, runtime, host, and organization boundary. Unreviewed rules are prohibited.
  3. Implement image controls in the Dockerfile, base selection, or copied configuration. Record inherited, not-applicable, and compensating controls with a precise rationale.
  4. Generate the XCCDF Tailoring file with ci/generate_xccdf_tailoring.py and commit both the matrix and deterministic XML.
  5. Run raw and tailored assessments together. The scanner copies the exact matrix and XML it used into the evidence artifact and verifies their catalogued SHA-256 hashes.
  6. Resolve unexpected tailored results through an image change or a reviewed matrix revision. Never change the expected result solely to make a pipeline green.
  7. Promote the tailored catalog entry from report-only to enforce and rerun the full pipeline.

This is how controls are applied without installing OpenSCAP, AIDE, a package manager, or host remediation tooling in the shipped Chiseled image. Supply-chain integrity, signed promotion, runtime least privilege, and host controls remain separately evidenced rather than being misrepresented as filesystem checks.

Adding a container such as NGINX

Adding an NGINX image requires the following reviewed changes:

  1. Add its Secure, Hardened, and Validated build sources and export its digest through a pipeline environment variable such as NGINX_IMAGE.
  2. Add the container to the catalog with that variable, its output prefix, and its operating-system profiles.
  3. Register an NGINX application profile when applicable. It can point to another data stream in a registered content archive without changing installer or scan logic. A genuinely different archive format requires a reviewed installer adapter.
  4. Add the NGINX configuration overlay or Dockerfile changes that apply the selected application controls.
  5. Run the raw profile in report-only mode and create an image-family-specific applicability matrix. A future NGINX profile must not inherit the .NET decision that the NGINX package is prohibited.
  6. Generate and run the tailored profile, implement remaining image controls, and record any narrowly scoped inherited or compensating decision.
  7. Assign the tailored profile to the appropriate tier only after the baseline produces the expected repeatable result. Keep raw profiles report-only for continuing visibility.

The catalog runner automatically evaluates every profile listed on every registered container. Adding another STIG therefore changes controlled catalog and build source, not the OpenSCAP execution logic.

Evidence boundary

The raw ARF and XCCDF files remain the authoritative scanner output. The normalized JSON is intended for pipeline gates and the assurance dashboard. Every evidence manifest includes the target digest, scanner digest, data-stream hash, Dockerfile hash, profile identity, matrix and tailoring hashes, result counts, expected-result deviations, and report hashes.

The CIS profile is described as a CIS-aligned engineering assessment. It is not a CIS-CAT result or a claim of CIS certification. Similarly, the STIG report covers the selected container-image boundary and is not a statement that the consuming FedRAMP or FISMA system is authorized or compliant.