From c35c2de5859443dd83e03ce38db206a794964da8 Mon Sep 17 00:00:00 2001 From: sm8949752-ux Date: Tue, 17 Mar 2026 02:40:22 +0000 Subject: [PATCH 01/21] do great --- .vscode/tasks.json | 22 ++++++++++ 2-builder/builder.toml | 96 +++++++++++++++++++++++++++++++++++------- 2 files changed, 102 insertions(+), 16 deletions(-) create mode 100644 .vscode/tasks.json diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..2e80f4e --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,22 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "echo", + "type": "shell", + "command": "echo Hello" + }, + { + "label": "build build image", + "type": "shell", + "command":"cd build-image && docker build -t taha/wolfi-build-image:latest ." + }, + { + "label": "build run run-image", + "type": "shell", + "command":"cd run-image && docker build -t taha/wolfi-run-image:latest ." + } + ] +} \ No newline at end of file diff --git a/2-builder/builder.toml b/2-builder/builder.toml index 0614365..6c639b5 100644 --- a/2-builder/builder.toml +++ b/2-builder/builder.toml @@ -1,22 +1,86 @@ -description = "My Custom Wolfi FIPS Builder" +description = "My Custom Wolfi FIPS Builder (Full Java Stack)" [stack] - id = "io.buildpacks.stacks.wolfi-fips" - build-image = "taha/wolfi-build-image:latest" - run-image = "taha/wolfi-run-image:latest" +id = "io.buildpacks.stacks.jammy" +build-image = "taha/wolfi-build-image:latest" +run-image = "taha/wolfi-run-image:latest" + +[[targets]] +os = "linux" +arch = "amd64" + +[[buildpacks]] +uri = "../fips-java-shim" + +[[buildpacks]] +uri = "docker://paketobuildpacks/ca-certificates:latest" + +[[buildpacks]] +uri = "docker://paketobuildpacks/syft:latest" + +[[buildpacks]] +uri = "docker://paketobuildpacks/environment-variables:latest" + +[[buildpacks]] +uri = "docker://paketobuildpacks/image-labels:latest" + +[[buildpacks]] +uri = "docker://paketobuildpacks/procfile:latest" + +[[buildpacks]] +uri = "docker://paketobuildpacks/jattach:latest" + +[[buildpacks]] +uri = "docker://paketobuildpacks/java-memory-assistant:latest" + +[[buildpacks]] +uri = "docker://paketobuildpacks/datadog:latest" + +[[buildpacks]] +uri = "docker://paketobuildpacks/azure-application-insights:latest" + +[[buildpacks]] +uri = "docker://paketobuildpacks/google-stackdriver:latest" + +[[buildpacks]] +uri = "docker://paketobuildpacks/maven:latest" + +[[buildpacks]] +uri = "docker://paketobuildpacks/gradle:latest" + +[[buildpacks]] +uri = "docker://paketobuildpacks/sbt:latest" + +[[buildpacks]] +uri = "docker://paketobuildpacks/executable-jar:latest" + +[[buildpacks]] +uri = "docker://paketobuildpacks/spring-boot:latest" + +[[buildpacks]] +uri = "docker://paketobuildpacks/apache-tomcat:latest" [[buildpacks]] - uri = "../fips-java-shim" +uri = "docker://paketobuildpacks/dist-zip:latest" [[order]] - group = [ - { id = "paketo-buildpacks/bellsoft-liberica", version = "99.9.9" }, - { id = "paketo-buildpacks/ca-certificates" }, - { id = "paketo-buildpacks/syft" }, - { id = "paketo-buildpacks/java-memory-assistant" }, - { id = "paketo-buildpacks/environment-variables" }, - { id = "paketo-buildpacks/gradle" }, - { id = "paketo-buildpacks/maven" }, - { id = "paketo-buildpacks/executable-jar" }, - { id = "paketo-buildpacks/spring-boot" } - ] +group = [ + { id = "paketo-buildpacks/bellsoft-liberica", version = "99.9.9" }, + { id = "paketo-buildpacks/ca-certificates" }, + { id = "paketo-buildpacks/syft" }, + { id = "paketo-buildpacks/environment-variables", optional = true }, + { id = "paketo-buildpacks/image-labels", optional = true }, + { id = "paketo-buildpacks/jattach", optional = true }, + { id = "paketo-buildpacks/java-memory-assistant", optional = true }, + { id = "paketo-buildpacks/datadog", optional = true }, + { id = "paketo-buildpacks/azure-application-insights", optional = true }, + { id = "paketo-buildpacks/google-stackdriver", optional = true }, + { id = "paketo-buildpacks/gradle", optional = true }, + { id = "paketo-buildpacks/maven", optional = true }, + { id = "paketo-buildpacks/sbt", optional = true }, + { id = "paketo-buildpacks/executable-jar", optional = true }, + { id = "paketo-buildpacks/spring-boot", optional = true }, + { id = "paketo-buildpacks/apache-tomcat", optional = true }, + { id = "paketo-buildpacks/dist-zip", optional = true }, + { id = "paketo-buildpacks/procfile", optional = true } +] \ No newline at end of file From 5a6c7545188cde3083470f25f621be617185cd90 Mon Sep 17 00:00:00 2001 From: sm8949752-ux Date: Tue, 17 Mar 2026 12:40:34 +0000 Subject: [PATCH 02/21] do --- .vscode/tasks.json | 6 ++++++ 2-builder/builder.toml | 2 +- fips-java-shim/buildpack.toml | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 2e80f4e..185b2c5 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -3,6 +3,7 @@ // for the documentation about the tasks.json format "version": "2.0.0", "tasks": [ + { "label": "echo", "type": "shell", @@ -17,6 +18,11 @@ "label": "build run run-image", "type": "shell", "command":"cd run-image && docker build -t taha/wolfi-run-image:latest ." + }, + { + "label": "build pack", + "type": "shell", + "command":"cd 2-builder && pack builder create taha/wolfi-fips-builder:latest --config builder.toml" } ] } \ No newline at end of file diff --git a/2-builder/builder.toml b/2-builder/builder.toml index 6c639b5..2052130 100644 --- a/2-builder/builder.toml +++ b/2-builder/builder.toml @@ -65,7 +65,7 @@ uri = "docker://paketobuildpacks/dist-zip:latest" [[order]] group = [ - { id = "paketo-buildpacks/bellsoft-liberica", version = "99.9.9" }, + { id = "taha/fips-java", version = "1.0.0" }, { id = "paketo-buildpacks/ca-certificates" }, { id = "paketo-buildpacks/syft" }, { id = "paketo-buildpacks/environment-variables", optional = true }, diff --git a/fips-java-shim/buildpack.toml b/fips-java-shim/buildpack.toml index 48f2686..b65f8f0 100755 --- a/fips-java-shim/buildpack.toml +++ b/fips-java-shim/buildpack.toml @@ -1,8 +1,8 @@ api = "0.7" [buildpack] -id = "paketo-buildpacks/bellsoft-liberica" -version = "99.9.9" +id = "taha/fips-java" +version = "1.0.0" name = "FIPS Java Shim" [[provides]] From 21de34af3f295fb65ddcf32b2c9880af8d6d648f Mon Sep 17 00:00:00 2001 From: sm8949752-ux Date: Tue, 17 Mar 2026 15:41:00 +0000 Subject: [PATCH 03/21] feat: Refactor build and detect scripts, update Dockerfiles, and enhance Java version support --- .vscode/tasks.json | 19 ++++----- 2-builder/builder.toml | 1 + build-image/Dockerfile | 41 ++++++++++++++++-- fips-java-shim/bin/build | 89 +++++++++++++++++++++++++-------------- fips-java-shim/bin/detect | 22 +++++++++- run-image/Dockerfile | 46 ++++++++++++++++---- 6 files changed, 160 insertions(+), 58 deletions(-) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 185b2c5..f969582 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,28 +1,25 @@ { - // See https://go.microsoft.com/fwlink/?LinkId=733558 - // for the documentation about the tasks.json format "version": "2.0.0", "tasks": [ - { - "label": "echo", + "label": "1. Prepare Builder", "type": "shell", - "command": "echo Hello" + "command": "cd build-image && docker build -t taha/wolfi-build-image:latest . && cd ../2-builder && pack builder create taha/wolfi-fips-builder:latest --config builder.toml" }, { - "label": "build build image", + "label": "2. Prepare Run Image", "type": "shell", - "command":"cd build-image && docker build -t taha/wolfi-build-image:latest ." + "command": "cd run-image && docker build -t taha/wolfi-run-image:latest ." }, { - "label": "build run run-image", + "label": "3. Build App", "type": "shell", - "command":"cd run-image && docker build -t taha/wolfi-run-image:latest ." + "command": "pack build taha/spring-boot-fips-app --path 3-sample-app --builder taha/wolfi-fips-builder:latest --env BP_JVM_TYPE=JRE --publish=false" }, { - "label": "build pack", + "label": "4. Run App", "type": "shell", - "command":"cd 2-builder && pack builder create taha/wolfi-fips-builder:latest --config builder.toml" + "command": "docker rm -f fips-app-container || true && docker run -d -p 8080:8080 --name fips-app-container taha/spring-boot-fips-app" } ] } \ No newline at end of file diff --git a/2-builder/builder.toml b/2-builder/builder.toml index 2052130..9416694 100644 --- a/2-builder/builder.toml +++ b/2-builder/builder.toml @@ -64,6 +64,7 @@ uri = "docker://paketobuildpacks/apache-tomcat:latest" uri = "docker://paketobuildpacks/dist-zip:latest" [[order]] + group = [ { id = "taha/fips-java", version = "1.0.0" }, { id = "paketo-buildpacks/ca-certificates" }, diff --git a/build-image/Dockerfile b/build-image/Dockerfile index 6f887c4..354ca47 100644 --- a/build-image/Dockerfile +++ b/build-image/Dockerfile @@ -1,12 +1,45 @@ -FROM ghcr.io/taha2samy/java:21.0.10_7-LTS-jdk_standard +FROM ghcr.io/taha2samy/java:8-jdk_standard AS jdk8 +FROM ghcr.io/taha2samy/java:11-jdk_standard AS jdk11 +FROM ghcr.io/taha2samy/java:17-jdk_standard AS jdk17 +FROM ghcr.io/taha2samy/java:21-jdk_standard AS jdk21 +FROM ghcr.io/taha2samy/java:25-jdk_standard AS jdk25 + +FROM ghcr.io/taha2samy/java:8-jre_distroless AS jre8 +FROM ghcr.io/taha2samy/java:11-jre_distroless AS jre11 +FROM ghcr.io/taha2samy/java:17-jre_distroless AS jre17 +FROM ghcr.io/taha2samy/java:21-jre_distroless AS jre21 +FROM ghcr.io/taha2samy/java:25-jre_distroless AS jre25 + +FROM chainguard/wolfi-base@sha256:9925d3017788558fa8f27e8bb160b791e56202b60c91fbcc5c867de3175986c8 USER root -RUN usermod -u 1000 java && groupmod -g 1000 java || true + +RUN apk update && \ + apk add --no-cache bash gzip curl jq ca-certificates shadow + +RUN mkdir -p /opt/jdks /opt/jres + +COPY --from=jdk8 /opt/java /opt/jdks/8 +COPY --from=jdk11 /opt/java /opt/jdks/11 +COPY --from=jdk17 /opt/java /opt/jdks/17 +COPY --from=jdk21 /opt/java /opt/jdks/21 +COPY --from=jdk25 /opt/java /opt/jdks/25 + +COPY --from=jre8 /opt/java /opt/jres/8 +COPY --from=jre11 /opt/java /opt/jres/11 +COPY --from=jre17 /opt/java /opt/jres/17 +COPY --from=jre21 /opt/java /opt/jres/21 +COPY --from=jre25 /opt/java /opt/jres/25 ENV CNB_USER_ID=1001 ENV CNB_GROUP_ID=1001 + +RUN groupadd -g ${CNB_GROUP_ID} cnb && \ + useradd -u ${CNB_USER_ID} -g ${CNB_GROUP_ID} -s /bin/bash -m cnb + LABEL io.buildpacks.stack.id="io.buildpacks.stacks.jammy" -RUN chmod -R 755 /opt/java +RUN chown -R ${CNB_USER_ID}:${CNB_GROUP_ID} /opt/jdks /opt/jres && \ + chmod -R 755 /opt/jdks /opt/jres -USER 1001 \ No newline at end of file +USER ${CNB_USER_ID}:${CNB_GROUP_ID} \ No newline at end of file diff --git a/fips-java-shim/bin/build b/fips-java-shim/bin/build index 117aa53..5ec8acd 100755 --- a/fips-java-shim/bin/build +++ b/fips-java-shim/bin/build @@ -1,35 +1,60 @@ -#!/bin/sh +#!/usr/bin/env bash set -e - layers_dir="$1" -java_layer="${layers_dir}/java-fips" - -mkdir -p "$java_layer/env.build" -mkdir -p "$java_layer/env.launch" - -echo "[types]" > "${java_layer}.toml" -echo "launch = true" >> "${java_layer}.toml" -echo "build = true" >> "${java_layer}.toml" - -JDK_PATH="/opt/java" - -# 3. تعيين JAVA_HOME -printf "%s" "$JDK_PATH" > "$java_layer/env.build/JAVA_HOME" -printf "%s" "$JDK_PATH" > "$java_layer/env.launch/JAVA_HOME" - -KEYSTORE_PWD="changeit" - -FIPS_OPTS="-Dorg.bouncycastle.fips.approved_only=true \ --Dorg.bouncycastle.jsse.client.assumeExtendedKeyUsage=false \ --Dorg.bouncycastle.jsse.trustManager.checkEKU=true \ --Djdk.tls.trustNameService=true \ --Dkeystore.type=BCFKS \ --Djavax.net.ssl.trustStore=$JDK_PATH/lib/security/cacerts \ --Djavax.net.ssl.trustStoreType=BCFKS \ --Djavax.net.ssl.trustStorePassword=$KEYSTORE_PWD \ --Xbootclasspath/a:$JDK_PATH/lib/bc-fips.jar:$JDK_PATH/lib/bcutil-fips.jar:$JDK_PATH/lib/bctls-fips.jar" - -printf "%s" "$FIPS_OPTS" > "$java_layer/env.build/JAVA_TOOL_OPTIONS" -printf "%s" "$FIPS_OPTS" > "$java_layer/env.launch/JAVA_TOOL_OPTIONS" -echo "Success: FIPS parameters applied. Ready for Maven." \ No newline at end of file +# Read version from where we saved it in detect +VERSION=$(cat "/tmp/java_version" 2>/dev/null || echo "21") + +if [ ! -d "/opt/jdks/$VERSION" ] || [ ! -d "/opt/jres/$VERSION" ]; then + echo "ERROR: Java version $VERSION is not supported!" + exit 1 +fi + +jdk_layer="${layers_dir}/jdk" +jre_layer="${layers_dir}/jre" + +mkdir -p "${jdk_layer}/env.build" +cat > "${jdk_layer}.toml" < "${jdk_layer}/env.build/JAVA_HOME" +echo -n "/opt/jdks/${VERSION}/bin" > "${jdk_layer}/env.build/PATH.prepend" +echo -n ":" > "${jdk_layer}/env.build/PATH.delim" + +mkdir -p "${jre_layer}/env.launch" +cat > "${jre_layer}.toml" < "${jre_layer}/env.launch/JAVA_HOME" +echo -n "${jre_layer}/bin" > "${jre_layer}/env.launch/PATH.prepend" +echo -n ":" > "${jre_layer}/env.launch/PATH.delim" + +# Memory & FIPS Config +TOTAL_MEMORY=$(cat /sys/fs/cgroup/memory/memory.limit_in_bytes 2>/dev/null || echo "1073741824") +MAX_HEAP=$(( (TOTAL_MEMORY * 75) / 100 / 1024 / 1024 )) +FIPS_BASE="-Dorg.bouncycastle.fips.approved_only=true -Dkeystore.type=BCFKS -Djavax.net.ssl.trustStoreType=BCFKS -Djavax.net.ssl.trustStorePassword=changeit" + +if [ "$VERSION" == "8" ]; then + JDK_TRUST="/opt/jdks/${VERSION}/jre/lib/security/cacerts" + JDK_BOOT="/opt/jdks/${VERSION}/jre/lib/ext/bc-fips.jar:/opt/jdks/${VERSION}/jre/lib/ext/bcutil-fips.jar:/opt/jdks/${VERSION}/jre/lib/ext/bctls-fips.jar" + JRE_TRUST="${jre_layer}/lib/security/cacerts" + JRE_BOOT="${jre_layer}/lib/ext/bc-fips.jar:${jre_layer}/lib/ext/bcutil-fips.jar:${jre_layer}/lib/ext/bctls-fips.jar" +else + JDK_TRUST="/opt/jdks/${VERSION}/lib/security/cacerts" + JDK_BOOT="/opt/jdks/${VERSION}/lib/bc-fips.jar:/opt/jdks/${VERSION}/lib/bcutil-fips.jar:/opt/jdks/${VERSION}/lib/bctls-fips.jar" + JRE_TRUST="${jre_layer}/lib/security/cacerts" + JRE_BOOT="${jre_layer}/lib/bc-fips.jar:${jre_layer}/lib/bcutil-fips.jar:${jre_layer}/lib/bcutil-fips.jar" +fi + +echo -n "${FIPS_BASE} -Djavax.net.ssl.trustStore=${JDK_TRUST} -Xbootclasspath/a:${JDK_BOOT}" > "${jdk_layer}/env.build/JAVA_TOOL_OPTIONS.override" +echo -n "${FIPS_BASE} -Djavax.net.ssl.trustStore=${JRE_TRUST} -Xbootclasspath/a:${JRE_BOOT} -XX:+ExitOnOutOfMemoryError -Xmx${MAX_HEAP}m" > "${jre_layer}/env.launch/JAVA_TOOL_OPTIONS.override" \ No newline at end of file diff --git a/fips-java-shim/bin/detect b/fips-java-shim/bin/detect index 668d1d3..5072aa8 100755 --- a/fips-java-shim/bin/detect +++ b/fips-java-shim/bin/detect @@ -1,13 +1,31 @@ #!/usr/bin/env bash set -e -plan=$2 +PLAN="$2" +VERSION="${BP_JVM_VERSION:-21}" -cat >> "$plan" <[0-9]+" pom.xml | head -n1 | sed -E 's/.*([0-9]+).*/\1/') + [ -n "$DETECTED" ] && VERSION="$DETECTED" +fi + +if [ ! -d "/opt/jdks/$VERSION" ]; then + exit 100 +fi + +cat > "${PLAN}" < "/tmp/java_version" exit 0 \ No newline at end of file diff --git a/run-image/Dockerfile b/run-image/Dockerfile index 0a3e531..bc1f25f 100644 --- a/run-image/Dockerfile +++ b/run-image/Dockerfile @@ -1,14 +1,42 @@ -FROM cgr.dev/chainguard/wolfi-base AS prep -RUN addgroup -g 1000 cnb && \ - adduser -u 1000 -G cnb -s /sbin/nologin -D cnb +# syntax=docker/dockerfile:1.6 -FROM ghcr.io/taha2samy/java:21-jre_distroless +FROM chainguard/wolfi-base@sha256:9925d3017788558fa8f27e8bb160b791e56202b60c91fbcc5c867de3175986c8 AS helper -COPY --from=prep /etc/passwd /etc/passwd -COPY --from=prep /etc/group /etc/group +RUN (addgroup -g 1001 java || true) && (adduser -u 1001 -G java -D -s /sbin/nologin java || true) +RUN mkdir -p /rootfs/etc /rootfs/usr/share/zoneinfo /rootfs/home/java /rootfs/tmp + +RUN cp /etc/passwd /rootfs/etc/passwd && \ + cp /etc/group /rootfs/etc/group && \ + echo "hosts: files dns" > /rootfs/etc/nsswitch.conf && \ + echo "UTC" > /rootfs/etc/timezone && \ + chown 1001:1001 /rootfs/home/java && \ + chmod 1777 /rootfs/tmp + + +FROM chainguard/wolfi-base@sha256:9925d3017788558fa8f27e8bb160b791e56202b60c91fbcc5c867de3175986c8 AS producer +USER root + +RUN mkdir -p /rootfs/run_distroless/etc/apk /rootfs/run_distroless/var/lib/apk + +RUN --mount=type=cache,id=wolfi-apk,target=/var/cache/apk \ + apk add --initdb --no-scripts --root /rootfs/run_distroless \ + --cache-dir /var/cache/apk --keys-dir /etc/apk/keys --repositories-file /etc/apk/repositories \ + glibc=2.43-r1 zlib=1.3.2-r0 ca-certificates=20251003-r3 wolfi-baselayout=20230201-r28 \ + wolfi-keys=1-r13 libgcc=15.2.0-r9 libstdc++=15.2.0-r9 tzdata=2026a-r0 && \ + ldconfig -r /rootfs/run_distroless + + +FROM scratch + +COPY --from=producer /rootfs/run_distroless / +COPY --from=helper /rootfs / + +ENV CNB_USER_ID=1001 +ENV CNB_GROUP_ID=1001 +ENV LANG=C.UTF-8 TZ=UTC -ENV CNB_USER_ID=1000 -ENV CNB_GROUP_ID=1000 LABEL io.buildpacks.stack.id="io.buildpacks.stacks.jammy" -USER ${CNB_USER_ID}:${CNB_GROUP_ID} \ No newline at end of file +USER 1001 +WORKDIR /home/java + From ae6f03a1bc2ceebb0714751d602ff622cc55229d Mon Sep 17 00:00:00 2001 From: sm8949752-ux Date: Wed, 18 Mar 2026 00:02:40 +0000 Subject: [PATCH 04/21] feat: Update build scripts and configurations for Gradle and Maven support, enhance FIPS compliance checks --- .vscode/tasks.json | 11 ++- 2-builder/builder.toml | 98 ++++++++++++++----- 4-gradle-app/build.gradle | 20 ++++ .../gradle/wrapper/gradle-wrapper.properties | 5 + 4-gradle-app/settings.gradle | 1 + .../com/taha/wolfidemo/DemoApplication.java | 59 +++++++++++ fips-java-shim/bin/build | 55 ++++++----- fips-java-shim/bin/detect | 17 ---- 8 files changed, 201 insertions(+), 65 deletions(-) create mode 100644 4-gradle-app/build.gradle create mode 100644 4-gradle-app/gradle/wrapper/gradle-wrapper.properties create mode 100644 4-gradle-app/settings.gradle create mode 100644 4-gradle-app/src/main/java/com/taha/wolfidemo/DemoApplication.java diff --git a/.vscode/tasks.json b/.vscode/tasks.json index f969582..215b506 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -12,14 +12,19 @@ "command": "cd run-image && docker build -t taha/wolfi-run-image:latest ." }, { - "label": "3. Build App", + "label": "3. Build App Gradle", "type": "shell", - "command": "pack build taha/spring-boot-fips-app --path 3-sample-app --builder taha/wolfi-fips-builder:latest --env BP_JVM_TYPE=JRE --publish=false" + "command": "pack build taha/gradle-fips-app --path 4-gradle-app --builder taha/wolfi-fips-builder:latest --env BP_JVM_TYPE=JRE --publish=false --clear-cache" + }, + { + "label": "3. Build App Maven", + "type": "shell", + "command": "pack build taha/maven-fips-app --path 3-sample-app --builder taha/wolfi-fips-builder:latest --env BP_JVM_TYPE=JRE --publish=false --clear-cache" }, { "label": "4. Run App", "type": "shell", - "command": "docker rm -f fips-app-container || true && docker run -d -p 8080:8080 --name fips-app-container taha/spring-boot-fips-app" + "command": "docker rm -f fips-app-container || true && docker run -d -p 8080:8080 --name fips-app-container taha/maven-fips-app" } ] } \ No newline at end of file diff --git a/2-builder/builder.toml b/2-builder/builder.toml index 9416694..6f58fb8 100644 --- a/2-builder/builder.toml +++ b/2-builder/builder.toml @@ -1,14 +1,18 @@ -description = "My Custom Wolfi FIPS Builder (Full Java Stack)" +description = "My Custom Wolfi FIPS Builder" [stack] id = "io.buildpacks.stacks.jammy" build-image = "taha/wolfi-build-image:latest" run-image = "taha/wolfi-run-image:latest" - [[targets]] os = "linux" arch = "amd64" +[[targets]] +os = "linux" +arch = "arm64" + + [[buildpacks]] uri = "../fips-java-shim" @@ -65,23 +69,73 @@ uri = "docker://paketobuildpacks/dist-zip:latest" [[order]] -group = [ - { id = "taha/fips-java", version = "1.0.0" }, - { id = "paketo-buildpacks/ca-certificates" }, - { id = "paketo-buildpacks/syft" }, - { id = "paketo-buildpacks/environment-variables", optional = true }, - { id = "paketo-buildpacks/image-labels", optional = true }, - { id = "paketo-buildpacks/jattach", optional = true }, - { id = "paketo-buildpacks/java-memory-assistant", optional = true }, - { id = "paketo-buildpacks/datadog", optional = true }, - { id = "paketo-buildpacks/azure-application-insights", optional = true }, - { id = "paketo-buildpacks/google-stackdriver", optional = true }, - { id = "paketo-buildpacks/gradle", optional = true }, - { id = "paketo-buildpacks/maven", optional = true }, - { id = "paketo-buildpacks/sbt", optional = true }, - { id = "paketo-buildpacks/executable-jar", optional = true }, - { id = "paketo-buildpacks/spring-boot", optional = true }, - { id = "paketo-buildpacks/apache-tomcat", optional = true }, - { id = "paketo-buildpacks/dist-zip", optional = true }, - { id = "paketo-buildpacks/procfile", optional = true } -] \ No newline at end of file + [[order.group]] + id = "paketo-buildpacks/ca-certificates" + optional = true + + [[order.group]] + id = "taha/fips-java" + + [[order.group]] + id = "paketo-buildpacks/syft" + optional = true + + [[order.group]] + id = "paketo-buildpacks/gradle" + optional = true + + [[order.group]] + id = "paketo-buildpacks/maven" + optional = true + + [[order.group]] + id = "paketo-buildpacks/sbt" + optional = true + + [[order.group]] + id = "paketo-buildpacks/executable-jar" + optional = true + + [[order.group]] + id = "paketo-buildpacks/apache-tomcat" + optional = true + + [[order.group]] + id = "paketo-buildpacks/dist-zip" + optional = true + + [[order.group]] + id = "paketo-buildpacks/spring-boot" + optional = true + + [[order.group]] + id = "paketo-buildpacks/procfile" + optional = true + + [[order.group]] + id = "paketo-buildpacks/jattach" + optional = true + + [[order.group]] + id = "paketo-buildpacks/azure-application-insights" + optional = true + + [[order.group]] + id = "paketo-buildpacks/google-stackdriver" + optional = true + + [[order.group]] + id = "paketo-buildpacks/datadog" + optional = true + + [[order.group]] + id = "paketo-buildpacks/java-memory-assistant" + optional = true + + [[order.group]] + id = "paketo-buildpacks/environment-variables" + optional = true + + [[order.group]] + id = "paketo-buildpacks/image-labels" + optional = true \ No newline at end of file diff --git a/4-gradle-app/build.gradle b/4-gradle-app/build.gradle new file mode 100644 index 0000000..96413f1 --- /dev/null +++ b/4-gradle-app/build.gradle @@ -0,0 +1,20 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '3.4.3' + id 'io.spring.dependency-management' version '1.1.7' +} + +group = 'com.taha' +version = '0.0.1-SNAPSHOT' + +java { + sourceCompatibility = '21' +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-web' +} \ No newline at end of file diff --git a/4-gradle-app/gradle/wrapper/gradle-wrapper.properties b/4-gradle-app/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..b1e749b --- /dev/null +++ b/4-gradle-app/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists \ No newline at end of file diff --git a/4-gradle-app/settings.gradle b/4-gradle-app/settings.gradle new file mode 100644 index 0000000..3ceba37 --- /dev/null +++ b/4-gradle-app/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'wolfi-demo-gradle' \ No newline at end of file diff --git a/4-gradle-app/src/main/java/com/taha/wolfidemo/DemoApplication.java b/4-gradle-app/src/main/java/com/taha/wolfidemo/DemoApplication.java new file mode 100644 index 0000000..8d10897 --- /dev/null +++ b/4-gradle-app/src/main/java/com/taha/wolfidemo/DemoApplication.java @@ -0,0 +1,59 @@ +package com.taha.wolfidemo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; +import java.security.KeyPairGenerator; +import java.security.Security; +import java.security.Provider; + +@SpringBootApplication +@RestController +public class DemoApplication { + + public static void main(String[] args) { + SpringApplication.run(DemoApplication.class, args); + } + + @GetMapping("/test-fips") + public String testFipsConstraint() { + try { + // Load BCFIPS provider using Reflection to bypass Maven compilation checks + if (Security.getProvider("BCFIPS") == null) { + try { + Class providerClass = Class.forName("org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider"); + Provider fipsProvider = (Provider) providerClass.getDeclaredConstructor().newInstance(); + Security.addProvider(fipsProvider); + } catch (Exception e) { + return "CRITICAL ERROR: BCFIPS Provider class not found in classpath."; + } + } + + // Attempt to generate an insecure 1024-bit RSA key + // This operation is forbidden in FIPS Approved Mode + KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "BCFIPS"); + kpg.initialize(1024); + kpg.generateKeyPair(); + + return "FAILURE: System allowed 1024-bit RSA. FIPS policy is not enforced."; + } catch (Throwable t) { + String message = t.getMessage(); + String errorType = t.getClass().getSimpleName(); + + // FipsUnapprovedOperationError or specific FIPS messages indicate success + if (errorType.contains("FipsUnapprovedOperationError") || + (message != null && message.toLowerCase().contains("approved only mode"))) { + return "SUCCESS: FIPS is strictly enforced. System blocked insecure RSA-1024 key generation. Error Type: " + errorType; + } + + return "TERMINATED: An unexpected error occurred: " + errorType + " - " + message; + } + } + + @GetMapping("/") + public String hello() { + boolean isFipsLoaded = (Security.getProvider("BCFIPS") != null); + return "Status: RUNNING | FIPS Provider: " + (isFipsLoaded ? "ACTIVE" : "INACTIVE") + " | Test Link: /test-fips"; + } +} \ No newline at end of file diff --git a/fips-java-shim/bin/build b/fips-java-shim/bin/build index 5ec8acd..5766d82 100755 --- a/fips-java-shim/bin/build +++ b/fips-java-shim/bin/build @@ -1,45 +1,52 @@ #!/usr/bin/env bash set -e + layers_dir="$1" +plan_path="$3" + +VERSION="" -# Read version from where we saved it in detect -VERSION=$(cat "/tmp/java_version" 2>/dev/null || echo "21") +if [ -n "$BP_JVM_VERSION" ]; then + VERSION="$BP_JVM_VERSION" +elif [ -f "$plan_path" ]; then + VERSION=$(grep -E 'version\s*=\s*"[0-9.]+"' "$plan_path" | head -n1 | grep -oE "[0-9.]+" | head -n1 || echo "") +fi -if [ ! -d "/opt/jdks/$VERSION" ] || [ ! -d "/opt/jres/$VERSION" ]; then - echo "ERROR: Java version $VERSION is not supported!" - exit 1 +if [ -z "$VERSION" ]; then + if [ -f "pom.xml" ]; then + VERSION=$(grep -E "<(java\.version|maven\.compiler\.source)>[0-9.]+" pom.xml | head -n1 | grep -oE "[0-9.]+" | head -n1 || echo "") + elif [ -f "build.gradle" ] || [ -f "build.gradle.kts" ]; then + VERSION=$(grep -E "JavaLanguageVersion\.of\(|sourceCompatibility|targetCompatibility" build.gradle build.gradle.kts 2>/dev/null | head -n1 | grep -oE "[0-9.]+" | head -n1 || echo "") + fi +fi + +VERSION="${VERSION:-21}" +[[ "$VERSION" == "1.8"* ]] && VERSION="8" +VERSION=$(echo "$VERSION" | cut -d. -f1) + +echo "---> FIPS Java Shim: Using Java $VERSION" + +if [ ! -d "/opt/jdks/$VERSION" ]; then + VERSION="21" + echo "---> Fallback: Using Java $VERSION" fi jdk_layer="${layers_dir}/jdk" jre_layer="${layers_dir}/jre" mkdir -p "${jdk_layer}/env.build" -cat > "${jdk_layer}.toml" < "${jdk_layer}.toml" echo -n "/opt/jdks/${VERSION}" > "${jdk_layer}/env.build/JAVA_HOME" echo -n "/opt/jdks/${VERSION}/bin" > "${jdk_layer}/env.build/PATH.prepend" echo -n ":" > "${jdk_layer}/env.build/PATH.delim" mkdir -p "${jre_layer}/env.launch" -cat > "${jre_layer}.toml" < "${jre_layer}.toml" cp -a /opt/jres/${VERSION}/* "${jre_layer}/" - echo -n "${jre_layer}" > "${jre_layer}/env.launch/JAVA_HOME" echo -n "${jre_layer}/bin" > "${jre_layer}/env.launch/PATH.prepend" echo -n ":" > "${jre_layer}/env.launch/PATH.delim" -# Memory & FIPS Config TOTAL_MEMORY=$(cat /sys/fs/cgroup/memory/memory.limit_in_bytes 2>/dev/null || echo "1073741824") MAX_HEAP=$(( (TOTAL_MEMORY * 75) / 100 / 1024 / 1024 )) FIPS_BASE="-Dorg.bouncycastle.fips.approved_only=true -Dkeystore.type=BCFKS -Djavax.net.ssl.trustStoreType=BCFKS -Djavax.net.ssl.trustStorePassword=changeit" @@ -53,8 +60,10 @@ else JDK_TRUST="/opt/jdks/${VERSION}/lib/security/cacerts" JDK_BOOT="/opt/jdks/${VERSION}/lib/bc-fips.jar:/opt/jdks/${VERSION}/lib/bcutil-fips.jar:/opt/jdks/${VERSION}/lib/bctls-fips.jar" JRE_TRUST="${jre_layer}/lib/security/cacerts" - JRE_BOOT="${jre_layer}/lib/bc-fips.jar:${jre_layer}/lib/bcutil-fips.jar:${jre_layer}/lib/bcutil-fips.jar" + JRE_BOOT="${jre_layer}/lib/bc-fips.jar:${jre_layer}/lib/bcutil-fips.jar:${jre_layer}/lib/bctls-fips.jar" fi echo -n "${FIPS_BASE} -Djavax.net.ssl.trustStore=${JDK_TRUST} -Xbootclasspath/a:${JDK_BOOT}" > "${jdk_layer}/env.build/JAVA_TOOL_OPTIONS.override" -echo -n "${FIPS_BASE} -Djavax.net.ssl.trustStore=${JRE_TRUST} -Xbootclasspath/a:${JRE_BOOT} -XX:+ExitOnOutOfMemoryError -Xmx${MAX_HEAP}m" > "${jre_layer}/env.launch/JAVA_TOOL_OPTIONS.override" \ No newline at end of file +echo -n "${FIPS_BASE} -Djavax.net.ssl.trustStore=${JRE_TRUST} -Xbootclasspath/a:${JRE_BOOT} -XX:+ExitOnOutOfMemoryError -Xmx${MAX_HEAP}m" > "${jre_layer}/env.launch/JAVA_TOOL_OPTIONS.override" + +exit 0 \ No newline at end of file diff --git a/fips-java-shim/bin/detect b/fips-java-shim/bin/detect index 5072aa8..7204fe0 100755 --- a/fips-java-shim/bin/detect +++ b/fips-java-shim/bin/detect @@ -2,16 +2,6 @@ set -e PLAN="$2" -VERSION="${BP_JVM_VERSION:-21}" - -if [ -f "pom.xml" ]; then - DETECTED=$(grep -E "[0-9]+" pom.xml | head -n1 | sed -E 's/.*([0-9]+).*/\1/') - [ -n "$DETECTED" ] && VERSION="$DETECTED" -fi - -if [ ! -d "/opt/jdks/$VERSION" ]; then - exit 100 -fi cat > "${PLAN}" < "/tmp/java_version" exit 0 \ No newline at end of file From 2282cb21b237968b8de307cd3372a0cc21ef1308 Mon Sep 17 00:00:00 2001 From: sm8949752-ux Date: Wed, 18 Mar 2026 19:15:46 +0000 Subject: [PATCH 05/21] feat: Enhance FIPS Java buildpack with Python support and improved detection logic --- .devcontainer/Dockerfile | 17 +++ .devcontainer/devcontainer.json | 24 +++ build-image/Dockerfile | 7 +- fips-java-shim/bin/build | 255 +++++++++++++++++++++++--------- fips-java-shim/bin/detect | 105 +++++++++++-- 5 files changed, 328 insertions(+), 80 deletions(-) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..1aeef33 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,17 @@ +FROM mcr.microsoft.com/devcontainers/base:jammy + +# Install Python and essential tools +RUN apt-get update && apt-get install -y \ + python3 \ + python3-pip \ + curl \ + git \ + xz-utils \ + && rm -rf /var/lib/apt/lists/* + +# Install pack CLI (Official Binary) +RUN curl -sSL "https://github.com/buildpacks/pack/releases/download/v0.36.4/pack-v0.36.4-linux.tgz" \ + | tar -C /usr/local/bin/ --no-same-owner -xzv pack + +# Install Python UI libraries for local testing of your Buildpack scripts +RUN pip3 install rich tomli tomli-w \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..e51fc91 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,24 @@ +{ + "name": "FIPS Buildpack Developer Environment", + "build": { + "dockerfile": "Dockerfile" + }, + "features": { + "ghcr.io/devcontainers/features/docker-outside-of-docker:1": { + "version": "latest", + "enableNonRootChildContainerUsage": true + } + }, + "customizations": { + "vscode": { + "extensions": [ + "ms-azuretools.vscode-docker", + "ms-python.python", + "tamasfe.even-better-toml", + "irongeek.vscode-env" + ] + } + }, + "remoteUser": "vscode", + "postCreateCommand": "sudo chown vscode:vscode /var/run/docker.sock || true" +} \ No newline at end of file diff --git a/build-image/Dockerfile b/build-image/Dockerfile index 354ca47..5d08b06 100644 --- a/build-image/Dockerfile +++ b/build-image/Dockerfile @@ -15,7 +15,12 @@ FROM chainguard/wolfi-base@sha256:9925d3017788558fa8f27e8bb160b791e56202b60c91fb USER root RUN apk update && \ - apk add --no-cache bash gzip curl jq ca-certificates shadow + apk add --no-cache bash gzip curl jq ca-certificates shadow python3 py3-pip + + +RUN pip install --no-cache-dir rich --break-system-packages + +RUN mkdir -p /opt/jdks /opt/jres RUN mkdir -p /opt/jdks /opt/jres diff --git a/fips-java-shim/bin/build b/fips-java-shim/bin/build index 5766d82..61f036b 100755 --- a/fips-java-shim/bin/build +++ b/fips-java-shim/bin/build @@ -1,69 +1,186 @@ -#!/usr/bin/env bash -set -e - -layers_dir="$1" -plan_path="$3" - -VERSION="" - -if [ -n "$BP_JVM_VERSION" ]; then - VERSION="$BP_JVM_VERSION" -elif [ -f "$plan_path" ]; then - VERSION=$(grep -E 'version\s*=\s*"[0-9.]+"' "$plan_path" | head -n1 | grep -oE "[0-9.]+" | head -n1 || echo "") -fi - -if [ -z "$VERSION" ]; then - if [ -f "pom.xml" ]; then - VERSION=$(grep -E "<(java\.version|maven\.compiler\.source)>[0-9.]+" pom.xml | head -n1 | grep -oE "[0-9.]+" | head -n1 || echo "") - elif [ -f "build.gradle" ] || [ -f "build.gradle.kts" ]; then - VERSION=$(grep -E "JavaLanguageVersion\.of\(|sourceCompatibility|targetCompatibility" build.gradle build.gradle.kts 2>/dev/null | head -n1 | grep -oE "[0-9.]+" | head -n1 || echo "") - fi -fi - -VERSION="${VERSION:-21}" -[[ "$VERSION" == "1.8"* ]] && VERSION="8" -VERSION=$(echo "$VERSION" | cut -d. -f1) - -echo "---> FIPS Java Shim: Using Java $VERSION" - -if [ ! -d "/opt/jdks/$VERSION" ]; then - VERSION="21" - echo "---> Fallback: Using Java $VERSION" -fi - -jdk_layer="${layers_dir}/jdk" -jre_layer="${layers_dir}/jre" - -mkdir -p "${jdk_layer}/env.build" -echo -e "[types]\nlaunch = false\nbuild = true\ncache = true" > "${jdk_layer}.toml" -echo -n "/opt/jdks/${VERSION}" > "${jdk_layer}/env.build/JAVA_HOME" -echo -n "/opt/jdks/${VERSION}/bin" > "${jdk_layer}/env.build/PATH.prepend" -echo -n ":" > "${jdk_layer}/env.build/PATH.delim" - -mkdir -p "${jre_layer}/env.launch" -echo -e "[types]\nlaunch = true\nbuild = false\ncache = true" > "${jre_layer}.toml" -cp -a /opt/jres/${VERSION}/* "${jre_layer}/" -echo -n "${jre_layer}" > "${jre_layer}/env.launch/JAVA_HOME" -echo -n "${jre_layer}/bin" > "${jre_layer}/env.launch/PATH.prepend" -echo -n ":" > "${jre_layer}/env.launch/PATH.delim" - -TOTAL_MEMORY=$(cat /sys/fs/cgroup/memory/memory.limit_in_bytes 2>/dev/null || echo "1073741824") -MAX_HEAP=$(( (TOTAL_MEMORY * 75) / 100 / 1024 / 1024 )) -FIPS_BASE="-Dorg.bouncycastle.fips.approved_only=true -Dkeystore.type=BCFKS -Djavax.net.ssl.trustStoreType=BCFKS -Djavax.net.ssl.trustStorePassword=changeit" - -if [ "$VERSION" == "8" ]; then - JDK_TRUST="/opt/jdks/${VERSION}/jre/lib/security/cacerts" - JDK_BOOT="/opt/jdks/${VERSION}/jre/lib/ext/bc-fips.jar:/opt/jdks/${VERSION}/jre/lib/ext/bcutil-fips.jar:/opt/jdks/${VERSION}/jre/lib/ext/bctls-fips.jar" - JRE_TRUST="${jre_layer}/lib/security/cacerts" - JRE_BOOT="${jre_layer}/lib/ext/bc-fips.jar:${jre_layer}/lib/ext/bcutil-fips.jar:${jre_layer}/lib/ext/bctls-fips.jar" -else - JDK_TRUST="/opt/jdks/${VERSION}/lib/security/cacerts" - JDK_BOOT="/opt/jdks/${VERSION}/lib/bc-fips.jar:/opt/jdks/${VERSION}/lib/bcutil-fips.jar:/opt/jdks/${VERSION}/lib/bctls-fips.jar" - JRE_TRUST="${jre_layer}/lib/security/cacerts" - JRE_BOOT="${jre_layer}/lib/bc-fips.jar:${jre_layer}/lib/bcutil-fips.jar:${jre_layer}/lib/bctls-fips.jar" -fi - -echo -n "${FIPS_BASE} -Djavax.net.ssl.trustStore=${JDK_TRUST} -Xbootclasspath/a:${JDK_BOOT}" > "${jdk_layer}/env.build/JAVA_TOOL_OPTIONS.override" -echo -n "${FIPS_BASE} -Djavax.net.ssl.trustStore=${JRE_TRUST} -Xbootclasspath/a:${JRE_BOOT} -XX:+ExitOnOutOfMemoryError -Xmx${MAX_HEAP}m" > "${jre_layer}/env.launch/JAVA_TOOL_OPTIONS.override" - -exit 0 \ No newline at end of file +#!/usr/bin/env python3 +import os +import sys +import re +import hashlib +import shutil +from pathlib import Path + +# ===================================================================== +# 0. UI & LOGGING SETUP +# ===================================================================== +try: + from rich.console import Console + from rich.table import Table + from rich.panel import Panel + from rich.columns import Columns +except ImportError: + class Console: + def print(self, *args, **kwargs): print(*args) + class Panel: + @staticmethod + def fit(text, title=""): return f"--- {title} ---\n{text}" + +console = Console() + +# ===================================================================== +# DEBUG HELPERS +# ===================================================================== + +def get_dir_fingerprint(directory: Path): + """Generates a fast fingerprint based on file metadata.""" + if not directory.exists(): return "N/A" + fingerprint = hashlib.sha256() + for path in sorted(directory.rglob('*')): + if path.is_file(): + stat = path.stat() + info = f"{path.relative_to(directory)}|{stat.st_size}|{stat.st_mtime}" + fingerprint.update(info.encode()) + return fingerprint.hexdigest()[:16] # Shortened for display + +def read_layer_metadata(toml_path: Path): + metadata = {} + if toml_path.exists(): + content = toml_path.read_text() + for line in content.splitlines(): + match = re.match(r'^\s*([a-zA-Z0-9_]+)\s*=\s*"([^"]+)"', line) + if match: metadata[match.group(1)] = match.group(2) + return metadata + +def write_layer_toml(toml_path: Path, types: dict, metadata: dict): + content = "[types]\n" + for k, v in types.items(): + content += f"{k} = {'true' if v else 'false'}\n" + content += "\n[metadata]\n" + for k, v in metadata.items(): + content += f'{k} = "{v}"\n' + toml_path.write_text(content) + +# ===================================================================== +# MAIN BUILD PROCESS +# ===================================================================== +def main(): + layers_dir = Path(sys.argv[1]) + platform_dir = Path(sys.argv[2]) + plan_path = Path(sys.argv[3]) if len(sys.argv) > 3 else Path("") + + console.print(Panel.fit("[bold cyan]FIPS Java Shim v4.6[/bold cyan]\n[white]Deep Debugging & Cache Analysis[/white]", title="DEBUG MODE")) + + # 1. ARGS DEBUGGING + args_table = Table(title="Buildpack Arguments") + args_table.add_column("Arg", style="dim") + args_table.add_column("Path") + args_table.add_row("$1 (Layers)", str(layers_dir)) + args_table.add_row("$2 (Platform)", str(platform_dir)) + args_table.add_row("$3 (Plan)", str(plan_path)) + console.print(args_table) + + # 2. VERSION RESOLUTION + version = "21" + if plan_path.exists(): + match = re.search(r'version\s*=\s*"([0-9.]+)"', plan_path.read_text()) + if match: version = match.group(1) + + jvm_type = os.getenv("BP_JVM_TYPE", "JRE").upper() + fips_base = "-Dorg.bouncycastle.fips.approved_only=true -Dkeystore.type=BCFKS -Djavax.net.ssl.trustStoreType=BCFKS -Djavax.net.ssl.trustStorePassword=changeit" + + # ================================================================= + # 1. JDK LAYER (BUILD-TIME) + # ================================================================= + jdk_layer = layers_dir / "jdk" + jdk_src = Path(f"/opt/jdks/{version}") + jdk_fp = get_dir_fingerprint(jdk_src) + + jdk_meta = read_layer_metadata(Path(f"{jdk_layer}.toml")) + old_jdk_fp = jdk_meta.get("fingerprint", "NEW") + + jdk_decision = "[bold green]REUSE[/bold green]" if old_jdk_fp == jdk_fp and jdk_layer.exists() else "[bold yellow]UPDATE[/bold yellow]" + + cache_table = Table(title="Layer Cache Analysis") + cache_table.add_column("Layer") + cache_table.add_column("Stored Hash") + cache_table.add_column("Current Hash") + cache_table.add_column("Action") + cache_table.add_row("JDK", old_jdk_fp, jdk_fp, jdk_decision) + + if "UPDATE" in jdk_decision: + if jdk_layer.exists(): shutil.rmtree(jdk_layer) + os.makedirs(jdk_layer, exist_ok=True) + + # Always refresh Metadata and Environment + write_layer_toml(Path(f"{jdk_layer}.toml"), {"launch": False, "build": True, "cache": True}, {"java_version": version, "fingerprint": jdk_fp}) + env_build_dir = jdk_layer / "env.build" + os.makedirs(env_build_dir, exist_ok=True) + (env_build_dir / "JAVA_HOME").write_text(str(jdk_src)) + (env_build_dir / "PATH.prepend").write_text(f"{jdk_src}/bin") + (env_build_dir / "PATH.delim").write_text(":") + + # FIPS JDK Options + trust_dir = "jre/lib" if version == "8" else "lib" + jdk_trust = f"{jdk_src}/{trust_dir}/security/cacerts" + jdk_boot = f"{jdk_src}/{trust_dir}/ext/bc-fips.jar:{jdk_src}/{trust_dir}/ext/bcutil-fips.jar:{jdk_src}/{trust_dir}/ext/bctls-fips.jar" if version == "8" else f"{jdk_src}/lib/bc-fips.jar:{jdk_src}/lib/bcutil-fips.jar:{jdk_src}/lib/bctls-fips.jar" + (env_build_dir / "JAVA_TOOL_OPTIONS.override").write_text(f"{fips_base} -Djavax.net.ssl.trustStore={jdk_trust} -Xbootclasspath/a:{jdk_boot}") + + # ================================================================= + # 2. JRE LAYER (LAUNCH-TIME) + # ================================================================= + jre_layer = layers_dir / "jre" + source_to_copy = jdk_src if jvm_type == "JDK" else Path(f"/opt/jres/{version}") + jre_fp = get_dir_fingerprint(source_to_copy) + + jre_meta = read_layer_metadata(Path(f"{jre_layer}.toml")) + old_jre_fp = jre_meta.get("fingerprint", "NEW") + + # Memory Calc + try: + with open("/sys/fs/cgroup/memory/memory.limit_in_bytes", "r") as f: + total_mem = int(f.read().strip()) + except: + total_mem = 1073741824 + + headroom = int(os.getenv("BPL_JVM_HEAD_ROOM", "25")) + max_heap = int((total_mem * (100 - headroom)) / 100 / 1024 / 1024) + + jre_decision = "[bold green]REUSE[/bold green]" if old_jre_fp == jre_fp and jre_layer.exists() else "[bold yellow]SYNC[/bold yellow]" + cache_table.add_row("JRE", old_jre_fp, jre_fp, jre_decision) + console.print(cache_table) + + if "SYNC" in jre_decision: + if jre_layer.exists(): shutil.rmtree(jre_layer) + shutil.copytree(source_to_copy, jre_layer) + + # Always refresh Metadata and Environment + write_layer_toml(Path(f"{jre_layer}.toml"), {"launch": True, "build": False, "cache": True}, {"java_version": version, "jvm_type": jvm_type, "fingerprint": jre_fp, "max_heap": str(max_heap)}) + + env_launch_dir = jre_layer / "env.launch" + profile_dir = jre_layer / "profile.d" + os.makedirs(env_launch_dir, exist_ok=True) + os.makedirs(profile_dir, exist_ok=True) + + (profile_dir / "symlink_java.sh").write_text(f'#!/bin/sh\nmkdir -p /opt && ln -sf {jre_layer} /opt/java\n') + (env_launch_dir / "JAVA_HOME").write_text("/opt/java") + (env_launch_dir / "PATH.prepend").write_text(f"/opt/java/bin:{jre_layer}/bin") + (env_launch_dir / "PATH.delim").write_text(":") + + # JRE FIPS Options + trust_dir = "lib" if version == "8" and jvm_type == "JRE" else ("jre/lib" if version == "8" else "lib") + jre_trust = f"{jre_layer}/{trust_dir}/security/cacerts" + jre_boot = f"{jre_layer}/{trust_dir}/ext/bc-fips.jar:{jre_layer}/{trust_dir}/ext/bcutil-fips.jar:{jre_layer}/{trust_dir}/ext/bctls-fips.jar" if version == "8" else f"{jre_layer}/lib/bc-fips.jar:{jre_layer}/lib/bcutil-fips.jar:{jre_layer}/lib/bctls-fips.jar" + (env_launch_dir / "JAVA_TOOL_OPTIONS.override").write_text(f"{fips_base} -Djavax.net.ssl.trustStore={jre_trust} -Xbootclasspath/a:{jre_boot} -XX:+ExitOnOutOfMemoryError -Xmx{max_heap}m") + + # ================================================================= + # 3. FINAL VALIDATION + # ================================================================= + final_table = Table(title="Final State Debug") + final_table.add_column("Item", style="cyan") + final_table.add_column("Status") + final_table.add_row("JRE at /opt/java", "READY (via profile.d)") + final_table.add_row("Calculated Xmx", f"{max_heap}MB") + final_table.add_row("Env Build Dir", "REWRITTEN") + console.print(final_table) + + console.print("[bold green]✔ Build Process Complete.[/bold green]") + sys.exit(0) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/fips-java-shim/bin/detect b/fips-java-shim/bin/detect index 7204fe0..29c987b 100755 --- a/fips-java-shim/bin/detect +++ b/fips-java-shim/bin/detect @@ -1,14 +1,99 @@ -#!/usr/bin/env bash -set -e +#!/usr/bin/env python3 +import os +import sys +import re +from pathlib import Path -PLAN="$2" +# ===================================================================== +# 0. UI & LOGGING SETUP +# ===================================================================== +try: + from rich.console import Console + from rich.panel import Panel +except ImportError: + class Console: + def print(self, *args, **kwargs): print(*args) + class Panel: + @staticmethod + def fit(text, title=""): return f"--- {title} ---\n{text}" -cat > "${PLAN}" <([0-9.]+) 8, 17.0.1 -> 17 + clean_version = "8" if "1.8" in version else version.split('.')[0] + + # Validate that we actually have this version in the Builder + jdk_path = Path(f"/opt/jdks/{clean_version}") + if not jdk_path.exists(): + console.print(f"[bold red]ERROR:[/bold red] Java {clean_version} requested but not found in Builder!") + # Force fallback to 21 to prevent build failure if possible + clean_version = "21" + source += " (Fallback to 21 due to missing version)" + + console.print(Panel.fit( + f"Detected Java: [bold yellow]{clean_version}[/bold yellow]\nSource: [bold blue]{source}[/bold blue]", + title="FIPS Java Shim: DETECT" + )) + + # ================================================================= + # 5. WRITE BUILD PLAN + # ================================================================= + # This writes to $2 (plan.toml) so the BUILD phase can read it via $3 + with open(plan_path, "w") as f: + f.write('[[provides]]\nname = "jdk"\n') + f.write('[[provides]]\nname = "jre"\n') + f.write('[[requires]]\nname = "jdk"\n[requires.metadata]\nversion = "' + clean_version + '"\n') + f.write('[[requires]]\nname = "jre"\n[requires.metadata]\nversion = "' + clean_version + '"\n') + + sys.exit(0) + +if __name__ == "__main__": + main() \ No newline at end of file From 2440a20864f5f590816ea9e01f8a06667334d1b7 Mon Sep 17 00:00:00 2001 From: sm8949752-ux Date: Wed, 18 Mar 2026 19:31:34 +0000 Subject: [PATCH 06/21] devcontainer --- .devcontainer/devcontainer.json | 41 ++++++++++++++++----------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index e51fc91..427da87 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,24 +1,23 @@ { - "name": "FIPS Buildpack Developer Environment", - "build": { - "dockerfile": "Dockerfile" - }, - "features": { - "ghcr.io/devcontainers/features/docker-outside-of-docker:1": { - "version": "latest", - "enableNonRootChildContainerUsage": true + "version": "2.0.0", + "tasks": [ + { + "label": "1. Prepare Builder", + "type": "shell", + "command": "export DOCKER_API_VERSION=1.43 && cd build-image && docker build -t taha/wolfi-build-image:latest . && cd ../2-builder && pack builder create taha/wolfi-fips-builder:latest --config builder.toml", + "problemMatcher": [] + }, + { + "label": "2. Prepare Run Image", + "type": "shell", + "command": "export DOCKER_API_VERSION=1.43 && cd run-image && docker build -t taha/wolfi-run-image:latest .", + "problemMatcher": [] + }, + { + "label": "3. Build App Maven", + "type": "shell", + "command": "export DOCKER_API_VERSION=1.43 && pack build taha/maven-fips-app --path 3-sample-app --builder taha/wolfi-fips-builder:latest --env BP_JVM_TYPE=JRE --publish=false", + "problemMatcher": [] } - }, - "customizations": { - "vscode": { - "extensions": [ - "ms-azuretools.vscode-docker", - "ms-python.python", - "tamasfe.even-better-toml", - "irongeek.vscode-env" - ] - } - }, - "remoteUser": "vscode", - "postCreateCommand": "sudo chown vscode:vscode /var/run/docker.sock || true" + ] } \ No newline at end of file From 494359baff0d4346e6e59c3e665b2f11e55a7262 Mon Sep 17 00:00:00 2001 From: sm8949752-ux Date: Wed, 18 Mar 2026 21:48:27 +0200 Subject: [PATCH 07/21] Change base image to Ubuntu 22.04 and update dependencies Updated base image to Ubuntu 22.04 and modified package installations. --- .devcontainer/Dockerfile | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 1aeef33..d069626 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,17 +1,16 @@ -FROM mcr.microsoft.com/devcontainers/base:jammy +FROM ubuntu:22.04 + +ENV DEBIAN_FRONTEND=noninteractive -# Install Python and essential tools RUN apt-get update && apt-get install -y \ python3 \ python3-pip \ curl \ git \ - xz-utils \ + sudo \ && rm -rf /var/lib/apt/lists/* -# Install pack CLI (Official Binary) RUN curl -sSL "https://github.com/buildpacks/pack/releases/download/v0.36.4/pack-v0.36.4-linux.tgz" \ | tar -C /usr/local/bin/ --no-same-owner -xzv pack -# Install Python UI libraries for local testing of your Buildpack scripts -RUN pip3 install rich tomli tomli-w \ No newline at end of file +RUN pip3 install rich From 24d373312d8a28b3fee9f3dff352b2f4bad03f77 Mon Sep 17 00:00:00 2001 From: sm8949752-ux Date: Wed, 18 Mar 2026 21:48:50 +0200 Subject: [PATCH 08/21] Update devcontainer configuration with new settings --- .devcontainer/devcontainer.json | 44 +++++++++++++++++---------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 427da87..596b801 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,23 +1,25 @@ { - "version": "2.0.0", - "tasks": [ - { - "label": "1. Prepare Builder", - "type": "shell", - "command": "export DOCKER_API_VERSION=1.43 && cd build-image && docker build -t taha/wolfi-build-image:latest . && cd ../2-builder && pack builder create taha/wolfi-fips-builder:latest --config builder.toml", - "problemMatcher": [] - }, - { - "label": "2. Prepare Run Image", - "type": "shell", - "command": "export DOCKER_API_VERSION=1.43 && cd run-image && docker build -t taha/wolfi-run-image:latest .", - "problemMatcher": [] - }, - { - "label": "3. Build App Maven", - "type": "shell", - "command": "export DOCKER_API_VERSION=1.43 && pack build taha/maven-fips-app --path 3-sample-app --builder taha/wolfi-fips-builder:latest --env BP_JVM_TYPE=JRE --publish=false", - "problemMatcher": [] + "name": "FIPS Buildpack Custom Dev", + "build": { + "dockerfile": "Dockerfile" + }, + "features": { + "ghcr.io/devcontainers/features/docker-outside-of-docker:1": { + "version": "latest" } - ] -} \ No newline at end of file + }, + "containerEnv": { + "DOCKER_API_VERSION": "1.43" + }, + "customizations": { + "vscode": { + "extensions": [ + "ms-azuretools.vscode-docker", + "ms-python.python", + "tamasfe.even-better-toml" + ] + } + }, + "remoteUser": "root", + "postCreateCommand": "sudo chown root:root /var/run/docker.sock || true" +} From 34a9e1755f1642ef60e87394890184c3bb2dffce Mon Sep 17 00:00:00 2001 From: sm8949752-ux Date: Wed, 18 Mar 2026 21:54:16 +0200 Subject: [PATCH 09/21] Fix Dockerfile to ensure rich is installed From ac98ce7a6ac64169e4dce6da346d2c699346c665 Mon Sep 17 00:00:00 2001 From: sm8949752-ux Date: Wed, 18 Mar 2026 21:54:31 +0200 Subject: [PATCH 10/21] Rename devcontainer to FIPS Buildpack Dev --- .devcontainer/devcontainer.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 596b801..25c2cf4 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,5 +1,5 @@ { - "name": "FIPS Buildpack Custom Dev", + "name": "FIPS Buildpack Dev", "build": { "dockerfile": "Dockerfile" }, @@ -20,6 +20,5 @@ ] } }, - "remoteUser": "root", - "postCreateCommand": "sudo chown root:root /var/run/docker.sock || true" + "remoteUser": "root" } From 28fb33d93de2596e93506ef20f8b33b41fe3d0fc Mon Sep 17 00:00:00 2001 From: sm8949752-ux Date: Wed, 18 Mar 2026 20:02:16 +0000 Subject: [PATCH 11/21] fix: devcontainer --- .devcontainer/Dockerfile | 12 +++++------- .devcontainer/devcontainer.json | 29 ++++++++++++++++++----------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index d069626..ca2fe54 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,14 +1,12 @@ FROM ubuntu:22.04 + ENV DEBIAN_FRONTEND=noninteractive -RUN apt-get update && apt-get install -y \ - python3 \ - python3-pip \ - curl \ - git \ - sudo \ - && rm -rf /var/lib/apt/lists/* +RUN apt-get update && apt-get install -y --no-install-recommends \ + sudo curl python3 python3-pip wget git ca-certificates jq iproute2 tcpdump dnsutils net-tools bash-completion tar gzip \ + && apt-get clean && rm -rf /var/lib/apt/lists/* + RUN curl -sSL "https://github.com/buildpacks/pack/releases/download/v0.36.4/pack-v0.36.4-linux.tgz" \ | tar -C /usr/local/bin/ --no-same-owner -xzv pack diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 25c2cf4..5ff1cdb 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,24 +1,31 @@ { - "name": "FIPS Buildpack Dev", + "name": "CNB java", "build": { "dockerfile": "Dockerfile" }, "features": { - "ghcr.io/devcontainers/features/docker-outside-of-docker:1": { - "version": "latest" + "ghcr.io/devcontainers/features/docker-in-docker:2": { + "version": "latest", + "enableNonRootDocker": true, + "moby": true + }, + "ghcr.io/devcontainers/features/common-utils:2": { + "username": "vscode" } }, - "containerEnv": { - "DOCKER_API_VERSION": "1.43" - }, "customizations": { "vscode": { "extensions": [ + "ms-kubernetes-tools.vscode-kubernetes-tools", + "redhat.vscode-yaml", "ms-azuretools.vscode-docker", - "ms-python.python", - "tamasfe.even-better-toml" - ] + "pkief.material-icon-theme" + ], + "settings": { + "terminal.integrated.defaultProfile.linux": "bash" + } } }, - "remoteUser": "root" -} + "remoteUser": "vscode", + "postCreateCommand": "echo 'The Environment is ready!'" +} \ No newline at end of file From bf17d83e5f21c517996989b65126df1c2118e6a2 Mon Sep 17 00:00:00 2001 From: sm8949752-ux Date: Wed, 18 Mar 2026 20:15:47 +0000 Subject: [PATCH 12/21] fix devcontainer --- .devcontainer/Dockerfile | 3 +-- .vscode/tasks.json | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index ca2fe54..8fcf6aa 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -4,11 +4,10 @@ FROM ubuntu:22.04 ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y --no-install-recommends \ - sudo curl python3 python3-pip wget git ca-certificates jq iproute2 tcpdump dnsutils net-tools bash-completion tar gzip \ + sudo curl python3 python3-pip wget git bash-completion tar gzip \ && apt-get clean && rm -rf /var/lib/apt/lists/* RUN curl -sSL "https://github.com/buildpacks/pack/releases/download/v0.36.4/pack-v0.36.4-linux.tgz" \ | tar -C /usr/local/bin/ --no-same-owner -xzv pack -RUN pip3 install rich diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 215b506..ef5eebb 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -14,12 +14,12 @@ { "label": "3. Build App Gradle", "type": "shell", - "command": "pack build taha/gradle-fips-app --path 4-gradle-app --builder taha/wolfi-fips-builder:latest --env BP_JVM_TYPE=JRE --publish=false --clear-cache" + "command": "pack build taha/gradle-fips-app --path 4-gradle-app --builder taha/wolfi-fips-builder:latest --env BP_JVM_TYPE=JRE --publish=false " }, { "label": "3. Build App Maven", "type": "shell", - "command": "pack build taha/maven-fips-app --path 3-sample-app --builder taha/wolfi-fips-builder:latest --env BP_JVM_TYPE=JRE --publish=false --clear-cache" + "command": "pack build taha/maven-fips-app --path 3-sample-app --builder taha/wolfi-fips-builder:latest --env BP_JVM_TYPE=JRE --publish=false " }, { "label": "4. Run App", From 2af91290e37771af2f656564616c08570fdbb695 Mon Sep 17 00:00:00 2001 From: sm8949752-ux Date: Wed, 18 Mar 2026 20:29:43 +0000 Subject: [PATCH 13/21] fix:update devcontainer --- .devcontainer/devcontainer.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 5ff1cdb..26cfd3e 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -3,6 +3,10 @@ "build": { "dockerfile": "Dockerfile" }, + "containerEnv": { + "DOCKER_API_VERSION": "1.41" + }, + "features": { "ghcr.io/devcontainers/features/docker-in-docker:2": { "version": "latest", From 73afbf6d5a4121a4a0cdc626cbca67b2032e8909 Mon Sep 17 00:00:00 2001 From: sm8949752-ux Date: Wed, 18 Mar 2026 21:29:27 +0000 Subject: [PATCH 14/21] fix devcontainer --- .devcontainer/Dockerfile | 14 ++++++++++---- .devcontainer/devcontainer.json | 13 +++++++------ 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 8fcf6aa..512d2c9 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,13 +1,19 @@ FROM ubuntu:22.04 - ENV DEBIAN_FRONTEND=noninteractive -RUN apt-get update && apt-get install -y --no-install-recommends \ - sudo curl python3 python3-pip wget git bash-completion tar gzip \ - && apt-get clean && rm -rf /var/lib/apt/lists/* +RUN apt-get update && apt-get install -y \ + python3 \ + python3-pip \ + curl \ + git \ + sudo \ + && rm -rf /var/lib/apt/lists/* +RUN useradd -m -s /bin/bash vscode && \ + echo "vscode ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers RUN curl -sSL "https://github.com/buildpacks/pack/releases/download/v0.36.4/pack-v0.36.4-linux.tgz" \ | tar -C /usr/local/bin/ --no-same-owner -xzv pack +USER vscode \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 26cfd3e..8042134 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -6,14 +6,13 @@ "containerEnv": { "DOCKER_API_VERSION": "1.41" }, - "features": { - "ghcr.io/devcontainers/features/docker-in-docker:2": { + "ghcr.io/devcontainers/features/docker-outside-of-docker:1": { "version": "latest", - "enableNonRootDocker": true, - "moby": true + "enableNonRootChildContainerUsage": true }, "ghcr.io/devcontainers/features/common-utils:2": { + "configureZshAsDefaultShell": false, "username": "vscode" } }, @@ -23,7 +22,9 @@ "ms-kubernetes-tools.vscode-kubernetes-tools", "redhat.vscode-yaml", "ms-azuretools.vscode-docker", - "pkief.material-icon-theme" + "pkief.material-icon-theme", + "ms-python.python", + "tamasfe.even-better-toml" ], "settings": { "terminal.integrated.defaultProfile.linux": "bash" @@ -31,5 +32,5 @@ } }, "remoteUser": "vscode", - "postCreateCommand": "echo 'The Environment is ready!'" + "postCreateCommand": "pip3 install rich && sudo chown vscode:vscode /var/run/docker.sock || true" } \ No newline at end of file From c0ffe1f5c814ee687d40c0d5a03d3e8a2391d782 Mon Sep 17 00:00:00 2001 From: sm8949752-ux Date: Wed, 18 Mar 2026 21:47:13 +0000 Subject: [PATCH 15/21] fix devcontainer --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 8042134..7527239 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -32,5 +32,5 @@ } }, "remoteUser": "vscode", - "postCreateCommand": "pip3 install rich && sudo chown vscode:vscode /var/run/docker.sock || true" + "postCreateCommand": "sudo chmod 666 /var/run/docker.sock && pip3 install rich && sudo chown vscode:vscode /var/run/docker.sock || true" } \ No newline at end of file From af1b8d42cd8c3398eebcb02333abea02447371e7 Mon Sep 17 00:00:00 2001 From: sm8949752-ux Date: Fri, 20 Mar 2026 06:28:10 +0000 Subject: [PATCH 16/21] refactor: streamline build process and enhance logging --- 2-builder/builder.toml | 2 +- fips-java-shim/bin/build | 261 ++++++++++++++++----------------------- 2 files changed, 109 insertions(+), 154 deletions(-) diff --git a/2-builder/builder.toml b/2-builder/builder.toml index 6f58fb8..d042324 100644 --- a/2-builder/builder.toml +++ b/2-builder/builder.toml @@ -1,4 +1,4 @@ -description = "My Custom Wolfi FIPS Builder" +description = "Custom Wolfi FIPS Builder" [stack] id = "io.buildpacks.stacks.jammy" diff --git a/fips-java-shim/bin/build b/fips-java-shim/bin/build index 90efa5b..2c7dbf8 100755 --- a/fips-java-shim/bin/build +++ b/fips-java-shim/bin/build @@ -6,181 +6,136 @@ import hashlib import shutil from pathlib import Path -# ===================================================================== -# 0. UI & LOGGING SETUP -# ===================================================================== -try: - from rich.console import Console - from rich.table import Table - from rich.panel import Panel - from rich.columns import Columns -except ImportError: - class Console: - def print(self, *args, **kwargs): print(*args) - class Panel: - @staticmethod - def fit(text, title=""): return f"--- {title} ---\n{text}" - -console = Console() - -# ===================================================================== -# DEBUG HELPERS -# ===================================================================== - -def get_dir_fingerprint(directory: Path): - """Generates a fast fingerprint based on file metadata.""" - if not directory.exists(): return "N/A" - fingerprint = hashlib.sha256() - for path in sorted(directory.rglob('*')): - if path.is_file(): - stat = path.stat() - info = f"{path.relative_to(directory)}|{stat.st_size}|{stat.st_mtime}" - fingerprint.update(info.encode()) - return fingerprint.hexdigest()[:16] # Shortened for display - -def read_layer_metadata(toml_path: Path): - metadata = {} - if toml_path.exists(): - content = toml_path.read_text() - for line in content.splitlines(): - match = re.match(r'^\s*([a-zA-Z0-9_]+)\s*=\s*"([^"]+)"', line) - if match: metadata[match.group(1)] = match.group(2) - return metadata - -def write_layer_toml(toml_path: Path, types: dict, metadata: dict): - content = "[types]\n" - for k, v in types.items(): - content += f"{k} = {'true' if v else 'false'}\n" - content += "\n[metadata]\n" - for k, v in metadata.items(): - content += f'{k} = "{v}"\n' - toml_path.write_text(content) - -# ===================================================================== -# MAIN BUILD PROCESS -# ===================================================================== +# --- Professional Logging UI Elements --- +G, Y, C, R, RESET, BOLD = "\033[0;32m", "\033[0;33m", "\033[0;36m", "\033[0;31m", "\033[0m", "\033[1m" +TICK, BOX, ARROW = "✓", "❒", "↳" + +def log_header(title): + print(f"\n{BOLD}{C}===> {title}{RESET}") + +def log_step(layer, action, detail=""): + color = G if action in ["REUSE", "HIT", "READY"] else Y + symbol = TICK if action in ["REUSE", "HIT", "READY"] else BOX + print(f" {BOLD}{layer:<10}{RESET} : {color}{symbol} {action:<10}{RESET} {R}{ARROW}{RESET} {detail}") + +def get_memory_limit(): + """Detects memory limit supporting both cgroup v1 and v2.""" + paths = [Path("/sys/fs/cgroup/memory.max"), Path("/sys/fs/cgroup/memory/memory.limit_in_bytes")] + for p in paths: + try: + if p.exists(): + val = p.read_text().strip() + if val != "max": return int(val) + except: pass + return 1073741824 # Fallback to 1GB + +def get_fingerprint(directory: Path): + """Fast fingerprint based on binary directory metadata.""" + if not directory.exists(): return "MISSING" + hasher = hashlib.sha256() + for p in sorted(directory.glob('bin/*')): + if p.is_file(): + hasher.update(f"{p.name}{p.stat().st_size}".encode()) + return hasher.hexdigest()[:12] + def main(): + if len(sys.argv) < 3: sys.exit(1) layers_dir = Path(sys.argv[1]) - platform_dir = Path(sys.argv[2]) plan_path = Path(sys.argv[3]) if len(sys.argv) > 3 else Path("") + + log_header("FIPS Java Shim v4.18 (FIPS Env Restored)") - console.print(Panel.fit("[bold cyan]FIPS Java Shim v4.6[/bold cyan]\n[white]Deep Debugging & Cache Analysis[/white]", title="DEBUG MODE")) - - # 1. ARGS DEBUGGING - args_table = Table(title="Buildpack Arguments") - args_table.add_column("Arg", style="dim") - args_table.add_column("Path") - args_table.add_row("$1 (Layers)", str(layers_dir)) - args_table.add_row("$2 (Platform)", str(platform_dir)) - args_table.add_row("$3 (Plan)", str(plan_path)) - console.print(args_table) - - # 2. VERSION RESOLUTION + # 1. RESOLVE GLOBAL CONFIGURATION version = "21" if plan_path.exists(): match = re.search(r'version\s*=\s*"([0-9.]+)"', plan_path.read_text()) if match: version = match.group(1) - + jvm_type = os.getenv("BP_JVM_TYPE", "JRE").upper() + mem_limit = get_memory_limit() + headroom = int(os.getenv("BPL_JVM_HEAD_ROOM", "25")) + max_heap = int((mem_limit * (100 - headroom)) / 100 / 1024 / 1024) + + # Standard FIPS base from your v4.6 fips_base = "-Dorg.bouncycastle.fips.approved_only=true -Dkeystore.type=BCFKS -Djavax.net.ssl.trustStoreType=BCFKS -Djavax.net.ssl.trustStorePassword=changeit" - # ================================================================= - # 1. JDK LAYER (BUILD-TIME) - # ================================================================= + # 2. JDK LAYER (BUILD-TIME) jdk_layer = layers_dir / "jdk" jdk_src = Path(f"/opt/jdks/{version}") - jdk_fp = get_dir_fingerprint(jdk_src) - - jdk_meta = read_layer_metadata(Path(f"{jdk_layer}.toml")) - old_jdk_fp = jdk_meta.get("fingerprint", "NEW") - - jdk_decision = "[bold green]REUSE[/bold green]" if old_jdk_fp == jdk_fp and jdk_layer.exists() else "[bold yellow]UPDATE[/bold yellow]" - - cache_table = Table(title="Layer Cache Analysis") - cache_table.add_column("Layer") - cache_table.add_column("Stored Hash") - cache_table.add_column("Current Hash") - cache_table.add_column("Action") - cache_table.add_row("JDK", old_jdk_fp, jdk_fp, jdk_decision) - - if "UPDATE" in jdk_decision: + jdk_fp = get_fingerprint(jdk_src) + jdk_toml = layers_dir / "jdk.toml" + + if jdk_toml.exists() and jdk_fp in jdk_toml.read_text() and jdk_layer.exists(): + log_step("JDK", "REUSE", f"Fingerprint: {jdk_fp}") + else: + log_step("JDK", "UPDATE", f"Source: {jdk_src}") if jdk_layer.exists(): shutil.rmtree(jdk_layer) - os.makedirs(jdk_layer, exist_ok=True) - - # Always refresh Metadata and Environment - write_layer_toml(Path(f"{jdk_layer}.toml"), {"launch": False, "build": True, "cache": True}, {"java_version": version, "fingerprint": jdk_fp}) - env_build_dir = jdk_layer / "env.build" - os.makedirs(env_build_dir, exist_ok=True) - (env_build_dir / "JAVA_HOME").write_text(str(jdk_src)) - (env_build_dir / "PATH.prepend").write_text(f"{jdk_src}/bin") - (env_build_dir / "PATH.delim").write_text(":") + jdk_layer.mkdir(parents=True) - # FIPS JDK Options - trust_dir = "jre/lib" if version == "8" else "lib" - jdk_trust = f"{jdk_src}/{trust_dir}/security/cacerts" - jdk_boot = f"{jdk_src}/{trust_dir}/ext/bc-fips.jar:{jdk_src}/{trust_dir}/ext/bcutil-fips.jar:{jdk_src}/{trust_dir}/ext/bctls-fips.jar" if version == "8" else f"{jdk_src}/lib/bc-fips.jar:{jdk_src}/lib/bcutil-fips.jar:{jdk_src}/lib/bctls-fips.jar" - (env_build_dir / "JAVA_TOOL_OPTIONS.override").write_text(f"{fips_base} -Djavax.net.ssl.trustStore={jdk_trust} -Xbootclasspath/a:{jdk_boot}") - - # ================================================================= - # 2. JRE LAYER (LAUNCH-TIME) - # ================================================================= - jre_layer = layers_dir / "jre" - source_to_copy = jdk_src if jvm_type == "JDK" else Path(f"/opt/jres/{version}") - jre_fp = get_dir_fingerprint(source_to_copy) + jdk_toml.write_text(f'[types]\nbuild = true\ncache = true\n[metadata]\nfingerprint = "{jdk_fp}"\n') - jre_meta = read_layer_metadata(Path(f"{jre_layer}.toml")) - old_jre_fp = jre_meta.get("fingerprint", "NEW") + # Configure JDK Environment (FIPS paths logic from v4.6) + env_build = jdk_layer / "env.build" + env_build.mkdir(exist_ok=True) + (env_build / "JAVA_HOME").write_text(str(jdk_src)) + (env_build / "PATH.prepend").write_text(f"{jdk_src}/bin") + (env_build / "PATH.delim").write_text(":") + + jdk_trust_dir = "jre/lib" if version == "8" else "lib" + jdk_trust = jdk_src / jdk_trust_dir / "security/cacerts" - # Memory Calc - try: - with open("/sys/fs/cgroup/memory/memory.limit_in_bytes", "r") as f: - total_mem = int(f.read().strip()) - except: - total_mem = 1073741824 + if version == "8": + jdk_boot = f"{jdk_src}/{jdk_trust_dir}/ext/bc-fips.jar:{jdk_src}/{jdk_trust_dir}/ext/bcutil-fips.jar:{jdk_src}/{jdk_trust_dir}/ext/bctls-fips.jar" + else: + jdk_boot = f"{jdk_src}/lib/bc-fips.jar:{jdk_src}/lib/bcutil-fips.jar:{jdk_src}/lib/bctls-fips.jar" - headroom = int(os.getenv("BPL_JVM_HEAD_ROOM", "25")) - max_heap = int((total_mem * (100 - headroom)) / 100 / 1024 / 1024) - - jre_decision = "[bold green]REUSE[/bold green]" if old_jre_fp == jre_fp and jre_layer.exists() else "[bold yellow]SYNC[/bold yellow]" - cache_table.add_row("JRE", old_jre_fp, jre_fp, jre_decision) - console.print(cache_table) + (env_build / "JAVA_TOOL_OPTIONS.override").write_text(f"{fips_base} -Djavax.net.ssl.trustStore={jdk_trust} -Xbootclasspath/a:{jdk_boot}") - if "SYNC" in jre_decision: + # 3. JRE LAYER (LAUNCH-TIME) + jre_layer = layers_dir / "jre" + jre_src = jdk_src if jvm_type == "JDK" else Path(f"/opt/jres/{version}") + jre_fp = get_fingerprint(jre_src) + jre_toml = layers_dir / "jre.toml" + + if jre_toml.exists() and jre_fp in jre_toml.read_text() and jre_layer.exists(): + log_step("JRE", "REUSE", "Restored from cache") + else: + log_step("JRE", "SYNC", f"Syncing {jre_src}") if jre_layer.exists(): shutil.rmtree(jre_layer) - shutil.copytree(source_to_copy, jre_layer) + shutil.copytree(jre_src, jre_layer) + + jre_toml.write_text(f'[types]\nlaunch = true\ncache = true\n[metadata]\nfingerprint = "{jre_fp}"\nmax_heap = "{max_heap}MB"\n') - # Always refresh Metadata and Environment - write_layer_toml(Path(f"{jre_layer}.toml"), {"launch": True, "build": False, "cache": True}, {"java_version": version, "jvm_type": jvm_type, "fingerprint": jre_fp, "max_heap": str(max_heap)}) + # 4. RUNTIME ENVIRONMENT (Distroless Direct Pathing) + env_launch = jre_layer / "env.launch" + env_launch.mkdir(exist_ok=True) + + # Absolute pathing for JAVA_HOME in Distroless + (env_launch / "JAVA_HOME").write_text(str(jre_layer)) + (env_launch / "PATH.prepend").write_text(str(jre_layer / "bin")) + (env_launch / "PATH.delim").write_text(":") - env_launch_dir = jre_layer / "env.launch" - profile_dir = jre_layer / "profile.d" - os.makedirs(env_launch_dir, exist_ok=True) - os.makedirs(profile_dir, exist_ok=True) + # FIPS JRE Options (Logic from v4.6) + if version == "8" and jvm_type == "JRE": + jre_trust_dir = "lib" + elif version == "8": + jre_trust_dir = "jre/lib" + else: + jre_trust_dir = "lib" + + jre_trust = jre_layer / jre_trust_dir / "security/cacerts" - (profile_dir / "symlink_java.sh").write_text(f'#!/bin/sh\nmkdir -p /opt && ln -sf {jre_layer} /opt/java\n') - (env_launch_dir / "JAVA_HOME").write_text("/opt/java") - (env_launch_dir / "PATH.prepend").write_text(f"/opt/java/bin:{jre_layer}/bin") - (env_launch_dir / "PATH.delim").write_text(":") - - # JRE FIPS Options - trust_dir = "lib" if version == "8" and jvm_type == "JRE" else ("jre/lib" if version == "8" else "lib") - jre_trust = f"{jre_layer}/{trust_dir}/security/cacerts" - jre_boot = f"{jre_layer}/{trust_dir}/ext/bc-fips.jar:{jre_layer}/{trust_dir}/ext/bcutil-fips.jar:{jre_layer}/{trust_dir}/ext/bctls-fips.jar" if version == "8" else f"{jre_layer}/lib/bc-fips.jar:{jre_layer}/lib/bcutil-fips.jar:{jre_layer}/lib/bctls-fips.jar" - (env_launch_dir / "JAVA_TOOL_OPTIONS.override").write_text(f"{fips_base} -Djavax.net.ssl.trustStore={jre_trust} -Xbootclasspath/a:{jre_boot} -XX:+ExitOnOutOfMemoryError -Xmx{max_heap}m") - - # ================================================================= - # 3. FINAL VALIDATION - # ================================================================= - final_table = Table(title="Final State Debug") - final_table.add_column("Item", style="cyan") - final_table.add_column("Status") - final_table.add_row("JRE at /opt/java", "READY (via profile.d)") - final_table.add_row("Calculated Xmx", f"{max_heap}MB") - final_table.add_row("Env Build Dir", "REWRITTEN") - console.print(final_table) - - console.print("[bold green]✔ Build Process Complete.[/bold green]") - sys.exit(0) + if version == "8": + jre_boot = f"{jre_layer}/{jre_trust_dir}/ext/bc-fips.jar:{jre_layer}/{jre_trust_dir}/ext/bcutil-fips.jar:{jre_layer}/{jre_trust_dir}/ext/bctls-fips.jar" + else: + jre_boot = f"{jre_layer}/lib/bc-fips.jar:{jre_layer}/lib/bcutil-fips.jar:{jre_layer}/lib/bctls-fips.jar" + + runtime_opts = f"{fips_base} -Djavax.net.ssl.trustStore={jre_trust} -Xbootclasspath/a:{jre_boot} -XX:+ExitOnOutOfMemoryError -Xmx{max_heap}m" + (env_launch / "JAVA_TOOL_OPTIONS.override").write_text(runtime_opts) + + # 5. SUMMARY + log_step("SUMMARY", "READY", f"Xmx: {max_heap}MB | FIPS: Enabled | Distroless: True") + print(f"{G}{BOLD}===> Buildpack successfully finished{RESET}\n") if __name__ == "__main__": - main() + main() \ No newline at end of file From d59a3bf7dc0c185a57b97c875ae6d43ecd1ac6a4 Mon Sep 17 00:00:00 2001 From: sm8949752-ux Date: Fri, 20 Mar 2026 22:12:24 +0000 Subject: [PATCH 17/21] feat: enhance build process with Java Memory Assistant integration and improved logging --- fips-java-shim/bin/build | 171 +++++++++++++++++++++++++++------------ 1 file changed, 120 insertions(+), 51 deletions(-) diff --git a/fips-java-shim/bin/build b/fips-java-shim/bin/build index 2c7dbf8..70ced9a 100755 --- a/fips-java-shim/bin/build +++ b/fips-java-shim/bin/build @@ -4,9 +4,12 @@ import sys import re import hashlib import shutil +import urllib.request from pathlib import Path -# --- Professional Logging UI Elements --- +# ============================================================================== +# [0] UTILITIES & CONFIGURATION +# ============================================================================== G, Y, C, R, RESET, BOLD = "\033[0;32m", "\033[0;33m", "\033[0;36m", "\033[0;31m", "\033[0m", "\033[1m" TICK, BOX, ARROW = "✓", "❒", "↳" @@ -18,19 +21,7 @@ def log_step(layer, action, detail=""): symbol = TICK if action in ["REUSE", "HIT", "READY"] else BOX print(f" {BOLD}{layer:<10}{RESET} : {color}{symbol} {action:<10}{RESET} {R}{ARROW}{RESET} {detail}") -def get_memory_limit(): - """Detects memory limit supporting both cgroup v1 and v2.""" - paths = [Path("/sys/fs/cgroup/memory.max"), Path("/sys/fs/cgroup/memory/memory.limit_in_bytes")] - for p in paths: - try: - if p.exists(): - val = p.read_text().strip() - if val != "max": return int(val) - except: pass - return 1073741824 # Fallback to 1GB - def get_fingerprint(directory: Path): - """Fast fingerprint based on binary directory metadata.""" if not directory.exists(): return "MISSING" hasher = hashlib.sha256() for p in sorted(directory.glob('bin/*')): @@ -38,6 +29,16 @@ def get_fingerprint(directory: Path): hasher.update(f"{p.name}{p.stat().st_size}".encode()) return hasher.hexdigest()[:12] +def download_jma(target_dir: Path): + jma_url = "https://github.com/SAP-archive/java-memory-assistant/releases/download/0.5.0/java-memory-assistant-0.5.0.jar" + jma_jar = target_dir / "java-memory-assistant.jar" + if not jma_jar.exists(): + urllib.request.urlretrieve(jma_url, jma_jar) + return jma_jar + +# ============================================================================== +# [1] GLOBAL PARAMETERS +# ============================================================================== def main(): if len(sys.argv) < 3: sys.exit(1) layers_dir = Path(sys.argv[1]) @@ -45,25 +46,23 @@ def main(): log_header("FIPS Java Shim v4.18 (FIPS Env Restored)") - # 1. RESOLVE GLOBAL CONFIGURATION version = "21" if plan_path.exists(): match = re.search(r'version\s*=\s*"([0-9.]+)"', plan_path.read_text()) if match: version = match.group(1) jvm_type = os.getenv("BP_JVM_TYPE", "JRE").upper() - mem_limit = get_memory_limit() headroom = int(os.getenv("BPL_JVM_HEAD_ROOM", "25")) - max_heap = int((mem_limit * (100 - headroom)) / 100 / 1024 / 1024) - - # Standard FIPS base from your v4.6 + ram_percentage = float(100 - headroom) fips_base = "-Dorg.bouncycastle.fips.approved_only=true -Dkeystore.type=BCFKS -Djavax.net.ssl.trustStoreType=BCFKS -Djavax.net.ssl.trustStorePassword=changeit" - # 2. JDK LAYER (BUILD-TIME) + # ========================================================================== + # [LAYER 1] JDK LAYER (DIRECTORY: jdk/ + METADATA: jdk.toml) + # ========================================================================== jdk_layer = layers_dir / "jdk" + jdk_toml = layers_dir / "jdk.toml" jdk_src = Path(f"/opt/jdks/{version}") jdk_fp = get_fingerprint(jdk_src) - jdk_toml = layers_dir / "jdk.toml" if jdk_toml.exists() and jdk_fp in jdk_toml.read_text() and jdk_layer.exists(): log_step("JDK", "REUSE", f"Fingerprint: {jdk_fp}") @@ -72,70 +71,140 @@ def main(): if jdk_layer.exists(): shutil.rmtree(jdk_layer) jdk_layer.mkdir(parents=True) - jdk_toml.write_text(f'[types]\nbuild = true\ncache = true\n[metadata]\nfingerprint = "{jdk_fp}"\n') - - # Configure JDK Environment (FIPS paths logic from v4.6) + jdk_toml.write_text(f""" + [types] + build = true + cache = true + launch = false + [metadata] + fingerprint = "{jdk_fp}" + """.strip()) + env_build = jdk_layer / "env.build" env_build.mkdir(exist_ok=True) (env_build / "JAVA_HOME").write_text(str(jdk_src)) (env_build / "PATH.prepend").write_text(f"{jdk_src}/bin") (env_build / "PATH.delim").write_text(":") - + jdk_trust_dir = "jre/lib" if version == "8" else "lib" jdk_trust = jdk_src / jdk_trust_dir / "security/cacerts" if version == "8": - jdk_boot = f"{jdk_src}/{jdk_trust_dir}/ext/bc-fips.jar:{jdk_src}/{jdk_trust_dir}/ext/bcutil-fips.jar:{jdk_src}/{jdk_trust_dir}/ext/bctls-fips.jar" + jdk_boot = ( + f"{jdk_src}/{jdk_trust_dir}/ext/bc-fips.jar:" + f"{jdk_src}/{jdk_trust_dir}/ext/bcutil-fips.jar:" + f"{jdk_src}/{jdk_trust_dir}/ext/bctls-fips.jar" + ) else: - jdk_boot = f"{jdk_src}/lib/bc-fips.jar:{jdk_src}/lib/bcutil-fips.jar:{jdk_src}/lib/bctls-fips.jar" - - (env_build / "JAVA_TOOL_OPTIONS.override").write_text(f"{fips_base} -Djavax.net.ssl.trustStore={jdk_trust} -Xbootclasspath/a:{jdk_boot}") + jdk_boot = ( + f"{jdk_src}/lib/bc-fips.jar:" + f"{jdk_src}/lib/bcutil-fips.jar:" + f"{jdk_src}/lib/bctls-fips.jar" + ) + + java_opts = ( + f"{fips_base} " + f"-Djavax.net.ssl.trustStore={jdk_trust} " + f"-Xbootclasspath/a:{jdk_boot}" + ) + + (env_build / "JAVA_TOOL_OPTIONS.override").write_text(java_opts) - # 3. JRE LAYER (LAUNCH-TIME) + + # ========================================================================== + # [LAYER 2] JRE LAYER (DIRECTORY: jre/ + METADATA: jre.toml) + # ========================================================================== jre_layer = layers_dir / "jre" + jre_toml = layers_dir / "jre.toml" + jre_src = jdk_src if jvm_type == "JDK" else Path(f"/opt/jres/{version}") jre_fp = get_fingerprint(jre_src) - jre_toml = layers_dir / "jre.toml" - if jre_toml.exists() and jre_fp in jre_toml.read_text() and jre_layer.exists(): + use_cache = ( + jre_toml.exists() and + jre_layer.exists() and + jre_fp in jre_toml.read_text() + ) + + if use_cache: log_step("JRE", "REUSE", "Restored from cache") else: log_step("JRE", "SYNC", f"Syncing {jre_src}") - if jre_layer.exists(): shutil.rmtree(jre_layer) + if jre_layer.exists(): + shutil.rmtree(jre_layer) shutil.copytree(jre_src, jre_layer) - jre_toml.write_text(f'[types]\nlaunch = true\ncache = true\n[metadata]\nfingerprint = "{jre_fp}"\nmax_heap = "{max_heap}MB"\n') + jre_toml.write_text(f""" + [types] + launch = true + cache = true + + [metadata] + fingerprint = "{jre_fp}" + ram_percentage = "{ram_percentage}%" + """.strip()) - # 4. RUNTIME ENVIRONMENT (Distroless Direct Pathing) env_launch = jre_layer / "env.launch" env_launch.mkdir(exist_ok=True) - - # Absolute pathing for JAVA_HOME in Distroless + (env_launch / "JAVA_HOME").write_text(str(jre_layer)) (env_launch / "PATH.prepend").write_text(str(jre_layer / "bin")) (env_launch / "PATH.delim").write_text(":") - - # FIPS JRE Options (Logic from v4.6) - if version == "8" and jvm_type == "JRE": - jre_trust_dir = "lib" - elif version == "8": - jre_trust_dir = "jre/lib" + + if version == "8": + if jvm_type == "JRE": + jre_trust_dir = "lib" + else: + jre_trust_dir = "jre/lib" else: jre_trust_dir = "lib" jre_trust = jre_layer / jre_trust_dir / "security/cacerts" - + if version == "8": - jre_boot = f"{jre_layer}/{jre_trust_dir}/ext/bc-fips.jar:{jre_layer}/{jre_trust_dir}/ext/bcutil-fips.jar:{jre_layer}/{jre_trust_dir}/ext/bctls-fips.jar" + base_path = f"{jre_layer}/{jre_trust_dir}/ext" else: - jre_boot = f"{jre_layer}/lib/bc-fips.jar:{jre_layer}/lib/bcutil-fips.jar:{jre_layer}/lib/bctls-fips.jar" - - runtime_opts = f"{fips_base} -Djavax.net.ssl.trustStore={jre_trust} -Xbootclasspath/a:{jre_boot} -XX:+ExitOnOutOfMemoryError -Xmx{max_heap}m" - (env_launch / "JAVA_TOOL_OPTIONS.override").write_text(runtime_opts) - - # 5. SUMMARY - log_step("SUMMARY", "READY", f"Xmx: {max_heap}MB | FIPS: Enabled | Distroless: True") + base_path = f"{jre_layer}/lib" + + jars = ["bc-fips.jar", "bcutil-fips.jar", "bctls-fips.jar"] + jre_boot = ":".join(f"{base_path}/{jar}" for jar in jars) + + jma_opts = "" + if os.getenv("BP_JMA_ENABLED", "false").lower() == "true": + jma_jar = download_jma(jre_layer / "lib") + jma_opts = f"-javaagent:{jma_jar} -Djma.check_interval=5s -Djma.log_level=ERROR -Djma.max_frequency=1/1m -Djma.heap_dump_folder=/tmp -Djma.thresholds.heap=80% " + if version != "8": + jma_opts += "--add-opens=jdk.management/com.sun.management.internal=ALL-UNNAMED " + log_step("JMA", "READY", "Java Memory Assistant Configured") + + ram_opts = f"-XX:+UseContainerSupport -XX:MaxRAMPercentage={ram_percentage}" if version == "8" else f"-XX:MaxRAMPercentage={ram_percentage}" + + runtime_opts = ( + f"{fips_base} " + f"-Djavax.net.ssl.trustStore={jre_trust} " + f"-Xbootclasspath/a:{jre_boot} " + f"{jma_opts}" + f"-XX:+ExitOnOutOfMemoryError " + f"{ram_opts}" + ) + + (env_launch / "JAVA_TOOL_OPTIONS.append").write_text(runtime_opts.strip()) + (env_launch / "JAVA_TOOL_OPTIONS.delim").write_text(" ") + + log_step("SUMMARY", "READY", f"RAM%: {ram_percentage}% | FIPS: Enabled | Distroless: True") print(f"{G}{BOLD}===> Buildpack successfully finished{RESET}\n") + + launch_toml = layers_dir / "launch.toml" + java_binary = jre_layer / "bin" / "java" + + launch_toml.write_text(f''' +[[processes]] +type = "check-java" +command = "{java_binary}" +args = ["-version"] +working-dir = "/workspace" +direct = true +''') if __name__ == "__main__": main() \ No newline at end of file From 4a222b3067cc99d941b6b8f5ba89838453a16f16 Mon Sep 17 00:00:00 2001 From: sm8949752-ux Date: Sat, 21 Mar 2026 01:38:54 +0000 Subject: [PATCH 18/21] feat: update build configuration and enhance FIPS compliance logging --- 2-builder/builder.toml | 170 ++++++++++++------ .../com/taha/wolfidemo/DemoApplication.java | 2 +- .../com/taha/wolfidemo/DemoApplication.java | 2 +- build-image/Dockerfile | 2 +- fips-java-shim/bin/build | 17 +- fips-java-shim/buildpack.toml | 34 +++- run-image/Dockerfile | 2 +- run-image/Dockerfile.run | 8 + 8 files changed, 181 insertions(+), 56 deletions(-) create mode 100644 run-image/Dockerfile.run diff --git a/2-builder/builder.toml b/2-builder/builder.toml index d042324..d676304 100644 --- a/2-builder/builder.toml +++ b/2-builder/builder.toml @@ -1,141 +1,211 @@ description = "Custom Wolfi FIPS Builder" [stack] -id = "io.buildpacks.stacks.jammy" -build-image = "taha/wolfi-build-image:latest" -run-image = "taha/wolfi-run-image:latest" + id = "taha/wolfi-build-image" + build-image = "taha/wolfi-build-image:latest" + run-image = "taha/wolfi-run-image:latest" + [[targets]] -os = "linux" -arch = "amd64" - + os = "linux" + arch = "amd64" [[targets]] -os = "linux" -arch = "arm64" - + os = "linux" + arch = "arm64" [[buildpacks]] -uri = "../fips-java-shim" + uri = "../fips-java-shim" [[buildpacks]] -uri = "docker://paketobuildpacks/ca-certificates:latest" + uri = "docker://paketobuildpacks/ca-certificates:latest" [[buildpacks]] -uri = "docker://paketobuildpacks/syft:latest" + uri = "docker://paketobuildpacks/syft:latest" [[buildpacks]] -uri = "docker://paketobuildpacks/environment-variables:latest" + uri = "docker://paketobuildpacks/environment-variables:latest" [[buildpacks]] -uri = "docker://paketobuildpacks/image-labels:latest" + uri = "docker://paketobuildpacks/image-labels:latest" [[buildpacks]] -uri = "docker://paketobuildpacks/procfile:latest" + uri = "docker://paketobuildpacks/procfile:latest" [[buildpacks]] -uri = "docker://paketobuildpacks/jattach:latest" + uri = "docker://paketobuildpacks/jattach:latest" [[buildpacks]] -uri = "docker://paketobuildpacks/java-memory-assistant:latest" + uri = "docker://paketobuildpacks/java-memory-assistant:latest" [[buildpacks]] -uri = "docker://paketobuildpacks/datadog:latest" + uri = "docker://paketobuildpacks/datadog:latest" [[buildpacks]] -uri = "docker://paketobuildpacks/azure-application-insights:latest" + uri = "docker://paketobuildpacks/azure-application-insights:latest" [[buildpacks]] -uri = "docker://paketobuildpacks/google-stackdriver:latest" + uri = "docker://paketobuildpacks/google-stackdriver:latest" [[buildpacks]] -uri = "docker://paketobuildpacks/maven:latest" + uri = "docker://paketobuildpacks/maven:latest" [[buildpacks]] -uri = "docker://paketobuildpacks/gradle:latest" + uri = "docker://paketobuildpacks/gradle:latest" [[buildpacks]] -uri = "docker://paketobuildpacks/sbt:latest" + uri = "docker://paketobuildpacks/sbt:latest" [[buildpacks]] -uri = "docker://paketobuildpacks/executable-jar:latest" + uri = "docker://paketobuildpacks/executable-jar:latest" [[buildpacks]] -uri = "docker://paketobuildpacks/spring-boot:latest" + uri = "docker://paketobuildpacks/spring-boot:latest" [[buildpacks]] -uri = "docker://paketobuildpacks/apache-tomcat:latest" + uri = "docker://paketobuildpacks/apache-tomcat:latest" [[buildpacks]] -uri = "docker://paketobuildpacks/dist-zip:latest" + uri = "docker://paketobuildpacks/dist-zip:latest" [[order]] - [[order.group]] id = "paketo-buildpacks/ca-certificates" optional = true - [[order.group]] id = "taha/fips-java" - [[order.group]] id = "paketo-buildpacks/syft" optional = true - - [[order.group]] - id = "paketo-buildpacks/gradle" - optional = true - [[order.group]] id = "paketo-buildpacks/maven" - optional = true - [[order.group]] - id = "paketo-buildpacks/sbt" + id = "paketo-buildpacks/executable-jar" optional = true - [[order.group]] - id = "paketo-buildpacks/executable-jar" + id = "paketo-buildpacks/spring-boot" optional = true - [[order.group]] id = "paketo-buildpacks/apache-tomcat" optional = true - [[order.group]] id = "paketo-buildpacks/dist-zip" optional = true + [[order.group]] + id = "paketo-buildpacks/procfile" + optional = true + [[order.group]] + id = "paketo-buildpacks/jattach" + optional = true + [[order.group]] + id = "paketo-buildpacks/azure-application-insights" + optional = true + [[order.group]] + id = "paketo-buildpacks/google-stackdriver" + optional = true + [[order.group]] + id = "paketo-buildpacks/datadog" + optional = true + [[order.group]] + id = "paketo-buildpacks/java-memory-assistant" + optional = true + [[order.group]] + id = "paketo-buildpacks/environment-variables" + optional = true + [[order.group]] + id = "paketo-buildpacks/image-labels" + optional = true +[[order]] + [[order.group]] + id = "paketo-buildpacks/ca-certificates" + optional = true + [[order.group]] + id = "taha/fips-java" + [[order.group]] + id = "paketo-buildpacks/syft" + optional = true + [[order.group]] + id = "paketo-buildpacks/gradle" + [[order.group]] + id = "paketo-buildpacks/executable-jar" + optional = true [[order.group]] id = "paketo-buildpacks/spring-boot" optional = true - + [[order.group]] + id = "paketo-buildpacks/apache-tomcat" + optional = true + [[order.group]] + id = "paketo-buildpacks/dist-zip" + optional = true [[order.group]] id = "paketo-buildpacks/procfile" optional = true - [[order.group]] id = "paketo-buildpacks/jattach" optional = true - [[order.group]] id = "paketo-buildpacks/azure-application-insights" optional = true - [[order.group]] id = "paketo-buildpacks/google-stackdriver" optional = true - [[order.group]] id = "paketo-buildpacks/datadog" optional = true - [[order.group]] id = "paketo-buildpacks/java-memory-assistant" optional = true - [[order.group]] id = "paketo-buildpacks/environment-variables" optional = true - [[order.group]] id = "paketo-buildpacks/image-labels" + optional = true + +[[order]] + [[order.group]] + id = "paketo-buildpacks/ca-certificates" + optional = true + [[order.group]] + id = "taha/fips-java" + [[order.group]] + id = "paketo-buildpacks/syft" + optional = true + [[order.group]] + id = "paketo-buildpacks/sbt" + [[order.group]] + id = "paketo-buildpacks/executable-jar" + optional = true + [[order.group]] + id = "paketo-buildpacks/spring-boot" + optional = true + +[[order]] + [[order.group]] + id = "paketo-buildpacks/ca-certificates" + optional = true + [[order.group]] + id = "taha/fips-java" + [[order.group]] + id = "paketo-buildpacks/syft" + optional = true + [[order.group]] + id = "paketo-buildpacks/executable-jar" + [[order.group]] + id = "paketo-buildpacks/spring-boot" + optional = true + [[order.group]] + id = "paketo-buildpacks/jattach" + optional = true + [[order.group]] + id = "paketo-buildpacks/java-memory-assistant" + optional = true + [[order.group]] + id = "paketo-buildpacks/datadog" + optional = true + [[order.group]] + id = "paketo-buildpacks/azure-application-insights" + optional = true + [[order.group]] + id = "paketo-buildpacks/google-stackdriver" optional = true \ No newline at end of file diff --git a/3-sample-app/src/main/java/com/taha/wolfidemo/DemoApplication.java b/3-sample-app/src/main/java/com/taha/wolfidemo/DemoApplication.java index 8d10897..e6fad5c 100644 --- a/3-sample-app/src/main/java/com/taha/wolfidemo/DemoApplication.java +++ b/3-sample-app/src/main/java/com/taha/wolfidemo/DemoApplication.java @@ -44,7 +44,7 @@ public String testFipsConstraint() { // FipsUnapprovedOperationError or specific FIPS messages indicate success if (errorType.contains("FipsUnapprovedOperationError") || (message != null && message.toLowerCase().contains("approved only mode"))) { - return "SUCCESS: FIPS is strictly enforced. System blocked insecure RSA-1024 key generation. Error Type: " + errorType; + return "just try anything SUCCESS: FIPS is strictly enforced. System blocked insecure RSA-1024 key generation. Error Type: " + errorType; } return "TERMINATED: An unexpected error occurred: " + errorType + " - " + message; diff --git a/4-gradle-app/src/main/java/com/taha/wolfidemo/DemoApplication.java b/4-gradle-app/src/main/java/com/taha/wolfidemo/DemoApplication.java index 8d10897..8758241 100644 --- a/4-gradle-app/src/main/java/com/taha/wolfidemo/DemoApplication.java +++ b/4-gradle-app/src/main/java/com/taha/wolfidemo/DemoApplication.java @@ -44,7 +44,7 @@ public String testFipsConstraint() { // FipsUnapprovedOperationError or specific FIPS messages indicate success if (errorType.contains("FipsUnapprovedOperationError") || (message != null && message.toLowerCase().contains("approved only mode"))) { - return "SUCCESS: FIPS is strictly enforced. System blocked insecure RSA-1024 key generation. Error Type: " + errorType; + return " just change SUCCESS: FIPS is strictly enforced. System blocked insecure RSA-1024 key generation. Error Type: " + errorType; } return "TERMINATED: An unexpected error occurred: " + errorType + " - " + message; diff --git a/build-image/Dockerfile b/build-image/Dockerfile index 5d08b06..bf39485 100644 --- a/build-image/Dockerfile +++ b/build-image/Dockerfile @@ -42,7 +42,7 @@ ENV CNB_GROUP_ID=1001 RUN groupadd -g ${CNB_GROUP_ID} cnb && \ useradd -u ${CNB_USER_ID} -g ${CNB_GROUP_ID} -s /bin/bash -m cnb -LABEL io.buildpacks.stack.id="io.buildpacks.stacks.jammy" +LABEL io.buildpacks.stack.id="taha/wolfi-build-image" RUN chown -R ${CNB_USER_ID}:${CNB_GROUP_ID} /opt/jdks /opt/jres && \ chmod -R 755 /opt/jdks /opt/jres diff --git a/fips-java-shim/bin/build b/fips-java-shim/bin/build index 70ced9a..a1b8011 100755 --- a/fips-java-shim/bin/build +++ b/fips-java-shim/bin/build @@ -205,6 +205,21 @@ args = ["-version"] working-dir = "/workspace" direct = true ''') - + # Logic to handle Vendor SBOM + vendor_sbom = jre_src / "java.cdx.json" + + if vendor_sbom.exists(): + # Define destination path based on CNB Spec + # Path: /sbom/// + sbom_dir = jre_layer / "sbom" / "launch" / "jre" + sbom_dir.mkdir(parents=True, exist_ok=True) + + # Copy the file + shutil.copy2(vendor_sbom, sbom_dir / "java.cdx.json") + + # Log discovery + log_step("JRE", "SBOM", f"Detected and linked: {vendor_sbom.name}") + else: + log_step("JRE", "SBOM", "No vendor SBOM found") if __name__ == "__main__": main() \ No newline at end of file diff --git a/fips-java-shim/buildpack.toml b/fips-java-shim/buildpack.toml index b65f8f0..3744142 100755 --- a/fips-java-shim/buildpack.toml +++ b/fips-java-shim/buildpack.toml @@ -1,10 +1,42 @@ -api = "0.7" +api = "0.8" + + +[[stacks]] + id = "*" + + +[metadata] + [[metadata.configurations]] + name = "BP_JVM_VERSION" + description = "The Java version to install (8, 11, 17, 21, 25)" + default = "21" + build = true + + [[metadata.configurations]] + name = "BP_JVM_TYPE" + description = "The JVM type to provide at runtime (JDK or JRE)" + default = "JRE" + build = true + + [[metadata.configurations]] + name = "BP_JMA_ENABLED" + description = "Enable downloading Java Memory Assistant agent during build" + default = "false" + build = true + + [[metadata.configurations]] + name = "BPL_JVM_HEAD_ROOM" + description = "The percentage of memory to leave as headroom (0-100)" + default = "25" + launch = true [buildpack] id = "taha/fips-java" version = "1.0.0" name = "FIPS Java Shim" + + [[provides]] name = "jdk" diff --git a/run-image/Dockerfile b/run-image/Dockerfile index bc1f25f..1756e54 100644 --- a/run-image/Dockerfile +++ b/run-image/Dockerfile @@ -35,7 +35,7 @@ ENV CNB_USER_ID=1001 ENV CNB_GROUP_ID=1001 ENV LANG=C.UTF-8 TZ=UTC -LABEL io.buildpacks.stack.id="io.buildpacks.stacks.jammy" +LABEL io.buildpacks.stack.id="taha/wolfi-build-image" USER 1001 WORKDIR /home/java diff --git a/run-image/Dockerfile.run b/run-image/Dockerfile.run new file mode 100644 index 0000000..684dbe4 --- /dev/null +++ b/run-image/Dockerfile.run @@ -0,0 +1,8 @@ +FROM cgr.dev/chainguard/wolfi-base:latest + +RUN addgroup -S cnb --gid 1000 && \ + adduser -S cnb -G cnb --uid 1000 + +LABEL io.buildpacks.stack.id="io.buildpacks.stacks.jammy" + +USER 1000 \ No newline at end of file From 5b08a9f9524c25c63ebd07b5efb80d1f755a4acc Mon Sep 17 00:00:00 2001 From: sm8949752-ux Date: Sat, 21 Mar 2026 07:46:35 +0000 Subject: [PATCH 19/21] feat: enhance build process with new task management and Dockerfile updates --- .devcontainer/Dockerfile | 3 +- .vscode/tasks.json | 30 ---------- 2-builder/builder.toml | 2 +- .../com/taha/wolfidemo/DemoApplication.java | 2 +- Taskfile.yml | 55 +++++++++++++++++++ layers.py | 53 ++++++++++++++++++ run-image/Dockerfile.run | 2 +- taskfile/app.Taskfile.yml | 35 ++++++++++++ taskfile/buildpack.Taskfile.yml | 31 +++++++++++ 9 files changed, 179 insertions(+), 34 deletions(-) delete mode 100644 .vscode/tasks.json create mode 100644 Taskfile.yml create mode 100755 layers.py create mode 100644 taskfile/app.Taskfile.yml create mode 100644 taskfile/buildpack.Taskfile.yml diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 512d2c9..9e3aba3 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -9,7 +9,8 @@ RUN apt-get update && apt-get install -y \ git \ sudo \ && rm -rf /var/lib/apt/lists/* - +RUN curl -1sLf 'https://dl.cloudsmith.io/public/task/task/setup.deb.sh' | sudo -E bash +RUN apt install task -y RUN useradd -m -s /bin/bash vscode && \ echo "vscode ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index ef5eebb..0000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "label": "1. Prepare Builder", - "type": "shell", - "command": "cd build-image && docker build -t taha/wolfi-build-image:latest . && cd ../2-builder && pack builder create taha/wolfi-fips-builder:latest --config builder.toml" - }, - { - "label": "2. Prepare Run Image", - "type": "shell", - "command": "cd run-image && docker build -t taha/wolfi-run-image:latest ." - }, - { - "label": "3. Build App Gradle", - "type": "shell", - "command": "pack build taha/gradle-fips-app --path 4-gradle-app --builder taha/wolfi-fips-builder:latest --env BP_JVM_TYPE=JRE --publish=false " - }, - { - "label": "3. Build App Maven", - "type": "shell", - "command": "pack build taha/maven-fips-app --path 3-sample-app --builder taha/wolfi-fips-builder:latest --env BP_JVM_TYPE=JRE --publish=false " - }, - { - "label": "4. Run App", - "type": "shell", - "command": "docker rm -f fips-app-container || true && docker run -d -p 8080:8080 --name fips-app-container taha/maven-fips-app" - } - ] -} \ No newline at end of file diff --git a/2-builder/builder.toml b/2-builder/builder.toml index d676304..4ae1dbf 100644 --- a/2-builder/builder.toml +++ b/2-builder/builder.toml @@ -13,7 +13,7 @@ description = "Custom Wolfi FIPS Builder" arch = "arm64" [[buildpacks]] - uri = "../fips-java-shim" + uri = "docker://taha/fips-java:1.0.0" [[buildpacks]] uri = "docker://paketobuildpacks/ca-certificates:latest" diff --git a/3-sample-app/src/main/java/com/taha/wolfidemo/DemoApplication.java b/3-sample-app/src/main/java/com/taha/wolfidemo/DemoApplication.java index e6fad5c..8d10897 100644 --- a/3-sample-app/src/main/java/com/taha/wolfidemo/DemoApplication.java +++ b/3-sample-app/src/main/java/com/taha/wolfidemo/DemoApplication.java @@ -44,7 +44,7 @@ public String testFipsConstraint() { // FipsUnapprovedOperationError or specific FIPS messages indicate success if (errorType.contains("FipsUnapprovedOperationError") || (message != null && message.toLowerCase().contains("approved only mode"))) { - return "just try anything SUCCESS: FIPS is strictly enforced. System blocked insecure RSA-1024 key generation. Error Type: " + errorType; + return "SUCCESS: FIPS is strictly enforced. System blocked insecure RSA-1024 key generation. Error Type: " + errorType; } return "TERMINATED: An unexpected error occurred: " + errorType + " - " + message; diff --git a/Taskfile.yml b/Taskfile.yml new file mode 100644 index 0000000..d071d34 --- /dev/null +++ b/Taskfile.yml @@ -0,0 +1,55 @@ +version: '3' + +includes: + bp: taskfile/buildpack.Taskfile.yml + app: taskfile/app.Taskfile.yml + +vars: + BUILD_IMAGE: taha/wolfi-build-image:latest + RUN_IMAGE: taha/wolfi-run-image:latest + BUILDER_NAME: taha/wolfi-fips-builder:latest + BUILDER_CONFIG: 2-builder/builder.toml + +tasks: + default: + cmds: + - task: all + + all: + desc: Build everything from scratch + cmds: + - task: build-img + - task: run-img + - task: bp:package + - task: builder + + build-img: + desc: Build the Wolfi Build Image + dir: build-image + cmds: + - docker build -t {{.BUILD_IMAGE}} . + + run-img: + desc: Build the Wolfi Run Image (Distroless) + dir: run-image + cmds: + - docker build -t {{.RUN_IMAGE}} . + run-img-with-shell: + desc: Build the Wolfi Run Image (with shell for debugging) + dir: run-image + cmds: + - docker build -t {{.RUN_IMAGE}}-shell -f Dockerfile.run . + builder: + desc: Create the final Cloud Native Builder + cmds: + - pack builder create {{.BUILDER_NAME}} --config {{.BUILDER_CONFIG}} + + inspect: + desc: Inspect the final builder + cmds: + - pack builder inspect {{.BUILDER_NAME}} + + app-maven: + desc: Build the sample Maven app using our custom builder + cmds: + - pack build taha/maven-fips-app --path 3-sample-app --builder {{.BUILDER_NAME}} --env BP_JVM_TYPE=JRE \ No newline at end of file diff --git a/layers.py b/layers.py new file mode 100755 index 0000000..b1e1b32 --- /dev/null +++ b/layers.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +import sys +import subprocess +import json +import csv + +def main(): + if len(sys.argv) < 3: + print("Usage: ./analyze.py ") + sys.exit(1) + + image_name, csv_path = sys.argv[1], sys.argv[2] + + try: + subprocess.run(f"dive {image_name} --json image_report.json", shell=True, check=True, capture_output=True) + + with open("image_report.json", 'r') as f: + data = json.load(f) + + layers = [] + for layer in data.get("layer", []): + size_mb = layer.get("sizeBytes", 0) / (1024 * 1024) + cmd = layer.get("command", "").replace("\n", " ") + layers.append({"size": size_mb, "cmd": cmd, "sha": layer.get("digestId")}) + + with open(csv_path, 'w', newline='') as f: + writer = csv.writer(f) + writer.writerow(["LAYER_TYPE", "SIZE_MB", "SHA256_HASH", "COMMAND"]) + + for l in layers: + if "taha/fips-java" in l['cmd']: + layer_type = "JRE/FIPS Layer" + elif "Application Slice" in l['cmd']: + layer_type = "App Code Layer" + elif "paketo-buildpacks" in l['cmd']: + layer_type = "Buildpack Helper" + else: + layer_type = "OS/Base Layer" + + writer.writerow([layer_type, f"{l['size']:.6f} MB", l['sha'], l['cmd']]) + + print(f"Success! Detailed report: {csv_path}") + + print("\n--- Top 5 Largest Layers ---") + top_layers = sorted(layers, key=lambda x: x['size'], reverse=True)[:5] + for i, l in enumerate(top_layers, 1): + print(f"{i}. {l['size']:.6f} MB | {l['sha'][:12]}... | {l['cmd'][:40]}") + + except Exception as e: + print(f"Error: {e}", file=sys.stderr) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/run-image/Dockerfile.run b/run-image/Dockerfile.run index 684dbe4..5de80c9 100644 --- a/run-image/Dockerfile.run +++ b/run-image/Dockerfile.run @@ -3,6 +3,6 @@ FROM cgr.dev/chainguard/wolfi-base:latest RUN addgroup -S cnb --gid 1000 && \ adduser -S cnb -G cnb --uid 1000 -LABEL io.buildpacks.stack.id="io.buildpacks.stacks.jammy" +LABEL io.buildpacks.stack.id="taha/wolfi-build-image" USER 1000 \ No newline at end of file diff --git a/taskfile/app.Taskfile.yml b/taskfile/app.Taskfile.yml new file mode 100644 index 0000000..0087293 --- /dev/null +++ b/taskfile/app.Taskfile.yml @@ -0,0 +1,35 @@ +version: '3' + +vars: + BUILDER: taha/wolfi-fips-builder:latest + MAVEN_APP_IMG: taha/maven-fips-app:latest + MAVEN_PATH: 3-sample-app + GRADLE_APP_IMG: taha/gradle-fips-app:latest + GRADLE_PATH: 4-gradle-app + +tasks: + build-maven: + desc: Build the Maven application + cmds: + - pack build {{.MAVEN_APP_IMG}} --path {{.MAVEN_PATH}} --builder {{.BUILDER}} --env BP_JVM_TYPE=JRE + + run-maven: + desc: Run the Maven application + cmds: + - docker run -it --rm -m 512m {{.MAVEN_APP_IMG}} + + build-gradle: + desc: Build the Gradle application + cmds: + - pack build {{.GRADLE_APP_IMG}} --path {{.GRADLE_PATH}} --builder {{.BUILDER}} --env BP_JVM_TYPE=JRE + + run-gradle: + desc: Run the Gradle application + cmds: + - docker run -it --rm -m 512m {{.GRADLE_APP_IMG}} + + build-all: + desc: Build both Maven and Gradle apps + cmds: + - task: build-maven + - task: build-gradle \ No newline at end of file diff --git a/taskfile/buildpack.Taskfile.yml b/taskfile/buildpack.Taskfile.yml new file mode 100644 index 0000000..d88be2d --- /dev/null +++ b/taskfile/buildpack.Taskfile.yml @@ -0,0 +1,31 @@ +version: '3' + +vars: + BP_NAME: taha/fips-java + BP_VERSION: 1.0.0 + BP_PATH: ./fips-java-shim + +tasks: + package: + desc: Package the FIPS Java Buildpack as an OCI image + cmds: + - pack buildpack package {{.BP_NAME}}:{{.BP_VERSION}} --path {{.BP_PATH}} --format image + + inspect: + desc: Inspect the packaged buildpack metadata + cmds: + - pack buildpack inspect {{.BP_NAME}}:{{.BP_VERSION}} + + clean: + desc: Remove the local buildpack image + cmds: + - docker rmi {{.BP_NAME}}:{{.BP_VERSION}} || true + + + inspect-any: + desc: Show layers for a specific image (usage task app:inspect-any IMG=name) + vars: + IMAGE: '{{default "taha/maven-fips-app:latest" .IMG}}' + cmds: + - | + paste <(docker inspect {{.IMAGE}} --format='{{range .RootFS.Layers}}{{.}}{{println}}{{end}}') <(docker history {{.IMAGE}} --format "{{.Size}}" | grep -v SIZE | tac) | column -t > 1.txt From ca3f7102ed2d8d929b33a61a7cc49ee691bfa14a Mon Sep 17 00:00:00 2001 From: sm8949752-ux Date: Tue, 24 Mar 2026 09:39:04 +0000 Subject: [PATCH 20/21] feat: restructure task files and enhance build process with new configurations --- Taskfile.yml | 48 +++++-------------- taskfile/{app.Taskfile.yml => app.yml} | 10 +++- taskfile/builder.yml | 12 +++++ .../{buildpack.Taskfile.yml => buildpack.yml} | 11 +---- taskfile/image.yml | 20 ++++++++ taskfile/util.yml | 10 ++++ 6 files changed, 63 insertions(+), 48 deletions(-) rename taskfile/{app.Taskfile.yml => app.yml} (73%) create mode 100644 taskfile/builder.yml rename taskfile/{buildpack.Taskfile.yml => buildpack.yml} (51%) create mode 100644 taskfile/image.yml create mode 100644 taskfile/util.yml diff --git a/Taskfile.yml b/Taskfile.yml index d071d34..5570906 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -1,8 +1,13 @@ version: '3' - +env: + DOCKER_API_VERSION: "1.43" includes: - bp: taskfile/buildpack.Taskfile.yml - app: taskfile/app.Taskfile.yml + img: taskfile/image.yml + builder: taskfile/builder.yml + app: taskfile/app.yml + util: taskfile/util.yml + bp: taskfile/buildpack.yml + vars: BUILD_IMAGE: taha/wolfi-build-image:latest @@ -18,38 +23,7 @@ tasks: all: desc: Build everything from scratch cmds: - - task: build-img - - task: run-img + - task: img:build-img + - task: img:run-img - task: bp:package - - task: builder - - build-img: - desc: Build the Wolfi Build Image - dir: build-image - cmds: - - docker build -t {{.BUILD_IMAGE}} . - - run-img: - desc: Build the Wolfi Run Image (Distroless) - dir: run-image - cmds: - - docker build -t {{.RUN_IMAGE}} . - run-img-with-shell: - desc: Build the Wolfi Run Image (with shell for debugging) - dir: run-image - cmds: - - docker build -t {{.RUN_IMAGE}}-shell -f Dockerfile.run . - builder: - desc: Create the final Cloud Native Builder - cmds: - - pack builder create {{.BUILDER_NAME}} --config {{.BUILDER_CONFIG}} - - inspect: - desc: Inspect the final builder - cmds: - - pack builder inspect {{.BUILDER_NAME}} - - app-maven: - desc: Build the sample Maven app using our custom builder - cmds: - - pack build taha/maven-fips-app --path 3-sample-app --builder {{.BUILDER_NAME}} --env BP_JVM_TYPE=JRE \ No newline at end of file + - task: builder:create \ No newline at end of file diff --git a/taskfile/app.Taskfile.yml b/taskfile/app.yml similarity index 73% rename from taskfile/app.Taskfile.yml rename to taskfile/app.yml index 0087293..476fe23 100644 --- a/taskfile/app.Taskfile.yml +++ b/taskfile/app.yml @@ -32,4 +32,12 @@ tasks: desc: Build both Maven and Gradle apps cmds: - task: build-maven - - task: build-gradle \ No newline at end of file + - task: build-gradle + sbom-maven: + desc: Download SBOM for the Maven application + cmds: + - pack sbom download {{.MAVEN_APP_IMG}} --output-dir ./sbom-maven + sbom-gradle: + desc: Download SBOM for the Gradle application + cmds: + - pack sbom download {{.GRADLE_APP_IMG}} --output-dir ./sbom-gradle diff --git a/taskfile/builder.yml b/taskfile/builder.yml new file mode 100644 index 0000000..949764e --- /dev/null +++ b/taskfile/builder.yml @@ -0,0 +1,12 @@ +version: '3' + +tasks: + create: + desc: Create the final Cloud Native Builder + cmds: + - pack builder create {{.BUILDER_NAME}} --config {{.BUILDER_CONFIG}} + + inspect: + desc: Inspect the final builder + cmds: + - pack builder inspect {{.BUILDER_NAME}} \ No newline at end of file diff --git a/taskfile/buildpack.Taskfile.yml b/taskfile/buildpack.yml similarity index 51% rename from taskfile/buildpack.Taskfile.yml rename to taskfile/buildpack.yml index d88be2d..4589304 100644 --- a/taskfile/buildpack.Taskfile.yml +++ b/taskfile/buildpack.yml @@ -19,13 +19,4 @@ tasks: clean: desc: Remove the local buildpack image cmds: - - docker rmi {{.BP_NAME}}:{{.BP_VERSION}} || true - - - inspect-any: - desc: Show layers for a specific image (usage task app:inspect-any IMG=name) - vars: - IMAGE: '{{default "taha/maven-fips-app:latest" .IMG}}' - cmds: - - | - paste <(docker inspect {{.IMAGE}} --format='{{range .RootFS.Layers}}{{.}}{{println}}{{end}}') <(docker history {{.IMAGE}} --format "{{.Size}}" | grep -v SIZE | tac) | column -t > 1.txt + - docker rmi {{.BP_NAME}}:{{.BP_VERSION}} || true \ No newline at end of file diff --git a/taskfile/image.yml b/taskfile/image.yml new file mode 100644 index 0000000..0779fa7 --- /dev/null +++ b/taskfile/image.yml @@ -0,0 +1,20 @@ +version: '3' + +tasks: + build-img: + desc: Build the Wolfi Build Image + dir: build-image + cmds: + - docker build -t {{.BUILD_IMAGE}} . + + run-img: + desc: Build the Wolfi Run Image (Distroless) + dir: run-image + cmds: + - docker build -t {{.RUN_IMAGE}} . + + run-img-with-shell: + desc: Build the Wolfi Run Image (with shell for debugging) + dir: run-image + cmds: + - docker build -t {{.RUN_IMAGE}}-shell -f Dockerfile.run . \ No newline at end of file diff --git a/taskfile/util.yml b/taskfile/util.yml new file mode 100644 index 0000000..a5c8cae --- /dev/null +++ b/taskfile/util.yml @@ -0,0 +1,10 @@ +version: '3' + +tasks: + inspect-any: + desc: Show layers for a specific image (usage > task util:inspect-any IMG=name) + vars: + IMAGE: '{{default "taha/maven-fips-app:latest" .IMG}}' + cmds: + - | + paste <(docker inspect {{.IMAGE}} --format='{{range .RootFS.Layers}}{{.}}{{println}}{{end}}') <(docker history {{.IMAGE}} --format "{{.Size}}" | grep -v SIZE | tac) | column -t > 1.txt \ No newline at end of file From 7fcac1622c8805b8152a2d5eadea1d898e28afae Mon Sep 17 00:00:00 2001 From: sm8949752-ux Date: Tue, 24 Mar 2026 10:09:00 +0000 Subject: [PATCH 21/21] feat: update builder configuration and enhance lifecycle image management --- 2-builder/builder.toml | 1 - Taskfile.yml | 3 ++- fips-java-shim/buildpack.toml | 10 +++++++++- taskfile/app.yml | 16 +++++----------- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/2-builder/builder.toml b/2-builder/builder.toml index 4ae1dbf..4c5431c 100644 --- a/2-builder/builder.toml +++ b/2-builder/builder.toml @@ -1,5 +1,4 @@ description = "Custom Wolfi FIPS Builder" - [stack] id = "taha/wolfi-build-image" build-image = "taha/wolfi-build-image:latest" diff --git a/Taskfile.yml b/Taskfile.yml index 5570906..177cac4 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -1,6 +1,7 @@ version: '3' env: - DOCKER_API_VERSION: "1.43" + DOCKER_API_VERSION: "1.50" + PACK_VOLUME_KEY: "taha-fips-cache-key" includes: img: taskfile/image.yml builder: taskfile/builder.yml diff --git a/fips-java-shim/buildpack.toml b/fips-java-shim/buildpack.toml index 3744142..5077712 100755 --- a/fips-java-shim/buildpack.toml +++ b/fips-java-shim/buildpack.toml @@ -1,4 +1,4 @@ -api = "0.8" +api = "0.12" [[stacks]] @@ -36,6 +36,14 @@ version = "1.0.0" name = "FIPS Java Shim" +[[targets]] +os = "linux" +arch = "amd64" + +[[targets]] +os = "linux" +arch = "arm64" + [[provides]] name = "jdk" diff --git a/taskfile/app.yml b/taskfile/app.yml index 476fe23..1af72b0 100644 --- a/taskfile/app.yml +++ b/taskfile/app.yml @@ -6,12 +6,14 @@ vars: MAVEN_PATH: 3-sample-app GRADLE_APP_IMG: taha/gradle-fips-app:latest GRADLE_PATH: 4-gradle-app + # only for github codespace Docker API 1.43 + LIFECYCLE_IMG: buildpacksio/lifecycle:0.17.2 tasks: build-maven: desc: Build the Maven application cmds: - - pack build {{.MAVEN_APP_IMG}} --path {{.MAVEN_PATH}} --builder {{.BUILDER}} --env BP_JVM_TYPE=JRE + - pack build {{.MAVEN_APP_IMG}} --path {{.MAVEN_PATH}} --builder {{.BUILDER}} --env BP_JVM_TYPE=JRE --lifecycle-image {{.LIFECYCLE_IMG}} run-maven: desc: Run the Maven application @@ -21,7 +23,7 @@ tasks: build-gradle: desc: Build the Gradle application cmds: - - pack build {{.GRADLE_APP_IMG}} --path {{.GRADLE_PATH}} --builder {{.BUILDER}} --env BP_JVM_TYPE=JRE + - pack build {{.GRADLE_APP_IMG}} --path {{.GRADLE_PATH}} --builder {{.BUILDER}} --env BP_JVM_TYPE=JRE --lifecycle-image {{.LIFECYCLE_IMG}} run-gradle: desc: Run the Gradle application @@ -32,12 +34,4 @@ tasks: desc: Build both Maven and Gradle apps cmds: - task: build-maven - - task: build-gradle - sbom-maven: - desc: Download SBOM for the Maven application - cmds: - - pack sbom download {{.MAVEN_APP_IMG}} --output-dir ./sbom-maven - sbom-gradle: - desc: Download SBOM for the Gradle application - cmds: - - pack sbom download {{.GRADLE_APP_IMG}} --output-dir ./sbom-gradle + - task: build-gradle \ No newline at end of file