4.1 Remove public fetches from source

Track 3 left you with an application in Gitea, a verified runtime base, and a selected Lightwell version. Track 4 turns those source choices into a build you can inspect. You first remove public fetches, then wire dependency prefetch, restrict build-pod egress, and run the build to collect an image and a software bill of materials (SBOM).

Continue in /home/lab-user/lightwell-workspace/spring-boot-lw-poc in the Showroom terminal. Keep the changes and merged Renovate pull request from Track 3. If that clone is missing, return to 3.2 to recover your student repository before proceeding.

Why this control exists

The application still has a public JDK builder and Maven Central repositories. Its Dockerfile also overrides the default Commons Lang version selected in Track 2. A correct POM alone therefore does not establish what the image will contain. You remove these alternate inputs before restricting the network.

For this workshop, the build’s trusted sources are the OpenShift internal registry and the in-cluster Nexus service. Importing an image makes it available internally; it does not independently verify its publisher. The runtime image’s trust evidence comes from Track 1. The JDK builder is the workshop’s UBI builder.

Track 3 inputs become internal builder and runtime references and Nexus-only Maven settings; the known-bad fixture stays separate

Learning objectives

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

  • Import the builder and verified runtime image into the build namespace.

  • Use the imported runtime manifest digest in the active Dockerfile.

  • Route Maven dependencies and plugins through Nexus without a public fallback.

  • Remove the Dockerfile version override and review the committed inputs.

Inspect your starting point

Read the active files before editing. Expect a public builder FROM, the Track 3 runtime reference, and a Maven command with -Dcommons.lang3.version=3.14.0. On a repeat attempt, some corrections may already be present; preserve them.

cd /home/lab-user/lightwell-workspace/spring-boot-lw-poc
git status --short
grep -nE '^FROM |curl |RUN mvn|repo.maven.apache.org' Dockerfile settings.xml
cat pom.xml

Exercise

Import the two base images

Read the verified destination from the Track 1 report, as you did in Track 3.2. Continue only when status is verified and the destination pull spec is populated. Do not substitute a tag or a digest copied from a diagram.

BUILD_NS="$(oc -n gitea get configmap lab-gitea -o jsonpath='{.data.student_build_namespace}')"
oc -n lw-poc-validate get configmap report-02-hummingbird-mirror \
  -o jsonpath='status={.data.status}{"\n"}destination={.data.destination_pullspec}{"\n"}'

The following block imports only after that prerequisite passes. Success produces ImageStreams openjdk-21-builder and hummingbird-openjdk in your build namespace.

if [ "$(oc -n lw-poc-validate get configmap report-02-hummingbird-mirror -o jsonpath='{.data.status}')" = verified ]; then
  DEST="$(oc -n lw-poc-validate get configmap report-02-hummingbird-mirror -o jsonpath='{.data.destination_pullspec}')"
  if [ -n "$BUILD_NS" ] && [ -n "$DEST" ]; then
    oc -n "$BUILD_NS" import-image openjdk-21-builder \
      --from=registry.access.redhat.com/ubi9/openjdk-21:1.21 --confirm &&
    oc -n "$BUILD_NS" import-image hummingbird-openjdk \
      --from="$DEST" --confirm --insecure=true
  else
    echo 'STOP: build namespace or verified destination is missing.'
  fi
else
  echo 'STOP: complete the Track 1 evidence review before importing.'
fi

Read the imported manifest digest and construct the two references you will put in the Dockerfile. Require a nonempty sha256: value before editing.

RUNTIME_DIGEST="$(oc -n "$BUILD_NS" get imagestream hummingbird-openjdk -o jsonpath='{.status.tags[0].items[0].image}')"
printf 'Builder: image-registry.openshift-image-registry.svc:5000/%s/openjdk-21-builder:latest\n' "$BUILD_NS"
printf 'Runtime: image-registry.openshift-image-registry.svc:5000/%s/hummingbird-openjdk@%s\n' "$BUILD_NS" "$RUNTIME_DIGEST"

Track 1 verified an image index, which lists platform manifests. The import stores the amd64 manifest used by this cluster. Use the imported image digest above on the internal registry host; putting the original index digest on that host can produce manifest unknown. Keep Track 1’s original index reference as evidence.

Edit the active Dockerfile and Maven settings

Open /home/lab-user/lightwell-workspace/spring-boot-lw-poc/Dockerfile. Replace the builder FROM with the printed builder reference and keep AS build. Replace the runtime FROM with the printed runtime reference, including its digest. Remove any curl installer and remove -Dcommons.lang3.version=3.14.0 from the Maven command so the POM’s selected version takes effect. Preserve the remaining application instructions. Module 4.2 will replace the Maven command with its offline form.

Read the Nexus service URL and channel names. These values should be populated. The build uses the service URL because the egress policy in 4.3 does not allow the external Route.

oc -n lightwell-repo get configmap lab-lightwell-repo \
  -o jsonpath='nexus={.data.nexus_internal_url}{"\n"}validated={.data.channel_validated}{"\n"}remediated={.data.channel_remediated}{"\n"}'

In the application’s settings.xml, keep the two Lightwell profiles and repository IDs. Set each repository URL to nexus_internal_url/repository/channel_name/, using the corresponding channel. Remove the Central repository and plugin-repository entries. Add this mirror inside <settings>, alongside <profiles>, replacing REPLACE_ME_NEXUS_INTERNAL_URL with the value you just read. If a <mirrors> element already exists, add the mirror inside it.

<mirrors>
  <mirror>
    <id>nexus-internal</id>
    <mirrorOf>*</mirrorOf>
    <url>REPLACE_ME_NEXUS_INTERNAL_URL/repository/maven-public/</url>
  </mirror>
</mirrors>

The mirror also routes Maven’s implicit Central and plugin requests through Nexus. The workshop’s maven-public group includes the required dependencies and plugins. Do not add membership passwords to this file. Leave Dockerfile.known-bad unchanged: it is a separate negative-test fixture, never the normal build input.

Review and publish the source changes

The diff should show internal FROM references, removal of the Maven version override, and Nexus-only repository settings. Preserve the selected POM version from Track 3.

cd /home/lab-user/lightwell-workspace/spring-boot-lw-poc
git diff -- Dockerfile settings.xml
git add Dockerfile settings.xml
git diff --cached
git commit -m "Use internal base images and Nexus-only Maven inputs"
git push origin HEAD

Review

Fetch the remote and inspect what the pipeline will clone. HEAD and origin/main should match after the push. Compare the runtime digest with the ImageStream value you read above. A host-name scan alone does not establish that the digest is correct.

git fetch origin
git rev-parse HEAD origin/main
git show origin/main:Dockerfile
git show origin/main:settings.xml
git show origin/main:Dockerfile.known-bad

Confirm that both active FROM lines use the internal registry, no active command downloads a public installer, and Maven settings contain no Central URL or unfilled placeholder. The known-bad file should still contain its public FROM. This review establishes source configuration; the pipeline in 4.4 establishes whether it builds.

Carry the result into module 4.2

Keep your local clone of the application repository from Gitea. Next you will connect a prefetch Task to the pipeline and make the Dockerfile consume its cache offline.

Python uses an internal package index, and Artifactory can provide the enterprise Maven repository. A Clearinghouse GAV uses the same enterprise-proxy pattern. The exercise remains the Java application and Nexus.

Official documentation