diff --git a/.github/actions/publish-image/action.yaml b/.github/actions/publish-image/action.yaml new file mode 100644 index 0000000..b1bad26 --- /dev/null +++ b/.github/actions/publish-image/action.yaml @@ -0,0 +1,89 @@ +name: Publish image + +description: Publishes a docker image, SBOM, scans vulns, and signs the image. + +inputs: + makefile-target: + required: true + description: makefile target to invoke for publishing image with ko + registry: + required: true + description: registry to publish image to + registry-username: + required: true + description: registry credentials username + registry-password: + required: true + description: registry credentials password + repository: + required: true + description: repository to publish image to + version: + required: true + description: published image version + sign-image: + required: true + description: sign image + sbom-name: + required: true + description: name of the cyclonedx sbom + sbom-repository: + required: true + description: sbom repository + signature-repository: + required: true + description: signature repository + main-path: + required: true + description: path to main go entry point + +outputs: + digest: + value: ${{ steps.digest.outputs.digest }} + description: published image digest + +runs: + using: composite + steps: + - shell: bash + id: ko-publish + env: + REGISTRY: ${{ inputs.registry }} + REPO: ${{ inputs.repository }} + REGISTRY_USERNAME: ${{ inputs.registry-username }} + REGISTRY_PASSWORD: ${{ inputs.registry-password }} + COSIGN_REPOSITORY: ${{ inputs.sbom-repository }} + run: | + set -e + echo "digest=$(VERSION=${{ inputs.version }} make ${{ inputs.makefile-target }})" >> $GITHUB_OUTPUT + - uses: CycloneDX/gh-gomod-generate-sbom@d4aee0cf5133055dbd98899978246c10c18c440f # v1.1.0 + with: + version: v1 + args: app -licenses -json -output ${{ inputs.sbom-name }}-bom.cdx.json -main ${{ inputs.main-path }} + - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + with: + name: ${{ inputs.sbom-name }}-bom-cdx + path: ${{ inputs.sbom-name }}-bom.cdx.json + - shell: bash + if: ${{ inputs.sign-image == 'true' }} + env: + COSIGN_REPOSITORY: ${{ inputs.signature-repository }} + run: | + set -e + cosign sign --yes \ + -a "repo=${{ github.repository }}" \ + -a "workflow=${{ github.workflow }}" \ + -a "ref=${{ github.sha }}" \ + ${{ steps.ko-publish.outputs.digest }} + - shell: bash + env: + COSIGN_REPOSITORY: ${{ inputs.sbom-repository }} + run: | + cosign attach sbom --sbom ./${{ inputs.sbom-name }}-bom.cdx.json --type cyclonedx ${{ steps.ko-publish.outputs.digest }} + - shell: bash + id: digest + run: | + echo "The image generated is: ${{ steps.ko-publish.outputs.digest }}" + DIGEST=$(echo ${{ steps.ko-publish.outputs.digest }} | cut -d '@' -f2) + echo "Digest from image is: $DIGEST" + echo "digest=$DIGEST" >> $GITHUB_OUTPUT diff --git a/.github/actions/setup-build-env/action.yaml b/.github/actions/setup-build-env/action.yaml new file mode 100644 index 0000000..6fe3805 --- /dev/null +++ b/.github/actions/setup-build-env/action.yaml @@ -0,0 +1,37 @@ +name: Setup build env + +description: Clone repo, unshallow, setup go, cache and install tools. + +inputs: + unshallow: + description: git unshallow + default: 'true' + free-disk-space: + description: free disk space + default: 'true' + +runs: + using: composite + steps: + - uses: jlumbroso/free-disk-space@76866dbe54312617f00798d1762df7f43def6e5c # v1.2.0 + if: ${{ inputs.free-disk-space == 'true' }} + with: + tool-cache: true + android: true + dotnet: true + haskell: true + large-packages: false + swap-storage: false + - shell: bash + if: ${{ inputs.unshallow == 'true' }} + run: | + git fetch --prune --unshallow + - uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0 + with: + go-version: ~1.21.3 + - shell: bash + run: | + go mod download + - shell: bash + run: | + GOCACHE=~/.cache/kyverno/tools make install-tools diff --git a/.github/actions/setup-caches/action.yaml b/.github/actions/setup-caches/action.yaml new file mode 100644 index 0000000..99be715 --- /dev/null +++ b/.github/actions/setup-caches/action.yaml @@ -0,0 +1,24 @@ +name: Setup caches + +description: Setup caches for go modules, tools and build cache. + +inputs: + build-cache-key: + description: build cache prefix + +runs: + using: composite + steps: + - uses: actions/cache@4723a57e26efda3a62cbde1812113b730952852d # v3.2.2 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-pkg-mod-${{ hashFiles('**/go.sum') }}-${{ hashFiles('Makefile') }} + - uses: actions/cache@4723a57e26efda3a62cbde1812113b730952852d # v3.2.2 + with: + path: ~/.cache/kyverno/tools + key: ${{ runner.os }}-cache-kyverno-tools-${{ hashFiles('**/go.sum') }}-${{ hashFiles('Makefile') }} + - uses: actions/cache@4723a57e26efda3a62cbde1812113b730952852d # v3.2.2 + if: ${{ inputs.build-cache-key }} + with: + path: ~/.cache/go-build + key: ${{ runner.os }}-build-cache-${{ inputs.build-cache-key }}-${{ hashFiles('**/go.sum') }}-${{ hashFiles('Makefile') }} diff --git a/.github/workflows/publish-images.yaml b/.github/workflows/publish-images.yaml new file mode 100644 index 0000000..6da5a4a --- /dev/null +++ b/.github/workflows/publish-images.yaml @@ -0,0 +1,75 @@ +# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json + +name: Publish images + +permissions: {} + +on: + push: + branches: + - 'main' + - 'release*' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + publish-images: + runs-on: ubuntu-latest + permissions: + packages: write + id-token: write + outputs: + reports-server-digest: ${{ steps.publish-reports-server.outputs.digest }} + steps: + - name: Checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: Setup caches + uses: ./.github/actions/setup-caches + timeout-minutes: 5 + continue-on-error: true + with: + build-cache-key: publish-images + - name: Setup build env + uses: ./.github/actions/setup-build-env + timeout-minutes: 30 + - name: Run Trivy vulnerability scanner in repo mode + uses: aquasecurity/trivy-action@d43c1f16c00cfd3978dde6c07f4bbcf9eb6993ca # v0.16.1 + with: + scan-type: 'fs' + ignore-unfixed: true + format: 'sarif' + output: 'trivy-results.sarif' + severity: 'CRITICAL,HIGH' + - name: Install Cosign + uses: sigstore/cosign-installer@e1523de7571e31dbe865fd2e80c5c7c23ae71eb4 # v3.4.0 + - name: Publish reports server + id: publish-reports-server + uses: ./.github/actions/publish-image + with: + makefile-target: ko-publish-reports-server + registry: ghcr.io + registry-username: ${{ github.actor }} + registry-password: ${{ secrets.GITHUB_TOKEN }} + repository: reports-server + version: ${{ github.ref_name }} + sign-image: true + sbom-name: reports-server + sbom-repository: ghcr.io/${{ github.repository_owner }}/reports-server/sbom + signature-repository: ghcr.io/${{ github.repository_owner }}/reports-server/signatures + main-path: . + generate-reports-server-provenance: + needs: publish-images + permissions: + id-token: write # To sign the provenance. + packages: write # To upload assets to release. + actions: read # To read the workflow path. + # NOTE: The container generator workflow is not officially released as GA. + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v1.9.0 + with: + image: ghcr.io/${{ github.repository_owner }}/reports-server + digest: "${{ needs.publish-images.outputs.reports-server-digest }}" + registry-username: ${{ github.actor }} + secrets: + registry-password: ${{ secrets.GITHUB_TOKEN }} diff --git a/Makefile b/Makefile index c26fe22..1589dbc 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,7 @@ GOOS ?= $(shell go env GOOS) GOARCH ?= $(shell go env GOARCH) REGISTRY ?= ghcr.io REPO ?= reports-server +REPO_REPORTS_SERVER ?= $(REGISTRY)/$(ORG)/$(REPO) ######### # TOOLS # @@ -66,12 +67,22 @@ clean-tools: ## Remove installed tools ######### CGO_ENABLED ?= 0 -LD_FLAGS := "-s -w" LOCAL_PLATFORM := linux/$(GOARCH) KO_REGISTRY := ko.local -KO_TAGS := $(GIT_SHA) KO_CACHE ?= /tmp/ko-cache BIN := reports-server +ifdef VERSION +LD_FLAGS := "-s -w -X $(PACKAGE)/pkg/version.BuildVersion=$(VERSION)" +else +LD_FLAGS := "-s -w" +endif +ifndef VERSION +KO_TAGS := $(GIT_SHA) +else ifeq ($(VERSION),main) +KO_TAGS := $(GIT_SHA),latest +else +KO_TAGS := $(GIT_SHA),$(subst /,-,$(VERSION)) +endif .PHONY: fmt fmt: ## Run go fmt @@ -212,3 +223,19 @@ kind-install: $(HELM) kind-load ## Build image, load it in kind cluster and depl .PHONY: help help: ## Shows the available commands @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-40s\033[0m %s\n", $$1, $$2}' + +################ +# PUBLISH (KO) # +################ + +REGISTRY_USERNAME ?= dummy +PLATFORMS := all + +.PHONY: ko-login +ko-login: $(KO) + @$(KO) login $(REGISTRY) --username $(REGISTRY_USERNAME) --password $(REGISTRY_PASSWORD) + +.PHONY: ko-publish-reports-server +ko-publish-reports-server: ko-login ## Build and publish reports-server image (with ko) + @LD_FLAGS=$(LD_FLAGS) KOCACHE=$(KOCACHE) KO_DOCKER_REPO=$(REPO_REPORTS_SERVER) \ + $(KO) build . --bare --tags=$(KO_TAGS) --platform=$(PLATFORMS) diff --git a/charts/reports-server/templates/cluster-roles.yaml b/charts/reports-server/templates/cluster-roles.yaml index 7966f1e..bb51d48 100644 --- a/charts/reports-server/templates/cluster-roles.yaml +++ b/charts/reports-server/templates/cluster-roles.yaml @@ -1,6 +1,5 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole -metadata: metadata: name: {{ include "reports-server.fullname" . }} labels: diff --git a/config/install.yaml b/config/install.yaml index 2c25188..dabb240 100644 --- a/config/install.yaml +++ b/config/install.yaml @@ -47,7 +47,6 @@ data: --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole -metadata: metadata: name: reports-server labels: diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 9dd941b..0349f99 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -7,7 +7,7 @@ If kyverno is already installed in the cluster, follow the [migration guide](#mi Reports-server comes with a postgreSQL database. It is recommended to bring-your-own postgres database to have finer control of database configurations ([see database configuration guide](#database-configuration)). ### YAML Manifest -It is recommended to install Reports-server using `kubectl apply`, especially when policy reports CRDs are already installed in the cluster ([see migration guide](#migration)). To install reports server using YAML manifest, run the following command: +It is recommended to install Reports-server using `kubectl apply`, especially when policy reports CRDs are already installed in the cluster ([see migration guide](#migration)). To install reports server using YAML manifest, create a `reports-server` namespace and run the following command: ```bash kubectl apply -f https://raw.githubusercontent.com/kyverno/reports-server/main/config/install.yaml