4.4 Build and SBOM

On this page you prove that the hermetic pipeline produced an application image and a CycloneDX SBOM of what went into it.

Track 4 is the hermetic build. This is the fourth page. The image is an OpenShift BuildConfig in namespace lw-poc-build, started from the pipeline. The SBOM is written by Task syft-sbom-rhtpa. Showroom may not have syft on PATH (syft_baked=false). You use the file that Task writes. Konflux often builds with Buildah. This cluster does not. oc tag into staging is Track 6. Keyless verify of the application image is Track 5.

Why this control exists

A trusted software supply chain needs the artifact and an inventory of what went into it. BuildConfig emits ImageStream spring-boot-lw-poc. The pipeline writes CycloneDX. That SBOM includes the Lightwell Network GAV you pinned. The known-bad Dockerfile still failing is the proof that hermetic is required: a public FROM cannot build once 4.1 through 4.3 are in place.

After 4.3, an HTTPS Route from lw-poc-build hangs. The PipelineRun therefore uses the in-cluster Gitea URL and the in-cluster Trusted Artifact Signer URLs. 5.1 Sign reads .tekton/pipelinerun.yaml from Gitea, so you commit the filled file before oc create. A run created only from a local file leaves the placeholders on origin, and 5.1 fails even when this run succeeds.

Lightwell Clearinghouse Premier does not change the builder. A member GAV shows up in the same SBOM that Track 7 ingests.

Wheels typically ship SPDX. This Check produces CycloneDX from the Maven and syft path. Trusted Profile Analyzer accepts either format as the system of record in Track 7.

In a customer engagement, CI produces a signed image and an SBOM. This page proves the image landed and the SBOM exists. Admission and GitOps promotion are later tracks.

Learning objectives

By the end of this module, you will be able to:

  • Fill the PipelineRun with in-cluster URLs and commit that file before you create the run

  • Produce ImageStream spring-boot-lw-poc and a CycloneDX SBOM from Task syft-sbom-rhtpa

  • Show that a build of Dockerfile.known-bad fails, then restore the BuildConfig to Dockerfile

  • Explain that Network and Premier libraries appear as GAV components in that SBOM

BuildConfig, not Buildah

The control a customer calls "the Konflux build" is often a Buildah task. Here the pipeline runs oc start-build --from-dir against a Binary BuildConfig. Adding a Buildah task fails the Check. The term map is Appendix: Konflux mapping.

The block below is that Buildah task, pointed at an image this cluster does not build. A paste of it fails the Check.

# Worked example ONLY — Konflux Buildah path. This cluster scores BuildConfig + syft.
- name: buildah
  taskRef:
    name: buildah
  params:
    - name: IMAGE
      value: example.invalid/not-your-app:latest

Your change

Apply the Pipeline you wired on 4.2, in the build namespace. REPO_URL is student_repo_internal_url, the in-cluster Gitea Service. Success is the Pipeline object present in that namespace, and the internal URL printed beside it.

Apply the Pipeline
BUILD_NS="$(oc -n gitea get configmap demo-userinfo-gitea -o jsonpath='{.data.student_build_namespace}')"
REPO_URL="$(oc -n gitea get configmap demo-userinfo-gitea -o jsonpath='{.data.student_repo_internal_url}')"
echo "BUILD_NS=${BUILD_NS}"
echo "REPO_URL=${REPO_URL}"
oc -n "${BUILD_NS}" apply -f /tmp/spring-boot-lw-poc/.tekton/rbac.yaml
oc -n "${BUILD_NS}" apply -f /tmp/spring-boot-lw-poc/.tekton/pipeline.yaml

