7.1 SBOM system of record

Overview

The promoted app digest from 6.2 must exist in Red Hat Trusted Profile Analyzer (RHTPA) as CycloneDX. That document is the system of record for what shipped. This is not the Track 2 OSV read and not the GAV VEX blast-radius lab (7.2).

Showroom syft may be missing (syft_baked=false). Use the CycloneDX file from Task syft-sbom-rhtpa (4.4). Do not curl github.com for syft. Do not enable the live Red Hat CSAF importer as this gate.

Why it matters

Compliance starts from the promoted artifact, not a laptop folder. Trusted Profile Analyzer stores the CycloneDX SBOM for that digest. You should be able to find the Lightwell-pinned component in that document.

You ingest with an OIDC token (/api/v3/sbom) and confirm in the TPA UI. Organizations keep a system of record such as TPA or Dependency Track. RHDA on a laptop is the shift-left client of the same intelligence. It is not this lab.

Lightwell Clearinghouse Premier member SBOMs ingest on the same API. Do not enable the live CSAF importer here. OS-layer Hummingbird CSAF is a 7.2 callout.

What does it solve

  • No durable record of what the promoted digest contains

  • Curling GitHub for syft

  • Treating RHDA IDE as the system of record

TPA vs RHDA

TPA is the SBOM and advisory system of record. Red Hat Dependency Analytics (RHDA) is the laptop IDE shift-left client of the same intelligence. This lab is the TPA ingest. There is no IDE in Showroom.

Discover TPA (no secrets in git)

oc -n trusted-profile-analyzer get configmap rhtpa-ingestion-info \
  -o jsonpath='tpa_ui={.data.server_url}{"\n"}csaf_gate={.data.live_csaf_gate}{"\n"}'
oc -n trusted-profile-analyzer get configmap demo-userinfo-rhtpa \
  -o jsonpath='url={.data.rhtpa_url}{"\n"}format={.data.sbom_format}{"\n"}'
oc -n sso get configmap demo-userinfo-keycloak \
  -o jsonpath='issuer={.data.oidc_issuer}{"\n"}user={.data.workshop_username}{"\n"}password={.data.workshop_password}{"\n"}'

The TPA password is the value of ConfigMap key workshop_password in demo-userinfo-keycloak (not the key name). CLI client secret is Secret tpa-realm-cli-clients. Do not commit either. Sign in from the TPA UI Route (realm tpa), not https://sso…/admin/.

Worked example (not the Check)

# Worked example ONLY — different purl / filename. Do not upload this as the Check.
curl -sk -X POST -H 'Content-Type: application/octet-stream' \
  --data-binary @/tmp/example-not-your-app.cdx.json \
  https://example.invalid/api/v3/sbom

Your change: copy 4.4 SBOM; ingest

Task syft-sbom-rhtpa writes ConfigMap lab-sbom-cyclonedx in the build namespace (the sbom workspace is emptyDir and is gone when the pod completes). oc cp / oc exec into a completed pod fails. Extract that ConfigMap — do not re-run the full 4.4 pipeline just to copy a file.

BUILD_NS="$(oc -n gitea get configmap demo-userinfo-gitea -o jsonpath='{.data.student_build_namespace}')"
oc -n "${BUILD_NS}" get tr -l tekton.dev/pipelineTask=syft-sbom-rhtpa
oc -n "${BUILD_NS}" extract configmap/lab-sbom-cyclonedx --to="${HOME}" --confirm
test -f ~/sbom.cyclonedx.json && jq '{bomFormat, specVersion, components:(.components|length)}' ~/sbom.cyclonedx.json || echo 'EXTRACT ConfigMap lab-sbom-cyclonedx FIRST'

Ingest this file (bound to the 6.2 digest) even if the pipeline already uploaded — you must be able to find the document. UI file picker or REST:

export OIDC_ISSUER="$(oc -n sso get configmap demo-userinfo-keycloak -o jsonpath='{.data.oidc_issuer}')"
export RHTPA_URL="$(oc -n trusted-profile-analyzer get configmap rhtpa-ingestion-info -o jsonpath='{.data.server_url}')"
export TPA_USER="$(oc -n sso get configmap demo-userinfo-keycloak -o jsonpath='{.data.workshop_username}')"
: "${TPA_PASS:=$(oc -n sso get configmap demo-userinfo-keycloak -o jsonpath='{.data.workshop_password}')}"
export CLI_SECRET="$(oc -n trusted-profile-analyzer get secret tpa-realm-cli-clients -o jsonpath='{.data.cli}' | base64 -d)"
TOKEN="$(curl -sk -X POST "${OIDC_ISSUER}/protocol/openid-connect/token" \
  -d grant_type=password -d client_id=cli -d client_secret="${CLI_SECRET}" \
  -d username="${TPA_USER}" -d password="${TPA_PASS}" -d scope=openid \
  | jq -r .access_token)"
curl -sk -X POST \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @"${HOME}/sbom.cyclonedx.json" \
  -w '\nHTTP %{http_code}\n' \
  "${RHTPA_URL%/}/api/v3/sbom"

Expect HTTP 201 (or another success). Open server_url, sign in, find the promoted digest / component.

TPA UI after ingesting the promoted app CycloneDX SBOM

Check: TPA has the promoted SBOM

Pass when TPA shows a CycloneDX document for the digest you promoted in 6.2 (UI or API list). live_csaf_gate stays false.

Fill the report

The Job also grades ConfigMap report-17-sbom-sor key sor_object. Set it to promoted-digest. Empty or REPLACE_ME fails even if cluster state is correct. Do not copy validate-docs.

oc -n lw-poc-validate edit configmap report-17-sbom-sor

The scored Check is Job validate-17-sbom-sor 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-17-sbom-sor --ignore-not-found
TPL='job-17.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-17-sbom-sor

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.

Continue to 7.2 when you are ready.

Official documentation

SPDX callout

Wheels typically ingest as SPDX. This Check looks for the CycloneDX document from the Maven / syft path. Either format is the system-of-record idea.

Key takeaways

  • Compliance starts from the promoted artifact, not a laptop folder.

  • CSAF is not this Check. Lightwell Network and Clearinghouse Premier GAV VEX is 7.2.

cd ~/ocp5-rhacs-showroom
bash setup/lab-cleanup.sh --module tssc-17