5.1 Sign (keyless)

Overview

You sign the application digest you built in 4.4 with keyless Red Hat Trusted Artifact Signer. Fulcio issues the short-lived certificate, Rekor records the signature, and TUF distributes the trust root. Then you run cosign verify on that digest.

This is not the Hummingbird runtime signature from Track 1. It is not Lightwell’s signed libraries. Key-based sign and --key verify are 5.3. Do not treat keyless-only as Track 5 done.

The seeded pipeline already includes task cosign-sign-keyless. Placeholders in the PipelineRun fail that task until you fill live in-cluster Fulcio, Rekor, and TUF URLs (fulcio_internal_url and the matching keys). Route hints (fulcio_url_hint) are for Showroom cosign verify only. After 4.3 the build namespace cannot reach those Routes.

Why it matters

Integrity is a signature on your application image. That is distinct from Red Hat’s Hummingbird key and from Lightwell’s signed libraries. Until the app digest verifies, later admission and promotion sit on an unsigned artifact.

You use in-cluster Fulcio, Rekor, and TUF URLs so the pipeline still signs after hermetic egress. A Hummingbird key, a fake issuer, or a Route URL after 4.3 is not this control. Admission in Track 6 still needs the 5.3 public key for native ImagePolicy. Keep both signatures.

Lightwell Network and Clearinghouse Premier sign dependencies. They do not sign this app digest. Premier does not replace RHTAS.

What does it solve

  • Application images with no signature

  • Using Route URLs for Fulcio, Rekor, or TUF after 4.3 hermetic egress

  • Treating Hummingbird verify as enough for the app

Keyless vs keys

Keyless RHTAS Fulcio Rekor TUF versus later key-based verify

Keyless is the connected path, when the cluster can reach Fulcio. The pipeline service account presents an OIDC token, Fulcio issues a short-lived cert, Rekor records the signature, and TUF distributes the trust root. When Fulcio is unreachable at verify time, you still need 5.3.

Discover RHTAS URLs

cosign is installed by Welcome Environment setup into ~/.local/bin. Do not curl github.com for the CLI.

command -v cosign
oc -n trusted-artifact-signer get configmap demo-userinfo-rhtas \
  -o jsonpath='{.data.signing_model}{"\n"}{.data.fulcio_internal_url}{"\n"}{.data.rekor_internal_url}{"\n"}{.data.tuf_internal_url}{"\n"}{.data.fulcio_url_hint}{"\n"}{.data.rekor_url_hint}{"\n"}{.data.tuf_url_hint}{"\n"}'
oc -n trusted-artifact-signer get routes

Confirm the hints against live Routes. Do not leave apps.<domain> in the PipelineRun.

Worked example (not the Check)

# Worked example ONLY — fake issuer/subject. Do not use as the scored verify.
cosign verify \
  --certificate-identity-regexp='https://example.invalid/not-the-pipeline-sa' \
  --certificate-oidc-issuer='https://example.invalid/oidc' \
  image-registry.openshift-image-registry.svc:5000/example/not-your-app:latest

Your change: fill URLs; sign the app digest

If 4.4 already ran cosign-sign-keyless to Succeeded, skip to verify after origin has the filled PipelineRun. Check 12 reads Gitea .tekton/pipelinerun.yaml, not the live object — STUDENT_REPO_URL_PLACEHOLDER or <lab-namespace> still on main fails even when sign Succeeded. Confirm, and commit if 4.4 only `oc create`d the local file:

cd /tmp/spring-boot-lw-poc
git fetch
git show origin/main:.tekton/pipelinerun.yaml | grep -E 'STUDENT_REPO_URL_PLACEHOLDER|<lab-namespace>' \
  && echo 'STILL HAS PLACEHOLDERS — commit the filled file from 4.4' \
  || echo 'Gitea pipelinerun is filled'

Otherwise edit .tekton/pipelinerun.yaml on lw-student/spring-boot-lw-poc: replace Fulcio / Rekor / TUF with fulcio_internal_url / rekor_internal_url / tuf_internal_url (not the HTTPS Route hints), STUDENT_REPO_URL_PLACEHOLDER with student_repo_internal_url (in-cluster Gitea, not the HTTPS Route), and <lab-namespace> with lw-poc-build. Commit and push that file (same as 4.4), then create a new run:

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}" apply -f .tekton/pipeline.yaml
oc -n "${BUILD_NS}" create -f .tekton/pipelinerun.yaml
oc -n "${BUILD_NS}" get pipelinerun -w

Wait until cosign-sign-keyless Succeeded. ACS may still fail; this Check is the signature, not ACS.

PipelineRun graph with cosign-sign-keyless Succeeded

Do not oc tag into staging here (Track 6). Do not generate a Showroom key pair or cosign sign --key here (5.3).

Check: cosign verify on the app digest

Identity is the pipeline SA in the build namespace (claim-proven), not a Hummingbird signer and not REPLACE_ME_*. Issuer is the Kubernetes API. If verify fails, capture the SAN from Rekor / cosign verify error text — do not invent an alternate issuer.

BUILD_NS="$(oc -n gitea get configmap demo-userinfo-gitea -o jsonpath='{.data.student_build_namespace}')"
TUF="$(oc -n trusted-artifact-signer get configmap demo-userinfo-rhtas -o jsonpath='{.data.tuf_url_hint}')"
REKOR="$(oc -n trusted-artifact-signer get configmap demo-userinfo-rhtas -o jsonpath='{.data.rekor_url_hint}')"
IMAGE="image-registry.openshift-image-registry.svc:5000/${BUILD_NS}/spring-boot-lw-poc:latest"
mkdir -p /tmp/lab-home
export HOME=/tmp/lab-home
cosign initialize --mirror="${TUF}" --root="${TUF}/root.json"
cosign login -u unused -p "$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
  image-registry.openshift-image-registry.svc:5000
cosign verify \
  --rekor-url="${REKOR}" \
  --certificate-identity-regexp="^https://kubernetes.io/namespaces/${BUILD_NS}/serviceaccounts/pipeline$" \
  --certificate-oidc-issuer="https://kubernetes.default.svc" \
  --allow-http-registry --allow-insecure-registry \
  "${IMAGE}"

Pass when that command exits 0 on your app digest. Record the digest (oc -n "${BUILD_NS}" get istag spring-boot-lw-poc:latest -o jsonpath='{.image.dockerImageReference}') — Track 6 promotes it.

Fill the report

The Job also grades ConfigMap report-12-sign-keyless key what_you_signed. Set it to app-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-12-sign-keyless

The scored Check is Job validate-12-sign-keyless 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-12-sign-keyless --ignore-not-found
TPL='job-12.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-12-sign-keyless

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 5.2 when you are ready.

Official documentation

Key takeaways

  • Keyless signing is the connected path for the app digest. 5.3 adds a key-based signature on the same digest.

  • Lightwell Network and Clearinghouse Premier signed the library. They did not sign this image.

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