diff --git a/.github/workflows/build-test-distribute.yaml b/.github/workflows/build-test-distribute.yaml index 73be6d99a5fa..bb92cdc92821 100644 --- a/.github/workflows/build-test-distribute.yaml +++ b/.github/workflows/build-test-distribute.yaml @@ -34,6 +34,7 @@ jobs: REGISTRY: ${{ steps.metadata.outputs.registry }} VERSION_NAME: ${{ steps.metadata.outputs.version }} NOTARY_REPOSITORY: ${{ (contains(steps.metadata.outputs.version, 'preview') && 'notary-internal') || 'notary' }} + CLOUDSMITH_REPOSITORY: ${{ steps.metadata.outputs.distribution_repository }} steps: - name: "Fail when 'ci/force-publish' label is present on PRs from forks" if: ${{ fromJSON(env.FORCE_PUBLISH_FROM_FORK) }} @@ -75,6 +76,7 @@ jobs: echo "images=$(make images/info/release/json)" >> $GITHUB_OUTPUT echo "registry=$(make docker/info/registry)" >> $GITHUB_OUTPUT echo "version=$(make build/info/version)" >> $GITHUB_OUTPUT + echo "distribution_repository=$(make build/info/distribution/repo)" >> $GITHUB_OUTPUT test: permissions: contents: read @@ -129,3 +131,94 @@ jobs: # so we manually check it here. An example could be found here: https://github.com/kumahq/kuma/actions/runs/7044980149 [[ ${{ contains(needs.*.result, 'failure')|| contains(needs.*.result, 'cancelled') }} == "true" ]] && exit 1 echo "All dependent jobs succeeded" + # Aggregated package for SBOMs helps avoid depending on variable asset names + # Easy to match and filter on file extensions produced in various distributed jobs + # (FIX): (Anchore SBOM action Bug)[https://github.com/anchore/sbom-action/issues/434] + - name: "Download all SBOM assets" + id: collect_sbom + if: ${{ fromJSON(needs.check.outputs.BUILD) && (needs.check.result == 'success' || needs.build_publish.result == 'success') }} + run: |- + echo "SBOM_DOWNLOAD_PATH=${{env.SBOM_DOWNLOAD_PATH}}" >> $GITHUB_OUTPUT + gh run download ${{ github.run_id }} -D ${{ env.SBOM_DOWNLOAD_PATH }} -p ${{ env.SBOM_ARTIFACT_GLOB_PATTERN }} + env: + SBOM_DOWNLOAD_PATH: ${{ github.workspace }}/security-assets/sboms + SBOM_ARTIFACT_GLOB_PATTERN: "*sbom.{cyclonedx,spdx}.json" + # uses: actions/download-artifact@v4 + # id: collect_sbom + # with: + # path: ${{ github.workspace }}/security-assets/sboms + # pattern: "*sbom.{cyclonedx,spdx}.json" + # merge-multiple: true # When set, all matched zipped artifacts are extracted into the specified path + - name: "Download binary artifact provenance" + if: ${{ needs.provenance.result == 'success' && github.ref_type == 'tag' }} + id: collect_provenance + run: |- + echo "PROVENANCE_DOWNLOAD_PATH=${{env.PROVENANCE_DOWNLOAD_PATH}}" >> $GITHUB_OUTPUT + gh run download ${{ github.run_id }} -D ${{ env.PROVENANCE_DOWNLOAD_PATH }} -n ${{ env.BINARY_PROVENANCE_ARTIFACT }} + env: + PROVENANCE_DOWNLOAD_PATH: ${{ github.workspace }}/security-assets/provenance + BINARY_PROVENANCE_ARTIFACT: "${{ github.event.repository.name }}.intoto.jsonl" + + # uses: actions/download-artifact@v4 + # with: + # path: ${{ github.workspace }}/security-assets/provenance + # pattern: ${{ github.event.repository.name }}.intoto.jsonl + # merge-multiple: true # When set, all matched zipped artifacts are extracted into the specified path + - name: "check sbom asset files existence" + uses: andstor/file-existence-action@v3 + id: check_sbom_assets + if: ${{ fromJSON(needs.check.outputs.BUILD) && (needs.check.result == 'success' || needs.build_publish.result == 'success') }} + with: + files: ${{ steps.collect_sbom.outputs.SBOM_DOWNLOAD_PATH }} + fail: true + - name: "check provenance asset files existence" + uses: andstor/file-existence-action@v3 + if: ${{ needs.provenance.result == 'success' && github.ref_type == 'tag' }} + id: check_provenance_assets + with: + files: ${{ steps.collect_sbom.outputs.PROVENANCE_DOWNLOAD_PATH }} + fail: true + - name: "prepare sbom package" # Zip all SBOM assets for artifact types (Images, Repository scanning) produced in the jobs + id: prepare_sbom_metadata + if: ${{ steps.check_sbom_assets.outputs.file_exists == 'true' }} + run: |- + SBOM_PACKAGE_NAME="${{github.repository}}-sbom" + echo "SBOM_PACKAGE_NAME=${SBOM_PACKAGE_NAME}" >> $GITHUB_OUTPUT + zip -rj ${SBOM_PACKAGE_NAME} ${{steps.collect_sbom.outputs.download-path}} -i '*sbom.spdx.json' '*sbom.cyclonedx.json' + - name: "Inspect slsa assets" + if: ${{ steps.check_provenance_assets.outputs.file_exists == 'true' || steps.check_sbom_assets.outputs.file_exists == 'true' }} + run: |- + ls -alR ${{github.workspace}}/security-assets + # Publish aggregated zip file of SBOMs to artifact regstry + - name: Push sbom to cloudsmith + id: push_sbom + if: ${{ steps.check_sbom_assets.outputs.file_exists == 'true' }} + uses: cloudsmith-io/action@master + with: + api-key: ${{ secrets.CLOUDSMITH_API_KEY }} + command: "push" + format: "raw" + owner: "kong" + repo: "${{ needs.check.outputs.CLOUDSMITH_REPOSITORY }}" + version: "${{ needs.check.outputs.VERSION_NAME }}" + file: "${{ steps.collect_sbom.outputs.download-path }}/${{ steps.prepare_sbom_metadata.outputs.SBOM_PACKAGE_NAME }}" + name: "${{ steps.prepare_sbom_metadata.outputs.SBOM_PACKAGE_NAME }}" + summary: "SBOM artifacts for ${{ github.repository }}" + description: "SBOM artifacts for binaries built from source code and container images" + - name: Push binary provenance to cloudsmith + if: ${{ steps.check_provenance_assets.outputs.file_exists == 'true' }} + id: push_binary_provenance + uses: cloudsmith-io/action@master + with: + api-key: ${{ secrets.CLOUDSMITH_API_KEY }} + command: "push" + format: "raw" + owner: "kong" + repo: "${{ needs.check.outputs.CLOUDSMITH_REPOSITORY }}" + version: "${{ needs.check.outputs.VERSION_NAME }}" + file: "${{ steps.collect_provenance.outputs.download-path }}/${{ github.event.repository.name }}.intoto.jsonl" + name: "${{ env.BINARY_PROVENANCE_PACKAGE_NAME }}" + summary: "Binary Artifact Provenance for ${{ github.repository }}" + description: "Provenance file for verifying ${{ github.repository }} binary artifacts" + env: + BINARY_PROVENANCE_PACKAGE_NAME: "${{github.repository}}-binary-provenance" diff --git a/mk/distribution.mk b/mk/distribution.mk index c5ef70cc0b6d..460778098e0e 100644 --- a/mk/distribution.mk +++ b/mk/distribution.mk @@ -107,6 +107,10 @@ endif build/distributions/out: $(patsubst %,build/distributions/out/$(DISTRIBUTION_TARGET_NAME)-%.tar.gz,$(ENABLED_DIST_NAMES)) cd $@; sha256sum *.tar.gz > $(DISTRIBUTION_TARGET_NAME).sha256 +.PHONY: build/info/distribution/repo +build/info/distribution/repo: + @echo $(PULP_PACKAGE_TYPE)-binaries-$(PULP_DIST_VERSION) + # Create a main target which will publish to pulp each to the tar.gz built .PHONY: publish/pulp ## Publish to pulp all enabled distributions publish/pulp: $(addprefix publish/pulp/$(DISTRIBUTION_TARGET_NAME)-,$(ENABLED_DIST_NAMES)) diff --git a/mk/docker.mk b/mk/docker.mk index 1a07bf3b290d..9c2089db91d6 100644 --- a/mk/docker.mk +++ b/mk/docker.mk @@ -19,7 +19,10 @@ KUMA_IMAGES = $(call build_image,$(IMAGES_RELEASE) $(IMAGES_TEST)) export DOCKER_BUILDKIT := 1 # add targets to build images for each arch -# $(1) - GOOS to build for +# $(1) - GOARCH to build for +# (TODO): Donot hardcode "linux" platform for images +# (TODO): May be support other image platforms using argument + define IMAGE_TARGETS_BY_ARCH .PHONY: image/static/$(1) image/static/$(1): ## Dev: Rebuild `kuma-static` Docker image @@ -65,8 +68,9 @@ $(foreach goarch,$(SUPPORTED_GOARCHES),$(eval $(call IMAGE_TARGETS_BY_ARCH,$(goa # add targets to generate docker/{save,load,tag,push} for each supported ARCH # add targets to build images for each arch -# $(1) - GOOS to build for +# $(1) - Imae Name to build for # $(2) - GOARCH to build for +# (TODO): Support image platform in output file names define DOCKER_TARGETS_BY_ARCH .PHONY: docker/save/$(1)/$(2) docker/save/$(1)/$(2):