diff --git a/.github/workflows/image-pr.yaml b/.github/workflows/image-pr.yaml index fe86108b..642c5602 100644 --- a/.github/workflows/image-pr.yaml +++ b/.github/workflows/image-pr.yaml @@ -12,9 +12,31 @@ env: FORCE_COLOR: 1 EARTHLY_TOKEN: ${{ secrets.EARTHLY_TOKEN }} jobs: + # Populate the trivy cache once for all later jobs to use + trivy-cache: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 + with: + fetch-depth: 0 + - name: Install earthly + uses: Luet-lab/luet-install-action@cec77490c3f2416d7d07a47cfab04d448641d7ce # v1.1 + with: + repository: quay.io/kairos/packages + packages: utils/earthly + - name: Restore trivy cache + uses: yogeshlonkar/trivy-cache-action@v0 + with: + gh-token: ${{ secrets.GITHUB_TOKEN }} + - name: Populate trivy Cache + run: | + [ ! -d ".trivy" ] && mkdir -p ".trivy" + earthly +trivy-download-db --DIR .trivy core-ubuntu-22-lts: uses: ./.github/workflows/reusable-build-flavor.yaml secrets: inherit + needs: + - trivy-cache permissions: contents: write security-events: write @@ -42,6 +64,8 @@ jobs: core-ubuntu-24-lts: uses: ./.github/workflows/reusable-build-flavor.yaml secrets: inherit + needs: + - trivy-cache permissions: contents: write security-events: write @@ -69,6 +93,8 @@ jobs: core-alpine: uses: ./.github/workflows/reusable-build-flavor.yaml secrets: inherit + needs: + - trivy-cache permissions: contents: write security-events: write @@ -96,6 +122,8 @@ jobs: standard: uses: ./.github/workflows/reusable-build-provider.yaml secrets: inherit + needs: + - trivy-cache permissions: id-token: write # OIDC support contents: write @@ -128,6 +156,7 @@ jobs: flavor_release: "24.04" secureboot: false needs: + - trivy-cache - core-ubuntu-24-lts install-target: @@ -138,6 +167,7 @@ jobs: flavor_release: "24.04" secureboot: false needs: + - trivy-cache - core-ubuntu-24-lts install-secureboot: @@ -148,6 +178,7 @@ jobs: flavor_release: "24.04" secureboot: true needs: + - trivy-cache - core-ubuntu-24-lts install-alpine: @@ -157,6 +188,7 @@ jobs: flavor: alpine flavor_release: "3.19" needs: + - trivy-cache - core-alpine zfs: @@ -166,6 +198,7 @@ jobs: flavor: ubuntu flavor_release: "22.04" needs: + - trivy-cache - core-ubuntu-22-lts acceptance: @@ -175,6 +208,7 @@ jobs: flavor: ubuntu flavor_release: "24.04" needs: + - trivy-cache - core-ubuntu-24-lts acceptance-alpine: @@ -184,6 +218,7 @@ jobs: flavor: alpine flavor_release: "3.19" needs: + - trivy-cache - core-alpine bundles: @@ -193,6 +228,7 @@ jobs: flavor: ubuntu flavor_release: "24.04" needs: + - trivy-cache - core-ubuntu-24-lts reset: @@ -202,6 +238,7 @@ jobs: flavor: ubuntu flavor_release: "24.04" needs: + - trivy-cache - core-ubuntu-24-lts reset-alpine: @@ -211,6 +248,7 @@ jobs: flavor: alpine flavor_release: "3.19" needs: + - trivy-cache - core-alpine netboot: @@ -224,6 +262,7 @@ jobs: model: generic variant: core needs: + - trivy-cache - core-ubuntu-24-lts netboot-alpine: @@ -237,6 +276,7 @@ jobs: model: generic variant: core needs: + - trivy-cache - core-alpine upgrade: @@ -246,6 +286,7 @@ jobs: flavor: ubuntu flavor_release: "24.04" needs: + - trivy-cache - core-ubuntu-24-lts upgrade-alpine: @@ -255,6 +296,7 @@ jobs: flavor: alpine flavor_release: "3.19" needs: + - trivy-cache - core-alpine upgrade-latest: @@ -266,6 +308,7 @@ jobs: family: "ubuntu" # release_matcher: "23.10" # introduced so tests can be green while we wait for the kairos release with the latest flavor release needs: + - trivy-cache - core-ubuntu-24-lts # enable once the first alpine only release is out as it currently cannot find the latest alpine release properly @@ -275,6 +318,7 @@ jobs: # flavor: alpine # flavor_release: "3.19" # needs: + # - trivy-cache # - core-alpine custom-partitioning: @@ -299,6 +343,7 @@ jobs: flavor: ${{ matrix.flavor }} flavor_release: ${{ matrix.flavorRelease }} needs: + - trivy-cache - core-ubuntu-24-lts strategy: fail-fast: true @@ -315,6 +360,7 @@ jobs: flavor_release: "24.04" label: ${{ matrix.label }} needs: + - trivy-cache - core-ubuntu-24-lts strategy: fail-fast: true @@ -334,6 +380,7 @@ jobs: flavor_release: "3.19" label: ${{ matrix.label }} needs: + - trivy-cache - core-alpine strategy: fail-fast: true diff --git a/.github/workflows/release-arm.yaml b/.github/workflows/release-arm.yaml index ea5097bf..a2f52832 100644 --- a/.github/workflows/release-arm.yaml +++ b/.github/workflows/release-arm.yaml @@ -77,6 +77,27 @@ jobs: # end of optional handling for multi line json echo "::set-output name=matrix::{\"include\": $content }" + # Populate the trivy cache once for all later jobs to use + trivy-cache: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 + with: + fetch-depth: 0 + - name: Install earthly + uses: Luet-lab/luet-install-action@cec77490c3f2416d7d07a47cfab04d448641d7ce # v1.1 + with: + repository: quay.io/kairos/packages + packages: utils/earthly + - name: Restore trivy cache + uses: yogeshlonkar/trivy-cache-action@v0 + with: + gh-token: ${{ secrets.GITHUB_TOKEN }} + - name: Populate trivy Cache + run: | + [ ! -d ".trivy" ] && mkdir -p ".trivy" + earthly +trivy-download-db --DIR .trivy + build-nvidia-base: runs-on: ARM64 steps: @@ -173,6 +194,7 @@ jobs: build-arm-core: runs-on: ${{ matrix.worker }} needs: + - trivy-cache - get-core-matrix permissions: id-token: write # OIDC support @@ -247,10 +269,19 @@ jobs: registry: quay.io username: ${{ secrets.QUAY_USERNAME }} password: ${{ secrets.QUAY_PASSWORD }} + - name: Restore trivy cache + uses: yogeshlonkar/trivy-cache-action@v0 + with: + gh-token: ${{ secrets.GITHUB_TOKEN }} + - name: Populate trivy Cache + run: | + [ ! -d ".trivy" ] && mkdir -p ".trivy" + earthly +trivy-download-db --DIR .trivy - name: Build 🔧 run: | earthly -P +all-arm \ -VARIANT=core \ + --TRIVY_CACHE_DIR=.trivy \ -MODEL=${{ matrix.model }} \ -FLAVOR=${{ matrix.flavor }} \ -FLAVOR_RELEASE=${{ matrix.flavorRelease }} \ @@ -315,6 +346,7 @@ jobs: build-arm-standard: runs-on: ARM64 needs: + - trivy-cache - get-standard-matrix permissions: id-token: write # OIDC support @@ -359,10 +391,19 @@ jobs: registry: quay.io username: ${{ secrets.QUAY_USERNAME }} password: ${{ secrets.QUAY_PASSWORD }} + - name: Restore trivy cache + uses: yogeshlonkar/trivy-cache-action@v0 + with: + gh-token: ${{ secrets.GITHUB_TOKEN }} + - name: Populate trivy Cache + run: | + [ ! -d ".trivy" ] && mkdir -p ".trivy" + earthly +trivy-download-db --DIR .trivy - name: Build 🔧 run: | earthly -P +all-arm \ -VARIANT=standard \ + --TRIVY_CACHE_DIR=.trivy \ -MODEL=${{ matrix.model }} \ -K3S_VERSION=${{ matrix.k3s_version }} \ -FLAVOR=${{ matrix.flavor }} \ diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 48384f40..1d5d0cc0 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -93,11 +93,31 @@ jobs: # end of optional handling for multi line json echo "::set-output name=matrix::{\"include\": $content }" - + # Populate the trivy cache once for all later jobs to use + trivy-cache: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 + with: + fetch-depth: 0 + - name: Install earthly + uses: Luet-lab/luet-install-action@cec77490c3f2416d7d07a47cfab04d448641d7ce # v1.1 + with: + repository: quay.io/kairos/packages + packages: utils/earthly + - name: Restore trivy cache + uses: yogeshlonkar/trivy-cache-action@v0 + with: + gh-token: ${{ secrets.GITHUB_TOKEN }} + - name: Populate trivy Cache + run: | + [ ! -d ".trivy" ] && mkdir -p ".trivy" + earthly +trivy-download-db --DIR .trivy build-core: runs-on: ubuntu-latest needs: - - get-core-matrix + - trivy-cache + - get-core-matrix permissions: id-token: write # OIDC support contents: write @@ -161,9 +181,18 @@ jobs: with: repository: quay.io/kairos/packages packages: utils/earthly + - name: Restore trivy cache + uses: yogeshlonkar/trivy-cache-action@v0 + with: + gh-token: ${{ secrets.GITHUB_TOKEN }} + - name: Populate trivy Cache + run: | + [ ! -d ".trivy" ] && mkdir -p ".trivy" + earthly +trivy-download-db --DIR .trivy - name: Build 🔧 run: | earthly +all \ + --TRIVY_CACHE_DIR=.trivy \ --VARIANT=${{ matrix.variant }} \ --FAMILY=${{ matrix.family }} \ --FLAVOR=${{ matrix.flavor }} \ @@ -232,6 +261,7 @@ jobs: actions: read security-events: write needs: + - trivy-cache - get-uki-matrix strategy: matrix: ${{ fromJson(needs.get-uki-matrix.outputs.matrix) }} @@ -345,7 +375,8 @@ jobs: build-standard: runs-on: ubuntu-latest needs: - - get-standard-matrix + - trivy-cache + - get-standard-matrix permissions: id-token: write # OIDC support contents: write @@ -407,9 +438,18 @@ jobs: packages: utils/earthly - name: Login to Quay Registry run: echo ${{ secrets.QUAY_PASSWORD }} | docker login -u ${{ secrets.QUAY_USERNAME }} --password-stdin quay.io + - name: Restore trivy cache + uses: yogeshlonkar/trivy-cache-action@v0 + with: + gh-token: ${{ secrets.GITHUB_TOKEN }} + - name: Populate trivy Cache + run: | + [ ! -d ".trivy" ] && mkdir -p ".trivy" + earthly +trivy-download-db --DIR .trivy - name: Build 🔧 run: | earthly +all \ + --TRIVY_CACHE_DIR=.trivy \ --VARIANT=${{ matrix.variant }} \ --FAMILY=${{ matrix.family }} \ --FLAVOR=${{ matrix.flavor }} \ diff --git a/.github/workflows/reusable-build-flavor.yaml b/.github/workflows/reusable-build-flavor.yaml index f2c4223f..34f62b34 100644 --- a/.github/workflows/reusable-build-flavor.yaml +++ b/.github/workflows/reusable-build-flavor.yaml @@ -106,6 +106,14 @@ jobs: - name: Login to earthly run: | earthly account login --token ${{ secrets.EARTHLY_TOKEN }} && earthly org select Kairos + - name: Restore trivy cache + uses: yogeshlonkar/trivy-cache-action@v0 + with: + gh-token: ${{ secrets.GITHUB_TOKEN }} + - name: Populate trivy Cache + run: | + [ ! -d ".trivy" ] && mkdir -p ".trivy" + earthly +trivy-download-db --DIR .trivy - name: Build PR 🔧 if: ${{ github.event_name == 'pull_request' }} run: | @@ -129,6 +137,7 @@ jobs: run: | earthly --platform=linux/${{ inputs.arch }} +ci \ --SECURITY_SCANS=true \ + --TRIVY_CACHE_DIR=.trivy \ --VARIANT=${{ inputs.variant }} \ --FLAVOR=${{ inputs.flavor }} \ --FLAVOR_RELEASE=${{ inputs.flavor_release }} \ diff --git a/.github/workflows/reusable-build-provider.yaml b/.github/workflows/reusable-build-provider.yaml index 0ece9a82..9d08ca73 100644 --- a/.github/workflows/reusable-build-provider.yaml +++ b/.github/workflows/reusable-build-provider.yaml @@ -90,6 +90,14 @@ jobs: - name: Login to earthly run: | earthly account login --token ${{ secrets.EARTHLY_TOKEN }} && earthly org select Kairos + - name: Restore trivy cache + uses: yogeshlonkar/trivy-cache-action@v0 + with: + gh-token: ${{ secrets.GITHUB_TOKEN }} + - name: Populate trivy Cache + run: | + [ ! -d ".trivy" ] && mkdir -p ".trivy" + earthly +trivy-download-db --DIR .trivy - name: Build PR 🔧 if: ${{ github.event_name == 'pull_request' }} run: | @@ -120,6 +128,7 @@ jobs: INIT=$([[ "${{ inputs.flavor }}" == "alpine" ]] && echo "openrc" || echo "systemd") K3S_VERSION=$(sudo luet --config framework-profile.yaml search -o json k8s/k3s | jq --arg INIT "$INIT" '.packages | map(select(.name == "k3s-" + $INIT)) | map(.version) | unique | last' | tr -d '"') earthly --platform=linux/${{ inputs.arch }} +ci \ + --TRIVY_CACHE_DIR=.trivy \ --SECURITY_SCANS=true \ --VARIANT=${{ inputs.variant }} \ --FLAVOR=${{ inputs.flavor }} \ diff --git a/.github/workflows/reusable-docker-arm-build.yaml b/.github/workflows/reusable-docker-arm-build.yaml index edbe4e3d..c210612d 100644 --- a/.github/workflows/reusable-docker-arm-build.yaml +++ b/.github/workflows/reusable-docker-arm-build.yaml @@ -131,9 +131,18 @@ jobs: - name: Login to earthly run: | earthly account login --token ${{ secrets.EARTHLY_TOKEN }} && earthly org select Kairos + - name: Restore trivy cache + uses: yogeshlonkar/trivy-cache-action@v0 + with: + gh-token: ${{ secrets.GITHUB_TOKEN }} + - name: Populate trivy Cache + run: | + [ ! -d ".trivy" ] && mkdir -p ".trivy" + earthly +trivy-download-db --DIR .trivy - name: Build 🔧 run: | earthly -P +all-arm \ + --TRIVY_CACHE_DIR=.trivy \ --VARIANT=core \ --MODEL=${{ inputs.model }} \ --FLAVOR=${{ inputs.flavor }} \ diff --git a/.gitignore b/.gitignore index 3ac5e31f..eb88d044 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ /kairos /dist /build +/trivy-cache coverage.out .DS_Store internal/webui/public/cypress/videos/ diff --git a/Earthfile b/Earthfile index de4a82c3..8b5bfd94 100644 --- a/Earthfile +++ b/Earthfile @@ -37,10 +37,12 @@ all: ARG --required MODEL ARG --required BASE_IMAGE # BASE_IMAGE is the image to apply the strategy (aka FLAVOR) on. E.g. ubuntu:20.04 + ARG TRIVY_CACHE_DIR + BUILD +base-image IF [ "$SECURITY_SCANS" = "true" ] BUILD +image-sbom - BUILD +trivy-scan + BUILD +trivy-scan --CACHEDIR=$TRIVY_CACHE_DIR BUILD +grype-scan END BUILD +iso @@ -59,10 +61,12 @@ ci: ARG --required VARIANT ARG --required FAMILY + ARG TRIVY_CACHE_DIR + BUILD +base-image IF [ "$SECURITY_SCANS" = "true" ] BUILD +image-sbom - BUILD +trivy-scan + BUILD +trivy-scan --CACHEDIR=$TRIVY_CACHE_DIR BUILD +grype-scan END BUILD +iso @@ -77,11 +81,12 @@ all-arm: ARG COMPRESS_IMG=true ARG SECURITY_SCANS=true + ARG TRIVY_CACHE_DIR BUILD --platform=linux/arm64 +base-image IF [ "$SECURITY_SCANS" = "true" ] BUILD --platform=linux/arm64 +image-sbom - BUILD --platform=linux/arm64 +trivy-scan + BUILD --platform=linux/arm64 +trivy-scan --CACHEDIR=$TRIVY_CACHE_DIR BUILD --platform=linux/arm64 +grype-scan END @@ -762,30 +767,45 @@ datasource-iso: RUN mkisofs -output ci.iso -volid cidata -joliet -rock user-data meta-data SAVE ARTIFACT /build/ci.iso iso.iso AS LOCAL build/datasource.iso -### -### Security target scan -### +trivy-download-db: + ARG TRIVY_VERSION + ARG DIR=trivy-cache + FROM aquasec/trivy:$TRIVY_VERSION + + COPY $DIR /trivy-cache + RUN /usr/local/bin/trivy --cache-dir /trivy-cache fs --download-db-only + SAVE ARTIFACT /trivy-cache AS LOCAL $DIR + trivy: ARG TRIVY_VERSION FROM aquasec/trivy:$TRIVY_VERSION SAVE ARTIFACT /contrib contrib SAVE ARTIFACT /usr/local/bin/trivy /trivy +### +### Security target scan +### trivy-scan: ARG TARGETARCH + ARG CACHEDIR # Use base-image so it can read original os-release file FROM +base-image ARG ISO_NAME=$(cat /etc/os-release | grep 'KAIROS_ARTIFACT' | sed 's/KAIROS_ARTIFACT=\"//' | sed 's/\"//') + ENV TRIVY_CACHE=/trivy-cache + IF [ -n "$CACHEDIR" ] + COPY $CACHEDIR $TRIVY_CACHE + END + COPY +trivy/trivy /trivy COPY +trivy/contrib /contrib WORKDIR /build - RUN /trivy filesystem --skip-dirs /tmp --timeout 30m --format sarif -o report.sarif --no-progress / - RUN /trivy filesystem --skip-dirs /tmp --timeout 30m --format template --template "@/contrib/html.tpl" -o report.html --no-progress / - RUN /trivy filesystem --skip-dirs /tmp --timeout 30m -f json -o results.json --no-progress / + RUN /trivy --cache-dir "${TRIVY_CACHE}" filesystem --skip-dirs /tmp --timeout 30m --format sarif -o report.sarif --no-progress / + RUN /trivy --cache-dir "${TRIVY_CACHE}" filesystem --skip-dirs /tmp --timeout 30m --format template --template "@/contrib/html.tpl" -o report.html --no-progress / + RUN /trivy --cache-dir "${TRIVY_CACHE}" filesystem --skip-dirs /tmp --timeout 30m -f json -o results.json --no-progress / SAVE ARTIFACT /build/report.sarif report.sarif AS LOCAL build/${ISO_NAME}-trivy.sarif SAVE ARTIFACT /build/report.html report.html AS LOCAL build/${ISO_NAME}-trivy.html SAVE ARTIFACT /build/results.json results.json AS LOCAL build/${ISO_NAME}-trivy.json