diff --git a/.github/workflows/presubmit-build.yaml b/.github/workflows/presubmit-build.yaml index 6ee2db65..dad7a7dd 100644 --- a/.github/workflows/presubmit-build.yaml +++ b/.github/workflows/presubmit-build.yaml @@ -42,3 +42,19 @@ jobs: uses: ./.github/workflows/.build.yaml with: image: wolfictl + + static-alpine: + uses: ./.github/workflows/.build.yaml + with: + image: static + + + git-alpine: + uses: ./.github/workflows/.build.yaml + with: + image: git + + busybox-alpine: + uses: ./.github/workflows/.build.yaml + with: + image: busybox diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index e086349c..9b33f664 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -58,3 +58,21 @@ jobs: with: image: wolfictl registry: ghcr.io/wolfi-dev/wolfictl + + static-alpibe: + uses: ./.github/workflows/.build.yaml + with: + image: static + registry: ghcr.io/wolfi-dev/static + + static-git: + uses: ./.github/workflows/.build.yaml + with: + image: git + registry: ghcr.io/wolfi-dev/git + + static-busybox: + uses: ./.github/workflows/.build.yaml + with: + image: busybox + registry: ghcr.io/wolfi-dev/busybox diff --git a/README.md b/README.md index 74b2f4e1..72a8549a 100644 --- a/README.md +++ b/README.md @@ -3,34 +3,64 @@ Various tools, images, etc. to support the Wolfi OSS project - [Images](#images) - - [sdk](#sdk) + - [alpine-base](#alpine-base) - [apko](#apko) + - [busybox](#busybox) + - [gcc-musl](#gcc-musl) + - [git](#git) - [melange](#melange) + - [musl-dynamic](#musl-dynamic) + - [sdk](#sdk) + - [static](#static) - [wolfictl](#wolfictl) ## Images -### sdk +### alpine-base -The [sdk](./images/sdk) image contains melange, apko, -wolfictl and other tools such as Go needed to build these projects. - -This image is also used by [dag](https://github.com/wolfi-dev/dag) -to build Wolfi packages for ARM etc. +The [alpine-base](./images/alpine-base) image is a minimal Alpine-based image containing `apk` and basic tools to get started. ``` -ghcr.io/wolfi-dev/sdk:latest +ghcr.io/wolfi-dev/alpine-base:latest ``` ### apko -The [apko](./images/apko) image contains -[apko](https://github.com/chainguard-dev/apko). +The [apko](./images/apko) image contains [apko](https://github.com/chainguard-dev/apko). ``` ghcr.io/wolfi-dev/apko:latest ``` +### busybox + +The [busybox](./images/busybox) image contains [busybox](https://busybox.net/) built from Alpine's busybox package. + +``` +ghcr.io/wolfi-dev/busybox:alpine +``` + +It's intended as a replacement for `cgr.dev/chainguard/busybox:latest`. + +### gcc-musl + +The [gcc-musl](./images/gcc-musl) image contains a GCC toolchain built with musl libc from Alpine's packages. + +``` +ghcr.io/wolfi-dev/gcc-musl:latest +``` + +### git + +The [git](./images/git) image contains [git](https://git-scm.com/) built from Alpine's git package. + +``` +ghcr.io/wolfi-dev/git:alpine +ghcr.io/wolfi-dev/git:alpine-root +``` + +It's intended as a replacement for `cgr.dev/chainguard/git:latest` and `cgr.dev/chainguard/git:latest-root`. + ### melange The [melange](./images/melange) image contains @@ -40,6 +70,32 @@ The [melange](./images/melange) image contains ghcr.io/wolfi-dev/melange:latest ``` +### musl-dynamic + +The [musl-dynamic](./images/musl-dynamic) image contains a musl libc built from Alpine's packages. + +``` +ghcr.io/wolfi-dev/musl-dynamic:latest +``` + +### sdk + +The [sdk](./images/sdk) image contains melange, apko, wolfictl and other tools such as Go needed to build these projects. + +``` +ghcr.io/wolfi-dev/sdk:latest +``` + +### static + +The [static](./images/static) image contains a minimal static base image built from Alpine's packages. + +``` +ghcr.io/wolfi-dev/static:alpine +``` + +It's intended as a replacement for `cgr.dev/chainguard/static:latest`. + ### wolfictl The [wolfictl](./images/wolfictl) image contains diff --git a/images/busybox/alpine.tf b/images/busybox/alpine.tf new file mode 100644 index 00000000..304572fa --- /dev/null +++ b/images/busybox/alpine.tf @@ -0,0 +1,18 @@ +module "alpine" { source = "./config/alpine" } + +module "latest-alpine" { + providers = { + apko = apko.alpine + } + source = "../../tflib/publisher" + + target_repository = var.target_repository + config = module.alpine.config + # Override the module's default wolfi packages that conflict with alpine + extra_packages = [] +} + +module "test-latest-alpine" { + source = "./tests" + digest = module.latest-alpine.image_ref +} diff --git a/images/busybox/config/alpine/main.tf b/images/busybox/config/alpine/main.tf new file mode 100644 index 00000000..bed8ece5 --- /dev/null +++ b/images/busybox/config/alpine/main.tf @@ -0,0 +1,28 @@ +variable "extra_packages" { + description = "Extra packages to install." + type = list(string) + default = [] +} + +output "config" { + value = jsonencode({ + contents = { + packages = concat([ + "busybox", + "ssl_client", # ssl_client allows the busybox wget applet to use https. + ], var.extra_packages) + } + accounts = { + groups = [{ + groupname = "nonroot" + gid = 65532 + }] + users = [{ + username = "nonroot" + uid = 65532 + gid = 65532 + }] + run-as = 65532 + } + }) +} diff --git a/images/busybox/main.tf b/images/busybox/main.tf new file mode 100644 index 00000000..01d8ae9e --- /dev/null +++ b/images/busybox/main.tf @@ -0,0 +1,30 @@ +terraform { + required_providers { + oci = { source = "chainguard-dev/oci" } + apko = { + source = "chainguard-dev/apko" + configuration_aliases = [apko.alpine] + } + } +} + +provider "apko" { + alias = "alpine" + + extra_repositories = ["https://dl-cdn.alpinelinux.org/alpine/edge/main"] + # These packages match chainguard-images/static + extra_packages = ["alpine-baselayout-data", "alpine-release", "ca-certificates-bundle"] + // Don't build for riscv64, 386, arm/v6 + // Only build for: amd64, arm/v7, arm64, ppc64le, s390x + default_archs = ["amd64", "arm/v7", "arm64", "ppc64le", "s390x"] +} + +variable "target_repository" { + description = "The docker repo into which the image and attestations should be published." +} + +resource "oci_tag" "alpine" { + depends_on = [module.test-latest-alpine] + digest_ref = module.latest-alpine.image_ref + tag = "alpine" +} diff --git a/images/busybox/tests/main.tf b/images/busybox/tests/main.tf new file mode 100644 index 00000000..25d2af27 --- /dev/null +++ b/images/busybox/tests/main.tf @@ -0,0 +1,14 @@ +terraform { + required_providers { + oci = { source = "chainguard-dev/oci" } + } +} + +variable "digest" { + description = "The image digest to run tests over." +} + +data "oci_exec_test" "runs" { + digest = var.digest + script = "${path.module}/runs.sh" +} diff --git a/images/busybox/tests/runs.sh b/images/busybox/tests/runs.sh new file mode 100755 index 00000000..3e3db57a --- /dev/null +++ b/images/busybox/tests/runs.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +set -o errexit -o nounset -o errtrace -o pipefail -x + +docker run --rm $IMAGE_NAME ls >/dev/null + +# The image runs as nonroot by default. +docker run --rm --entrypoint '' $IMAGE_NAME whoami | grep "^nonroot$" + +# The image contains many common utilities (some in /usr/bin and some in /bin) +for cmd in awk basename cat chmod chown cp cut date dirname du echo egrep expr find grep head id ln ls mkdir mktemp mv printf pwd rm rmdir sed sh sort tail tar tee test touch tr uname uniq wc xargs; do + docker run --rm $IMAGE_NAME which $cmd | grep "/bin/$cmd$" +done + +# The image can be used as a base image. +cat < hello.rs +RUN rustc -C target-feature=+crt-static hello.rs + +FROM $BASE + +COPY --from=build /work/hello /usr/local/bin/ +CMD ["hello"] diff --git a/images/static/examples/hello.c b/images/static/examples/hello.c new file mode 100644 index 00000000..c461cda8 --- /dev/null +++ b/images/static/examples/hello.c @@ -0,0 +1,6 @@ +#include + +int main() { + printf("Hello!\n"); + return 0; +} diff --git a/images/static/examples/main.go b/images/static/examples/main.go new file mode 100644 index 00000000..44ee7ea6 --- /dev/null +++ b/images/static/examples/main.go @@ -0,0 +1,7 @@ +package main + +import "fmt" + +func main() { + fmt.Println("Hello!") +} diff --git a/images/static/main.tf b/images/static/main.tf new file mode 100644 index 00000000..85f673f2 --- /dev/null +++ b/images/static/main.tf @@ -0,0 +1,30 @@ +terraform { + required_providers { + oci = { source = "chainguard-dev/oci" } + apko = { + source = "chainguard-dev/apko" + configuration_aliases = [apko.alpine] + } + } +} + +provider "apko" { + alias = "alpine" + + extra_repositories = ["https://dl-cdn.alpinelinux.org/alpine/edge/main"] + # These packages match chainguard-images/static + extra_packages = ["alpine-baselayout-data", "alpine-release", "ca-certificates-bundle"] + // Don't build for riscv64, 386, arm/v6 + // Only build for: amd64, arm/v7, arm64, ppc64le, s390x + default_archs = ["amd64", "arm/v7", "arm64", "ppc64le", "s390x"] +} + +variable "target_repository" { + description = "The docker repo into which the image and attestations should be published." +} + +resource "oci_tag" "alpine" { + depends_on = [module.test-alpine] + digest_ref = module.alpine.image_ref + tag = "alpine" +} diff --git a/images/static/tests/01-multi-dockerfile-build.sh b/images/static/tests/01-multi-dockerfile-build.sh new file mode 100755 index 00000000..4517ff66 --- /dev/null +++ b/images/static/tests/01-multi-dockerfile-build.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -o errexit -o nounset -o errtrace -o pipefail -x + +cd "$(dirname ${BASH_SOURCE[0]})/.." + +# Using registry.local:5000 as the BASE arg in `docker build` fails with +# current versions of docker that use containerd under the hood. +# Pre-pulling it uses docker's heuristics for allowing insecure registries. +docker pull ${IMAGE_NAME} + +for lang in c golang rust; do + docker build --build-arg BASE=${IMAGE_NAME} --tag smoke-test-${lang}-${FREE_PORT} --file examples/Dockerfile.${lang} examples + docker run --rm smoke-test-${lang}-${FREE_PORT} +done diff --git a/images/static/tests/main.tf b/images/static/tests/main.tf new file mode 100644 index 00000000..af2d8cfa --- /dev/null +++ b/images/static/tests/main.tf @@ -0,0 +1,15 @@ +terraform { + required_providers { + oci = { source = "chainguard-dev/oci" } + } +} + +variable "digest" { + description = "The image digest to run tests over." +} + +data "oci_exec_test" "version" { + digest = var.digest + script = "./01-multi-dockerfile-build.sh" + working_dir = path.module +} diff --git a/tflib/publisher/main.tf b/tflib/publisher/main.tf index 7f473cd3..4c937263 100644 --- a/tflib/publisher/main.tf +++ b/tflib/publisher/main.tf @@ -2,11 +2,11 @@ terraform { required_providers { cosign = { source = "chainguard-dev/cosign" - version = "0.0.17" + version = "0.0.19" } apko = { source = "chainguard-dev/apko" - version = "0.13.0" + version = "0.15.2" } } } @@ -20,13 +20,20 @@ variable "extra_packages" { default = ["wolfi-baselayout"] } +variable "check_sbom" { + type = bool + default = false + description = "Whether to run the NTIA conformance checker over the images we produce prior to attesting the SBOMs." +} + module "this" { source = "chainguard-dev/apko/publisher" - version = "0.0.10" + version = "0.0.12" target_repository = var.target_repository config = var.config extra_packages = var.extra_packages + check_sbom = var.check_sbom } output "image_ref" {