diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 583748b8..b98304bb 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -113,6 +113,29 @@ jobs: - name: Run govulncheck run: go tool govulncheck ./... + scan-fs: + name: Trivy filesystem scan + needs: changes + if: github.event_name == 'merge_group' || ((needs.changes.outputs.go == 'true' || needs.changes.outputs.workflows == 'true') && (github.event_name != 'push' || github.actor != 'github-merge-queue[bot]')) + runs-on: depot-ubuntu-24.04-8 + timeout-minutes: 20 + permissions: + contents: read + steps: + - name: Checkout + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false + + - name: Trivy filesystem scan + uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # v0.33.1 + with: + scan-type: fs + scan-ref: . + skip-dirs: vendor + severity: HIGH,CRITICAL + exit-code: '1' + test: needs: changes if: github.event_name == 'merge_group' || (needs.changes.outputs.go == 'true' && (github.event_name != 'push' || github.actor != 'github-merge-queue[bot]')) @@ -290,6 +313,45 @@ jobs: echo "=== CNPG controller logs ===" kubectl -n cnpg-system logs deploy/cnpg-controller-manager --tail=200 || true + image-scan: + name: Trivy image scan + needs: changes + if: github.event_name == 'merge_group' || (needs.changes.outputs.publish == 'true' && (github.event_name != 'push' || github.actor != 'github-merge-queue[bot]')) + runs-on: depot-ubuntu-24.04-8 + timeout-minutes: 20 + steps: + - name: Checkout + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false + + - name: Setup Go + uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0 + with: + go-version-file: go.mod + cache: true + + - name: Build linux/amd64 binary for image + env: + GOFLAGS: -mod=vendor + CGO_ENABLED: "0" + GOOS: linux + GOARCH: amd64 + run: | + mkdir -p linux/amd64 + go build -o linux/amd64/coder-k8s ./ + + - name: Build local image + run: docker build -f Dockerfile.goreleaser -t coder-k8s:scan . + + - name: Trivy image scan + uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # v0.33.1 + with: + scan-type: image + image-ref: coder-k8s:scan + severity: HIGH,CRITICAL + exit-code: '1' + terraform: name: Terraform (fmt/validate/tflint/trivy) needs: changes @@ -393,7 +455,7 @@ jobs: publish-main: name: Publish GHCR :main - needs: [changes, test, lint, lint-actions, e2e-kind, terraform] + needs: [changes, test, lint, scan-fs, lint-actions, e2e-kind, image-scan, terraform] if: | always() && github.event_name == 'push' && @@ -401,8 +463,10 @@ jobs: needs.changes.outputs.publish == 'true' && (needs.test.result == 'success' || needs.test.result == 'skipped') && (needs.lint.result == 'success' || needs.lint.result == 'skipped') && + (needs.scan-fs.result == 'success' || needs.scan-fs.result == 'skipped') && (needs.lint-actions.result == 'success' || needs.lint-actions.result == 'skipped') && (needs.e2e-kind.result == 'success' || needs.e2e-kind.result == 'skipped') && + (needs.image-scan.result == 'success' || needs.image-scan.result == 'skipped') && (needs.terraform.result == 'success' || needs.terraform.result == 'skipped') runs-on: depot-ubuntu-24.04-8 timeout-minutes: 30 @@ -464,3 +528,11 @@ jobs: org.opencontainers.image.vendor=Coder org.opencontainers.image.licenses=Apache-2.0 org.opencontainers.image.authors=Coder + + - name: Trivy image scan (:main) + uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # v0.33.1 + with: + scan-type: image + image-ref: ghcr.io/coder/coder-k8s:main + severity: HIGH,CRITICAL + exit-code: '1' diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml new file mode 100644 index 00000000..5b1de6ef --- /dev/null +++ b/.github/workflows/codeql.yaml @@ -0,0 +1,44 @@ +name: CodeQL + +on: + pull_request: + push: + branches: + - main + schedule: + - cron: '0 6 * * 1' + +permissions: + contents: read + security-events: write + actions: read + +jobs: + analyze: + name: Analyze (Go) + runs-on: depot-ubuntu-24.04-8 + timeout-minutes: 30 + steps: + - name: Checkout + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false + + - name: Setup Go + uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0 + with: + go-version-file: go.mod + cache: true + + - name: Initialize CodeQL + uses: github/codeql-action/init@f5c2471be782132e47a6e6f9c725e56730d6e9a3 # v3.32.3 + with: + languages: go + + - name: Build + env: + GOFLAGS: -mod=vendor + run: go build ./... + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@f5c2471be782132e47a6e6f9c725e56730d6e9a3 # v3.32.3 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 0a344c49..bd0cb98d 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -43,3 +43,20 @@ jobs: args: release --clean env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Compute release image tag + id: release_image_tag + env: + RELEASE_TAG: ${{ github.event.release.tag_name }} + run: | + IMAGE_TAG="${RELEASE_TAG#v}" + test -n "$IMAGE_TAG" + echo "value=$IMAGE_TAG" >> "$GITHUB_OUTPUT" + + - name: Trivy image scan (release) + uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # v0.33.1 + with: + scan-type: image + image-ref: ghcr.io/coder/coder-k8s:${{ steps.release_image_tag.outputs.value }} + severity: HIGH,CRITICAL + exit-code: '1' diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 1c297aa3..77153c52 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -38,7 +38,7 @@ dockers_v2: - latest platforms: - linux/amd64 - sbom: false + sbom: true labels: org.opencontainers.image.created: "{{ .Date }}" org.opencontainers.image.source: https://github.com/coder/coder-k8s