diff --git a/content/en/docs/02/2.1/_index.md b/content/en/docs/02/2.1/_index.md index 284f1f6..d3cba2a 100644 --- a/content/en/docs/02/2.1/_index.md +++ b/content/en/docs/02/2.1/_index.md @@ -1,5 +1,5 @@ --- -title: "2.1 Container images - Drop-in replacements" +title: "2.1 Drop-in replacements" weight: 21 sectionnumber: 2.1 --- diff --git a/content/en/docs/02/2.2/_index.md b/content/en/docs/02/2.2/_index.md index 858d22a..a77fecb 100644 --- a/content/en/docs/02/2.2/_index.md +++ b/content/en/docs/02/2.2/_index.md @@ -1,5 +1,5 @@ --- -title: "2.2 Container images - More challenging swaps" +title: "2.2 More challenging swaps" weight: 22 sectionnumber: 2.2 --- diff --git a/content/en/docs/03/_index.md b/content/en/docs/03/_index.md index 7ed56f7..1782494 100644 --- a/content/en/docs/03/_index.md +++ b/content/en/docs/03/_index.md @@ -1,12 +1,35 @@ --- -title: "3. Chainguard Helm images" +title: "3. Chainguard Helm Charts" weight: 2 sectionnumber: 3 description: > - Test Migrations of Helm Images. + Test Migrations of Helm Charts. --- ## Helm Charts -As Helm charts aren't available for free yet, we will describe the migration in theory. +https://edu.chainguard.dev/chainguard/chainguard-images/how-to-use/use-chainguard-helm-charts/ + +```bash +chainctl auth login +chainctl auth configure-docker --pull-token --save --ttl=24h + + +chainctl auth configure-docker --pull-token --save --ttl=24h + + With which location is the pull token associated? + + [puzzle-partner.com] puzzle-partner.com images catalog. + > └ [iamguarded-charts] + + export HELMUSER= + export HELMPASS= + + +helm registry login cgr.dev \ + --username=$HELMUSER \ + --password=$HELMPASS + +helm template oci://cgr.dev/puzzle-partner.com/iamguarded-charts/kafka +``` diff --git a/content/en/docs/05/5.1/_index.md b/content/en/docs/05/5.1/_index.md new file mode 100644 index 0000000..edce259 --- /dev/null +++ b/content/en/docs/05/5.1/_index.md @@ -0,0 +1,87 @@ +--- +title: "5.1 Example Application" +weight: 51 +sectionnumber: 5.1 +--- + +## App - the standard way + +Using example [Spring Boot app](https://github.com/spring-guides/gs-spring-boot/tree/main/initial) + +```bash +git clone https://github.com/spring-guides/gs-spring-boot.git +cd gs-spring-boot/initial +``` + +Create the `.dockerignore` file inside `gs-spring-boot/initial` with following content: + +``` +Containerfile* +``` + +This should make builds faster. Changes in Containerfiles have no impact on build context and caching. + + +Test base image candidate and get infos: +```bash +docker run -ti docker.io/eclipse-temurin:21-jdk-ubi9-minimal /bin/bash + +# execute inside the image: + +# user +whoami + +# location +pwd + +# java version +java -version +``` + +As we see, this image runs as user `root` inside root `/` and has java version 21. + + +Create the `Containerfile.jdk` file inside `gs-spring-boot/initial` with following content: + +```Dockerfile +FROM docker.io/eclipse-temurin:21-jdk-ubi9-minimal AS build +# user: root! +COPY . . +RUN ./gradlew build + +FROM docker.io/eclipse-temurin:21-jre-ubi9-minimal +COPY --from=build /build/libs/spring-boot-0.0.1-SNAPSHOT.jar / +EXPOSE 8080 +ENTRYPOINT ["java", "-jar", "/spring-boot-0.0.1-SNAPSHOT.jar"] +``` + +This is a multistage build using a JDK to build the app and a JRE container to run it. + + +Build image (includes app build): +```bash +docker build -t my-spring-jdk -f Containerfile.jdk . +``` + +Attention: Clean local build and .gradle files if you encounter file permission problems. + + +Test app inside container: +```bash +docker run -ti --entrypoint /bin/bash my-spring-jdk +java -jar /spring-boot-0.0.1-SNAPSHOT.jar +``` + +Exit with ctrl+d + + +Run container: +```bash +docker run -p 8080:8080 my-spring-jdk +``` + +Open your browser at http://localhost:8080/ + +You should see: `Greetings from Spring Boot!` + +Stop container with ctrl+c diff --git a/content/en/docs/05/5.2/_index.md b/content/en/docs/05/5.2/_index.md new file mode 100644 index 0000000..cdf3832 --- /dev/null +++ b/content/en/docs/05/5.2/_index.md @@ -0,0 +1,80 @@ +--- +title: "5.2 Use Chainguard Image" +weight: 52 +sectionnumber: 5.2 +--- + +## App - the Chainguard way + +Go to the [Chainguard console](https://console.chainguard.dev/) and search for a Java image. + +The `Organization` tab shows all images that we can use at Puzzle. Thanks to our Chainguard partnership. +The `Chainguard catalog` tab shows all Chainguard Images. We can ask Chainguard to provide us with images from their catalog such that they are available in our org. + +Test Chainguard base image candidate and get infos: + +```bash +docker run -ti cgr.dev/puzzle-partner.com/jdk:openjdk-21 /bin/sh + +# execute inside the image: + +# user +whoami + +# location +pwd + +# java version +java -version +``` + +As we see, this image runs as user `java` inside `/home/build` and has java version 21. +As you know, running as root in production is a no-go. OpenShift will also prevent the container from starting. + +Change the greetings inside `src/main/java/com/example/springboot/HelloController.java` to `Greetings from Chainguard!`. + + +Create the `Containerfile.cg` file inside `gs-spring-boot/initial` with following content: + +```Dockerfile +FROM cgr.dev/puzzle-partner.com/jdk:openjdk-21 AS build +COPY . . +RUN ./gradlew build + +FROM cgr.dev/puzzle-partner.com/jre:openjdk-21 +COPY --from=build /home/build/./build/libs/spring-boot-0.0.1-SNAPSHOT.jar /home/build/ +EXPOSE 8080 +ENTRYPOINT ["java", "-jar", "/home/build/spring-boot-0.0.1-SNAPSHOT.jar"] +``` + + +This is also a multistage build using a Chainguard JDK image to build the app and a Chainguard JRE container to run it. + +Build: +```bash +docker build -t my-spring-cg -f Containerfile.cg . +``` + +Attention: Clean local build and .gradle files if you encounter file permission problems. + + +Test app inside container: +```bash +docker run -ti --entrypoint /bin/sh my-spring-cg +java -jar ./build/libs/spring-boot-0.0.1-SNAPSHOT.jar +``` + +You shold get an error. +The images are minimal and hardened. This to keep the attack surface as small as possible. + + +Run container: +```bash +docker run -p 8080:8080 my-spring-cg +``` + +Open your browser at http://localhost:8080/ + +You should see: `Greetings from Chainguard!` + +Stop contaier with ctrl+c diff --git a/content/en/docs/05/5.3/_index.md b/content/en/docs/05/5.3/_index.md new file mode 100644 index 0000000..162a5a7 --- /dev/null +++ b/content/en/docs/05/5.3/_index.md @@ -0,0 +1,87 @@ +--- +title: "5.3 Use Chainguard Libraries" +weight: 53 +sectionnumber: 5.3 +--- + +## Get Libraries + +Now we will also use Chainguard Libraries. + +The [CG doc](https://edu.chainguard.dev/chainguard/libraries/access/) states following to get access to the [Java libraries](https://edu.chainguard.dev/chainguard/libraries/java/overview/): + +```bash +chainctl auth pull-token --repository=java --parent=puzzle-partner.com --ttl=8670h +``` + +We will use the eval command that will set the needed env vars: +```bash +eval $(chainctl auth pull-token --output env --repository=java --parent=puzzle-partner.com) +``` + +Check the Gradle build configuration (`initial/build.gradle`) for dependencies. + +Chainguard provides the `spring-boot-starter-web` library: + +https://libraries.cgr.dev/java/org/springframework/boot/spring-boot-starter-web/ + + +Now we have to configure Gradle to use Chainguard libraries that are available through the Chainguard repository: `https://libraries.cgr.dev/java/` + + +Extend the file `build.gradle` to get Chainguard libraries: + +```shell +... +repositories { + maven { + url = uri("https://libraries.cgr.dev/java/") + credentials { + username = "CHAINGUARD_JAVA_IDENTITY_ID" + password = "CHAINGUARD_JAVA_TOKEN" + } + } + mavenCentral() +} +... +``` + +Official documentation: https://edu.chainguard.dev/chainguard/libraries/java/build-configuration/#gradle + + +We will build the application outside of the container. +Java 21 is needed and a clean Gradle cache. + +Clean the Gradle cache: + +```bash +rm -rf .gradle/caches/ +rm -rf ~/.gradle/caches/ +``` + +Build the app: + +```bash +./gradlew clean build +``` + +Run the app: + +```bash +java -jar build/libs/spring-boot-0.0.1-SNAPSHOT.jar +``` + +Open your browser at http://localhost:8080/ + +You should see: `Greetings from Chainguard!` + +Stop the app with ctrl+c + + +Now we can verify the usage of Chainguard libraries inside our Java app: + +```bash +chainctl libraries verify --detailed --parent=puzzle-partner.com ./build/libs/spring-boot-0.0.1-SNAPSHOT.jar +``` + +Official documentation: https://edu.chainguard.dev/chainguard/libraries/verification/ diff --git a/content/en/docs/05/5.4/_index.md b/content/en/docs/05/5.4/_index.md new file mode 100644 index 0000000..134a5d1 --- /dev/null +++ b/content/en/docs/05/5.4/_index.md @@ -0,0 +1,28 @@ +--- +title: "5.4 Vulnerability Scan and CVE comparison" +weight: 54 +sectionnumber: 5.4 +--- + +## Scan Images + +We will scan and compare both images. + +Check the Grype tutorial for installing Grype or using the Grype container: https://edu.chainguard.dev/chainguard/chainguard-images/staying-secure/working-with-scanners/grype-tutorial/ + +Scan both images to compare the vulnerabilities: + +```bash +grype my-spring-jdk:latest + +grype my-spring-cg:latest +``` + +Alternatively with docker: + +```bash +docker run --rm -it --volume /var/run/docker.sock:/var/run/docker.sock anchore/grype my-spring-jdk:latest +docker run --rm -it --volume /var/run/docker.sock:/var/run/docker.sock anchore/grype my-spring-cg:latest +``` + +What are the differences? diff --git a/content/en/docs/05/_index.md b/content/en/docs/05/_index.md new file mode 100644 index 0000000..3c291e4 --- /dev/null +++ b/content/en/docs/05/_index.md @@ -0,0 +1,7 @@ +--- +title: "5. Application Migration to Chainguard" +weight: 2 +sectionnumber: 2 +description: > + Build an application and migrate it to Chainguard Images and Libs. +---