From ccc512642eaec9b2f1baddc9662db8cda7ce5435 Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Thu, 27 Apr 2023 13:00:32 +0200 Subject: [PATCH 1/3] ci: improve CI Signed-off-by: Mark Sagi-Kazar --- .github/workflows/analysis-scorecard.yaml | 47 +++++++ .github/workflows/artifacts.yaml | 164 ++++++++++++++++++++++ .github/workflows/ci.yaml | 21 +++ .github/workflows/docker.yml | 55 -------- .github/workflows/release.yaml | 23 +++ 5 files changed, 255 insertions(+), 55 deletions(-) create mode 100644 .github/workflows/analysis-scorecard.yaml create mode 100644 .github/workflows/artifacts.yaml create mode 100644 .github/workflows/ci.yaml delete mode 100644 .github/workflows/docker.yml create mode 100644 .github/workflows/release.yaml diff --git a/.github/workflows/analysis-scorecard.yaml b/.github/workflows/analysis-scorecard.yaml new file mode 100644 index 0000000..bf27f4e --- /dev/null +++ b/.github/workflows/analysis-scorecard.yaml @@ -0,0 +1,47 @@ +name: OpenSSF Scorecard + +on: + branch_protection_rule: + push: + branches: [ main ] + schedule: + - cron: '30 0 * * 5' + +permissions: + contents: read + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + + permissions: + actions: read + contents: read + id-token: write + security-events: write + + steps: + - name: Checkout repository + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + with: + persist-credentials: false + + - name: Run analysis + uses: ossf/scorecard-action@80e868c13c90f172d68d1f4501dee99e2479f7af # v2.1.3 + with: + results_file: results.sarif + results_format: sarif + publish_results: true + + - name: Upload results as artifact + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + with: + name: OpenSSF Scorecard results + path: results.sarif + retention-days: 5 + + - name: Upload results to GitHub Security tab + uses: github/codeql-action/upload-sarif@8662eabe0e9f338a07350b7fd050732745f93848 # v2.3.1 + with: + sarif_file: results.sarif diff --git a/.github/workflows/artifacts.yaml b/.github/workflows/artifacts.yaml new file mode 100644 index 0000000..e75763c --- /dev/null +++ b/.github/workflows/artifacts.yaml @@ -0,0 +1,164 @@ +name: Artifacts + +on: + workflow_call: + inputs: + publish: + description: Publish artifacts to the artifact store + default: false + required: false + type: boolean + outputs: + container-image-name: + description: Container image name + value: ${{ jobs.container-image.outputs.name }} + container-image-digest: + description: Container image digest + value: ${{ jobs.container-image.outputs.digest }} + container-image-ref: + description: Container image ref + value: ${{ jobs.container-image.outputs.ref }} + +permissions: + contents: read + +jobs: + container-image: + name: Container image + runs-on: ubuntu-latest + + permissions: + contents: read + packages: write + id-token: write + security-events: write + + outputs: + name: ${{ steps.image-name.outputs.value }} + digest: ${{ steps.build.outputs.digest }} + ref: ${{ steps.image-ref.outputs.value }} + + steps: + - name: Checkout repository + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + + - name: Set up QEMU + uses: docker/setup-qemu-action@e81a89b1732b9c48d79cd809d8d81d79c4647a18 # v2.1.0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@4b4e9c3e2d4531116a6f8ba8e71fc6e2cb6e6c8c # v2.5.0 + + - name: Set up Cosign + uses: sigstore/cosign-installer@204a51a57a74d190b284a0ce69b44bc37201f343 # v3.0.3 + if: inputs.publish + + - name: Set up Syft + uses: anchore/sbom-action/download-syft@422cb34a0f8b599678c41b21163ea6088edb2624 # v0.14.1 + + - name: Set image name + id: image-name + run: echo "value=ghcr.io/${{ github.repository_owner }}/kafka" >> "$GITHUB_OUTPUT" + + - name: Gather build metadata + id: meta + uses: docker/metadata-action@c4ee3adeed93b1fa6a762f209fb01608c1a22f1e # v4.4.0 + with: + images: ${{ steps.image-name.outputs.value }} + flavor: | + latest = false + tags: | + type=ref,event=branch + type=ref,event=pr,prefix=pr- + type=semver,pattern={{raw}} + type=raw,value=latest,enable={{is_default_branch}} + + # Multiple exporters are not supported yet + # See https://github.com/moby/buildkit/pull/2760 + - name: Determine build output + uses: haya14busa/action-cond@1d6e8a12b20cdb4f1954feef9aa475b9c390cab5 # v1.1.1 + id: build-output + with: + cond: ${{ inputs.publish }} + if_true: type=image,push=true + if_false: type=oci,dest=image.tar + + - name: Login to GitHub Container Registry + uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # v2.1.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ github.token }} + if: inputs.publish + + - name: Build and push image + id: build + uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671 # v4.0.0 + with: + context: . + platforms: linux/amd64 + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + outputs: ${{ steps.build-output.outputs.value }} + # push: ${{ inputs.publish }} + + - name: Set image ref + id: image-ref + run: echo "value=${{ steps.image-name.outputs.value }}@${{ steps.build.outputs.digest }}" >> "$GITHUB_OUTPUT" + + - name: Fetch image + run: skopeo --insecure-policy copy docker://${{ steps.image-ref.outputs.value }} oci-archive:image.tar + if: inputs.publish + + - name: Extract OCI tarball + run: | + mkdir -p image + tar -xf image.tar -C image + + # See https://github.com/anchore/syft/issues/1545 + - name: Extract image from multi-arch image + run: skopeo --override-os linux --override-arch amd64 --insecure-policy copy oci:image docker-archive:docker.tar + + - name: Generate SBOM + run: syft -o spdx-json=sbom-spdx.json docker-archive:docker.tar + + - name: Upload SBOM as artifact + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + with: + name: "[${{ github.job }}] SBOM" + path: sbom-spdx.json + retention-days: 5 + + - name: Sign image + run: | + cosign sign --yes --recursive "${{ steps.image-ref.outputs.value }}" + echo "::notice title=Verify signature::cosign verify --certificate-identity 'https://github.com/${{ github.workflow_ref }}' --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' ${{ steps.image-ref.outputs.value }}" + echo "::notice title=Verify signature(pretty print)::cosign verify --certificate-identity 'https://github.com/${{ github.workflow_ref }}' --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' ${{ steps.image-ref.outputs.value }} | jq '.[0]'" + if: inputs.publish + + - name: Attach SBOM attestation + run: | + cosign attest --yes --predicate sbom-spdx.json --type spdx "${{ steps.image-ref.outputs.value }}" + echo "::notice title=Verify SBOM attestation::cosign verify-attestation --certificate-identity 'https://github.com/${{ github.workflow_ref }}' --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' --type spdx ${{ steps.image-ref.outputs.value }}" + echo "::notice title=Inspect SBOM::cosign verify-attestation --certificate-identity 'https://github.com/${{ github.workflow_ref }}' --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' --type spdx ${{ steps.image-ref.outputs.value }} | jq '.payload |= @base64d | .payload | fromjson | select(.predicateType == \"https://spdx.dev/Document\") | .predicate | fromjson'" + if: inputs.publish + + - name: Run Trivy vulnerability scanner + uses: aquasecurity/trivy-action@e5f43133f6e8736992c9f3c1b3296e24b37e17f2 # 0.10.0 + with: + input: image + format: sarif + output: trivy-results.sarif + + - name: Upload Trivy scan results as artifact + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + with: + name: "[${{ github.job }}] Trivy scan results" + path: trivy-results.sarif + retention-days: 5 + + - name: Upload Trivy scan results to GitHub Security tab + uses: github/codeql-action/upload-sarif@8662eabe0e9f338a07350b7fd050732745f93848 # v2.3.1 + with: + sarif_file: trivy-results.sarif diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..4368452 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,21 @@ +name: CI + +on: + push: + branches: [ main ] + pull_request: + +permissions: + contents: read + +jobs: + artifacts: + name: Artifacts + uses: ./.github/workflows/artifacts.yaml + with: + publish: ${{ github.event_name == 'push' }} + permissions: + contents: read + packages: write + id-token: write + security-events: write diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml deleted file mode 100644 index 266c296..0000000 --- a/.github/workflows/docker.yml +++ /dev/null @@ -1,55 +0,0 @@ -name: Docker -on: - push: - branches: - - master - tags: - - "[0-9]+.[0-9]+-[0-9]+.[0-9]+.[0-9]+-bzc.?[0-9]+" - - "[0-9]+.[0-9]+-[0-9]+.[0-9]+.[0-9]+" -# pull_request: -env: - PLATFORMS: linux/amd64 -jobs: - docker: - name: Docker - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - name: Cache Docker layers - uses: actions/cache@v2 - with: - path: /tmp/.buildx-cache - key: ${{ runner.os }}-buildx-${{ github.ref }} - restore-keys: | - ${{ runner.os }}-buildx- - - name: Determine tag or commit - uses: haya14busa/action-cond@v1 - id: refortag - with: - cond: ${{ startsWith(github.ref, 'refs/tags/') }} - if_true: ${{ github.ref }} - if_false: latest - - name: Determine image tag - id: imagetag - run: echo "value=${TAG_OR_BRANCH##*/}" >> $GITHUB_OUTPUT - env: - TAG_OR_BRANCH: ${{ steps.refortag.outputs.value }} - - - name: Login to GitHub Container Registry - uses: docker/login-action@v1 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.CR_PAT }} - - name: Build Apache Kafka - uses: docker/build-push-action@v2 - with: - tags: ghcr.io/banzaicloud/kafka:${{ steps.imagetag.outputs.value }} - file: Dockerfile - platforms: ${{ env.PLATFORMS }} - push: true - cache-from: type=local,src=/tmp/.buildx-cache - cache-to: type=local,dest=/tmp/.buildx-cache diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..723163b --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,23 @@ +name: Release + +on: + push: + tags: + - "[0-9]+.[0-9]+-[0-9]+.[0-9]+.[0-9]+-bzc.?[0-9]+" + - "[0-9]+.[0-9]+-[0-9]+.[0-9]+.[0-9]+-cisco.?[0-9]+" + - "[0-9]+.[0-9]+-[0-9]+.[0-9]+.[0-9]+" + +permissions: + contents: read + +jobs: + artifacts: + name: Artifacts + uses: ./.github/workflows/artifacts.yaml + with: + publish: true + permissions: + contents: read + packages: write + id-token: write + security-events: write From 525c492b65b1607401d7ac749dbe79abc3e28d65 Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Thu, 27 Apr 2023 13:00:43 +0200 Subject: [PATCH 2/3] ci: add dependabot Signed-off-by: Mark Sagi-Kazar --- .github/.editorconfig | 2 ++ .github/dependabot.yaml | 12 ++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 .github/.editorconfig create mode 100644 .github/dependabot.yaml diff --git a/.github/.editorconfig b/.github/.editorconfig new file mode 100644 index 0000000..0902c6a --- /dev/null +++ b/.github/.editorconfig @@ -0,0 +1,2 @@ +[{*.yml,*.yaml}] +indent_size = 2 diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml new file mode 100644 index 0000000..177d137 --- /dev/null +++ b/.github/dependabot.yaml @@ -0,0 +1,12 @@ +version: 2 + +updates: + - package-ecosystem: "docker" + directory: "/" + schedule: + interval: "daily" + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" From dc2f93584dd888ce5b4d20bd071d7dcec47ce257 Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Thu, 27 Apr 2023 13:00:51 +0200 Subject: [PATCH 3/3] chore: update readme Signed-off-by: Mark Sagi-Kazar --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 692e7be..6c45d64 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ # Apache Kafka Docker Image +[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/banzaicloud/docker-kafka/ci.yaml?style=flat-square)](https://github.com/banzaicloud/docker-kafka/actions/workflows/ci.yaml) +[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/banzaicloud/docker-kafka/badge?style=flat-square)](https://api.securityscorecards.dev/projects/github.com/banzaicloud/docker-kafka) + Docker file for building docker image for [Apache Kafka](https://kafka.apache.org) from official [Apache Kafka Distros](https://www.apache.org/dyn/closer.cgi?path=/kafka/) running on Java 17.