Edit .tekton/pipelinerun.yaml. Replace STUDENT_REPO_URL_PLACEHOLDER with student_repo_internal_url (http://gitea.gitea.svc:3000/…). The HTTPS Route is blocked after 4.3. Replace <lab-namespace> with lw-poc-build. Fill Fulcio, Rekor, and TUF from ConfigMap demo-userinfo-rhtas in namespace trusted-artifact-signer, using fulcio_internal_url, rekor_internal_url, and tuf_internal_url. Those are in-cluster Services. The Route hints (fulcio_url_hint and its siblings) fail after 4.3. Leave the syft rhtpa-url empty. Track 7 uploads the SBOM from Showroom.

5.1 reads this file from Gitea, not from the live PipelineRun. oc create alone leaves the placeholder on origin. Commit and push before you create the run. Success is a push of .tekton/pipelinerun.yaml with the placeholders gone.

Commit the filled PipelineRun
cd /tmp/spring-boot-lw-poc
git add .tekton/pipelinerun.yaml
git status
git diff --cached
git commit -m "Fill PipelineRun in-cluster repo, namespace, and RHTAS URLs"
git push origin HEAD

Create the PipelineRun from that file. Success is a run whose tasks openshift-build and syft-sbom-rhtpa succeed. ACS may fail or soft-skip. This Check is the image and the SBOM. ACS is Track 7. cosign verify is Track 5.

Create the PipelineRun
BUILD_NS="$(oc -n gitea get configmap demo-userinfo-gitea -o jsonpath='{.data.student_build_namespace}')"
oc -n "${BUILD_NS}" create -f /tmp/spring-boot-lw-poc/.tekton/pipelinerun.yaml
oc -n "${BUILD_NS}" get pipelinerun -w
PipelineRun task list with openshift-build and syft-sbom-rhtpa Succeeded

The capture is tkn pipelinerun describe for a run in lw-poc-build. Read openshift-build and syft-sbom-rhtpa as Succeeded. acs-image-check may show Failed on that capture. This page does not grade ACS. The task list is newest-first, so clone appears at the bottom.

Check

Success is ImageStream spring-boot-lw-poc in the build namespace, a PipelineRun, and a succeeded TaskRun for syft-sbom-rhtpa. The SBOM file lands in ConfigMap lab-sbom-cyclonedx. Track 7 copies it from there.

BUILD_NS="$(oc -n gitea get configmap demo-userinfo-gitea -o jsonpath='{.data.student_build_namespace}')"
oc -n "${BUILD_NS}" get imagestream spring-boot-lw-poc
oc -n "${BUILD_NS}" get pipelinerun
# SBOM workspace / Task result — name may vary; confirm the syft task Succeeded
oc -n "${BUILD_NS}" get tr -l tekton.dev/pipelineTask=syft-sbom-rhtpa

The known-bad path is a separate build of Dockerfile.known-bad. oc start-build has no -DdockerfilePath, so you patch the BuildConfig, start a binary build, and then restore dockerfilePath to Dockerfile. The first registry-1.docker.io timeout (dial tcp …:443: i/o timeout) is the failure. Press Ctrl-C. That stops --follow only. OpenShift keeps retrying the pull for many minutes and queues later Binary builds, including the PipelineRuns on 5.2 and 7.2. Cancel the Build, then restore dockerfilePath.

Success is a build that fails on the public pull, a cancelled Build, and a BuildConfig whose dockerfilePath is Dockerfile again.

Fail the known-bad Dockerfile, then restore the good path
BUILD_NS="$(oc -n gitea get configmap demo-userinfo-gitea -o jsonpath='{.data.student_build_namespace}')"
cd /tmp/spring-boot-lw-poc
oc -n "${BUILD_NS}" patch bc spring-boot-lw-poc --type=json \
  -p '[{"op":"replace","path":"/spec/strategy/dockerStrategy/dockerfilePath","value":"Dockerfile.known-bad"}]'
# Ctrl-C after the first registry-1.docker.io timeout — do not wait out retries.
oc -n "${BUILD_NS}" start-build spring-boot-lw-poc --from-dir=. --follow || true
# Ctrl-C does not cancel the Build. Cancel it so later oc start-build / PipelineRuns are not queued.
oc -n "${BUILD_NS}" cancel-build bc/spring-boot-lw-poc
oc -n "${BUILD_NS}" patch bc spring-boot-lw-poc --type=json \
  -p '[{"op":"replace","path":"/spec/strategy/dockerStrategy/dockerfilePath","value":"Dockerfile"}]'

The public FROM and the curl fail because of 4.1 through 4.3. Leave the BuildConfig on Dockerfile. Leave no known-bad Build in Running.

Fill the report

The Job also grades ConfigMap report-11-build-sbom key image_builder. Set it to buildconfig. Empty or REPLACE_ME fails even if cluster state is correct. Do not copy validate-docs.

oc -n lw-poc-validate edit configmap report-11-build-sbom

The scored Check is Job validate-11-build-sbom in lw-poc-validate. Direct nav URLs still work (honor system). Unlimited retries. There is no Solve.

Run the Validate Job
oc -n lw-poc-validate delete job validate-11-build-sbom --ignore-not-found
TPL='job-11.yaml'
oc -n lw-poc-validate get configmap validate-job-templates \
  -o go-template="{{ index .data \"${TPL}\" }}" | oc create -f -
oc -n lw-poc-validate logs -f job/validate-11-build-sbom

Expect CHECK PASSED: before you continue. CHECK FAILED: names the object to fix. Delete the Job and create it again as often as you need.

The Validate Job grades the image and the SBOM. Track 5 still opens if you skip this page. oc tag into staging is Track 6. A Clearinghouse Premier member GAV would appear in the same CycloneDX document.

Official documentation

Key takeaways

  • The build on this cluster is a BuildConfig plus Tekton, and the SBOM includes the Lightwell pin.

  • The filled PipelineRun is committed to Gitea before the run is created.

  • The known-bad Dockerfile fails, and the BuildConfig is restored to Dockerfile before you leave the page.