Skip to content

Commit bddbe31

Browse files
authored
Merge pull request #70 from chainguard-demo/cg-libraries
initial commit for libraries workshop
2 parents fbcc560 + c3e0d38 commit bddbe31

19 files changed

Lines changed: 1829 additions & 0 deletions

File tree

chainguard-libraries/java/demo.sh

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
#! env bash
2+
3+
###############################################################################
4+
# Demo Magic Script: Java Libraries Workshop
5+
# This script uses demo-magic to simulate a live terminal demo.
6+
###############################################################################
7+
8+
# Load demo-magic
9+
# Ensure demo-magic.sh is in the same directory or adjust the path accordingly
10+
. ../../base.sh
11+
12+
pei cd step1-orig/
13+
14+
# Speed (lower = faster). Use -w for waits and ENTER manually if you prefer.
15+
TYPE_SPEED=100
16+
DEMO_PROMPT="${GREEN}${CYAN}\W ${COLOR_RESET}"
17+
clear
18+
19+
###############################################################################
20+
# Intro
21+
###############################################################################
22+
echo -e "
23+
🧰 Demo: Converting a Java App to Use Chainguard Libraries
24+
25+
This demo walks through taking an existing sample Java application and rebuilding it using Chainguard Libraries for Java.
26+
We’ll demonstrate how to transition from using Maven Central to Chainguard’s trusted library source — without modifying your source code or build process — while gaining improved security and provenance.
27+
28+
To keep everything portable and reproducible, the demo uses containerized builds rather than local Maven setups.
29+
30+
The application is a simple Java Spring Boot application that returns a string when a post is sent.
31+
32+
The demo includes three main stages:
33+
1. Baseline Build (Upstream Maven & Temurin Images):
34+
- Build the Java application using upstream Maven build containers and an Eclipse Temurin runtime container.
35+
- This represents a typical Java build pipeline that relies on Maven Central for dependencies.
36+
- Verify the application runs successfully, then scan the resulting image to confirm that all dependencies are sourced from Maven Central.
37+
38+
2. Chainguard Libraries Migration (Same Upstream Builders):
39+
- Rebuild the same application using Chainguard Libraries for Java, keeping the same upstream Maven and Temurin containers.
40+
- Demonstrate that switching dependency sources has no impact on functionality.
41+
- Re-scan the image to show that dependencies are now covered by Chainguard’s verified library set.
42+
43+
3. Chainguard Build & Runtime Containers:
44+
- Rebuild and run the application using both Chainguard’s build and runtime container images together with Chainguard Libraries.
45+
- Perform a final scan to confirm full coverage from Chainguard’s trusted ecosystem and show that the application still functions as expected.
46+
47+
4. Lastly we will look at how to view provenance for Chainguard Libraries for Java. We will look at an SBOM for one of the dependencies and discuss some key attributes.
48+
49+
Let's get started!
50+
"
51+
wait
52+
53+
###############################################################################
54+
# Setup
55+
###############################################################################
56+
57+
banner "# Let's start by setting up some environment variables."
58+
pei "ECOSYSTEM=\"java\""
59+
pei "TOKEN_NAME=\"java-libraries-workshop-token-$USER\""
60+
pei "TTL=\"8760h\""
61+
pei ""
62+
pei ""
63+
64+
read -p "Enter your Chainguard organization name (e.g. myorg.com): " ORG_NAME
65+
export ORG_NAME
66+
67+
###############################################################################
68+
# Step 1: Build with Upstream and Maven Central
69+
###############################################################################
70+
banner "Step 1: Build and run using upstream Java images and Maven Central - Let's get a baseline by building our app as is, without using Chainguard Libraries"
71+
72+
pei "# We will build a sample Java app using Maven Central for dependencies and the upstream maven image."
73+
pei "# Lets take a look at the pom file first, if you focus on the dependencies you'll see some standard spring boot dependencies are needed for the build:"
74+
pe "awk '/<dependencies>/,/<\/dependencies>/' pom.xml"
75+
pei ""
76+
77+
p "# Let's take a look at the dockerfile:"
78+
pei 'cat Dockerfile'
79+
pei ""
80+
81+
p '# Now lets set our builder and runtime image and build the project. This is a simple spring boot app that returns a sting when sending a request.'
82+
pei "TAG=\"upstream\""
83+
pei "BUILDER_IMAGE=\"maven\""
84+
pei "RUNTIME_IMAGE=\"eclipse-temurin\""
85+
86+
pei 'docker build --build-arg BASE_IMAGE=$BUILDER_IMAGE --build-arg RUNTIME_IMAGE=$RUNTIME_IMAGE -t java-lib-example:$TAG .'
87+
88+
p "# Run the container and test it."
89+
pei 'docker run -d -p 8081:8080 --name java-lib-example-1 java-lib-example:$TAG'
90+
91+
pe 'curl http://localhost:8081'
92+
pei ""
93+
94+
p "# Copy the built jar file from the container locally so we can scan it with chainver."
95+
pei 'docker cp java-lib-example-1:/app/java-demo-app-1.0.0.jar .'
96+
97+
p "# Analyze the image and jar with chainver."
98+
pei 'chainver --parent $ORG_NAME java-demo-app-1.0.0.jar'
99+
100+
# clean up
101+
pei "# Stop the running container and remove the local jar file:"
102+
pei 'docker stop java-lib-example-1 && docker rm java-lib-example-1 && rm java-demo-app-1.0.0.jar'
103+
104+
###############################################################################
105+
# Step 2: Build with Chainguard Libraries (Upstream Maven)
106+
###############################################################################
107+
banner "Step 2: Build using Chainguard Libraries with upstream Maven and Temurin Images."
108+
109+
p "# In order to use Chainguard Libraries for Java to build our app, we will need to create a pull token for the Java ecosystem. Press enter to create your token."
110+
pei 'CREDS_OUTPUT=$(chainctl auth pull-token --library-ecosystem="${ECOSYSTEM}" --parent="${ORG_NAME}" --name="${TOKEN_NAME}" --ttl="${TTL}" -o json)'
111+
pei 'CGR_MAVEN_USER=$(echo $CREDS_OUTPUT | jq -r ".identity_id")'
112+
pei 'CGR_MAVEN_PASS=$(echo $CREDS_OUTPUT | jq -r ".token")'
113+
114+
pe "# Now that we have our credentials we need to create a settings.xml file to configure it to use the Chainguard repo, notice that we are referencing our credentials in the file as environment variables:"
115+
pei 'cat settings.xml'
116+
pei ""
117+
118+
119+
pe '# Now lets set our tag, builder and runtime image and build the same app as before but using chainguard libraries.'
120+
pei "TAG=\"upstream-cg-libs\""
121+
pei "BUILDER_IMAGE=\"maven\""
122+
pei "RUNTIME_IMAGE=\"eclipse-temurin\""
123+
124+
pe "# Lets take a look at the dockerfile as it is slightly different from before, notice that we will be passing in our credentials as build secrets so that they are not stored in the layers or in the builder logs:"
125+
pei 'cat ../step2-cg-build/Dockerfile'
126+
pei ""
127+
128+
pei "# Below is the command we will use to build the image, notice we are passing in the credentials as build secrets."
129+
pe "docker build \
130+
-t java-lib-example:\$TAG \
131+
--build-arg BUILDER_IMAGE=\$BUILDER_IMAGE \
132+
--build-arg RUNTIME_IMAGE=\$RUNTIME_IMAGE \
133+
--secret id=cgr_user,src=<(echo -n \"\$CGR_MAVEN_USER\") \
134+
--secret id=cgr_pass,src=<(echo -n \"\$CGR_MAVEN_PASS\") \
135+
-f ../step2-cg-build/Dockerfile ."
136+
137+
p "# Run the container and test it."
138+
pei 'docker run -d -p 8081:8080 --name java-lib-example-1 java-lib-example:$TAG'
139+
pe 'curl http://localhost:8081'
140+
pei ""
141+
142+
p "# Copy the built jar file from the container locally so we can scan it with chainver."
143+
pei 'docker cp java-lib-example-1:/app/java-demo-app-1.0.0.jar .'
144+
145+
p "# Analyze the image and jar with chainver."
146+
pei 'chainver --parent $ORG_NAME java-demo-app-1.0.0.jar'
147+
148+
# clean up
149+
pei "# Stop the running container and remove the local jar file:"
150+
pei 'docker stop java-lib-example-1 && docker rm java-lib-example-1 && rm java-demo-app-1.0.0.jar'
151+
152+
###############################################################################
153+
# Step 3: Build Fully Chainguard (Image + Libraries)
154+
###############################################################################
155+
banner "Step 3: Full Chainguard Build (Chainguard Java images + Chainguard Libraries for Java)"
156+
pei "# In this step we will use the same app but this time we will build with Chainguard libraries, using the Chainguard maven image and jre runtime."
157+
pe '# Now lets set our tag, builder and runtime image and build the same app as before but using chainguard libraries.'
158+
pei "TAG=\"chainguard-cg-libs\""
159+
pei "BUILDER_IMAGE=\"cgr.dev/chainguard/maven:latest\""
160+
pei "RUNTIME_IMAGE=\"cgr.dev/chainguard/jre:latest\""
161+
pei "MAVEN_SETTINGS_PATH=\"/usr/share/java/maven/conf/settings.xml\""
162+
163+
pei "# For this build we will use the same settings.xml and pom.xml file as in the previous step."
164+
pe "docker build \
165+
-t java-lib-example:\$TAG \
166+
--build-arg BUILDER_IMAGE=\$BUILDER_IMAGE \
167+
--build-arg RUNTIME_IMAGE=\$RUNTIME_IMAGE \
168+
--build-arg MAVEN_SETTINGS_PATH=\$MAVEN_SETTINGS_PATH \
169+
--secret id=cgr_user,src=<(echo -n \"\$CGR_MAVEN_USER\") \
170+
--secret id=cgr_pass,src=<(echo -n \"\$CGR_MAVEN_PASS\") \
171+
-f ../step2-cg-build/Dockerfile ."
172+
173+
p "# Run the container and test it."
174+
pei 'docker run -d -p 8081:8080 --name java-lib-example-1 java-lib-example:$TAG'
175+
pe 'curl http://localhost:8081'
176+
pei ""
177+
178+
p "# Copy the built jar file from the container locally so we can scan it with chainver."
179+
pei 'docker cp java-lib-example-1:/app/java-demo-app-1.0.0.jar .'
180+
181+
p "# Analyze the image and jar with chainver."
182+
pei 'chainver --parent $ORG_NAME java-demo-app-1.0.0.jar'
183+
184+
p "# Cleanup: Stop the container and delete the jar."
185+
pei 'docker stop java-lib-example-1 && docker rm java-lib-example-1 && rm java-demo-app-1.0.0.jar'
186+
187+
###############################################################################
188+
# Step 4. Provenance
189+
###############################################################################
190+
banner "Step 4: View Java Library Provenance"
191+
pei "# Each Java dependency built by Chainguard is accompanied by an SBOM, the SBOMs are published alongside each artifact as an SPDX JSON file named artifactId-version.spdx.json in the Chainguard Maven Repository."
192+
pei '# Chainver compares the package checksum with the one listed in the SBOM to determine if the package was built by Chainguard or not. Lets take a look at the SBOM for the spring-boot-starter-web dependency, we will start by downloading the SBOM from the Chainguard Maven repository:'
193+
pei "curl -L --user \"\$CGR_MAVEN_USER:\$CGR_MAVEN_PASS\" \
194+
-O https://libraries.cgr.dev/java/org/springframework/boot/spring-boot-starter-web/3.3.5/spring-boot-starter-web-3.3.5.spdx.json"
195+
pei '# Now lets take a look at the relevant section of the SBOM:'
196+
pe "jq '{spdxVersion, dataLicense, SPDXID, name, documentNamespace, creationInfo, packages: [.packages[0]]}' spring-boot-starter-web-3.3.5.spdx.json | jq ."
197+
pei ""
198+
199+
###############################################################################
200+
# Final Cleanup
201+
###############################################################################
202+
banner "Final cleanup delete local files and delete the Chainguard pull token"
203+
pei "ID=\$(chainctl iam ids ls --parent=\"\${ORG_NAME}\" -o json | jq -r --arg name \"\${TOKEN_NAME}\" '.items[] | select(.name | startswith(\$name)) | .id')"
204+
pei 'chainctl iam identities delete "$ID" --parent "$ORG_NAME" --yes'
205+
pei 'rm spring-boot-starter-web-3.3.5.spdx.json'
206+
207+
p "# Demo complete!"
208+
exit 0

0 commit comments

Comments
 (0)