diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 9eead1e..ea4cde9 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,79 +1,110 @@ name: Build on: + pull_request: + branches: + - main push: branches: - main tags: - - v* + - v?* jobs: - images: + build: runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 + steps: - name: Prepare id: prep run: | - DOCKER_IMAGE=quay.io/k0sproject/cni-node - VERSION=latest - SHORTREF=${GITHUB_SHA::8} - - # If this is git tag, use the tag name as a docker tag - if [[ $GITHUB_REF == refs/tags/* ]]; then - VERSION=${GITHUB_REF#refs/tags/v} + # If this is a git tag, use the tag name as a docker tag + if [[ $GITHUB_REF == refs/tags/v?* ]]; then + registry=quay.io + name="$GITHUB_REPOSITORY" + tag="${GITHUB_REF#refs/tags/v}" + tag="${tag//+/-}" + else + registry=ttl.sh + name="${GITHUB_REPOSITORY//\//-}-$GITHUB_SHA-$GITHUB_RUN_ID" + tag=1d fi - TAGS="${DOCKER_IMAGE}:${VERSION},${DOCKER_IMAGE}:${SHORTREF}" - # If the VERSION looks like a version number, assume that - # this is the most recent version of the image and also - # tag it 'latest'. - if [[ $VERSION =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then - TAGS="$TAGS,${DOCKER_IMAGE}:latest" - fi - - # Set output parameters. - echo ::set-output name=tags::${TAGS} - echo ::set-output name=docker_image::${DOCKER_IMAGE} + { + echo registry="$registry" + echo name="$name" + echo tag="$tag" + } >>"$GITHUB_OUTPUT" - name: Set up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v3.0.0 with: - platforms: all + platforms: amd64,arm64,arm - name: Set up Docker Buildx id: buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Quay - if: github.event_name != 'pull_request' - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - registry: quay.io + uses: docker/setup-buildx-action@v3.0.0 - - name: Build - uses: docker/build-push-action@v2 + - name: Build OCI image archive + id: build + uses: docker/build-push-action@v5.0.0 with: builder: ${{ steps.buildx.outputs.name }} - context: . - file: ./Dockerfile platforms: linux/amd64,linux/arm64,linux/arm - push: true - tags: ${{ steps.prep.outputs.tags }} + tags: ${{ format('{0}/{1}:{2}', steps.prep.outputs.registry, steps.prep.outputs.name, steps.prep.outputs.tag) }} + outputs: type=oci,dest=oci-image.tar + + - name: Compress OCI image archive + # Pre-compress the image archive so that the upload-artifact action + # doesn't try to do it. The layers inside the tar archive are themselves + # already gzip compressed, so this is not for size reduction, but solely + # to prevent the very slow compression process in the upload-artifact + # action. + # See: https://github.com/actions/upload-artifact/issues/199 + # See: https://github.com/actions/toolkit/blob/6c1f9eaae833355a0b212b66c5f2e3ac366de185/packages/artifact/src/internal/upload-gzip.ts#L11-L33 + # Might be fixed when upload-artifact@v4 gets released: https://github.com/actions/toolkit/pull/1488 + run: zstdmt --fast oci-image.tar + + - name: Upload OCI image archive + uses: actions/upload-artifact@v3 + with: + name: oci-image.tar.zst + path: oci-image.tar.zst + + - name: Extract OCI image archive + run: mkdir image && tar xf oci-image.tar.zst -C image/ - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@master + uses: aquasecurity/trivy-action@0.12.0 with: - image-ref: ${{ steps.prep.outputs.tags }} - ignore-unfixed: true - format: 'sarif' - output: 'trivy-results.sarif' + input: image/ + format: table + list-all-pkgs: "true" # Flags a warning, but prints out stuff nevertheless + exit-code: "1" - - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@v2 + - name: Log in to registry + if: steps.prep.outputs.registry != 'ttl.sh' + uses: redhat-actions/podman-login@v1 with: - sarif_file: 'trivy-results.sarif' + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + registry: ${{ steps.prep.outputs.registry }} + + - name: Upload OCI image to registry + env: + REGISTRY: ${{ steps.prep.outputs.registry }} + NAME: ${{ steps.prep.outputs.name }} + TAG: ${{ steps.prep.outputs.tag }} + run: | + podmanArgs=(-v "$(realpath oci-image.tar):/image.tar:ro") + skopeoArgs=(--multi-arch all --preserve-digests) + + if [ -e "$REGISTRY_AUTH_FILE" ]; then + podmanArgs+=(-v "$REGISTRY_AUTH_FILE:/auth.json:ro") + skopeoArgs+=(--authfile=/auth.json) + fi + + set -x + podman run "${podmanArgs[@]}" \ + docker://quay.io/skopeo/stable:v1.13.3 copy "${skopeoArgs[@]}" \ + oci-archive:/image.tar "docker://$REGISTRY/$NAME:$TAG" diff --git a/.github/workflows/scan.yaml b/.github/workflows/scan.yaml new file mode 100644 index 0000000..86c44d2 --- /dev/null +++ b/.github/workflows/scan.yaml @@ -0,0 +1,59 @@ +name: Security scan +on: + schedule: + - cron: 0 2 * * 1-5 + release: + types: + - published + workflow_dispatch: + +jobs: + trivy: + runs-on: ubuntu-latest + permissions: + security-events: write # upload sarif results + + steps: + - name: Prepare + id: prep + env: + PUBLISHED_TAG: ${{ github.event.release.tag_name }} + GH_REPO: ${{ github.repository }} + GH_TOKEN: ${{ github.token }} + run: | + if [ -n "$PUBLISHED_TAG" ]; then + gitTag="$PUBLISHED_TAG" + else + # Get the tag name from the latest GitHub release + gitTag="$(gh api repos/{owner}/{repo}/releases/latest --jq .tag_name)" + fi + + # Determine OCI image tag + imageTag="${gitTag//+/-}" + imageTag="${imageTag#v}" + + { + echo git-tag="$gitTag" + echo image-tag="$imageTag" + } >>"$GITHUB_OUTPUT" + + # The checkout is solely required for the upload-sarif action. It needs to + # know the ref and sha. Providing those manually won't work, for unknown + # reasons. + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ format('refs/tags/{0}', steps.prep.outputs.git-tag) }} + persist-credentials: false + + - name: Run Trivy vulnerability scanner + uses: aquasecurity/trivy-action@0.12.0 + with: + image-ref: ${{ format('quay.io/{0}:{1}', github.repository, steps.prep.outputs.image-tag) }} + format: sarif + output: trivy-results.sarif + + - name: Upload Trivy scan results to GitHub Security tab + uses: github/codeql-action/upload-sarif@v2 + with: + sarif_file: trivy-results.sarif diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml deleted file mode 100644 index 5da6ed5..0000000 --- a/.github/workflows/trivy.yaml +++ /dev/null @@ -1,25 +0,0 @@ -name: Security scan -on: - pull_request: - schedule: - - cron: '0 2 * * 1-5' - -jobs: - build: - name: Trivy - runs-on: ubuntu-20.04 - steps: - - name: Checkout code - uses: actions/checkout@v2 - - name: Build an image from Dockerfile - run: | - docker build -t quay.io/k0sproject/cni-node:${{ github.sha }} . - - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@master - with: - image-ref: 'quay.io/k0sproject/cni-node:${{ github.sha }}' - format: 'table' - exit-code: '1' - ignore-unfixed: true - vuln-type: 'os,library' - severity: 'CRITICAL,HIGH'