From 29e718a503b534c1f84ccdf440c2a6c5426a6975 Mon Sep 17 00:00:00 2001 From: Sushanta Das Date: Tue, 7 Jan 2025 13:27:59 +0530 Subject: [PATCH] Validate kustomize build in CI commit auto-generated manifests for existsing tasks --- .github/workflows/check-kustomize-build.yaml | 13 + README.md | 8 + .../tekton.dev_v1_pipeline_docker-build.yaml | 518 +++++++++++++ ...ne_docker-build-multi-platform-oci-ta.yaml | 455 +++++++++++ ...n.dev_v1_pipeline_docker-build-oci-ta.yaml | 442 +++++++++++ ...on.dev_v1_pipeline_docker-build-rhtap.yaml | 285 +++++++ .../tekton.dev_v1_pipeline_docker-build.yaml | 444 +++++++++++ .../tekton.dev_v1_pipeline_fbc-builder.yaml | 261 +++++++ ...n.dev_v1_pipeline_gitops-pull-request.yaml | 162 ++++ ...ev_v1_pipeline_maven-zip-build-oci-ta.yaml | 245 ++++++ ...ekton.dev_v1_pipeline_maven-zip-build.yaml | 250 ++++++ ...on.dev_v1_pipeline_docker-build-rhtap.yaml | 285 +++++++ ...n.dev_v1_pipeline_gitops-pull-request.yaml | 162 ++++ ...dev_v1_pipeline_tekton-bundle-builder.yaml | 269 +++++++ ...ne_docker-build-multi-platform-oci-ta.yaml | 455 +++++++++++ ...n.dev_v1_pipeline_docker-build-oci-ta.yaml | 442 +++++++++++ .../tekton.dev_v1_pipeline_docker-build.yaml | 444 +++++++++++ ...n.dev_v1_pipeline_enterprise-contract.yaml | 119 +++ .../tekton.dev_v1_pipeline_fbc-builder.yaml | 261 +++++++ ...ev_v1_pipeline_maven-zip-build-oci-ta.yaml | 245 ++++++ ...ekton.dev_v1_pipeline_maven-zip-build.yaml | 250 ++++++ ...dev_v1_pipeline_tekton-bundle-builder.yaml | 269 +++++++ ...tekton.dev_v1_pipeline_template-build.yaml | 410 ++++++++++ .../tekton.dev_v1_task_build-image-index.yaml | 222 ++++++ ...kton.dev_v1_task_build-image-manifest.yaml | 222 ++++++ ...on.dev_v1_task_build-maven-zip-oci-ta.yaml | 207 +++++ .../tekton.dev_v1_task_build-maven-zip.yaml | 197 +++++ .../0.1/tekton.dev_v1_task_buildah-10gb.yaml | 585 ++++++++++++++ .../0.2/tekton.dev_v1_task_buildah-10gb.yaml | 722 ++++++++++++++++++ .../0.1/tekton.dev_v1_task_buildah-20gb.yaml | 585 ++++++++++++++ .../0.2/tekton.dev_v1_task_buildah-20gb.yaml | 722 ++++++++++++++++++ .../0.1/tekton.dev_v1_task_buildah-24gb.yaml | 586 ++++++++++++++ .../0.2/tekton.dev_v1_task_buildah-24gb.yaml | 722 ++++++++++++++++++ .../0.1/tekton.dev_v1_task_buildah-6gb.yaml | 585 ++++++++++++++ .../0.2/tekton.dev_v1_task_buildah-6gb.yaml | 722 ++++++++++++++++++ .../0.1/tekton.dev_v1_task_buildah-8gb.yaml | 585 ++++++++++++++ .../0.2/tekton.dev_v1_task_buildah-8gb.yaml | 722 ++++++++++++++++++ .../0.1/tekton.dev_v1_task_buildah-min.yaml | 582 ++++++++++++++ .../0.2/tekton.dev_v1_task_buildah-min.yaml | 718 +++++++++++++++++ .../tekton.dev_v1_task_buildah-oci-ta.yaml | 583 ++++++++++++++ .../0.1/tekton.dev_v1_task_buildah.yaml | 582 ++++++++++++++ .../0.2/tekton.dev_v1_task_buildah.yaml | 718 +++++++++++++++++ .../0.3/tekton.dev_v1_task_buildah.yaml | 681 +++++++++++++++++ ...n.dev_v1_task_fbc-related-image-check.yaml | 72 ++ ...n.dev_v1_task_fbc-related-image-check.yaml | 72 ++ .../tekton.dev_v1_task_fbc-validation.yaml | 278 +++++++ .../tekton.dev_v1_task_fbc-validation.yaml | 278 +++++++ ...ev_v1beta1_task_generate-odcs-compose.yaml | 51 ++ ...ev_v1beta1_task_generate-odcs-compose.yaml | 51 ++ ...tekton.dev_v1beta1_task_inspect-image.yaml | 168 ++++ ...tekton.dev_v1beta1_task_inspect-image.yaml | 168 ++++ ...rovision-env-with-ephemeral-namespace.yaml | 55 ++ ...ev_v1_task_verify-enterprise-contract.yaml | 181 +++++ ...tekton.dev_v1_task_verify-signed-rpms.yaml | 70 ++ hack/build-manifests.sh | 46 ++ hack/get-kustomize.sh | 20 + hack/verify-manifests.sh | 22 + 57 files changed, 19474 insertions(+) create mode 100644 .github/workflows/check-kustomize-build.yaml create mode 100644 auto-generated/pipelines/core-services/tekton.dev_v1_pipeline_docker-build.yaml create mode 100644 auto-generated/pipelines/docker-build-multi-platform-oci-ta/tekton.dev_v1_pipeline_docker-build-multi-platform-oci-ta.yaml create mode 100644 auto-generated/pipelines/docker-build-oci-ta/tekton.dev_v1_pipeline_docker-build-oci-ta.yaml create mode 100644 auto-generated/pipelines/docker-build-rhtap/tekton.dev_v1_pipeline_docker-build-rhtap.yaml create mode 100644 auto-generated/pipelines/docker-build/tekton.dev_v1_pipeline_docker-build.yaml create mode 100644 auto-generated/pipelines/fbc-builder/tekton.dev_v1_pipeline_fbc-builder.yaml create mode 100644 auto-generated/pipelines/gitops-pull-request-rhtap/tekton.dev_v1_pipeline_gitops-pull-request.yaml create mode 100644 auto-generated/pipelines/maven-zip-build-oci-ta/tekton.dev_v1_pipeline_maven-zip-build-oci-ta.yaml create mode 100644 auto-generated/pipelines/maven-zip-build/tekton.dev_v1_pipeline_maven-zip-build.yaml create mode 100644 auto-generated/pipelines/rhtap/tekton.dev_v1_pipeline_docker-build-rhtap.yaml create mode 100644 auto-generated/pipelines/rhtap/tekton.dev_v1_pipeline_gitops-pull-request.yaml create mode 100644 auto-generated/pipelines/tekton-bundle-builder/tekton.dev_v1_pipeline_tekton-bundle-builder.yaml create mode 100644 auto-generated/pipelines/tekton.dev_v1_pipeline_docker-build-multi-platform-oci-ta.yaml create mode 100644 auto-generated/pipelines/tekton.dev_v1_pipeline_docker-build-oci-ta.yaml create mode 100644 auto-generated/pipelines/tekton.dev_v1_pipeline_docker-build.yaml create mode 100644 auto-generated/pipelines/tekton.dev_v1_pipeline_enterprise-contract.yaml create mode 100644 auto-generated/pipelines/tekton.dev_v1_pipeline_fbc-builder.yaml create mode 100644 auto-generated/pipelines/tekton.dev_v1_pipeline_maven-zip-build-oci-ta.yaml create mode 100644 auto-generated/pipelines/tekton.dev_v1_pipeline_maven-zip-build.yaml create mode 100644 auto-generated/pipelines/tekton.dev_v1_pipeline_tekton-bundle-builder.yaml create mode 100644 auto-generated/pipelines/template-build/tekton.dev_v1_pipeline_template-build.yaml create mode 100644 auto-generated/task/build-image-index/0.1/tekton.dev_v1_task_build-image-index.yaml create mode 100644 auto-generated/task/build-image-manifest/0.1/tekton.dev_v1_task_build-image-manifest.yaml create mode 100644 auto-generated/task/build-maven-zip-oci-ta/0.1/tekton.dev_v1_task_build-maven-zip-oci-ta.yaml create mode 100644 auto-generated/task/build-maven-zip/0.1/tekton.dev_v1_task_build-maven-zip.yaml create mode 100644 auto-generated/task/buildah-10gb/0.1/tekton.dev_v1_task_buildah-10gb.yaml create mode 100644 auto-generated/task/buildah-10gb/0.2/tekton.dev_v1_task_buildah-10gb.yaml create mode 100644 auto-generated/task/buildah-20gb/0.1/tekton.dev_v1_task_buildah-20gb.yaml create mode 100644 auto-generated/task/buildah-20gb/0.2/tekton.dev_v1_task_buildah-20gb.yaml create mode 100644 auto-generated/task/buildah-24gb/0.1/tekton.dev_v1_task_buildah-24gb.yaml create mode 100644 auto-generated/task/buildah-24gb/0.2/tekton.dev_v1_task_buildah-24gb.yaml create mode 100644 auto-generated/task/buildah-6gb/0.1/tekton.dev_v1_task_buildah-6gb.yaml create mode 100644 auto-generated/task/buildah-6gb/0.2/tekton.dev_v1_task_buildah-6gb.yaml create mode 100644 auto-generated/task/buildah-8gb/0.1/tekton.dev_v1_task_buildah-8gb.yaml create mode 100644 auto-generated/task/buildah-8gb/0.2/tekton.dev_v1_task_buildah-8gb.yaml create mode 100644 auto-generated/task/buildah-min/0.1/tekton.dev_v1_task_buildah-min.yaml create mode 100644 auto-generated/task/buildah-min/0.2/tekton.dev_v1_task_buildah-min.yaml create mode 100644 auto-generated/task/buildah-oci-ta/0.1/tekton.dev_v1_task_buildah-oci-ta.yaml create mode 100644 auto-generated/task/buildah/0.1/tekton.dev_v1_task_buildah.yaml create mode 100644 auto-generated/task/buildah/0.2/tekton.dev_v1_task_buildah.yaml create mode 100644 auto-generated/task/buildah/0.3/tekton.dev_v1_task_buildah.yaml create mode 100644 auto-generated/task/fbc-related-image-check/0.1/tekton.dev_v1_task_fbc-related-image-check.yaml create mode 100644 auto-generated/task/fbc-related-image-check/0.2/tekton.dev_v1_task_fbc-related-image-check.yaml create mode 100644 auto-generated/task/fbc-validation/0.1/tekton.dev_v1_task_fbc-validation.yaml create mode 100644 auto-generated/task/fbc-validation/0.2/tekton.dev_v1_task_fbc-validation.yaml create mode 100644 auto-generated/task/generate-odcs-compose/0.1/tekton.dev_v1beta1_task_generate-odcs-compose.yaml create mode 100644 auto-generated/task/generate-odcs-compose/0.2/tekton.dev_v1beta1_task_generate-odcs-compose.yaml create mode 100644 auto-generated/task/inspect-image/0.1/tekton.dev_v1beta1_task_inspect-image.yaml create mode 100644 auto-generated/task/inspect-image/0.2/tekton.dev_v1beta1_task_inspect-image.yaml create mode 100644 auto-generated/task/provision-env-with-ephemeral-namespace/0.1/tekton.dev_v1_task_provision-env-with-ephemeral-namespace.yaml create mode 100644 auto-generated/task/verify-enterprise-contract/0.1/tekton.dev_v1_task_verify-enterprise-contract.yaml create mode 100644 auto-generated/task/verify-signed-rpms/0.1/tekton.dev_v1_task_verify-signed-rpms.yaml create mode 100755 hack/build-manifests.sh create mode 100755 hack/get-kustomize.sh create mode 100755 hack/verify-manifests.sh diff --git a/.github/workflows/check-kustomize-build.yaml b/.github/workflows/check-kustomize-build.yaml new file mode 100644 index 0000000000..01ef0b40f5 --- /dev/null +++ b/.github/workflows/check-kustomize-build.yaml @@ -0,0 +1,13 @@ +name: Validate PR - kustomize manifests +'on': + pull_request: + branches: [main] +jobs: + kustomize-build: + name: Check Kustomize Build of Task and Pipelines + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v4 + - name: Validate Manifests + run: hack/verify-manifests.sh diff --git a/README.md b/README.md index f90a979965..0aff82744b 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,14 @@ Buildah also has a remote version, which can be generated with: ./hack/generate-buildah-remote.sh ``` +## Making Changes to tasks and pipelines + +If your tasks or pipelines contains `kustomization.yaml`, after making changes to the tasks or pipelines, run `hack/build-manifests.sh` and +commit the `auto-generated` directory (in addition to your changes). It will help us to make sure the kustomize build is successful and review the changes. + +`hack/build-manifests.sh` needs `kustomize` to be installed locally.It can be downloaded using `hack/get-kustomize.sh` script. + + ## Testing ### Prerequisites diff --git a/auto-generated/pipelines/core-services/tekton.dev_v1_pipeline_docker-build.yaml b/auto-generated/pipelines/core-services/tekton.dev_v1_pipeline_docker-build.yaml new file mode 100644 index 0000000000..192ee15288 --- /dev/null +++ b/auto-generated/pipelines/core-services/tekton.dev_v1_pipeline_docker-build.yaml @@ -0,0 +1,518 @@ +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + annotations: + appstudio.openshift.io/core-services-ci: "1" + labels: + pipelines.openshift.io/runtime: generic + pipelines.openshift.io/strategy: docker + pipelines.openshift.io/used-by: build-cloud + name: docker-build +spec: + description: | + This pipeline is ideal for building container images from a Containerfile while reducing network traffic. + + _Uses `buildah` to create a container image. It also optionally creates a source image and runs some build-time tests. EC will flag a violation for [`trusted_task.trusted`](https://enterprisecontract.dev/docs/ec-policies/release_policy.html#trusted_task__trusted) if any tasks are added to the pipeline. + This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/repository/konflux-ci/tekton-catalog/pipeline-docker-build?tab=tags)_ + finally: + - name: show-sbom + params: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + taskRef: + name: show-sbom + version: "0.1" + - name: show-summary + params: + - name: pipelinerun-name + value: $(context.pipelineRun.name) + - name: git-url + value: $(tasks.clone-repository.results.url)?rev=$(tasks.clone-repository.results.commit) + - name: image-url + value: $(params.output-image) + - name: build-task-status + value: $(tasks.build-image-index.status) + taskRef: + name: summary + version: "0.2" + workspaces: + - name: workspace + workspace: workspace + - name: infra-deployments-mr + params: + - name: ORIGIN_REPO + value: $(params.git-url) + - name: REVISION + value: $(params.revision) + - name: SCRIPT + value: $(params.infra-deployment-update-script) + taskRef: + name: update-infra-deployments + version: "0.1" + when: + - input: $(params.infra-deployment-update-script) + operator: notin + values: + - "" + - input: $(tasks.status) + operator: notin + values: + - Failed + - name: update-repo + params: + - name: ORIGIN_REPO + value: $(params.git-url) + - name: REVISION + value: $(params.revision) + - name: SCRIPT + value: $(params.update-repo-script) + - name: TARGET_GH_REPO + value: $(params.update-repo-name) + taskRef: + name: update-infra-deployments + version: "0.1" + when: + - input: $(params.update-repo-script) + operator: notin + values: + - "" + - input: $(params.update-repo-name) + operator: notin + values: + - "" + - input: $(tasks.status) + operator: notin + values: + - Failed + - name: slack-webhook-notification + params: + - name: message + value: Tekton pipelineRun $(context.pipelineRun.name) failed + - name: key-name + value: $(params.slack-webhook-notification-team) + taskRef: + name: slack-webhook-notification + version: "0.1" + when: + - input: $(params.slack-webhook-notification-team) + operator: notin + values: + - "" + - input: $(tasks.status) + operator: in + values: + - Failed + params: + - description: Source Repository URL + name: git-url + type: string + - default: "" + description: Revision of the Source Repository + name: revision + type: string + - description: Fully Qualified Output Image + name: output-image + type: string + - default: . + description: Path to the source code of an application's component from where + to build image. + name: path-context + type: string + - default: Dockerfile + description: Path to the Dockerfile inside the context specified by parameter + path-context + name: dockerfile + type: string + - default: "false" + description: Force rebuild image + name: rebuild + type: string + - default: "false" + description: Skip checks against built image + name: skip-checks + type: string + - default: "false" + description: Execute the build with network isolation + name: hermetic + type: string + - default: "" + description: Build dependencies to be prefetched by Cachi2 + name: prefetch-input + type: string + - default: "" + description: Image tag expiration time, time values could be something like 1h, + 2d, 3w for hours, days, and weeks, respectively. + name: image-expires-after + - default: "false" + description: Build a source image. + name: build-source-image + type: string + - default: "false" + description: Add built image into an OCI image index + name: build-image-index + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) for buildah + name: build-args + type: array + - default: "" + description: Path to a file with build arguments for buildah, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: build-args-file + type: string + - default: "" + name: infra-deployment-update-script + - default: "" + name: update-repo-script + - default: "" + name: update-repo-name + - default: "" + name: slack-webhook-notification-team + results: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: CHAINS-GIT_URL + value: $(tasks.clone-repository.results.url) + - name: CHAINS-GIT_COMMIT + value: $(tasks.clone-repository.results.commit) + tasks: + - name: init + params: + - name: image-url + value: $(params.output-image) + - name: rebuild + value: $(params.rebuild) + - name: skip-checks + value: $(params.skip-checks) + taskRef: + name: init + version: "0.2" + - name: clone-repository + params: + - name: url + value: $(params.git-url) + - name: revision + value: $(params.revision) + runAfter: + - init + taskRef: + name: git-clone + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: output + workspace: workspace + - name: basic-auth + workspace: git-auth + - name: prefetch-dependencies + params: + - name: input + value: $(params.prefetch-input) + runAfter: + - clone-repository + taskRef: + name: prefetch-dependencies + version: "0.1" + when: + - input: $(params.prefetch-input) + operator: notin + values: + - "" + workspaces: + - name: source + workspace: workspace + - name: git-basic-auth + workspace: git-auth + - name: netrc + workspace: netrc + - name: build-container + params: + - name: IMAGE + value: $(params.output-image) + - name: DOCKERFILE + value: $(params.dockerfile) + - name: CONTEXT + value: $(params.path-context) + - name: HERMETIC + value: $(params.hermetic) + - name: PREFETCH_INPUT + value: $(params.prefetch-input) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + - name: COMMIT_SHA + value: $(tasks.clone-repository.results.commit) + - name: BUILD_ARGS + value: + - $(params.build-args[*]) + - name: BUILD_ARGS_FILE + value: $(params.build-args-file) + runAfter: + - prefetch-dependencies + taskRef: + name: buildah + version: "0.3" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: source + workspace: workspace + - name: build-image-index + params: + - name: IMAGE + value: $(params.output-image) + - name: COMMIT_SHA + value: $(tasks.clone-repository.results.commit) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + - name: ALWAYS_BUILD_INDEX + value: $(params.build-image-index) + - name: IMAGES + value: + - $(tasks.build-container.results.IMAGE_URL)@$(tasks.build-container.results.IMAGE_DIGEST) + runAfter: + - build-container + taskRef: + name: build-image-index + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + - name: build-source-image + params: + - name: BINARY_IMAGE + value: $(params.output-image) + runAfter: + - build-image-index + taskRef: + name: source-build + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + - input: $(params.build-source-image) + operator: in + values: + - "true" + workspaces: + - name: workspace + workspace: workspace + - name: deprecated-base-image-check + params: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + runAfter: + - build-image-index + taskRef: + name: deprecated-image-check + version: "0.4" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: clair-scan + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: clair-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: ecosystem-cert-preflight-checks + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: ecosystem-cert-preflight-checks + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: sast-snyk-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: sast-snyk-check + version: "0.3" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + - name: clamav-scan + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: clamav-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: sast-coverity-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - coverity-availability-check + taskRef: + name: sast-coverity-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - input: $(tasks.coverity-availability-check.results.STATUS) + operator: in + values: + - success + workspaces: + - name: workspace + workspace: workspace + - name: coverity-availability-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: coverity-availability-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + - name: sast-shell-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: sast-shell-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + - name: sast-unicode-check + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: sast-unicode-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + - name: apply-tags + params: + - name: IMAGE + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: apply-tags + version: "0.1" + - name: push-dockerfile + params: + - name: IMAGE + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: DOCKERFILE + value: $(params.dockerfile) + - name: CONTEXT + value: $(params.path-context) + runAfter: + - build-image-index + taskRef: + name: push-dockerfile + version: "0.1" + workspaces: + - name: workspace + workspace: workspace + - name: rpms-signature-scan + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + runAfter: + - build-image-index + taskRef: + name: rpms-signature-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + - name: git-auth + optional: true + - name: netrc + optional: true diff --git a/auto-generated/pipelines/docker-build-multi-platform-oci-ta/tekton.dev_v1_pipeline_docker-build-multi-platform-oci-ta.yaml b/auto-generated/pipelines/docker-build-multi-platform-oci-ta/tekton.dev_v1_pipeline_docker-build-multi-platform-oci-ta.yaml new file mode 100644 index 0000000000..eba8824056 --- /dev/null +++ b/auto-generated/pipelines/docker-build-multi-platform-oci-ta/tekton.dev_v1_pipeline_docker-build-multi-platform-oci-ta.yaml @@ -0,0 +1,455 @@ +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + labels: + pipelines.openshift.io/runtime: generic + pipelines.openshift.io/strategy: docker + pipelines.openshift.io/used-by: build-cloud + name: docker-build-multi-platform-oci-ta +spec: + description: | + This pipeline is ideal for building multi-arch container images from a Containerfile while maintaining trust after pipeline customization. + + _Uses `buildah` to create a multi-platform container image leveraging [trusted artifacts](https://konflux-ci.dev/architecture/ADR/0036-trusted-artifacts.html). It also optionally creates a source image and runs some build-time tests. This pipeline requires that the [multi platform controller](https://github.com/konflux-ci/multi-platform-controller) is deployed and configured on your Konflux instance. Information is shared between tasks using OCI artifacts instead of PVCs. EC will pass the [`trusted_task.trusted`](https://enterprisecontract.dev/docs/ec-policies/release_policy.html#trusted_task__trusted) policy as long as all data used to build the artifact is generated from trusted tasks. + This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/repository/konflux-ci/tekton-catalog/pipeline-docker-build-multi-platform-oci-ta?tab=tags)_ + finally: + - name: show-sbom + params: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + taskRef: + name: show-sbom + version: "0.1" + params: + - description: Source Repository URL + name: git-url + type: string + - default: "" + description: Revision of the Source Repository + name: revision + type: string + - description: Fully Qualified Output Image + name: output-image + type: string + - default: . + description: Path to the source code of an application's component from where + to build image. + name: path-context + type: string + - default: Dockerfile + description: Path to the Dockerfile inside the context specified by parameter + path-context + name: dockerfile + type: string + - default: "false" + description: Force rebuild image + name: rebuild + type: string + - default: "false" + description: Skip checks against built image + name: skip-checks + type: string + - default: "false" + description: Execute the build with network isolation + name: hermetic + type: string + - default: "" + description: Build dependencies to be prefetched by Cachi2 + name: prefetch-input + type: string + - default: "" + description: Image tag expiration time, time values could be something like 1h, + 2d, 3w for hours, days, and weeks, respectively. + name: image-expires-after + - default: "false" + description: Build a source image. + name: build-source-image + type: string + - default: "true" + description: Add built image into an OCI image index + name: build-image-index + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) for buildah + name: build-args + type: array + - default: "" + description: Path to a file with build arguments for buildah, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: build-args-file + type: string + - default: + - linux/x86_64 + description: List of platforms to build the container images on. The available + set of values is determined by the configuration of the multi-platform-controller. + name: build-platforms + type: array + results: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: CHAINS-GIT_URL + value: $(tasks.clone-repository.results.url) + - name: CHAINS-GIT_COMMIT + value: $(tasks.clone-repository.results.commit) + tasks: + - name: init + params: + - name: image-url + value: $(params.output-image) + - name: rebuild + value: $(params.rebuild) + - name: skip-checks + value: $(params.skip-checks) + taskRef: + name: init + version: "0.2" + - name: clone-repository + params: + - name: url + value: $(params.git-url) + - name: revision + value: $(params.revision) + - name: ociStorage + value: $(params.output-image).git + - name: ociArtifactExpiresAfter + value: $(params.image-expires-after) + runAfter: + - init + taskRef: + name: git-clone-oci-ta + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: basic-auth + workspace: git-auth + - name: prefetch-dependencies + params: + - name: input + value: $(params.prefetch-input) + - name: SOURCE_ARTIFACT + value: $(tasks.clone-repository.results.SOURCE_ARTIFACT) + - name: ociStorage + value: $(params.output-image).prefetch + - name: ociArtifactExpiresAfter + value: $(params.image-expires-after) + runAfter: + - clone-repository + taskRef: + name: prefetch-dependencies-oci-ta + version: "0.1" + workspaces: + - name: git-basic-auth + workspace: git-auth + - name: netrc + workspace: netrc + - matrix: + params: + - name: PLATFORM + value: + - $(params.build-platforms) + name: build-images + params: + - name: IMAGE + value: $(params.output-image) + - name: DOCKERFILE + value: $(params.dockerfile) + - name: CONTEXT + value: $(params.path-context) + - name: HERMETIC + value: $(params.hermetic) + - name: PREFETCH_INPUT + value: $(params.prefetch-input) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + - name: COMMIT_SHA + value: $(tasks.clone-repository.results.commit) + - name: BUILD_ARGS + value: + - $(params.build-args[*]) + - name: BUILD_ARGS_FILE + value: $(params.build-args-file) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + - name: IMAGE_APPEND_PLATFORM + value: "true" + runAfter: + - prefetch-dependencies + taskRef: + name: buildah-remote-oci-ta + version: "0.3" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: [] + - name: build-image-index + params: + - name: IMAGE + value: $(params.output-image) + - name: COMMIT_SHA + value: $(tasks.clone-repository.results.commit) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + - name: ALWAYS_BUILD_INDEX + value: $(params.build-image-index) + - name: IMAGES + value: + - $(tasks.build-images.results.IMAGE_REF[*]) + runAfter: + - build-images + taskRef: + name: build-image-index + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + - name: build-source-image + params: + - name: BINARY_IMAGE + value: $(params.output-image) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-image-index + taskRef: + name: source-build-oci-ta + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + - input: $(params.build-source-image) + operator: in + values: + - "true" + workspaces: [] + - name: deprecated-base-image-check + params: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + runAfter: + - build-image-index + taskRef: + name: deprecated-image-check + version: "0.4" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: clair-scan + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: clair-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: ecosystem-cert-preflight-checks + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: ecosystem-cert-preflight-checks + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: sast-snyk-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-image-index + taskRef: + name: sast-snyk-check-oci-ta + version: "0.3" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: [] + - name: clamav-scan + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: clamav-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: sast-coverity-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - coverity-availability-check + taskRef: + name: sast-coverity-check-oci-ta + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - input: $(tasks.coverity-availability-check.results.STATUS) + operator: in + values: + - success + workspaces: [] + - name: coverity-availability-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-image-index + taskRef: + name: coverity-availability-check-oci-ta + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: [] + - name: sast-shell-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-image-index + taskRef: + name: sast-shell-check-oci-ta + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: [] + - name: sast-unicode-check + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-image-index + taskRef: + name: sast-shell-check-oci-ta + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: [] + - name: apply-tags + params: + - name: IMAGE + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: apply-tags + version: "0.1" + - name: push-dockerfile + params: + - name: IMAGE + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: DOCKERFILE + value: $(params.dockerfile) + - name: CONTEXT + value: $(params.path-context) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + runAfter: + - build-image-index + taskRef: + name: push-dockerfile-oci-ta + version: "0.1" + workspaces: [] + - name: rpms-signature-scan + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + runAfter: + - build-image-index + taskRef: + name: rpms-signature-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: git-auth + optional: true + - name: netrc + optional: true diff --git a/auto-generated/pipelines/docker-build-oci-ta/tekton.dev_v1_pipeline_docker-build-oci-ta.yaml b/auto-generated/pipelines/docker-build-oci-ta/tekton.dev_v1_pipeline_docker-build-oci-ta.yaml new file mode 100644 index 0000000000..1045bc82a9 --- /dev/null +++ b/auto-generated/pipelines/docker-build-oci-ta/tekton.dev_v1_pipeline_docker-build-oci-ta.yaml @@ -0,0 +1,442 @@ +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + labels: + pipelines.openshift.io/runtime: generic + pipelines.openshift.io/strategy: docker + pipelines.openshift.io/used-by: build-cloud + name: docker-build-oci-ta +spec: + description: | + This pipeline is ideal for building container images from a Containerfile while maintaining trust after pipeline customization. + + _Uses `buildah` to create a container image leveraging [trusted artifacts](https://konflux-ci.dev/architecture/ADR/0036-trusted-artifacts.html). It also optionally creates a source image and runs some build-time tests. Information is shared between tasks using OCI artifacts instead of PVCs. EC will pass the [`trusted_task.trusted`](https://enterprisecontract.dev/docs/ec-policies/release_policy.html#trusted_task__trusted) policy as long as all data used to build the artifact is generated from trusted tasks. + This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/repository/konflux-ci/tekton-catalog/pipeline-docker-build-oci-ta?tab=tags)_ + finally: + - name: show-sbom + params: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + taskRef: + name: show-sbom + version: "0.1" + params: + - description: Source Repository URL + name: git-url + type: string + - default: "" + description: Revision of the Source Repository + name: revision + type: string + - description: Fully Qualified Output Image + name: output-image + type: string + - default: . + description: Path to the source code of an application's component from where + to build image. + name: path-context + type: string + - default: Dockerfile + description: Path to the Dockerfile inside the context specified by parameter + path-context + name: dockerfile + type: string + - default: "false" + description: Force rebuild image + name: rebuild + type: string + - default: "false" + description: Skip checks against built image + name: skip-checks + type: string + - default: "false" + description: Execute the build with network isolation + name: hermetic + type: string + - default: "" + description: Build dependencies to be prefetched by Cachi2 + name: prefetch-input + type: string + - default: "" + description: Image tag expiration time, time values could be something like 1h, + 2d, 3w for hours, days, and weeks, respectively. + name: image-expires-after + - default: "false" + description: Build a source image. + name: build-source-image + type: string + - default: "false" + description: Add built image into an OCI image index + name: build-image-index + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) for buildah + name: build-args + type: array + - default: "" + description: Path to a file with build arguments for buildah, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: build-args-file + type: string + results: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: CHAINS-GIT_URL + value: $(tasks.clone-repository.results.url) + - name: CHAINS-GIT_COMMIT + value: $(tasks.clone-repository.results.commit) + tasks: + - name: init + params: + - name: image-url + value: $(params.output-image) + - name: rebuild + value: $(params.rebuild) + - name: skip-checks + value: $(params.skip-checks) + taskRef: + name: init + version: "0.2" + - name: clone-repository + params: + - name: url + value: $(params.git-url) + - name: revision + value: $(params.revision) + - name: ociStorage + value: $(params.output-image).git + - name: ociArtifactExpiresAfter + value: $(params.image-expires-after) + runAfter: + - init + taskRef: + name: git-clone-oci-ta + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: basic-auth + workspace: git-auth + - name: prefetch-dependencies + params: + - name: input + value: $(params.prefetch-input) + - name: SOURCE_ARTIFACT + value: $(tasks.clone-repository.results.SOURCE_ARTIFACT) + - name: ociStorage + value: $(params.output-image).prefetch + - name: ociArtifactExpiresAfter + value: $(params.image-expires-after) + runAfter: + - clone-repository + taskRef: + name: prefetch-dependencies-oci-ta + version: "0.1" + workspaces: + - name: git-basic-auth + workspace: git-auth + - name: netrc + workspace: netrc + - name: build-container + params: + - name: IMAGE + value: $(params.output-image) + - name: DOCKERFILE + value: $(params.dockerfile) + - name: CONTEXT + value: $(params.path-context) + - name: HERMETIC + value: $(params.hermetic) + - name: PREFETCH_INPUT + value: $(params.prefetch-input) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + - name: COMMIT_SHA + value: $(tasks.clone-repository.results.commit) + - name: BUILD_ARGS + value: + - $(params.build-args[*]) + - name: BUILD_ARGS_FILE + value: $(params.build-args-file) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - prefetch-dependencies + taskRef: + name: buildah-oci-ta + version: "0.3" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: [] + - name: build-image-index + params: + - name: IMAGE + value: $(params.output-image) + - name: COMMIT_SHA + value: $(tasks.clone-repository.results.commit) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + - name: ALWAYS_BUILD_INDEX + value: $(params.build-image-index) + - name: IMAGES + value: + - $(tasks.build-container.results.IMAGE_URL)@$(tasks.build-container.results.IMAGE_DIGEST) + runAfter: + - build-container + taskRef: + name: build-image-index + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + - name: build-source-image + params: + - name: BINARY_IMAGE + value: $(params.output-image) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-image-index + taskRef: + name: source-build-oci-ta + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + - input: $(params.build-source-image) + operator: in + values: + - "true" + workspaces: [] + - name: deprecated-base-image-check + params: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + runAfter: + - build-image-index + taskRef: + name: deprecated-image-check + version: "0.4" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: clair-scan + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: clair-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: ecosystem-cert-preflight-checks + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: ecosystem-cert-preflight-checks + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: sast-snyk-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-image-index + taskRef: + name: sast-snyk-check-oci-ta + version: "0.3" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: [] + - name: clamav-scan + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: clamav-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: sast-coverity-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - coverity-availability-check + taskRef: + name: sast-coverity-check-oci-ta + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - input: $(tasks.coverity-availability-check.results.STATUS) + operator: in + values: + - success + workspaces: [] + - name: coverity-availability-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-image-index + taskRef: + name: coverity-availability-check-oci-ta + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: [] + - name: sast-shell-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-image-index + taskRef: + name: sast-shell-check-oci-ta + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: [] + - name: sast-unicode-check + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-image-index + taskRef: + name: sast-shell-check-oci-ta + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: [] + - name: apply-tags + params: + - name: IMAGE + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: apply-tags + version: "0.1" + - name: push-dockerfile + params: + - name: IMAGE + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: DOCKERFILE + value: $(params.dockerfile) + - name: CONTEXT + value: $(params.path-context) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + runAfter: + - build-image-index + taskRef: + name: push-dockerfile-oci-ta + version: "0.1" + workspaces: [] + - name: rpms-signature-scan + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + runAfter: + - build-image-index + taskRef: + name: rpms-signature-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: git-auth + optional: true + - name: netrc + optional: true diff --git a/auto-generated/pipelines/docker-build-rhtap/tekton.dev_v1_pipeline_docker-build-rhtap.yaml b/auto-generated/pipelines/docker-build-rhtap/tekton.dev_v1_pipeline_docker-build-rhtap.yaml new file mode 100644 index 0000000000..28ba88e58f --- /dev/null +++ b/auto-generated/pipelines/docker-build-rhtap/tekton.dev_v1_pipeline_docker-build-rhtap.yaml @@ -0,0 +1,285 @@ +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + labels: + pipelines.openshift.io/runtime: generic + pipelines.openshift.io/strategy: docker + pipelines.openshift.io/used-by: build-cloud + name: docker-build-rhtap +spec: + finally: + - name: show-sbom + params: + - name: IMAGE_URL + value: $(tasks.build-container.results.IMAGE_URL) + taskRef: + name: show-sbom-rhdh + version: "0.1" + - name: show-summary + params: + - name: pipelinerun-name + value: $(context.pipelineRun.name) + - name: git-url + value: $(tasks.clone-repository.results.url)?rev=$(tasks.clone-repository.results.commit) + - name: image-url + value: $(params.output-image) + - name: build-task-status + value: $(tasks.build-container.status) + taskRef: + name: summary + version: "0.2" + workspaces: + - name: workspace + workspace: workspace + params: + - description: Source Repository URL + name: git-url + type: string + - default: "" + description: Revision of the Source Repository + name: revision + type: string + - description: Fully Qualified Output Image + name: output-image + type: string + - default: . + description: Path to the source code of an application's component from where + to build image. + name: path-context + type: string + - default: Dockerfile + description: Path to the Dockerfile inside the context specified by parameter + path-context + name: dockerfile + type: string + - default: "false" + description: Force rebuild image + name: rebuild + type: string + - default: "" + description: Image tag expiration time, time values could be something like 1h, + 2d, 3w for hours, days, and weeks, respectively. + name: image-expires-after + - default: rox-api-token + name: stackrox-secret + type: string + - default: gitops-auth-secret + description: 'Secret name to enable this pipeline to update the gitops repo with + the new image. ' + name: gitops-auth-secret-name + type: string + - default: push + description: Event that triggered the pipeline run, e.g. push, pull_request + name: event-type + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) for buildah + name: build-args + type: array + - default: "" + description: Path to a file with build arguments for buildah, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: build-args-file + type: string + results: + - name: IMAGE_URL + value: $(tasks.build-container.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-container.results.IMAGE_DIGEST) + - name: CHAINS-GIT_URL + value: $(tasks.clone-repository.results.url) + - name: CHAINS-GIT_COMMIT + value: $(tasks.clone-repository.results.commit) + - name: ACS_SCAN_OUTPUT + value: $(tasks.acs-image-scan.results.SCAN_OUTPUT) + tasks: + - name: init + params: + - name: image-url + value: $(params.output-image) + - name: rebuild + value: $(params.rebuild) + taskRef: + name: init + version: "0.2" + - name: clone-repository + params: + - name: url + value: $(params.git-url) + - name: revision + value: $(params.revision) + runAfter: + - init + taskRef: + name: git-clone + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: output + workspace: workspace + - name: basic-auth + workspace: git-auth + - name: build-container + params: + - name: IMAGE + value: $(params.output-image) + - name: DOCKERFILE + value: $(params.dockerfile) + - name: CONTEXT + value: $(params.path-context) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + - name: COMMIT_SHA + value: $(tasks.clone-repository.results.commit) + - name: BUILD_ARGS + value: + - $(params.build-args[*]) + - name: BUILD_ARGS_FILE + value: $(params.build-args-file) + runAfter: + - clone-repository + taskRef: + name: buildah-rhtap + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: source + workspace: workspace + - name: sast-unicode-check + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: sast-unicode-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + - name: apply-tags + params: + - name: IMAGE + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: apply-tags + version: "0.1" + - name: push-dockerfile + params: + - name: IMAGE + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: DOCKERFILE + value: $(params.dockerfile) + - name: CONTEXT + value: $(params.path-context) + runAfter: + - build-image-index + taskRef: + name: push-dockerfile + version: "0.1" + workspaces: + - name: workspace + workspace: workspace + - name: rpms-signature-scan + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + runAfter: + - build-image-index + taskRef: + name: rpms-signature-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: acs-image-check + params: + - name: rox-secret-name + value: $(params.stackrox-secret) + - name: image + value: $(params.output-image) + - name: insecure-skip-tls-verify + value: "true" + - name: image-digest + value: $(tasks.build-container.results.IMAGE_DIGEST) + runAfter: + - build-container + taskRef: + name: acs-image-check + - name: acs-image-scan + params: + - name: rox-secret-name + value: $(params.stackrox-secret) + - name: image + value: $(params.output-image) + - name: insecure-skip-tls-verify + value: "true" + - name: image-digest + value: $(tasks.build-container.results.IMAGE_DIGEST) + runAfter: + - build-container + taskRef: + kind: Task + name: acs-image-scan + - name: acs-deploy-check + params: + - name: rox-secret-name + value: $(params.stackrox-secret) + - name: gitops-repo-url + value: $(params.git-url)-gitops + - name: insecure-skip-tls-verify + value: "true" + runAfter: + - update-deployment + taskRef: + kind: Task + name: acs-deploy-check + when: + - input: $(params.event-type) + operator: in + values: + - push + - Push + - name: update-deployment + params: + - name: gitops-repo-url + value: $(params.git-url)-gitops + - name: image + value: $(tasks.build-container.results.IMAGE_URL)@$(tasks.build-container.results.IMAGE_DIGEST) + - name: gitops-auth-secret-name + value: $(params.gitops-auth-secret-name) + runAfter: + - build-container + taskRef: + kind: Task + name: update-deployment + when: + - input: $(params.event-type) + operator: notin + values: + - pull_request + - Merge Request + workspaces: + - name: workspace + - name: git-auth + optional: true diff --git a/auto-generated/pipelines/docker-build/tekton.dev_v1_pipeline_docker-build.yaml b/auto-generated/pipelines/docker-build/tekton.dev_v1_pipeline_docker-build.yaml new file mode 100644 index 0000000000..93ec9aabe4 --- /dev/null +++ b/auto-generated/pipelines/docker-build/tekton.dev_v1_pipeline_docker-build.yaml @@ -0,0 +1,444 @@ +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + labels: + pipelines.openshift.io/runtime: generic + pipelines.openshift.io/strategy: docker + pipelines.openshift.io/used-by: build-cloud + name: docker-build +spec: + description: | + This pipeline is ideal for building container images from a Containerfile while reducing network traffic. + + _Uses `buildah` to create a container image. It also optionally creates a source image and runs some build-time tests. EC will flag a violation for [`trusted_task.trusted`](https://enterprisecontract.dev/docs/ec-policies/release_policy.html#trusted_task__trusted) if any tasks are added to the pipeline. + This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/repository/konflux-ci/tekton-catalog/pipeline-docker-build?tab=tags)_ + finally: + - name: show-sbom + params: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + taskRef: + name: show-sbom + version: "0.1" + - name: show-summary + params: + - name: pipelinerun-name + value: $(context.pipelineRun.name) + - name: git-url + value: $(tasks.clone-repository.results.url)?rev=$(tasks.clone-repository.results.commit) + - name: image-url + value: $(params.output-image) + - name: build-task-status + value: $(tasks.build-image-index.status) + taskRef: + name: summary + version: "0.2" + workspaces: + - name: workspace + workspace: workspace + params: + - description: Source Repository URL + name: git-url + type: string + - default: "" + description: Revision of the Source Repository + name: revision + type: string + - description: Fully Qualified Output Image + name: output-image + type: string + - default: . + description: Path to the source code of an application's component from where + to build image. + name: path-context + type: string + - default: Dockerfile + description: Path to the Dockerfile inside the context specified by parameter + path-context + name: dockerfile + type: string + - default: "false" + description: Force rebuild image + name: rebuild + type: string + - default: "false" + description: Skip checks against built image + name: skip-checks + type: string + - default: "false" + description: Execute the build with network isolation + name: hermetic + type: string + - default: "" + description: Build dependencies to be prefetched by Cachi2 + name: prefetch-input + type: string + - default: "" + description: Image tag expiration time, time values could be something like 1h, + 2d, 3w for hours, days, and weeks, respectively. + name: image-expires-after + - default: "false" + description: Build a source image. + name: build-source-image + type: string + - default: "false" + description: Add built image into an OCI image index + name: build-image-index + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) for buildah + name: build-args + type: array + - default: "" + description: Path to a file with build arguments for buildah, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: build-args-file + type: string + results: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: CHAINS-GIT_URL + value: $(tasks.clone-repository.results.url) + - name: CHAINS-GIT_COMMIT + value: $(tasks.clone-repository.results.commit) + tasks: + - name: init + params: + - name: image-url + value: $(params.output-image) + - name: rebuild + value: $(params.rebuild) + - name: skip-checks + value: $(params.skip-checks) + taskRef: + name: init + version: "0.2" + - name: clone-repository + params: + - name: url + value: $(params.git-url) + - name: revision + value: $(params.revision) + runAfter: + - init + taskRef: + name: git-clone + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: output + workspace: workspace + - name: basic-auth + workspace: git-auth + - name: prefetch-dependencies + params: + - name: input + value: $(params.prefetch-input) + runAfter: + - clone-repository + taskRef: + name: prefetch-dependencies + version: "0.1" + when: + - input: $(params.prefetch-input) + operator: notin + values: + - "" + workspaces: + - name: source + workspace: workspace + - name: git-basic-auth + workspace: git-auth + - name: netrc + workspace: netrc + - name: build-container + params: + - name: IMAGE + value: $(params.output-image) + - name: DOCKERFILE + value: $(params.dockerfile) + - name: CONTEXT + value: $(params.path-context) + - name: HERMETIC + value: $(params.hermetic) + - name: PREFETCH_INPUT + value: $(params.prefetch-input) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + - name: COMMIT_SHA + value: $(tasks.clone-repository.results.commit) + - name: BUILD_ARGS + value: + - $(params.build-args[*]) + - name: BUILD_ARGS_FILE + value: $(params.build-args-file) + runAfter: + - prefetch-dependencies + taskRef: + name: buildah + version: "0.3" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: source + workspace: workspace + - name: build-image-index + params: + - name: IMAGE + value: $(params.output-image) + - name: COMMIT_SHA + value: $(tasks.clone-repository.results.commit) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + - name: ALWAYS_BUILD_INDEX + value: $(params.build-image-index) + - name: IMAGES + value: + - $(tasks.build-container.results.IMAGE_URL)@$(tasks.build-container.results.IMAGE_DIGEST) + runAfter: + - build-container + taskRef: + name: build-image-index + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + - name: build-source-image + params: + - name: BINARY_IMAGE + value: $(params.output-image) + runAfter: + - build-image-index + taskRef: + name: source-build + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + - input: $(params.build-source-image) + operator: in + values: + - "true" + workspaces: + - name: workspace + workspace: workspace + - name: deprecated-base-image-check + params: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + runAfter: + - build-image-index + taskRef: + name: deprecated-image-check + version: "0.4" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: clair-scan + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: clair-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: ecosystem-cert-preflight-checks + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: ecosystem-cert-preflight-checks + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: sast-snyk-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: sast-snyk-check + version: "0.3" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + - name: clamav-scan + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: clamav-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: sast-coverity-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - coverity-availability-check + taskRef: + name: sast-coverity-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - input: $(tasks.coverity-availability-check.results.STATUS) + operator: in + values: + - success + workspaces: + - name: workspace + workspace: workspace + - name: coverity-availability-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: coverity-availability-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + - name: sast-shell-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: sast-shell-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + - name: sast-unicode-check + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: sast-unicode-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + - name: apply-tags + params: + - name: IMAGE + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: apply-tags + version: "0.1" + - name: push-dockerfile + params: + - name: IMAGE + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: DOCKERFILE + value: $(params.dockerfile) + - name: CONTEXT + value: $(params.path-context) + runAfter: + - build-image-index + taskRef: + name: push-dockerfile + version: "0.1" + workspaces: + - name: workspace + workspace: workspace + - name: rpms-signature-scan + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + runAfter: + - build-image-index + taskRef: + name: rpms-signature-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + - name: git-auth + optional: true + - name: netrc + optional: true diff --git a/auto-generated/pipelines/fbc-builder/tekton.dev_v1_pipeline_fbc-builder.yaml b/auto-generated/pipelines/fbc-builder/tekton.dev_v1_pipeline_fbc-builder.yaml new file mode 100644 index 0000000000..4af194f3ab --- /dev/null +++ b/auto-generated/pipelines/fbc-builder/tekton.dev_v1_pipeline_fbc-builder.yaml @@ -0,0 +1,261 @@ +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + labels: + pipelines.openshift.io/runtime: fbc + pipelines.openshift.io/strategy: fbc + pipelines.openshift.io/used-by: build-cloud + name: fbc-builder +spec: + description: | + This pipeline is ideal for building and verifying [file-based catalogs](https://konflux-ci.dev/docs/advanced-how-tos/building-olm.adoc#building-the-file-based-catalog). + + _Uses `buildah` to create a container image. Its build-time tests are limited to verifying the included catalog and do not scan the image. + This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/repository/konflux-ci/tekton-catalog/pipeline-fbc-builder?tab=tags)_ + finally: + - name: show-sbom + params: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + taskRef: + name: show-sbom + version: "0.1" + params: + - description: Source Repository URL + name: git-url + type: string + - default: "" + description: Revision of the Source Repository + name: revision + type: string + - description: Fully Qualified Output Image + name: output-image + type: string + - default: . + description: Path to the source code of an application's component from where + to build image. + name: path-context + type: string + - default: Dockerfile + description: Path to the Dockerfile inside the context specified by parameter + path-context + name: dockerfile + type: string + - default: "false" + description: Force rebuild image + name: rebuild + type: string + - default: "false" + description: Skip checks against built image + name: skip-checks + type: string + - default: "true" + description: Execute the build with network isolation + name: hermetic + type: string + - default: "" + description: Build dependencies to be prefetched by Cachi2 + name: prefetch-input + type: string + - default: "" + description: Image tag expiration time, time values could be something like 1h, + 2d, 3w for hours, days, and weeks, respectively. + name: image-expires-after + - default: "false" + description: Build a source image. + name: build-source-image + type: string + - default: "true" + description: Add built image into an OCI image index + name: build-image-index + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) for buildah + name: build-args + type: array + - default: "" + description: Path to a file with build arguments for buildah, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: build-args-file + type: string + - default: + - linux/x86_64 + description: List of platforms to build the container images on. The available + set of values is determined by the configuration of the multi-platform-controller. + name: build-platforms + type: array + results: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: CHAINS-GIT_URL + value: $(tasks.clone-repository.results.url) + - name: CHAINS-GIT_COMMIT + value: $(tasks.clone-repository.results.commit) + tasks: + - name: init + params: + - name: image-url + value: $(params.output-image) + - name: rebuild + value: $(params.rebuild) + - name: skip-checks + value: $(params.skip-checks) + taskRef: + name: init + version: "0.2" + - name: clone-repository + params: + - name: url + value: $(params.git-url) + - name: revision + value: $(params.revision) + - name: ociStorage + value: $(params.output-image).git + - name: ociArtifactExpiresAfter + value: $(params.image-expires-after) + runAfter: + - init + taskRef: + name: git-clone-oci-ta + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: basic-auth + workspace: git-auth + - name: prefetch-dependencies + params: + - name: input + value: $(params.prefetch-input) + - name: SOURCE_ARTIFACT + value: $(tasks.clone-repository.results.SOURCE_ARTIFACT) + - name: ociStorage + value: $(params.output-image).prefetch + - name: ociArtifactExpiresAfter + value: $(params.image-expires-after) + runAfter: + - clone-repository + taskRef: + name: prefetch-dependencies-oci-ta + version: "0.1" + workspaces: + - name: git-basic-auth + workspace: git-auth + - name: netrc + workspace: netrc + - matrix: + params: + - name: PLATFORM + value: + - $(params.build-platforms) + name: build-images + params: + - name: IMAGE + value: $(params.output-image) + - name: DOCKERFILE + value: $(params.dockerfile) + - name: CONTEXT + value: $(params.path-context) + - name: HERMETIC + value: $(params.hermetic) + - name: PREFETCH_INPUT + value: $(params.prefetch-input) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + - name: COMMIT_SHA + value: $(tasks.clone-repository.results.commit) + - name: BUILD_ARGS + value: + - $(params.build-args[*]) + - name: BUILD_ARGS_FILE + value: $(params.build-args-file) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + - name: IMAGE_APPEND_PLATFORM + value: "true" + runAfter: + - clone-repository + taskRef: + name: buildah-remote-oci-ta + version: "0.3" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: [] + - name: build-image-index + params: + - name: IMAGE + value: $(params.output-image) + - name: COMMIT_SHA + value: $(tasks.clone-repository.results.commit) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + - name: ALWAYS_BUILD_INDEX + value: $(params.build-image-index) + - name: IMAGES + value: + - $(tasks.build-images.results.IMAGE_REF[*]) + runAfter: + - build-images + taskRef: + name: build-image-index + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + - name: deprecated-base-image-check + params: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + runAfter: + - build-image-index + taskRef: + name: deprecated-image-check + version: "0.4" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: apply-tags + params: + - name: IMAGE + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: apply-tags + version: "0.1" + - name: validate-fbc + params: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + runAfter: + - build-image-index + taskRef: + name: validate-fbc + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: git-auth + optional: true + - name: netrc + optional: true diff --git a/auto-generated/pipelines/gitops-pull-request-rhtap/tekton.dev_v1_pipeline_gitops-pull-request.yaml b/auto-generated/pipelines/gitops-pull-request-rhtap/tekton.dev_v1_pipeline_gitops-pull-request.yaml new file mode 100644 index 0000000000..e69d959abc --- /dev/null +++ b/auto-generated/pipelines/gitops-pull-request-rhtap/tekton.dev_v1_pipeline_gitops-pull-request.yaml @@ -0,0 +1,162 @@ +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + name: gitops-pull-request +spec: + params: + - description: Gitops repo url + name: git-url + type: string + - default: "" + description: Gitops repo revision + name: revision + type: string + - default: main + description: The target branch for the pull request + name: target-branch + type: string + - default: github.com/enterprise-contract/config//default + description: Enterprise Contract policy to validate against + name: ec-policy-configuration + type: string + - default: "true" + description: Should EC violations cause the pipeline to fail? + name: ec-strict + type: string + - default: k8s://$(context.pipelineRun.namespace)/cosign-pub + description: The public key that EC should use to verify signatures + name: ec-public-key + type: string + - default: http://rekor-server.rhtap-tas.svc + description: The Rekor host that EC should use to look up transparency logs + name: ec-rekor-host + type: string + - default: http://tuf.rhtap-tas.svc + description: The TUF mirror that EC should use + name: ec-tuf-mirror + type: string + - default: tpa-secret + description: The name of the Secret that contains Trustification (TPA) configuration + name: trustification-secret-name + type: string + - default: "true" + description: Should the pipeline fail when there are SBOMs to upload but Trustification + is not properly configured (i.e. the secret is missing or doesn't have all the + required keys)? + name: fail-if-trustification-not-configured + type: string + tasks: + - name: clone-repository + params: + - name: url + value: $(params.git-url) + - name: revision + value: $(params.revision) + - name: fetchTags + value: "true" + taskRef: + name: git-clone + version: "0.1" + workspaces: + - name: output + workspace: workspace + - name: basic-auth + workspace: git-auth + - name: get-images-to-verify + params: + - name: TARGET_BRANCH + value: $(params.target-branch) + runAfter: + - clone-repository + taskRef: + name: gather-deploy-images + version: "0.1" + workspaces: + - name: source + workspace: workspace + - name: verify-enterprise-contract + params: + - name: IMAGES + value: $(tasks.get-images-to-verify.results.IMAGES_TO_VERIFY) + - name: STRICT + value: $(params.ec-strict) + - name: POLICY_CONFIGURATION + value: $(params.ec-policy-configuration) + - name: PUBLIC_KEY + value: $(params.ec-public-key) + - name: REKOR_HOST + value: $(params.ec-rekor-host) + - name: TUF_MIRROR + value: $(params.ec-tuf-mirror) + runAfter: + - get-images-to-verify + taskRef: + name: verify-enterprise-contract + version: "0.1" + when: + - input: $(tasks.get-images-to-verify.results.IMAGES_TO_VERIFY) + operator: notin + values: + - "" + - name: get-images-to-upload-sbom + params: + - name: TARGET_BRANCH + value: $(params.target-branch) + - name: FROM_ENVIRONMENTS + value: + - stage + - prod + runAfter: + - clone-repository + taskRef: + name: gather-deploy-images + version: "0.1" + workspaces: + - name: source + workspace: workspace + - name: download-sboms + params: + - name: IMAGES + value: $(tasks.get-images-to-upload-sbom.results.IMAGES_TO_VERIFY) + - name: SBOMS_DIR + value: sboms + - name: PUBLIC_KEY + value: $(params.ec-public-key) + - name: REKOR_HOST + value: $(params.ec-rekor-host) + - name: TUF_MIRROR + value: $(params.ec-tuf-mirror) + runAfter: + - get-images-to-upload-sbom + taskRef: + name: download-sbom-from-url-in-attestation + version: "0.1" + when: + - input: $(tasks.get-images-to-upload-sbom.results.IMAGES_TO_VERIFY) + operator: notin + values: + - "" + workspaces: + - name: sboms + workspace: workspace + - name: upload-sboms-to-trustification + params: + - name: SBOMS_DIR + value: sboms + - name: TRUSTIFICATION_SECRET_NAME + value: $(params.trustification-secret-name) + - name: FAIL_IF_TRUSTIFICATION_NOT_CONFIGURED + value: $(params.fail-if-trustification-not-configured) + runAfter: + - download-sboms + taskRef: + name: upload-sbom-to-trustification + version: "0.1" + when: + - input: $(tasks.get-images-to-upload-sbom.results.IMAGES_TO_VERIFY) + operator: notin + values: + - "" + workspaces: + - name: sboms + workspace: workspace diff --git a/auto-generated/pipelines/maven-zip-build-oci-ta/tekton.dev_v1_pipeline_maven-zip-build-oci-ta.yaml b/auto-generated/pipelines/maven-zip-build-oci-ta/tekton.dev_v1_pipeline_maven-zip-build-oci-ta.yaml new file mode 100644 index 0000000000..484bd8724d --- /dev/null +++ b/auto-generated/pipelines/maven-zip-build-oci-ta/tekton.dev_v1_pipeline_maven-zip-build-oci-ta.yaml @@ -0,0 +1,245 @@ +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + labels: + pipelines.openshift.io/runtime: generic + pipelines.openshift.io/strategy: maven-zip + pipelines.openshift.io/used-by: build-cloud + name: maven-zip-build-oci-ta +spec: + description: | + This pipeline will build the maven zip to oci-artifact while maintaining trust after pipeline customization. + + _Uses `prefetch-dependencies` to fetch all artifacts which will be the content of the maven zip, and then uses `build-maven-zip-oci-ta` to create zip and push it to quay.io as oci-artifact. Information is shared between tasks using OCI artifacts instead of PVCs. + This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/repository/konflux-ci/tekton-catalog/pipeline-maven-zip-build-oci-ta?tab=tags)_ + finally: + - name: show-sbom + params: + - name: IMAGE_URL + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + taskRef: + name: show-sbom + version: "0.1" + params: + - description: Source Repository URL + name: git-url + type: string + - default: "" + description: Revision of the Source Repository + name: revision + type: string + - description: Fully Qualified Output Image + name: output-image + type: string + - default: "false" + description: Force rebuild image + name: rebuild + type: string + - default: "false" + description: Skip checks against built image + name: skip-checks + type: string + - default: generic + description: Build dependencies to be prefetched by Cachi2 + name: prefetch-input + type: string + - default: "" + description: Image tag expiration time, time values could be something like 1h, + 2d, 3w for hours, days, and weeks, respectively. + name: image-expires-after + results: + - name: IMAGE_URL + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-oci-artifact.results.IMAGE_DIGEST) + - name: CHAINS-GIT_URL + value: $(tasks.clone-repository.results.url) + - name: CHAINS-GIT_COMMIT + value: $(tasks.clone-repository.results.commit) + tasks: + - name: init + params: + - name: image-url + value: $(params.output-image) + - name: rebuild + value: $(params.rebuild) + - name: skip-checks + value: $(params.skip-checks) + taskRef: + name: init + version: "0.2" + - name: clone-repository + params: + - name: url + value: $(params.git-url) + - name: revision + value: $(params.revision) + - name: ociStorage + value: $(params.output-image).git + - name: ociArtifactExpiresAfter + value: $(params.image-expires-after) + runAfter: + - init + taskRef: + name: git-clone-oci-ta + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: basic-auth + workspace: git-auth + - name: prefetch-dependencies + params: + - name: input + value: $(params.prefetch-input) + - name: SOURCE_ARTIFACT + value: $(tasks.clone-repository.results.SOURCE_ARTIFACT) + - name: ociStorage + value: $(params.output-image).prefetch + - name: ociArtifactExpiresAfter + value: $(params.image-expires-after) + runAfter: + - clone-repository + taskRef: + name: prefetch-dependencies-oci-ta + version: "0.1" + workspaces: + - name: git-basic-auth + workspace: git-auth + - name: netrc + workspace: netrc + - name: build-oci-artifact + params: + - name: IMAGE + value: $(params.output-image) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - prefetch-dependencies + taskRef: + name: build-maven-zip-oci-ta + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: [] + - name: sast-snyk-check + params: + - name: image-digest + value: $(tasks.build-oci-artifact.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-oci-artifact + taskRef: + name: sast-snyk-check-oci-ta + version: "0.3" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: [] + - name: sast-coverity-check + params: + - name: image-digest + value: $(tasks.build-oci-artifact.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - coverity-availability-check + taskRef: + name: sast-coverity-check-oci-ta + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - input: $(tasks.coverity-availability-check.results.STATUS) + operator: in + values: + - success + workspaces: [] + - name: coverity-availability-check + params: + - name: image-digest + value: $(tasks.build-oci-artifact.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-oci-artifact + taskRef: + name: coverity-availability-check-oci-ta + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: [] + - name: sast-shell-check + params: + - name: image-digest + value: $(tasks.build-oci-artifact.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-oci-artifact + taskRef: + name: sast-shell-check-oci-ta + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: [] + - name: sast-unicode-check + params: + - name: image-url + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-oci-artifact + taskRef: + name: sast-shell-check-oci-ta + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: [] + workspaces: + - name: workspace + - name: git-auth + optional: true + - name: netrc + optional: true diff --git a/auto-generated/pipelines/maven-zip-build/tekton.dev_v1_pipeline_maven-zip-build.yaml b/auto-generated/pipelines/maven-zip-build/tekton.dev_v1_pipeline_maven-zip-build.yaml new file mode 100644 index 0000000000..4e2ecbbaaa --- /dev/null +++ b/auto-generated/pipelines/maven-zip-build/tekton.dev_v1_pipeline_maven-zip-build.yaml @@ -0,0 +1,250 @@ +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + labels: + pipelines.openshift.io/runtime: generic + pipelines.openshift.io/strategy: maven-zip + pipelines.openshift.io/used-by: build-cloud + name: maven-zip-build +spec: + description: | + This pipeline will build the maven zip to oci-artifact. + + _Uses `prefetch-dependencies` to fetch all artifacts which will be the content of the maven zip, and then uses `build-maven-zip` to create zip and push it to quay.io as oci-artifact. + This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/repository/konflux-ci/tekton-catalog/pipeline-maven-zip-build?tab=tags)_ + finally: + - name: show-sbom + params: + - name: IMAGE_URL + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + taskRef: + name: show-sbom + version: "0.1" + - name: show-summary + params: + - name: pipelinerun-name + value: $(context.pipelineRun.name) + - name: git-url + value: $(tasks.clone-repository.results.url)?rev=$(tasks.clone-repository.results.commit) + - name: image-url + value: $(params.output-image) + - name: build-task-status + value: $(tasks.build-oci-artifact.status) + taskRef: + name: summary + version: "0.2" + workspaces: + - name: workspace + workspace: workspace + params: + - description: Source Repository URL + name: git-url + type: string + - default: "" + description: Revision of the Source Repository + name: revision + type: string + - description: Fully Qualified Output Image + name: output-image + type: string + - default: "false" + description: Force rebuild image + name: rebuild + type: string + - default: "false" + description: Skip checks against built image + name: skip-checks + type: string + - default: generic + description: Build dependencies to be prefetched by Cachi2 + name: prefetch-input + type: string + - default: "" + description: Image tag expiration time, time values could be something like 1h, + 2d, 3w for hours, days, and weeks, respectively. + name: image-expires-after + results: + - name: IMAGE_URL + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-oci-artifact.results.IMAGE_DIGEST) + - name: CHAINS-GIT_URL + value: $(tasks.clone-repository.results.url) + - name: CHAINS-GIT_COMMIT + value: $(tasks.clone-repository.results.commit) + tasks: + - name: init + params: + - name: image-url + value: $(params.output-image) + - name: rebuild + value: $(params.rebuild) + - name: skip-checks + value: $(params.skip-checks) + taskRef: + name: init + version: "0.2" + - name: clone-repository + params: + - name: url + value: $(params.git-url) + - name: revision + value: $(params.revision) + runAfter: + - init + taskRef: + name: git-clone + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: output + workspace: workspace + - name: basic-auth + workspace: git-auth + - name: prefetch-dependencies + params: + - name: input + value: $(params.prefetch-input) + runAfter: + - clone-repository + taskRef: + name: prefetch-dependencies + version: "0.1" + when: + - input: $(params.prefetch-input) + operator: notin + values: + - "" + workspaces: + - name: source + workspace: workspace + - name: git-basic-auth + workspace: git-auth + - name: netrc + workspace: netrc + - name: build-oci-artifact + params: + - name: IMAGE + value: $(params.output-image) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + runAfter: + - prefetch-dependencies + taskRef: + name: build-maven-zip + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: source + workspace: workspace + - name: sast-snyk-check + params: + - name: image-digest + value: $(tasks.build-oci-artifact.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + runAfter: + - build-oci-artifact + taskRef: + name: sast-snyk-check + version: "0.3" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + - name: sast-coverity-check + params: + - name: image-digest + value: $(tasks.build-oci-artifact.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + runAfter: + - coverity-availability-check + taskRef: + name: sast-coverity-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - input: $(tasks.coverity-availability-check.results.STATUS) + operator: in + values: + - success + workspaces: + - name: workspace + workspace: workspace + - name: coverity-availability-check + params: + - name: image-digest + value: $(tasks.build-oci-artifact.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + runAfter: + - build-oci-artifact + taskRef: + name: coverity-availability-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + - name: sast-shell-check + params: + - name: image-digest + value: $(tasks.build-oci-artifact.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + runAfter: + - build-oci-artifact + taskRef: + name: sast-shell-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + - name: sast-unicode-check + params: + - name: image-url + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + runAfter: + - build-oci-artifact + taskRef: + name: sast-unicode-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + workspaces: + - name: workspace + - name: git-auth + optional: true + - name: netrc + optional: true diff --git a/auto-generated/pipelines/rhtap/tekton.dev_v1_pipeline_docker-build-rhtap.yaml b/auto-generated/pipelines/rhtap/tekton.dev_v1_pipeline_docker-build-rhtap.yaml new file mode 100644 index 0000000000..28ba88e58f --- /dev/null +++ b/auto-generated/pipelines/rhtap/tekton.dev_v1_pipeline_docker-build-rhtap.yaml @@ -0,0 +1,285 @@ +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + labels: + pipelines.openshift.io/runtime: generic + pipelines.openshift.io/strategy: docker + pipelines.openshift.io/used-by: build-cloud + name: docker-build-rhtap +spec: + finally: + - name: show-sbom + params: + - name: IMAGE_URL + value: $(tasks.build-container.results.IMAGE_URL) + taskRef: + name: show-sbom-rhdh + version: "0.1" + - name: show-summary + params: + - name: pipelinerun-name + value: $(context.pipelineRun.name) + - name: git-url + value: $(tasks.clone-repository.results.url)?rev=$(tasks.clone-repository.results.commit) + - name: image-url + value: $(params.output-image) + - name: build-task-status + value: $(tasks.build-container.status) + taskRef: + name: summary + version: "0.2" + workspaces: + - name: workspace + workspace: workspace + params: + - description: Source Repository URL + name: git-url + type: string + - default: "" + description: Revision of the Source Repository + name: revision + type: string + - description: Fully Qualified Output Image + name: output-image + type: string + - default: . + description: Path to the source code of an application's component from where + to build image. + name: path-context + type: string + - default: Dockerfile + description: Path to the Dockerfile inside the context specified by parameter + path-context + name: dockerfile + type: string + - default: "false" + description: Force rebuild image + name: rebuild + type: string + - default: "" + description: Image tag expiration time, time values could be something like 1h, + 2d, 3w for hours, days, and weeks, respectively. + name: image-expires-after + - default: rox-api-token + name: stackrox-secret + type: string + - default: gitops-auth-secret + description: 'Secret name to enable this pipeline to update the gitops repo with + the new image. ' + name: gitops-auth-secret-name + type: string + - default: push + description: Event that triggered the pipeline run, e.g. push, pull_request + name: event-type + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) for buildah + name: build-args + type: array + - default: "" + description: Path to a file with build arguments for buildah, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: build-args-file + type: string + results: + - name: IMAGE_URL + value: $(tasks.build-container.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-container.results.IMAGE_DIGEST) + - name: CHAINS-GIT_URL + value: $(tasks.clone-repository.results.url) + - name: CHAINS-GIT_COMMIT + value: $(tasks.clone-repository.results.commit) + - name: ACS_SCAN_OUTPUT + value: $(tasks.acs-image-scan.results.SCAN_OUTPUT) + tasks: + - name: init + params: + - name: image-url + value: $(params.output-image) + - name: rebuild + value: $(params.rebuild) + taskRef: + name: init + version: "0.2" + - name: clone-repository + params: + - name: url + value: $(params.git-url) + - name: revision + value: $(params.revision) + runAfter: + - init + taskRef: + name: git-clone + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: output + workspace: workspace + - name: basic-auth + workspace: git-auth + - name: build-container + params: + - name: IMAGE + value: $(params.output-image) + - name: DOCKERFILE + value: $(params.dockerfile) + - name: CONTEXT + value: $(params.path-context) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + - name: COMMIT_SHA + value: $(tasks.clone-repository.results.commit) + - name: BUILD_ARGS + value: + - $(params.build-args[*]) + - name: BUILD_ARGS_FILE + value: $(params.build-args-file) + runAfter: + - clone-repository + taskRef: + name: buildah-rhtap + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: source + workspace: workspace + - name: sast-unicode-check + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: sast-unicode-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + - name: apply-tags + params: + - name: IMAGE + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: apply-tags + version: "0.1" + - name: push-dockerfile + params: + - name: IMAGE + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: DOCKERFILE + value: $(params.dockerfile) + - name: CONTEXT + value: $(params.path-context) + runAfter: + - build-image-index + taskRef: + name: push-dockerfile + version: "0.1" + workspaces: + - name: workspace + workspace: workspace + - name: rpms-signature-scan + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + runAfter: + - build-image-index + taskRef: + name: rpms-signature-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: acs-image-check + params: + - name: rox-secret-name + value: $(params.stackrox-secret) + - name: image + value: $(params.output-image) + - name: insecure-skip-tls-verify + value: "true" + - name: image-digest + value: $(tasks.build-container.results.IMAGE_DIGEST) + runAfter: + - build-container + taskRef: + name: acs-image-check + - name: acs-image-scan + params: + - name: rox-secret-name + value: $(params.stackrox-secret) + - name: image + value: $(params.output-image) + - name: insecure-skip-tls-verify + value: "true" + - name: image-digest + value: $(tasks.build-container.results.IMAGE_DIGEST) + runAfter: + - build-container + taskRef: + kind: Task + name: acs-image-scan + - name: acs-deploy-check + params: + - name: rox-secret-name + value: $(params.stackrox-secret) + - name: gitops-repo-url + value: $(params.git-url)-gitops + - name: insecure-skip-tls-verify + value: "true" + runAfter: + - update-deployment + taskRef: + kind: Task + name: acs-deploy-check + when: + - input: $(params.event-type) + operator: in + values: + - push + - Push + - name: update-deployment + params: + - name: gitops-repo-url + value: $(params.git-url)-gitops + - name: image + value: $(tasks.build-container.results.IMAGE_URL)@$(tasks.build-container.results.IMAGE_DIGEST) + - name: gitops-auth-secret-name + value: $(params.gitops-auth-secret-name) + runAfter: + - build-container + taskRef: + kind: Task + name: update-deployment + when: + - input: $(params.event-type) + operator: notin + values: + - pull_request + - Merge Request + workspaces: + - name: workspace + - name: git-auth + optional: true diff --git a/auto-generated/pipelines/rhtap/tekton.dev_v1_pipeline_gitops-pull-request.yaml b/auto-generated/pipelines/rhtap/tekton.dev_v1_pipeline_gitops-pull-request.yaml new file mode 100644 index 0000000000..e69d959abc --- /dev/null +++ b/auto-generated/pipelines/rhtap/tekton.dev_v1_pipeline_gitops-pull-request.yaml @@ -0,0 +1,162 @@ +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + name: gitops-pull-request +spec: + params: + - description: Gitops repo url + name: git-url + type: string + - default: "" + description: Gitops repo revision + name: revision + type: string + - default: main + description: The target branch for the pull request + name: target-branch + type: string + - default: github.com/enterprise-contract/config//default + description: Enterprise Contract policy to validate against + name: ec-policy-configuration + type: string + - default: "true" + description: Should EC violations cause the pipeline to fail? + name: ec-strict + type: string + - default: k8s://$(context.pipelineRun.namespace)/cosign-pub + description: The public key that EC should use to verify signatures + name: ec-public-key + type: string + - default: http://rekor-server.rhtap-tas.svc + description: The Rekor host that EC should use to look up transparency logs + name: ec-rekor-host + type: string + - default: http://tuf.rhtap-tas.svc + description: The TUF mirror that EC should use + name: ec-tuf-mirror + type: string + - default: tpa-secret + description: The name of the Secret that contains Trustification (TPA) configuration + name: trustification-secret-name + type: string + - default: "true" + description: Should the pipeline fail when there are SBOMs to upload but Trustification + is not properly configured (i.e. the secret is missing or doesn't have all the + required keys)? + name: fail-if-trustification-not-configured + type: string + tasks: + - name: clone-repository + params: + - name: url + value: $(params.git-url) + - name: revision + value: $(params.revision) + - name: fetchTags + value: "true" + taskRef: + name: git-clone + version: "0.1" + workspaces: + - name: output + workspace: workspace + - name: basic-auth + workspace: git-auth + - name: get-images-to-verify + params: + - name: TARGET_BRANCH + value: $(params.target-branch) + runAfter: + - clone-repository + taskRef: + name: gather-deploy-images + version: "0.1" + workspaces: + - name: source + workspace: workspace + - name: verify-enterprise-contract + params: + - name: IMAGES + value: $(tasks.get-images-to-verify.results.IMAGES_TO_VERIFY) + - name: STRICT + value: $(params.ec-strict) + - name: POLICY_CONFIGURATION + value: $(params.ec-policy-configuration) + - name: PUBLIC_KEY + value: $(params.ec-public-key) + - name: REKOR_HOST + value: $(params.ec-rekor-host) + - name: TUF_MIRROR + value: $(params.ec-tuf-mirror) + runAfter: + - get-images-to-verify + taskRef: + name: verify-enterprise-contract + version: "0.1" + when: + - input: $(tasks.get-images-to-verify.results.IMAGES_TO_VERIFY) + operator: notin + values: + - "" + - name: get-images-to-upload-sbom + params: + - name: TARGET_BRANCH + value: $(params.target-branch) + - name: FROM_ENVIRONMENTS + value: + - stage + - prod + runAfter: + - clone-repository + taskRef: + name: gather-deploy-images + version: "0.1" + workspaces: + - name: source + workspace: workspace + - name: download-sboms + params: + - name: IMAGES + value: $(tasks.get-images-to-upload-sbom.results.IMAGES_TO_VERIFY) + - name: SBOMS_DIR + value: sboms + - name: PUBLIC_KEY + value: $(params.ec-public-key) + - name: REKOR_HOST + value: $(params.ec-rekor-host) + - name: TUF_MIRROR + value: $(params.ec-tuf-mirror) + runAfter: + - get-images-to-upload-sbom + taskRef: + name: download-sbom-from-url-in-attestation + version: "0.1" + when: + - input: $(tasks.get-images-to-upload-sbom.results.IMAGES_TO_VERIFY) + operator: notin + values: + - "" + workspaces: + - name: sboms + workspace: workspace + - name: upload-sboms-to-trustification + params: + - name: SBOMS_DIR + value: sboms + - name: TRUSTIFICATION_SECRET_NAME + value: $(params.trustification-secret-name) + - name: FAIL_IF_TRUSTIFICATION_NOT_CONFIGURED + value: $(params.fail-if-trustification-not-configured) + runAfter: + - download-sboms + taskRef: + name: upload-sbom-to-trustification + version: "0.1" + when: + - input: $(tasks.get-images-to-upload-sbom.results.IMAGES_TO_VERIFY) + operator: notin + values: + - "" + workspaces: + - name: sboms + workspace: workspace diff --git a/auto-generated/pipelines/tekton-bundle-builder/tekton.dev_v1_pipeline_tekton-bundle-builder.yaml b/auto-generated/pipelines/tekton-bundle-builder/tekton.dev_v1_pipeline_tekton-bundle-builder.yaml new file mode 100644 index 0000000000..d6e3ffa1ba --- /dev/null +++ b/auto-generated/pipelines/tekton-bundle-builder/tekton.dev_v1_pipeline_tekton-bundle-builder.yaml @@ -0,0 +1,269 @@ +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + labels: + pipelines.openshift.io/runtime: "" + pipelines.openshift.io/strategy: "" + pipelines.openshift.io/used-by: "" + name: tekton-bundle-builder +spec: + finally: + - name: show-summary + params: + - name: pipelinerun-name + value: $(context.pipelineRun.name) + - name: git-url + value: $(tasks.clone-repository.results.url)?rev=$(tasks.clone-repository.results.commit) + - name: image-url + value: $(params.output-image) + - name: build-task-status + value: $(tasks.build-image-index.status) + taskRef: + name: summary + version: "0.2" + workspaces: + - name: workspace + workspace: workspace + params: + - description: Source Repository URL + name: git-url + type: string + - default: "" + description: Revision of the Source Repository + name: revision + type: string + - description: Fully Qualified Output Image + name: output-image + type: string + - default: . + description: Path to the source code of an application's component from where + to build image. + name: path-context + type: string + - default: Dockerfile + description: Path to the Dockerfile inside the context specified by parameter + path-context + name: dockerfile + type: string + - default: "false" + description: Force rebuild image + name: rebuild + type: string + - default: "false" + description: Skip checks against built image + name: skip-checks + type: string + - default: "false" + description: Execute the build with network isolation + name: hermetic + type: string + - default: "" + description: Build dependencies to be prefetched by Cachi2 + name: prefetch-input + type: string + - default: "" + description: Image tag expiration time, time values could be something like 1h, + 2d, 3w for hours, days, and weeks, respectively. + name: image-expires-after + - default: "false" + description: Build a source image. + name: build-source-image + type: string + - default: "false" + description: Add built image into an OCI image index + name: build-image-index + type: string + results: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: CHAINS-GIT_URL + value: $(tasks.clone-repository.results.url) + - name: CHAINS-GIT_COMMIT + value: $(tasks.clone-repository.results.commit) + tasks: + - name: init + params: + - name: image-url + value: $(params.output-image) + - name: rebuild + value: $(params.rebuild) + - name: skip-checks + value: $(params.skip-checks) + taskRef: + name: init + version: "0.2" + - name: clone-repository + params: + - name: url + value: $(params.git-url) + - name: revision + value: $(params.revision) + runAfter: + - init + taskRef: + name: git-clone + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: output + workspace: workspace + - name: basic-auth + workspace: git-auth + - name: prefetch-dependencies + params: + - name: input + value: $(params.prefetch-input) + runAfter: + - clone-repository + taskRef: + name: prefetch-dependencies + version: "0.1" + when: + - input: $(params.prefetch-input) + operator: notin + values: + - "" + workspaces: + - name: source + workspace: workspace + - name: git-basic-auth + workspace: git-auth + - name: netrc + workspace: netrc + - name: build-container + params: + - name: IMAGE + value: $(params.output-image) + - name: CONTEXT + value: $(params.path-context) + runAfter: + - prefetch-dependencies + taskRef: + name: tkn-bundle + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: source + workspace: workspace + - name: build-image-index + params: + - name: IMAGE + value: $(params.output-image) + - name: COMMIT_SHA + value: $(tasks.clone-repository.results.commit) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + - name: ALWAYS_BUILD_INDEX + value: $(params.build-image-index) + - name: IMAGES + value: + - $(tasks.build-container.results.IMAGE_URL)@$(tasks.build-container.results.IMAGE_DIGEST) + runAfter: + - build-container + taskRef: + name: build-image-index + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + - name: sast-coverity-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - coverity-availability-check + taskRef: + name: sast-coverity-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - input: $(tasks.coverity-availability-check.results.STATUS) + operator: in + values: + - success + workspaces: + - name: workspace + workspace: workspace + - name: sast-unicode-check + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: sast-unicode-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + - name: apply-tags + params: + - name: IMAGE + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: apply-tags + version: "0.1" + - name: push-dockerfile + params: + - name: IMAGE + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: DOCKERFILE + value: $(params.dockerfile) + - name: CONTEXT + value: $(params.path-context) + runAfter: + - build-image-index + taskRef: + name: push-dockerfile + version: "0.1" + workspaces: + - name: workspace + workspace: workspace + - name: rpms-signature-scan + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + runAfter: + - build-image-index + taskRef: + name: rpms-signature-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + - name: git-auth + optional: true + - name: netrc + optional: true diff --git a/auto-generated/pipelines/tekton.dev_v1_pipeline_docker-build-multi-platform-oci-ta.yaml b/auto-generated/pipelines/tekton.dev_v1_pipeline_docker-build-multi-platform-oci-ta.yaml new file mode 100644 index 0000000000..eba8824056 --- /dev/null +++ b/auto-generated/pipelines/tekton.dev_v1_pipeline_docker-build-multi-platform-oci-ta.yaml @@ -0,0 +1,455 @@ +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + labels: + pipelines.openshift.io/runtime: generic + pipelines.openshift.io/strategy: docker + pipelines.openshift.io/used-by: build-cloud + name: docker-build-multi-platform-oci-ta +spec: + description: | + This pipeline is ideal for building multi-arch container images from a Containerfile while maintaining trust after pipeline customization. + + _Uses `buildah` to create a multi-platform container image leveraging [trusted artifacts](https://konflux-ci.dev/architecture/ADR/0036-trusted-artifacts.html). It also optionally creates a source image and runs some build-time tests. This pipeline requires that the [multi platform controller](https://github.com/konflux-ci/multi-platform-controller) is deployed and configured on your Konflux instance. Information is shared between tasks using OCI artifacts instead of PVCs. EC will pass the [`trusted_task.trusted`](https://enterprisecontract.dev/docs/ec-policies/release_policy.html#trusted_task__trusted) policy as long as all data used to build the artifact is generated from trusted tasks. + This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/repository/konflux-ci/tekton-catalog/pipeline-docker-build-multi-platform-oci-ta?tab=tags)_ + finally: + - name: show-sbom + params: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + taskRef: + name: show-sbom + version: "0.1" + params: + - description: Source Repository URL + name: git-url + type: string + - default: "" + description: Revision of the Source Repository + name: revision + type: string + - description: Fully Qualified Output Image + name: output-image + type: string + - default: . + description: Path to the source code of an application's component from where + to build image. + name: path-context + type: string + - default: Dockerfile + description: Path to the Dockerfile inside the context specified by parameter + path-context + name: dockerfile + type: string + - default: "false" + description: Force rebuild image + name: rebuild + type: string + - default: "false" + description: Skip checks against built image + name: skip-checks + type: string + - default: "false" + description: Execute the build with network isolation + name: hermetic + type: string + - default: "" + description: Build dependencies to be prefetched by Cachi2 + name: prefetch-input + type: string + - default: "" + description: Image tag expiration time, time values could be something like 1h, + 2d, 3w for hours, days, and weeks, respectively. + name: image-expires-after + - default: "false" + description: Build a source image. + name: build-source-image + type: string + - default: "true" + description: Add built image into an OCI image index + name: build-image-index + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) for buildah + name: build-args + type: array + - default: "" + description: Path to a file with build arguments for buildah, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: build-args-file + type: string + - default: + - linux/x86_64 + description: List of platforms to build the container images on. The available + set of values is determined by the configuration of the multi-platform-controller. + name: build-platforms + type: array + results: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: CHAINS-GIT_URL + value: $(tasks.clone-repository.results.url) + - name: CHAINS-GIT_COMMIT + value: $(tasks.clone-repository.results.commit) + tasks: + - name: init + params: + - name: image-url + value: $(params.output-image) + - name: rebuild + value: $(params.rebuild) + - name: skip-checks + value: $(params.skip-checks) + taskRef: + name: init + version: "0.2" + - name: clone-repository + params: + - name: url + value: $(params.git-url) + - name: revision + value: $(params.revision) + - name: ociStorage + value: $(params.output-image).git + - name: ociArtifactExpiresAfter + value: $(params.image-expires-after) + runAfter: + - init + taskRef: + name: git-clone-oci-ta + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: basic-auth + workspace: git-auth + - name: prefetch-dependencies + params: + - name: input + value: $(params.prefetch-input) + - name: SOURCE_ARTIFACT + value: $(tasks.clone-repository.results.SOURCE_ARTIFACT) + - name: ociStorage + value: $(params.output-image).prefetch + - name: ociArtifactExpiresAfter + value: $(params.image-expires-after) + runAfter: + - clone-repository + taskRef: + name: prefetch-dependencies-oci-ta + version: "0.1" + workspaces: + - name: git-basic-auth + workspace: git-auth + - name: netrc + workspace: netrc + - matrix: + params: + - name: PLATFORM + value: + - $(params.build-platforms) + name: build-images + params: + - name: IMAGE + value: $(params.output-image) + - name: DOCKERFILE + value: $(params.dockerfile) + - name: CONTEXT + value: $(params.path-context) + - name: HERMETIC + value: $(params.hermetic) + - name: PREFETCH_INPUT + value: $(params.prefetch-input) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + - name: COMMIT_SHA + value: $(tasks.clone-repository.results.commit) + - name: BUILD_ARGS + value: + - $(params.build-args[*]) + - name: BUILD_ARGS_FILE + value: $(params.build-args-file) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + - name: IMAGE_APPEND_PLATFORM + value: "true" + runAfter: + - prefetch-dependencies + taskRef: + name: buildah-remote-oci-ta + version: "0.3" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: [] + - name: build-image-index + params: + - name: IMAGE + value: $(params.output-image) + - name: COMMIT_SHA + value: $(tasks.clone-repository.results.commit) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + - name: ALWAYS_BUILD_INDEX + value: $(params.build-image-index) + - name: IMAGES + value: + - $(tasks.build-images.results.IMAGE_REF[*]) + runAfter: + - build-images + taskRef: + name: build-image-index + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + - name: build-source-image + params: + - name: BINARY_IMAGE + value: $(params.output-image) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-image-index + taskRef: + name: source-build-oci-ta + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + - input: $(params.build-source-image) + operator: in + values: + - "true" + workspaces: [] + - name: deprecated-base-image-check + params: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + runAfter: + - build-image-index + taskRef: + name: deprecated-image-check + version: "0.4" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: clair-scan + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: clair-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: ecosystem-cert-preflight-checks + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: ecosystem-cert-preflight-checks + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: sast-snyk-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-image-index + taskRef: + name: sast-snyk-check-oci-ta + version: "0.3" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: [] + - name: clamav-scan + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: clamav-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: sast-coverity-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - coverity-availability-check + taskRef: + name: sast-coverity-check-oci-ta + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - input: $(tasks.coverity-availability-check.results.STATUS) + operator: in + values: + - success + workspaces: [] + - name: coverity-availability-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-image-index + taskRef: + name: coverity-availability-check-oci-ta + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: [] + - name: sast-shell-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-image-index + taskRef: + name: sast-shell-check-oci-ta + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: [] + - name: sast-unicode-check + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-image-index + taskRef: + name: sast-shell-check-oci-ta + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: [] + - name: apply-tags + params: + - name: IMAGE + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: apply-tags + version: "0.1" + - name: push-dockerfile + params: + - name: IMAGE + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: DOCKERFILE + value: $(params.dockerfile) + - name: CONTEXT + value: $(params.path-context) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + runAfter: + - build-image-index + taskRef: + name: push-dockerfile-oci-ta + version: "0.1" + workspaces: [] + - name: rpms-signature-scan + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + runAfter: + - build-image-index + taskRef: + name: rpms-signature-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: git-auth + optional: true + - name: netrc + optional: true diff --git a/auto-generated/pipelines/tekton.dev_v1_pipeline_docker-build-oci-ta.yaml b/auto-generated/pipelines/tekton.dev_v1_pipeline_docker-build-oci-ta.yaml new file mode 100644 index 0000000000..1045bc82a9 --- /dev/null +++ b/auto-generated/pipelines/tekton.dev_v1_pipeline_docker-build-oci-ta.yaml @@ -0,0 +1,442 @@ +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + labels: + pipelines.openshift.io/runtime: generic + pipelines.openshift.io/strategy: docker + pipelines.openshift.io/used-by: build-cloud + name: docker-build-oci-ta +spec: + description: | + This pipeline is ideal for building container images from a Containerfile while maintaining trust after pipeline customization. + + _Uses `buildah` to create a container image leveraging [trusted artifacts](https://konflux-ci.dev/architecture/ADR/0036-trusted-artifacts.html). It also optionally creates a source image and runs some build-time tests. Information is shared between tasks using OCI artifacts instead of PVCs. EC will pass the [`trusted_task.trusted`](https://enterprisecontract.dev/docs/ec-policies/release_policy.html#trusted_task__trusted) policy as long as all data used to build the artifact is generated from trusted tasks. + This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/repository/konflux-ci/tekton-catalog/pipeline-docker-build-oci-ta?tab=tags)_ + finally: + - name: show-sbom + params: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + taskRef: + name: show-sbom + version: "0.1" + params: + - description: Source Repository URL + name: git-url + type: string + - default: "" + description: Revision of the Source Repository + name: revision + type: string + - description: Fully Qualified Output Image + name: output-image + type: string + - default: . + description: Path to the source code of an application's component from where + to build image. + name: path-context + type: string + - default: Dockerfile + description: Path to the Dockerfile inside the context specified by parameter + path-context + name: dockerfile + type: string + - default: "false" + description: Force rebuild image + name: rebuild + type: string + - default: "false" + description: Skip checks against built image + name: skip-checks + type: string + - default: "false" + description: Execute the build with network isolation + name: hermetic + type: string + - default: "" + description: Build dependencies to be prefetched by Cachi2 + name: prefetch-input + type: string + - default: "" + description: Image tag expiration time, time values could be something like 1h, + 2d, 3w for hours, days, and weeks, respectively. + name: image-expires-after + - default: "false" + description: Build a source image. + name: build-source-image + type: string + - default: "false" + description: Add built image into an OCI image index + name: build-image-index + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) for buildah + name: build-args + type: array + - default: "" + description: Path to a file with build arguments for buildah, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: build-args-file + type: string + results: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: CHAINS-GIT_URL + value: $(tasks.clone-repository.results.url) + - name: CHAINS-GIT_COMMIT + value: $(tasks.clone-repository.results.commit) + tasks: + - name: init + params: + - name: image-url + value: $(params.output-image) + - name: rebuild + value: $(params.rebuild) + - name: skip-checks + value: $(params.skip-checks) + taskRef: + name: init + version: "0.2" + - name: clone-repository + params: + - name: url + value: $(params.git-url) + - name: revision + value: $(params.revision) + - name: ociStorage + value: $(params.output-image).git + - name: ociArtifactExpiresAfter + value: $(params.image-expires-after) + runAfter: + - init + taskRef: + name: git-clone-oci-ta + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: basic-auth + workspace: git-auth + - name: prefetch-dependencies + params: + - name: input + value: $(params.prefetch-input) + - name: SOURCE_ARTIFACT + value: $(tasks.clone-repository.results.SOURCE_ARTIFACT) + - name: ociStorage + value: $(params.output-image).prefetch + - name: ociArtifactExpiresAfter + value: $(params.image-expires-after) + runAfter: + - clone-repository + taskRef: + name: prefetch-dependencies-oci-ta + version: "0.1" + workspaces: + - name: git-basic-auth + workspace: git-auth + - name: netrc + workspace: netrc + - name: build-container + params: + - name: IMAGE + value: $(params.output-image) + - name: DOCKERFILE + value: $(params.dockerfile) + - name: CONTEXT + value: $(params.path-context) + - name: HERMETIC + value: $(params.hermetic) + - name: PREFETCH_INPUT + value: $(params.prefetch-input) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + - name: COMMIT_SHA + value: $(tasks.clone-repository.results.commit) + - name: BUILD_ARGS + value: + - $(params.build-args[*]) + - name: BUILD_ARGS_FILE + value: $(params.build-args-file) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - prefetch-dependencies + taskRef: + name: buildah-oci-ta + version: "0.3" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: [] + - name: build-image-index + params: + - name: IMAGE + value: $(params.output-image) + - name: COMMIT_SHA + value: $(tasks.clone-repository.results.commit) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + - name: ALWAYS_BUILD_INDEX + value: $(params.build-image-index) + - name: IMAGES + value: + - $(tasks.build-container.results.IMAGE_URL)@$(tasks.build-container.results.IMAGE_DIGEST) + runAfter: + - build-container + taskRef: + name: build-image-index + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + - name: build-source-image + params: + - name: BINARY_IMAGE + value: $(params.output-image) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-image-index + taskRef: + name: source-build-oci-ta + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + - input: $(params.build-source-image) + operator: in + values: + - "true" + workspaces: [] + - name: deprecated-base-image-check + params: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + runAfter: + - build-image-index + taskRef: + name: deprecated-image-check + version: "0.4" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: clair-scan + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: clair-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: ecosystem-cert-preflight-checks + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: ecosystem-cert-preflight-checks + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: sast-snyk-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-image-index + taskRef: + name: sast-snyk-check-oci-ta + version: "0.3" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: [] + - name: clamav-scan + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: clamav-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: sast-coverity-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - coverity-availability-check + taskRef: + name: sast-coverity-check-oci-ta + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - input: $(tasks.coverity-availability-check.results.STATUS) + operator: in + values: + - success + workspaces: [] + - name: coverity-availability-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-image-index + taskRef: + name: coverity-availability-check-oci-ta + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: [] + - name: sast-shell-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-image-index + taskRef: + name: sast-shell-check-oci-ta + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: [] + - name: sast-unicode-check + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-image-index + taskRef: + name: sast-shell-check-oci-ta + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: [] + - name: apply-tags + params: + - name: IMAGE + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: apply-tags + version: "0.1" + - name: push-dockerfile + params: + - name: IMAGE + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: DOCKERFILE + value: $(params.dockerfile) + - name: CONTEXT + value: $(params.path-context) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + runAfter: + - build-image-index + taskRef: + name: push-dockerfile-oci-ta + version: "0.1" + workspaces: [] + - name: rpms-signature-scan + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + runAfter: + - build-image-index + taskRef: + name: rpms-signature-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: git-auth + optional: true + - name: netrc + optional: true diff --git a/auto-generated/pipelines/tekton.dev_v1_pipeline_docker-build.yaml b/auto-generated/pipelines/tekton.dev_v1_pipeline_docker-build.yaml new file mode 100644 index 0000000000..93ec9aabe4 --- /dev/null +++ b/auto-generated/pipelines/tekton.dev_v1_pipeline_docker-build.yaml @@ -0,0 +1,444 @@ +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + labels: + pipelines.openshift.io/runtime: generic + pipelines.openshift.io/strategy: docker + pipelines.openshift.io/used-by: build-cloud + name: docker-build +spec: + description: | + This pipeline is ideal for building container images from a Containerfile while reducing network traffic. + + _Uses `buildah` to create a container image. It also optionally creates a source image and runs some build-time tests. EC will flag a violation for [`trusted_task.trusted`](https://enterprisecontract.dev/docs/ec-policies/release_policy.html#trusted_task__trusted) if any tasks are added to the pipeline. + This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/repository/konflux-ci/tekton-catalog/pipeline-docker-build?tab=tags)_ + finally: + - name: show-sbom + params: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + taskRef: + name: show-sbom + version: "0.1" + - name: show-summary + params: + - name: pipelinerun-name + value: $(context.pipelineRun.name) + - name: git-url + value: $(tasks.clone-repository.results.url)?rev=$(tasks.clone-repository.results.commit) + - name: image-url + value: $(params.output-image) + - name: build-task-status + value: $(tasks.build-image-index.status) + taskRef: + name: summary + version: "0.2" + workspaces: + - name: workspace + workspace: workspace + params: + - description: Source Repository URL + name: git-url + type: string + - default: "" + description: Revision of the Source Repository + name: revision + type: string + - description: Fully Qualified Output Image + name: output-image + type: string + - default: . + description: Path to the source code of an application's component from where + to build image. + name: path-context + type: string + - default: Dockerfile + description: Path to the Dockerfile inside the context specified by parameter + path-context + name: dockerfile + type: string + - default: "false" + description: Force rebuild image + name: rebuild + type: string + - default: "false" + description: Skip checks against built image + name: skip-checks + type: string + - default: "false" + description: Execute the build with network isolation + name: hermetic + type: string + - default: "" + description: Build dependencies to be prefetched by Cachi2 + name: prefetch-input + type: string + - default: "" + description: Image tag expiration time, time values could be something like 1h, + 2d, 3w for hours, days, and weeks, respectively. + name: image-expires-after + - default: "false" + description: Build a source image. + name: build-source-image + type: string + - default: "false" + description: Add built image into an OCI image index + name: build-image-index + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) for buildah + name: build-args + type: array + - default: "" + description: Path to a file with build arguments for buildah, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: build-args-file + type: string + results: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: CHAINS-GIT_URL + value: $(tasks.clone-repository.results.url) + - name: CHAINS-GIT_COMMIT + value: $(tasks.clone-repository.results.commit) + tasks: + - name: init + params: + - name: image-url + value: $(params.output-image) + - name: rebuild + value: $(params.rebuild) + - name: skip-checks + value: $(params.skip-checks) + taskRef: + name: init + version: "0.2" + - name: clone-repository + params: + - name: url + value: $(params.git-url) + - name: revision + value: $(params.revision) + runAfter: + - init + taskRef: + name: git-clone + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: output + workspace: workspace + - name: basic-auth + workspace: git-auth + - name: prefetch-dependencies + params: + - name: input + value: $(params.prefetch-input) + runAfter: + - clone-repository + taskRef: + name: prefetch-dependencies + version: "0.1" + when: + - input: $(params.prefetch-input) + operator: notin + values: + - "" + workspaces: + - name: source + workspace: workspace + - name: git-basic-auth + workspace: git-auth + - name: netrc + workspace: netrc + - name: build-container + params: + - name: IMAGE + value: $(params.output-image) + - name: DOCKERFILE + value: $(params.dockerfile) + - name: CONTEXT + value: $(params.path-context) + - name: HERMETIC + value: $(params.hermetic) + - name: PREFETCH_INPUT + value: $(params.prefetch-input) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + - name: COMMIT_SHA + value: $(tasks.clone-repository.results.commit) + - name: BUILD_ARGS + value: + - $(params.build-args[*]) + - name: BUILD_ARGS_FILE + value: $(params.build-args-file) + runAfter: + - prefetch-dependencies + taskRef: + name: buildah + version: "0.3" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: source + workspace: workspace + - name: build-image-index + params: + - name: IMAGE + value: $(params.output-image) + - name: COMMIT_SHA + value: $(tasks.clone-repository.results.commit) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + - name: ALWAYS_BUILD_INDEX + value: $(params.build-image-index) + - name: IMAGES + value: + - $(tasks.build-container.results.IMAGE_URL)@$(tasks.build-container.results.IMAGE_DIGEST) + runAfter: + - build-container + taskRef: + name: build-image-index + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + - name: build-source-image + params: + - name: BINARY_IMAGE + value: $(params.output-image) + runAfter: + - build-image-index + taskRef: + name: source-build + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + - input: $(params.build-source-image) + operator: in + values: + - "true" + workspaces: + - name: workspace + workspace: workspace + - name: deprecated-base-image-check + params: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + runAfter: + - build-image-index + taskRef: + name: deprecated-image-check + version: "0.4" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: clair-scan + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: clair-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: ecosystem-cert-preflight-checks + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: ecosystem-cert-preflight-checks + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: sast-snyk-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: sast-snyk-check + version: "0.3" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + - name: clamav-scan + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: clamav-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: sast-coverity-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - coverity-availability-check + taskRef: + name: sast-coverity-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - input: $(tasks.coverity-availability-check.results.STATUS) + operator: in + values: + - success + workspaces: + - name: workspace + workspace: workspace + - name: coverity-availability-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: coverity-availability-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + - name: sast-shell-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: sast-shell-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + - name: sast-unicode-check + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: sast-unicode-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + - name: apply-tags + params: + - name: IMAGE + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: apply-tags + version: "0.1" + - name: push-dockerfile + params: + - name: IMAGE + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: DOCKERFILE + value: $(params.dockerfile) + - name: CONTEXT + value: $(params.path-context) + runAfter: + - build-image-index + taskRef: + name: push-dockerfile + version: "0.1" + workspaces: + - name: workspace + workspace: workspace + - name: rpms-signature-scan + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + runAfter: + - build-image-index + taskRef: + name: rpms-signature-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + - name: git-auth + optional: true + - name: netrc + optional: true diff --git a/auto-generated/pipelines/tekton.dev_v1_pipeline_enterprise-contract.yaml b/auto-generated/pipelines/tekton.dev_v1_pipeline_enterprise-contract.yaml new file mode 100644 index 0000000000..cbec413560 --- /dev/null +++ b/auto-generated/pipelines/tekton.dev_v1_pipeline_enterprise-contract.yaml @@ -0,0 +1,119 @@ +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + labels: + build.appstudio.redhat.com/pipeline: enterprise-contract + name: enterprise-contract +spec: + params: + - description: | + Spec section of an ApplicationSnapshot resource. Not all fields of the + resource are required. A minimal example: + { + "components": [ + { + "containerImage": "quay.io/example/repo:latest" + } + ] + } + Each "containerImage" in the "components" array is validated. + name: SNAPSHOT + type: string + - default: enterprise-contract-service/default + description: | + Name of the policy configuration (EnterpriseContractConfiguration + object) to use. `namespace/name` or `name` syntax supported. If + namespace is omitted the namespace where the task runs is used. + name: POLICY_CONFIGURATION + type: string + - default: "" + description: | + Path to a directory containing SSL certs to be used when communicating + with external services. This is useful when using the integrated registry + and a local instance of Rekor on a development cluster which may use + certificates issued by a not-commonly trusted root CA. In such cases, + "/var/run/secrets/kubernetes.io/serviceaccount" is a good value. Multiple + paths can be provided by using the ":" separator. + name: SSL_CERT_DIR + type: string + - default: k8s://openshift-pipelines/public-key + description: | + Public key used to verify signatures. Must be a valid k8s cosign + reference, e.g. k8s://my-space/my-secret where my-secret contains + the expected cosign.pub attribute. + name: PUBLIC_KEY + type: string + - default: 5m0s + description: Timeout setting for `ec validate`. + name: TIMEOUT + type: string + - default: "1" + description: Number of parallel workers to use for policy evaluation. + name: WORKERS + type: string + - default: trusted-ca + description: The name of the ConfigMap to read CA bundle data from. + name: CA_TRUST_CONFIGMAP_NAME + type: string + - default: ca-bundle.crt + description: The name of the key in the ConfigMap that contains the CA bundle + data. + name: CA_TRUST_CONFIG_MAP_KEY + type: string + - default: "false" + description: Reduce the Snapshot to only the component whose build caused the + Snapshot to be created + name: SINGLE_COMPONENT + type: string + - default: pr/$(context.pipelineRun.name) + description: PipelineRun ID + name: SINGLE_COMPONENT_CUSTOM_RESOURCE + type: string + - default: "true" + description: | + A boolean flag that determines whether the result of the test will mark the TaskRun as passing or not. + Swap to false to make the IntegrationTestScenario informative. + + Setting to false is useful on specific conditions but will always mark the integration test as successful and + humans will tend to ignore the test results if they failed. Use with caution. + name: STRICT + type: string + results: + - name: TEST_OUTPUT + value: $(tasks.verify.results.TEST_OUTPUT) + tasks: + - name: verify + params: + - name: POLICY_CONFIGURATION + value: $(params.POLICY_CONFIGURATION) + - name: IMAGES + value: $(params.SNAPSHOT) + - name: SSL_CERT_DIR + value: $(params.SSL_CERT_DIR) + - name: STRICT + value: $(params.STRICT) + - name: PUBLIC_KEY + value: $(params.PUBLIC_KEY) + - name: IGNORE_REKOR + value: "true" + - name: TIMEOUT + value: $(params.TIMEOUT) + - name: WORKERS + value: $(params.WORKERS) + - name: CA_TRUST_CONFIGMAP_NAME + value: $(params.CA_TRUST_CONFIGMAP_NAME) + - name: CA_TRUST_CONFIG_MAP_KEY + value: $(params.CA_TRUST_CONFIG_MAP_KEY) + - name: SINGLE_COMPONENT + value: $(params.SINGLE_COMPONENT) + - name: SINGLE_COMPONENT_CUSTOM_RESOURCE + value: $(params.SINGLE_COMPONENT_CUSTOM_RESOURCE) + taskRef: + params: + - name: bundle + value: quay.io/enterprise-contract/ec-task-bundle:snapshot@sha256:d6a784046fada0d061a731e704333e07261fc4035f7186718153eb0c1880765c + - name: name + value: verify-enterprise-contract + - name: kind + value: task + resolver: bundles diff --git a/auto-generated/pipelines/tekton.dev_v1_pipeline_fbc-builder.yaml b/auto-generated/pipelines/tekton.dev_v1_pipeline_fbc-builder.yaml new file mode 100644 index 0000000000..4af194f3ab --- /dev/null +++ b/auto-generated/pipelines/tekton.dev_v1_pipeline_fbc-builder.yaml @@ -0,0 +1,261 @@ +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + labels: + pipelines.openshift.io/runtime: fbc + pipelines.openshift.io/strategy: fbc + pipelines.openshift.io/used-by: build-cloud + name: fbc-builder +spec: + description: | + This pipeline is ideal for building and verifying [file-based catalogs](https://konflux-ci.dev/docs/advanced-how-tos/building-olm.adoc#building-the-file-based-catalog). + + _Uses `buildah` to create a container image. Its build-time tests are limited to verifying the included catalog and do not scan the image. + This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/repository/konflux-ci/tekton-catalog/pipeline-fbc-builder?tab=tags)_ + finally: + - name: show-sbom + params: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + taskRef: + name: show-sbom + version: "0.1" + params: + - description: Source Repository URL + name: git-url + type: string + - default: "" + description: Revision of the Source Repository + name: revision + type: string + - description: Fully Qualified Output Image + name: output-image + type: string + - default: . + description: Path to the source code of an application's component from where + to build image. + name: path-context + type: string + - default: Dockerfile + description: Path to the Dockerfile inside the context specified by parameter + path-context + name: dockerfile + type: string + - default: "false" + description: Force rebuild image + name: rebuild + type: string + - default: "false" + description: Skip checks against built image + name: skip-checks + type: string + - default: "true" + description: Execute the build with network isolation + name: hermetic + type: string + - default: "" + description: Build dependencies to be prefetched by Cachi2 + name: prefetch-input + type: string + - default: "" + description: Image tag expiration time, time values could be something like 1h, + 2d, 3w for hours, days, and weeks, respectively. + name: image-expires-after + - default: "false" + description: Build a source image. + name: build-source-image + type: string + - default: "true" + description: Add built image into an OCI image index + name: build-image-index + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) for buildah + name: build-args + type: array + - default: "" + description: Path to a file with build arguments for buildah, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: build-args-file + type: string + - default: + - linux/x86_64 + description: List of platforms to build the container images on. The available + set of values is determined by the configuration of the multi-platform-controller. + name: build-platforms + type: array + results: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: CHAINS-GIT_URL + value: $(tasks.clone-repository.results.url) + - name: CHAINS-GIT_COMMIT + value: $(tasks.clone-repository.results.commit) + tasks: + - name: init + params: + - name: image-url + value: $(params.output-image) + - name: rebuild + value: $(params.rebuild) + - name: skip-checks + value: $(params.skip-checks) + taskRef: + name: init + version: "0.2" + - name: clone-repository + params: + - name: url + value: $(params.git-url) + - name: revision + value: $(params.revision) + - name: ociStorage + value: $(params.output-image).git + - name: ociArtifactExpiresAfter + value: $(params.image-expires-after) + runAfter: + - init + taskRef: + name: git-clone-oci-ta + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: basic-auth + workspace: git-auth + - name: prefetch-dependencies + params: + - name: input + value: $(params.prefetch-input) + - name: SOURCE_ARTIFACT + value: $(tasks.clone-repository.results.SOURCE_ARTIFACT) + - name: ociStorage + value: $(params.output-image).prefetch + - name: ociArtifactExpiresAfter + value: $(params.image-expires-after) + runAfter: + - clone-repository + taskRef: + name: prefetch-dependencies-oci-ta + version: "0.1" + workspaces: + - name: git-basic-auth + workspace: git-auth + - name: netrc + workspace: netrc + - matrix: + params: + - name: PLATFORM + value: + - $(params.build-platforms) + name: build-images + params: + - name: IMAGE + value: $(params.output-image) + - name: DOCKERFILE + value: $(params.dockerfile) + - name: CONTEXT + value: $(params.path-context) + - name: HERMETIC + value: $(params.hermetic) + - name: PREFETCH_INPUT + value: $(params.prefetch-input) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + - name: COMMIT_SHA + value: $(tasks.clone-repository.results.commit) + - name: BUILD_ARGS + value: + - $(params.build-args[*]) + - name: BUILD_ARGS_FILE + value: $(params.build-args-file) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + - name: IMAGE_APPEND_PLATFORM + value: "true" + runAfter: + - clone-repository + taskRef: + name: buildah-remote-oci-ta + version: "0.3" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: [] + - name: build-image-index + params: + - name: IMAGE + value: $(params.output-image) + - name: COMMIT_SHA + value: $(tasks.clone-repository.results.commit) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + - name: ALWAYS_BUILD_INDEX + value: $(params.build-image-index) + - name: IMAGES + value: + - $(tasks.build-images.results.IMAGE_REF[*]) + runAfter: + - build-images + taskRef: + name: build-image-index + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + - name: deprecated-base-image-check + params: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + runAfter: + - build-image-index + taskRef: + name: deprecated-image-check + version: "0.4" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: apply-tags + params: + - name: IMAGE + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: apply-tags + version: "0.1" + - name: validate-fbc + params: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + runAfter: + - build-image-index + taskRef: + name: validate-fbc + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: git-auth + optional: true + - name: netrc + optional: true diff --git a/auto-generated/pipelines/tekton.dev_v1_pipeline_maven-zip-build-oci-ta.yaml b/auto-generated/pipelines/tekton.dev_v1_pipeline_maven-zip-build-oci-ta.yaml new file mode 100644 index 0000000000..484bd8724d --- /dev/null +++ b/auto-generated/pipelines/tekton.dev_v1_pipeline_maven-zip-build-oci-ta.yaml @@ -0,0 +1,245 @@ +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + labels: + pipelines.openshift.io/runtime: generic + pipelines.openshift.io/strategy: maven-zip + pipelines.openshift.io/used-by: build-cloud + name: maven-zip-build-oci-ta +spec: + description: | + This pipeline will build the maven zip to oci-artifact while maintaining trust after pipeline customization. + + _Uses `prefetch-dependencies` to fetch all artifacts which will be the content of the maven zip, and then uses `build-maven-zip-oci-ta` to create zip and push it to quay.io as oci-artifact. Information is shared between tasks using OCI artifacts instead of PVCs. + This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/repository/konflux-ci/tekton-catalog/pipeline-maven-zip-build-oci-ta?tab=tags)_ + finally: + - name: show-sbom + params: + - name: IMAGE_URL + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + taskRef: + name: show-sbom + version: "0.1" + params: + - description: Source Repository URL + name: git-url + type: string + - default: "" + description: Revision of the Source Repository + name: revision + type: string + - description: Fully Qualified Output Image + name: output-image + type: string + - default: "false" + description: Force rebuild image + name: rebuild + type: string + - default: "false" + description: Skip checks against built image + name: skip-checks + type: string + - default: generic + description: Build dependencies to be prefetched by Cachi2 + name: prefetch-input + type: string + - default: "" + description: Image tag expiration time, time values could be something like 1h, + 2d, 3w for hours, days, and weeks, respectively. + name: image-expires-after + results: + - name: IMAGE_URL + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-oci-artifact.results.IMAGE_DIGEST) + - name: CHAINS-GIT_URL + value: $(tasks.clone-repository.results.url) + - name: CHAINS-GIT_COMMIT + value: $(tasks.clone-repository.results.commit) + tasks: + - name: init + params: + - name: image-url + value: $(params.output-image) + - name: rebuild + value: $(params.rebuild) + - name: skip-checks + value: $(params.skip-checks) + taskRef: + name: init + version: "0.2" + - name: clone-repository + params: + - name: url + value: $(params.git-url) + - name: revision + value: $(params.revision) + - name: ociStorage + value: $(params.output-image).git + - name: ociArtifactExpiresAfter + value: $(params.image-expires-after) + runAfter: + - init + taskRef: + name: git-clone-oci-ta + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: basic-auth + workspace: git-auth + - name: prefetch-dependencies + params: + - name: input + value: $(params.prefetch-input) + - name: SOURCE_ARTIFACT + value: $(tasks.clone-repository.results.SOURCE_ARTIFACT) + - name: ociStorage + value: $(params.output-image).prefetch + - name: ociArtifactExpiresAfter + value: $(params.image-expires-after) + runAfter: + - clone-repository + taskRef: + name: prefetch-dependencies-oci-ta + version: "0.1" + workspaces: + - name: git-basic-auth + workspace: git-auth + - name: netrc + workspace: netrc + - name: build-oci-artifact + params: + - name: IMAGE + value: $(params.output-image) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - prefetch-dependencies + taskRef: + name: build-maven-zip-oci-ta + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: [] + - name: sast-snyk-check + params: + - name: image-digest + value: $(tasks.build-oci-artifact.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-oci-artifact + taskRef: + name: sast-snyk-check-oci-ta + version: "0.3" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: [] + - name: sast-coverity-check + params: + - name: image-digest + value: $(tasks.build-oci-artifact.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - coverity-availability-check + taskRef: + name: sast-coverity-check-oci-ta + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - input: $(tasks.coverity-availability-check.results.STATUS) + operator: in + values: + - success + workspaces: [] + - name: coverity-availability-check + params: + - name: image-digest + value: $(tasks.build-oci-artifact.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-oci-artifact + taskRef: + name: coverity-availability-check-oci-ta + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: [] + - name: sast-shell-check + params: + - name: image-digest + value: $(tasks.build-oci-artifact.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-oci-artifact + taskRef: + name: sast-shell-check-oci-ta + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: [] + - name: sast-unicode-check + params: + - name: image-url + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + - name: SOURCE_ARTIFACT + value: $(tasks.prefetch-dependencies.results.SOURCE_ARTIFACT) + - name: CACHI2_ARTIFACT + value: $(tasks.prefetch-dependencies.results.CACHI2_ARTIFACT) + runAfter: + - build-oci-artifact + taskRef: + name: sast-shell-check-oci-ta + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: [] + workspaces: + - name: workspace + - name: git-auth + optional: true + - name: netrc + optional: true diff --git a/auto-generated/pipelines/tekton.dev_v1_pipeline_maven-zip-build.yaml b/auto-generated/pipelines/tekton.dev_v1_pipeline_maven-zip-build.yaml new file mode 100644 index 0000000000..4e2ecbbaaa --- /dev/null +++ b/auto-generated/pipelines/tekton.dev_v1_pipeline_maven-zip-build.yaml @@ -0,0 +1,250 @@ +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + labels: + pipelines.openshift.io/runtime: generic + pipelines.openshift.io/strategy: maven-zip + pipelines.openshift.io/used-by: build-cloud + name: maven-zip-build +spec: + description: | + This pipeline will build the maven zip to oci-artifact. + + _Uses `prefetch-dependencies` to fetch all artifacts which will be the content of the maven zip, and then uses `build-maven-zip` to create zip and push it to quay.io as oci-artifact. + This pipeline is pushed as a Tekton bundle to [quay.io](https://quay.io/repository/konflux-ci/tekton-catalog/pipeline-maven-zip-build?tab=tags)_ + finally: + - name: show-sbom + params: + - name: IMAGE_URL + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + taskRef: + name: show-sbom + version: "0.1" + - name: show-summary + params: + - name: pipelinerun-name + value: $(context.pipelineRun.name) + - name: git-url + value: $(tasks.clone-repository.results.url)?rev=$(tasks.clone-repository.results.commit) + - name: image-url + value: $(params.output-image) + - name: build-task-status + value: $(tasks.build-oci-artifact.status) + taskRef: + name: summary + version: "0.2" + workspaces: + - name: workspace + workspace: workspace + params: + - description: Source Repository URL + name: git-url + type: string + - default: "" + description: Revision of the Source Repository + name: revision + type: string + - description: Fully Qualified Output Image + name: output-image + type: string + - default: "false" + description: Force rebuild image + name: rebuild + type: string + - default: "false" + description: Skip checks against built image + name: skip-checks + type: string + - default: generic + description: Build dependencies to be prefetched by Cachi2 + name: prefetch-input + type: string + - default: "" + description: Image tag expiration time, time values could be something like 1h, + 2d, 3w for hours, days, and weeks, respectively. + name: image-expires-after + results: + - name: IMAGE_URL + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-oci-artifact.results.IMAGE_DIGEST) + - name: CHAINS-GIT_URL + value: $(tasks.clone-repository.results.url) + - name: CHAINS-GIT_COMMIT + value: $(tasks.clone-repository.results.commit) + tasks: + - name: init + params: + - name: image-url + value: $(params.output-image) + - name: rebuild + value: $(params.rebuild) + - name: skip-checks + value: $(params.skip-checks) + taskRef: + name: init + version: "0.2" + - name: clone-repository + params: + - name: url + value: $(params.git-url) + - name: revision + value: $(params.revision) + runAfter: + - init + taskRef: + name: git-clone + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: output + workspace: workspace + - name: basic-auth + workspace: git-auth + - name: prefetch-dependencies + params: + - name: input + value: $(params.prefetch-input) + runAfter: + - clone-repository + taskRef: + name: prefetch-dependencies + version: "0.1" + when: + - input: $(params.prefetch-input) + operator: notin + values: + - "" + workspaces: + - name: source + workspace: workspace + - name: git-basic-auth + workspace: git-auth + - name: netrc + workspace: netrc + - name: build-oci-artifact + params: + - name: IMAGE + value: $(params.output-image) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + runAfter: + - prefetch-dependencies + taskRef: + name: build-maven-zip + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: source + workspace: workspace + - name: sast-snyk-check + params: + - name: image-digest + value: $(tasks.build-oci-artifact.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + runAfter: + - build-oci-artifact + taskRef: + name: sast-snyk-check + version: "0.3" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + - name: sast-coverity-check + params: + - name: image-digest + value: $(tasks.build-oci-artifact.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + runAfter: + - coverity-availability-check + taskRef: + name: sast-coverity-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - input: $(tasks.coverity-availability-check.results.STATUS) + operator: in + values: + - success + workspaces: + - name: workspace + workspace: workspace + - name: coverity-availability-check + params: + - name: image-digest + value: $(tasks.build-oci-artifact.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + runAfter: + - build-oci-artifact + taskRef: + name: coverity-availability-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + - name: sast-shell-check + params: + - name: image-digest + value: $(tasks.build-oci-artifact.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + runAfter: + - build-oci-artifact + taskRef: + name: sast-shell-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + - name: sast-unicode-check + params: + - name: image-url + value: $(tasks.build-oci-artifact.results.IMAGE_URL) + runAfter: + - build-oci-artifact + taskRef: + name: sast-unicode-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + workspaces: + - name: workspace + - name: git-auth + optional: true + - name: netrc + optional: true diff --git a/auto-generated/pipelines/tekton.dev_v1_pipeline_tekton-bundle-builder.yaml b/auto-generated/pipelines/tekton.dev_v1_pipeline_tekton-bundle-builder.yaml new file mode 100644 index 0000000000..d6e3ffa1ba --- /dev/null +++ b/auto-generated/pipelines/tekton.dev_v1_pipeline_tekton-bundle-builder.yaml @@ -0,0 +1,269 @@ +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + labels: + pipelines.openshift.io/runtime: "" + pipelines.openshift.io/strategy: "" + pipelines.openshift.io/used-by: "" + name: tekton-bundle-builder +spec: + finally: + - name: show-summary + params: + - name: pipelinerun-name + value: $(context.pipelineRun.name) + - name: git-url + value: $(tasks.clone-repository.results.url)?rev=$(tasks.clone-repository.results.commit) + - name: image-url + value: $(params.output-image) + - name: build-task-status + value: $(tasks.build-image-index.status) + taskRef: + name: summary + version: "0.2" + workspaces: + - name: workspace + workspace: workspace + params: + - description: Source Repository URL + name: git-url + type: string + - default: "" + description: Revision of the Source Repository + name: revision + type: string + - description: Fully Qualified Output Image + name: output-image + type: string + - default: . + description: Path to the source code of an application's component from where + to build image. + name: path-context + type: string + - default: Dockerfile + description: Path to the Dockerfile inside the context specified by parameter + path-context + name: dockerfile + type: string + - default: "false" + description: Force rebuild image + name: rebuild + type: string + - default: "false" + description: Skip checks against built image + name: skip-checks + type: string + - default: "false" + description: Execute the build with network isolation + name: hermetic + type: string + - default: "" + description: Build dependencies to be prefetched by Cachi2 + name: prefetch-input + type: string + - default: "" + description: Image tag expiration time, time values could be something like 1h, + 2d, 3w for hours, days, and weeks, respectively. + name: image-expires-after + - default: "false" + description: Build a source image. + name: build-source-image + type: string + - default: "false" + description: Add built image into an OCI image index + name: build-image-index + type: string + results: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: CHAINS-GIT_URL + value: $(tasks.clone-repository.results.url) + - name: CHAINS-GIT_COMMIT + value: $(tasks.clone-repository.results.commit) + tasks: + - name: init + params: + - name: image-url + value: $(params.output-image) + - name: rebuild + value: $(params.rebuild) + - name: skip-checks + value: $(params.skip-checks) + taskRef: + name: init + version: "0.2" + - name: clone-repository + params: + - name: url + value: $(params.git-url) + - name: revision + value: $(params.revision) + runAfter: + - init + taskRef: + name: git-clone + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: output + workspace: workspace + - name: basic-auth + workspace: git-auth + - name: prefetch-dependencies + params: + - name: input + value: $(params.prefetch-input) + runAfter: + - clone-repository + taskRef: + name: prefetch-dependencies + version: "0.1" + when: + - input: $(params.prefetch-input) + operator: notin + values: + - "" + workspaces: + - name: source + workspace: workspace + - name: git-basic-auth + workspace: git-auth + - name: netrc + workspace: netrc + - name: build-container + params: + - name: IMAGE + value: $(params.output-image) + - name: CONTEXT + value: $(params.path-context) + runAfter: + - prefetch-dependencies + taskRef: + name: tkn-bundle + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: source + workspace: workspace + - name: build-image-index + params: + - name: IMAGE + value: $(params.output-image) + - name: COMMIT_SHA + value: $(tasks.clone-repository.results.commit) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + - name: ALWAYS_BUILD_INDEX + value: $(params.build-image-index) + - name: IMAGES + value: + - $(tasks.build-container.results.IMAGE_URL)@$(tasks.build-container.results.IMAGE_DIGEST) + runAfter: + - build-container + taskRef: + name: build-image-index + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + - name: sast-coverity-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - coverity-availability-check + taskRef: + name: sast-coverity-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - input: $(tasks.coverity-availability-check.results.STATUS) + operator: in + values: + - success + workspaces: + - name: workspace + workspace: workspace + - name: sast-unicode-check + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: sast-unicode-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + - name: apply-tags + params: + - name: IMAGE + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: apply-tags + version: "0.1" + - name: push-dockerfile + params: + - name: IMAGE + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: DOCKERFILE + value: $(params.dockerfile) + - name: CONTEXT + value: $(params.path-context) + runAfter: + - build-image-index + taskRef: + name: push-dockerfile + version: "0.1" + workspaces: + - name: workspace + workspace: workspace + - name: rpms-signature-scan + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + runAfter: + - build-image-index + taskRef: + name: rpms-signature-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + - name: git-auth + optional: true + - name: netrc + optional: true diff --git a/auto-generated/pipelines/template-build/tekton.dev_v1_pipeline_template-build.yaml b/auto-generated/pipelines/template-build/tekton.dev_v1_pipeline_template-build.yaml new file mode 100644 index 0000000000..5d7f4c8c7e --- /dev/null +++ b/auto-generated/pipelines/template-build/tekton.dev_v1_pipeline_template-build.yaml @@ -0,0 +1,410 @@ +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + labels: + pipelines.openshift.io/runtime: "" + pipelines.openshift.io/strategy: "" + pipelines.openshift.io/used-by: "" + name: template-build +spec: + finally: + - name: show-sbom + params: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + taskRef: + name: show-sbom + version: "0.1" + - name: show-summary + params: + - name: pipelinerun-name + value: $(context.pipelineRun.name) + - name: git-url + value: $(tasks.clone-repository.results.url)?rev=$(tasks.clone-repository.results.commit) + - name: image-url + value: $(params.output-image) + - name: build-task-status + value: $(tasks.build-image-index.status) + taskRef: + name: summary + version: "0.2" + workspaces: + - name: workspace + workspace: workspace + params: + - description: Source Repository URL + name: git-url + type: string + - default: "" + description: Revision of the Source Repository + name: revision + type: string + - description: Fully Qualified Output Image + name: output-image + type: string + - default: . + description: Path to the source code of an application's component from where + to build image. + name: path-context + type: string + - default: Dockerfile + description: Path to the Dockerfile inside the context specified by parameter + path-context + name: dockerfile + type: string + - default: "false" + description: Force rebuild image + name: rebuild + type: string + - default: "false" + description: Skip checks against built image + name: skip-checks + type: string + - default: "false" + description: Execute the build with network isolation + name: hermetic + type: string + - default: "" + description: Build dependencies to be prefetched by Cachi2 + name: prefetch-input + type: string + - default: "" + description: Image tag expiration time, time values could be something like 1h, + 2d, 3w for hours, days, and weeks, respectively. + name: image-expires-after + - default: "false" + description: Build a source image. + name: build-source-image + type: string + - default: "false" + description: Add built image into an OCI image index + name: build-image-index + type: string + results: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: CHAINS-GIT_URL + value: $(tasks.clone-repository.results.url) + - name: CHAINS-GIT_COMMIT + value: $(tasks.clone-repository.results.commit) + tasks: + - name: init + params: + - name: image-url + value: $(params.output-image) + - name: rebuild + value: $(params.rebuild) + - name: skip-checks + value: $(params.skip-checks) + taskRef: + name: init + version: "0.2" + - name: clone-repository + params: + - name: url + value: $(params.git-url) + - name: revision + value: $(params.revision) + runAfter: + - init + taskRef: + name: git-clone + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: output + workspace: workspace + - name: basic-auth + workspace: git-auth + - name: prefetch-dependencies + params: + - name: input + value: $(params.prefetch-input) + runAfter: + - clone-repository + taskRef: + name: prefetch-dependencies + version: "0.1" + when: + - input: $(params.prefetch-input) + operator: notin + values: + - "" + workspaces: + - name: source + workspace: workspace + - name: git-basic-auth + workspace: git-auth + - name: netrc + workspace: netrc + - name: build-container + runAfter: + - prefetch-dependencies + taskRef: + name: $REPLACE_ME + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + workspaces: + - name: source + workspace: workspace + - name: build-image-index + params: + - name: IMAGE + value: $(params.output-image) + - name: COMMIT_SHA + value: $(tasks.clone-repository.results.commit) + - name: IMAGE_EXPIRES_AFTER + value: $(params.image-expires-after) + - name: ALWAYS_BUILD_INDEX + value: $(params.build-image-index) + - name: IMAGES + value: + - $(tasks.build-container.results.IMAGE_URL)@$(tasks.build-container.results.IMAGE_DIGEST) + runAfter: + - build-container + taskRef: + name: build-image-index + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + - name: build-source-image + params: + - name: BINARY_IMAGE + value: $(params.output-image) + runAfter: + - build-image-index + taskRef: + name: source-build + version: "0.1" + when: + - input: $(tasks.init.results.build) + operator: in + values: + - "true" + - input: $(params.build-source-image) + operator: in + values: + - "true" + workspaces: + - name: workspace + workspace: workspace + - name: deprecated-base-image-check + params: + - name: IMAGE_URL + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + runAfter: + - build-image-index + taskRef: + name: deprecated-image-check + version: "0.4" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: clair-scan + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: clair-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: ecosystem-cert-preflight-checks + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: ecosystem-cert-preflight-checks + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: sast-snyk-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: sast-snyk-check + version: "0.3" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + - name: clamav-scan + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: clamav-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - name: sast-coverity-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - coverity-availability-check + taskRef: + name: sast-coverity-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + - input: $(tasks.coverity-availability-check.results.STATUS) + operator: in + values: + - success + workspaces: + - name: workspace + workspace: workspace + - name: coverity-availability-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: coverity-availability-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + - name: sast-shell-check + params: + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: sast-shell-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + - name: sast-unicode-check + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: sast-unicode-check + version: "0.1" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + workspace: workspace + - name: apply-tags + params: + - name: IMAGE + value: $(tasks.build-image-index.results.IMAGE_URL) + runAfter: + - build-image-index + taskRef: + name: apply-tags + version: "0.1" + - name: push-dockerfile + params: + - name: IMAGE + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + - name: DOCKERFILE + value: $(params.dockerfile) + - name: CONTEXT + value: $(params.path-context) + runAfter: + - build-image-index + taskRef: + name: push-dockerfile + version: "0.1" + workspaces: + - name: workspace + workspace: workspace + - name: rpms-signature-scan + params: + - name: image-url + value: $(tasks.build-image-index.results.IMAGE_URL) + - name: image-digest + value: $(tasks.build-image-index.results.IMAGE_DIGEST) + runAfter: + - build-image-index + taskRef: + name: rpms-signature-scan + version: "0.2" + when: + - input: $(params.skip-checks) + operator: in + values: + - "false" + workspaces: + - name: workspace + - name: git-auth + optional: true + - name: netrc + optional: true diff --git a/auto-generated/task/build-image-index/0.1/tekton.dev_v1_task_build-image-index.yaml b/auto-generated/task/build-image-index/0.1/tekton.dev_v1_task_build-image-index.yaml new file mode 100644 index 0000000000..1fcd501808 --- /dev/null +++ b/auto-generated/task/build-image-index/0.1/tekton.dev_v1_task_build-image-index.yaml @@ -0,0 +1,222 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + annotations: + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: image-build, konflux + labels: + app.kubernetes.io/version: "0.1" + build.appstudio.redhat.com/build_type: docker + name: build-image-index +spec: + description: This takes existing Image Manifests and combines them in an Image Index. + params: + - description: The target image and tag where the image will be pushed to. + name: IMAGE + type: string + - default: "true" + description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS + registry) + name: TLSVERIFY + type: string + - default: "" + description: The commit the image is built from. + name: COMMIT_SHA + type: string + - description: List of Image Manifests to be referenced by the Image Index + name: IMAGES + type: array + - default: "" + description: Delete image tag after specified time resulting in garbage collection + of the digest. Empty means to keep the image tag. Time values could be something + like 1h, 2d, 3w for hours, days, and weeks, respectively. + name: IMAGE_EXPIRES_AFTER + type: string + - default: "true" + description: Build an image index even if IMAGES is of length 1. Default true. + If the image index generation is skipped, the task will forward values for params.IMAGES[0] + to results.IMAGE_*. In order to properly set all results, use the repository:tag@sha256:digest + format for the IMAGES parameter. + name: ALWAYS_BUILD_INDEX + type: string + - default: vfs + description: Storage driver to configure for buildah + name: STORAGE_DRIVER + type: string + results: + - description: Digest of the image just built + name: IMAGE_DIGEST + - description: Image repository and tag where the built image was pushed + name: IMAGE_URL + - description: List of all referenced image manifests + name: IMAGES + - description: Image reference of the built image containing both the repository + and the digest + name: IMAGE_REF + - description: Reference of SBOM blob digest to enable digest-based verification + from provenance + name: SBOM_BLOB_URL + type: string + stepTemplate: + env: + - name: BUILDAH_FORMAT + value: oci + - name: COMMIT_SHA + value: $(params.COMMIT_SHA) + - name: IMAGE + value: $(params.IMAGE) + - name: TLSVERIFY + value: $(params.TLSVERIFY) + - name: ALWAYS_BUILD_INDEX + value: $(params.ALWAYS_BUILD_INDEX) + - name: STORAGE_DRIVER + value: $(params.STORAGE_DRIVER) + volumeMounts: + - mountPath: /index-build-data + name: shared-dir + steps: + - args: + - $(params.IMAGES[*]) + computeResources: + limits: + memory: 4Gi + requests: + cpu: 250m + memory: 512Mi + image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: build + script: | + #!/bin/bash + # Fixing group permission on /var/lib/containers + set -eu + set -o pipefail + chown root:root /var/lib/containers + + sed -i 's/^\s*short-name-mode\s*=\s*.*/short-name-mode = "disabled"/' /etc/containers/registries.conf + + if [[ $# -ne 1 && "$ALWAYS_BUILD_INDEX" != "true" ]]; then + echo "Skipping image index generation while supplying multiple image inputs is unsupported." + exit 2 + fi + + buildah manifest create "$IMAGE" + for i in $@ + do + TOADD="$i" + TOADD_URL="$(echo "$i" | cut -d@ -f1)" + TOADD_DIGEST="$(echo "$i" | cut -d@ -f2)" + if [[ $(echo "$i" | tr -cd ":" | wc -c) == 2 ]]; then + #format is repository:tag@sha256:digest + #we need to remove the tag, and just reference the digest + #as tag + digest is not supported + TOADD_REPOSITORY="$(echo "$i" | cut -d: -f1)" + TOADD="${TOADD_REPOSITORY}@${TOADD_DIGEST}" + fi + if [[ "$ALWAYS_BUILD_INDEX" != "true" ]]; then + echo "Skipping image index generation. Returning results for $TOADD." + echo -n "${TOADD_URL}" > "$(results.IMAGE_URL.path)" + echo -n "${TOADD_DIGEST}" > "$(results.IMAGE_DIGEST.path)" + echo -n "${TOADD}" > "$(results.IMAGES.path)" + exit 0 + fi + echo "Adding $TOADD" + buildah manifest add $IMAGE "docker://$TOADD" --all + done + + status=-1 + max_run=5 + sleep_sec=10 + for run in $(seq 1 $max_run); do + status=0 + [ "$run" -gt 1 ] && sleep $sleep_sec + echo "Pushing image to registry" + buildah manifest push \ + --tls-verify=$TLSVERIFY \ + --digestfile image-digest $IMAGE \ + docker://$IMAGE && break || status=$? + done + if [ "$status" -ne 0 ]; then + echo "Failed to push image to registry after ${max_run} tries" + exit 1 + fi + + INDEX_REPOSITORY="$(echo "$IMAGE" | cut -d@ -f1 | cut -d: -f1)" + MANIFEST_DIGESTS=$(buildah manifest inspect "$IMAGE" | jq -er ".manifests[].digest") + image_manifests="" + for i in $MANIFEST_DIGESTS + do + image_manifests="${image_manifests} ${INDEX_REPOSITORY}@${i}," + done + + cat image-digest | tee $(results.IMAGE_DIGEST.path) + echo -n "$IMAGE" | tee "$(results.IMAGE_URL.path)" + { + echo -n "${IMAGE}@" + cat "image-digest" + } > "$(results.IMAGE_REF.path)" + echo -n "${image_manifests:1:-1}" > "$(results.IMAGES.path)" + + IMAGE_DIGEST=$(cat image-digest) + + INDEX_IMAGE_PULLSPEC="${IMAGE}@${IMAGE_DIGEST}" + buildah manifest inspect "$INDEX_IMAGE_PULLSPEC" > /index-build-data/manifest_data.json + securityContext: + capabilities: + add: + - SETFCAP + - computeResources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + image: quay.io/redhat-appstudio/sbom-utility-scripts-image@sha256:9f1fd11d9c3c517ecc112d192ad361d16ecf6ce00b83b109c93cf3d1c644a357 + name: create-sbom + script: | + #!/bin/bash + set -e + + MANIFEST_DATA_FILE="/index-build-data/manifest_data.json" + if [ ! -f "$MANIFEST_DATA_FILE" ]; then + echo "The manifest_data.json file does not exist. Skipping the SBOM creation..." + exit 0 + fi + + IMAGE_URL="$(cat "$(results.IMAGE_URL.path)")" + IMAGE_DIGEST="$(cat "$(results.IMAGE_DIGEST.path)")" + echo "Creating SBOM result file..." + python3 index_image_sbom_script.py \ + --image-index-url "$IMAGE_URL" \ + --image-index-digest "$IMAGE_DIGEST" \ + --inspect-input-file "$MANIFEST_DATA_FILE" \ + --output-path /index-build-data/sbom-results.json + - computeResources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + image: quay.io/konflux-ci/appstudio-utils:48c311af02858e2422d6229600e9959e496ddef1@sha256:91ddd999271f65d8ec8487b10f3dd378f81aa894e11b9af4d10639fd52bba7e8 + name: upload-sbom + script: | + #!/bin/bash + set -e + + SBOM_RESULT_FILE="/index-build-data/sbom-results.json" + if [ ! -f "$SBOM_RESULT_FILE" ]; then + echo "The sbom_results.json file does not exists. Skipping the SBOM upload..." + exit 0 + fi + + cosign attach sbom --sbom "$SBOM_RESULT_FILE" --type spdx "$(cat "$(results.IMAGE_REF.path)")" + + # Remove tag from IMAGE while allowing registry to contain a port number. + sbom_repo="${IMAGE%:*}" + sbom_digest="$(sha256sum "$SBOM_RESULT_FILE" | cut -d' ' -f1)" + # The SBOM_BLOB_URL is created by `cosign attach sbom`. + echo -n "${sbom_repo}@sha256:${sbom_digest}" | tee "$(results.SBOM_BLOB_URL.path)" + volumes: + - emptyDir: {} + name: shared-dir diff --git a/auto-generated/task/build-image-manifest/0.1/tekton.dev_v1_task_build-image-manifest.yaml b/auto-generated/task/build-image-manifest/0.1/tekton.dev_v1_task_build-image-manifest.yaml new file mode 100644 index 0000000000..edc4562cf3 --- /dev/null +++ b/auto-generated/task/build-image-manifest/0.1/tekton.dev_v1_task_build-image-manifest.yaml @@ -0,0 +1,222 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + annotations: + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: image-build, konflux + labels: + app.kubernetes.io/version: "0.1" + build.appstudio.redhat.com/build_type: docker + name: build-image-manifest +spec: + description: This takes existing Image Manifests and combines them in an Image Index. + params: + - description: The target image and tag where the image will be pushed to. + name: IMAGE + type: string + - default: "true" + description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS + registry) + name: TLSVERIFY + type: string + - default: "" + description: The commit the image is built from. + name: COMMIT_SHA + type: string + - description: List of Image Manifests to be referenced by the Image Index + name: IMAGES + type: array + - default: "" + description: Delete image tag after specified time resulting in garbage collection + of the digest. Empty means to keep the image tag. Time values could be something + like 1h, 2d, 3w for hours, days, and weeks, respectively. + name: IMAGE_EXPIRES_AFTER + type: string + - default: "true" + description: Build an image index even if IMAGES is of length 1. Default true. + If the image index generation is skipped, the task will forward values for params.IMAGES[0] + to results.IMAGE_*. In order to properly set all results, use the repository:tag@sha256:digest + format for the IMAGES parameter. + name: ALWAYS_BUILD_INDEX + type: string + - default: vfs + description: Storage driver to configure for buildah + name: STORAGE_DRIVER + type: string + results: + - description: Digest of the image just built + name: IMAGE_DIGEST + - description: Image repository and tag where the built image was pushed + name: IMAGE_URL + - description: List of all referenced image manifests + name: IMAGES + - description: Image reference of the built image containing both the repository + and the digest + name: IMAGE_REF + - description: Reference of SBOM blob digest to enable digest-based verification + from provenance + name: SBOM_BLOB_URL + type: string + stepTemplate: + env: + - name: BUILDAH_FORMAT + value: oci + - name: COMMIT_SHA + value: $(params.COMMIT_SHA) + - name: IMAGE + value: $(params.IMAGE) + - name: TLSVERIFY + value: $(params.TLSVERIFY) + - name: ALWAYS_BUILD_INDEX + value: $(params.ALWAYS_BUILD_INDEX) + - name: STORAGE_DRIVER + value: $(params.STORAGE_DRIVER) + volumeMounts: + - mountPath: /index-build-data + name: shared-dir + steps: + - args: + - $(params.IMAGES[*]) + computeResources: + limits: + memory: 4Gi + requests: + cpu: 250m + memory: 512Mi + image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: build + script: | + #!/bin/bash + # Fixing group permission on /var/lib/containers + set -eu + set -o pipefail + chown root:root /var/lib/containers + + sed -i 's/^\s*short-name-mode\s*=\s*.*/short-name-mode = "disabled"/' /etc/containers/registries.conf + + if [[ $# -ne 1 && "$ALWAYS_BUILD_INDEX" != "true" ]]; then + echo "Skipping image index generation while supplying multiple image inputs is unsupported." + exit 2 + fi + + buildah manifest create "$IMAGE" + for i in $@ + do + TOADD="$i" + TOADD_URL="$(echo "$i" | cut -d@ -f1)" + TOADD_DIGEST="$(echo "$i" | cut -d@ -f2)" + if [[ $(echo "$i" | tr -cd ":" | wc -c) == 2 ]]; then + #format is repository:tag@sha256:digest + #we need to remove the tag, and just reference the digest + #as tag + digest is not supported + TOADD_REPOSITORY="$(echo "$i" | cut -d: -f1)" + TOADD="${TOADD_REPOSITORY}@${TOADD_DIGEST}" + fi + if [[ "$ALWAYS_BUILD_INDEX" != "true" ]]; then + echo "Skipping image index generation. Returning results for $TOADD." + echo -n "${TOADD_URL}" > "$(results.IMAGE_URL.path)" + echo -n "${TOADD_DIGEST}" > "$(results.IMAGE_DIGEST.path)" + echo -n "${TOADD}" > "$(results.IMAGES.path)" + exit 0 + fi + echo "Adding $TOADD" + buildah manifest add $IMAGE "docker://$TOADD" --all + done + + status=-1 + max_run=5 + sleep_sec=10 + for run in $(seq 1 $max_run); do + status=0 + [ "$run" -gt 1 ] && sleep $sleep_sec + echo "Pushing image to registry" + buildah manifest push \ + --tls-verify=$TLSVERIFY \ + --digestfile image-digest $IMAGE \ + docker://$IMAGE && break || status=$? + done + if [ "$status" -ne 0 ]; then + echo "Failed to push image to registry after ${max_run} tries" + exit 1 + fi + + INDEX_REPOSITORY="$(echo "$IMAGE" | cut -d@ -f1 | cut -d: -f1)" + MANIFEST_DIGESTS=$(buildah manifest inspect "$IMAGE" | jq -er ".manifests[].digest") + image_manifests="" + for i in $MANIFEST_DIGESTS + do + image_manifests="${image_manifests} ${INDEX_REPOSITORY}@${i}," + done + + cat image-digest | tee $(results.IMAGE_DIGEST.path) + echo -n "$IMAGE" | tee "$(results.IMAGE_URL.path)" + { + echo -n "${IMAGE}@" + cat "image-digest" + } > "$(results.IMAGE_REF.path)" + echo -n "${image_manifests:1:-1}" > "$(results.IMAGES.path)" + + IMAGE_DIGEST=$(cat image-digest) + + INDEX_IMAGE_PULLSPEC="${IMAGE}@${IMAGE_DIGEST}" + buildah manifest inspect "$INDEX_IMAGE_PULLSPEC" > /index-build-data/manifest_data.json + securityContext: + capabilities: + add: + - SETFCAP + - computeResources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + image: quay.io/redhat-appstudio/sbom-utility-scripts-image@sha256:9f1fd11d9c3c517ecc112d192ad361d16ecf6ce00b83b109c93cf3d1c644a357 + name: create-sbom + script: | + #!/bin/bash + set -e + + MANIFEST_DATA_FILE="/index-build-data/manifest_data.json" + if [ ! -f "$MANIFEST_DATA_FILE" ]; then + echo "The manifest_data.json file does not exist. Skipping the SBOM creation..." + exit 0 + fi + + IMAGE_URL="$(cat "$(results.IMAGE_URL.path)")" + IMAGE_DIGEST="$(cat "$(results.IMAGE_DIGEST.path)")" + echo "Creating SBOM result file..." + python3 index_image_sbom_script.py \ + --image-index-url "$IMAGE_URL" \ + --image-index-digest "$IMAGE_DIGEST" \ + --inspect-input-file "$MANIFEST_DATA_FILE" \ + --output-path /index-build-data/sbom-results.json + - computeResources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + image: quay.io/konflux-ci/appstudio-utils:48c311af02858e2422d6229600e9959e496ddef1@sha256:91ddd999271f65d8ec8487b10f3dd378f81aa894e11b9af4d10639fd52bba7e8 + name: upload-sbom + script: | + #!/bin/bash + set -e + + SBOM_RESULT_FILE="/index-build-data/sbom-results.json" + if [ ! -f "$SBOM_RESULT_FILE" ]; then + echo "The sbom_results.json file does not exists. Skipping the SBOM upload..." + exit 0 + fi + + cosign attach sbom --sbom "$SBOM_RESULT_FILE" --type spdx "$(cat "$(results.IMAGE_REF.path)")" + + # Remove tag from IMAGE while allowing registry to contain a port number. + sbom_repo="${IMAGE%:*}" + sbom_digest="$(sha256sum "$SBOM_RESULT_FILE" | cut -d' ' -f1)" + # The SBOM_BLOB_URL is created by `cosign attach sbom`. + echo -n "${sbom_repo}@sha256:${sbom_digest}" | tee "$(results.SBOM_BLOB_URL.path)" + volumes: + - emptyDir: {} + name: shared-dir diff --git a/auto-generated/task/build-maven-zip-oci-ta/0.1/tekton.dev_v1_task_build-maven-zip-oci-ta.yaml b/auto-generated/task/build-maven-zip-oci-ta/0.1/tekton.dev_v1_task_build-maven-zip-oci-ta.yaml new file mode 100644 index 0000000000..caafad41a3 --- /dev/null +++ b/auto-generated/task/build-maven-zip-oci-ta/0.1/tekton.dev_v1_task_build-maven-zip-oci-ta.yaml @@ -0,0 +1,207 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + annotations: + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: maven-build, konflux + labels: + app.kubernetes.io/version: "0.1" + build.appstudio.redhat.com/build_type: maven-zip + name: build-maven-zip-oci-ta +spec: + description: |- + Build-maven-zip task builds prefetched maven artifacts into a OCI-artifact with zip bundle and pushes the OCI-artifact into container registry. + In addition it will use the SBOM file in prefetch-task, pushes the SBOM file to same registry of zip oci-artifact using cosign tool. + Note that this task needs the output of prefetch-dependencies task. If it is not activated, there will not be any output from this task. + params: + - default: "" + description: The Trusted Artifact URI pointing to the artifact with the prefetched + dependencies. + name: CACHI2_ARTIFACT + type: string + - default: maven-repository + description: The zip bundle file name of archived artifacts + name: FILE_NAME + type: string + - description: Reference of the OCI-Artifact this build task will produce. + name: IMAGE + type: string + - default: "" + description: Delete image tag after specified time. Empty means to keep the image + tag. Time values could be something like 1h, 2d, 3w for hours, days, and weeks, + respectively. + name: IMAGE_EXPIRES_AFTER + type: string + - default: maven-repository + description: The root directory of the artifacts under the prefetched directory. + Will be kept in the maven zip as the top directory for all artifacts. + name: PREFETCH_ROOT + type: string + - default: ca-bundle.crt + description: The name of the key in the ConfigMap that contains the CA bundle + data. + name: caTrustConfigMapKey + type: string + - default: trusted-ca + description: The name of the ConfigMap to read CA bundle data from. + name: caTrustConfigMapName + type: string + results: + - description: Digest of the OCI-Artifact just built + name: IMAGE_DIGEST + - description: OCI-Artifact reference of the built OCI-Artifact + name: IMAGE_REF + - description: OCI-Artifact repository and tag where the built OCI-Artifact was + pushed + name: IMAGE_URL + - description: Reference of SBOM blob digest to enable digest-based verification + from provenance + name: SBOM_BLOB_URL + type: string + stepTemplate: + env: + - name: FILE_NAME + value: $(params.FILE_NAME) + - name: IMAGE + value: $(params.IMAGE) + - name: IMAGE_EXPIRES_AFTER + value: $(params.IMAGE_EXPIRES_AFTER) + - name: PKG_ROOT + value: $(params.PREFETCH_ROOT) + volumeMounts: + - mountPath: /shared + name: shared + - mountPath: /var/workdir + name: workdir + steps: + - args: + - use + - $(params.CACHI2_ARTIFACT)=/var/workdir/cachi2 + image: quay.io/redhat-appstudio/build-trusted-artifacts:latest@sha256:b31dc501d5068e30621e51681a2921d4e43f5a030ab78c8991f83a5e774534a3 + name: use-trusted-artifact + - computeResources: + limits: + cpu: "4" + memory: 8Gi + requests: + cpu: "1" + memory: 2Gi + image: quay.io/konflux-ci/appstudio-utils@sha256:426143910a9fe57a340143f8c19f1ad8e7103749be84096c3faacc20b260b15a + name: prepare + script: | + #!/bin/bash + set -euo pipefail + # Generate checksums for all maven artifact files. It will ignore the checksum files + # and signature files if they existed there + pkgpath="/var/workdir/cachi2/output/deps/generic" + if [ -d "$pkgpath/${PKG_ROOT}" ]; then + echo "Generating checksums for artifacts" + while IFS= read -r -d '' f; do + md5sum "$f" | awk '{print $1}' >"$f.md5" + sha1sum "$f" | awk '{print $1}' >"$f.sha1" + sha256sum "$f" | awk '{print $1}' >"$f.sha256" + done < <(find "$pkgpath/${PKG_ROOT}" -type f ! -name "*.md5" \ + ! -name "*.sha1" ! -name "*.sha128" ! -name "*.sha256" \ + ! -name "*.sha512" ! -name "*.asc" -print0) + # Bundle the artifacts and checksums together into a zip file + cd "$pkgpath" + echo "create maven zip to /var/workdir/cachi2/output/${FILE_NAME}.zip" + zip -rq "${FILE_NAME}.zip" "${PKG_ROOT}" + mv "${FILE_NAME}.zip" "/shared/${FILE_NAME}.zip" + else + echo "No ${PKG_ROOT} dir found, can not generate maven zip!" + exit 1 + fi + securityContext: + capabilities: + add: + - SETFCAP + workingDir: /var/workdir + - computeResources: + limits: + cpu: "4" + memory: 8Gi + requests: + cpu: "1" + memory: 2Gi + image: quay.io/konflux-ci/oras:latest@sha256:66ccc8c3698304036a42739f6e1836f3399a46645be2d3c5d6d456b9c79fff40 + name: build + script: | + #!/bin/bash + set -euo pipefail + if [ -f "/shared/${FILE_NAME}.zip" ]; then + mv "/shared/${FILE_NAME}.zip" "./${FILE_NAME}.zip" + select-oci-auth "$IMAGE" >auth.json + [ -n "$IMAGE_EXPIRES_AFTER" ] && EXPIRE_LABEL=("--annotation" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + oras push "$IMAGE" \ + --registry-config auth.json \ + "${EXPIRE_LABEL[@]}" \ + --artifact-type application/vnd.maven+zip "${FILE_NAME}.zip" + RESULTING_DIGEST=$(oras resolve --registry-config auth.json "${IMAGE}") + echo -n "$IMAGE" | tee "$(results.IMAGE_URL.path)" + echo -n "$RESULTING_DIGEST" | tee "$(results.IMAGE_DIGEST.path)" + echo -n "${IMAGE}@${RESULTING_DIGEST}" | tee "$(results.IMAGE_REF.path)" + else + echo "The maven zip file is not found!" + exit 1 + fi + + # Save the SBOM produced by Cachi2 so it can be merged into the final SBOM later + if [ -f "/var/workdir/cachi2/output/bom.json" ]; then + cp -vf "/var/workdir/cachi2/output/bom.json" ./sbom-cyclonedx.json + else + echo "The SBOM file for fetched artifacts is not found!" + exit 1 + fi + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: /var/workdir + - computeResources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + image: quay.io/konflux-ci/appstudio-utils:ab6b0b8e40e440158e7288c73aff1cf83a2cc8a9@sha256:24179f0efd06c65d16868c2d7eb82573cce8e43533de6cea14fec3b7446e0b14 + name: upload-sbom + script: | + #!/bin/bash + set -euo pipefail + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + cosign attach sbom --sbom sbom-cyclonedx.json --type cyclonedx "$IMAGE" + + # Remove tag from IMAGE while allowing registry to contain a port number. + sbom_repo="${IMAGE%:*}" + sbom_tag="sha256-$( <"$(results.IMAGE_DIGEST.path)" cut -d: -f2).sbom" + # The SBOM_BLOB_URL is created by `cosign attach sbom`. + echo -n "${sbom_repo}:${sbom_tag}" | tee "$(results.SBOM_BLOB_URL.path)" + volumeMounts: + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: /var/workdir + volumes: + - emptyDir: {} + name: shared + - configMap: + items: + - key: $(params.caTrustConfigMapKey) + path: ca-bundle.crt + name: $(params.caTrustConfigMapName) + optional: true + name: trusted-ca + - emptyDir: {} + name: workdir diff --git a/auto-generated/task/build-maven-zip/0.1/tekton.dev_v1_task_build-maven-zip.yaml b/auto-generated/task/build-maven-zip/0.1/tekton.dev_v1_task_build-maven-zip.yaml new file mode 100644 index 0000000000..a18117e4bc --- /dev/null +++ b/auto-generated/task/build-maven-zip/0.1/tekton.dev_v1_task_build-maven-zip.yaml @@ -0,0 +1,197 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + annotations: + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: maven-build, konflux + labels: + app.kubernetes.io/version: "0.1" + build.appstudio.redhat.com/build_type: maven-zip + name: build-maven-zip +spec: + description: |- + Build-maven-zip task builds prefetched maven artifacts into a OCI-artifact with zip bundle and pushes the OCI-artifact into container registry. + In addition it will use the SBOM file in prefetch-task, pushes the SBOM file to same registry of zip oci-artifact using cosign tool. + Note that this task needs the output of prefetch-dependencies task. If it is not activated, there will not be any output from this task. + params: + - description: Reference of the OCI-Artifact this build task will produce. + name: IMAGE + type: string + - default: maven-repository + description: The root directory of the artifacts under the prefetched directory. + Will be kept in the maven zip as the top directory for all artifacts. + name: PREFETCH_ROOT + type: string + - default: maven-repository + description: The zip bundle file name of archived artifacts + name: FILE_NAME + type: string + - default: "" + description: Delete image tag after specified time. Empty means to keep the image + tag. Time values could be something like 1h, 2d, 3w for hours, days, and weeks, + respectively. + name: IMAGE_EXPIRES_AFTER + type: string + - default: trusted-ca + description: The name of the ConfigMap to read CA bundle data from. + name: caTrustConfigMapName + type: string + - default: ca-bundle.crt + description: The name of the key in the ConfigMap that contains the CA bundle + data. + name: caTrustConfigMapKey + type: string + results: + - description: Digest of the OCI-Artifact just built + name: IMAGE_DIGEST + - description: OCI-Artifact repository and tag where the built OCI-Artifact was + pushed + name: IMAGE_URL + - description: OCI-Artifact reference of the built OCI-Artifact + name: IMAGE_REF + - description: Reference of SBOM blob digest to enable digest-based verification + from provenance + name: SBOM_BLOB_URL + type: string + stepTemplate: + env: + - name: IMAGE + value: $(params.IMAGE) + - name: PKG_ROOT + value: $(params.PREFETCH_ROOT) + - name: FILE_NAME + value: $(params.FILE_NAME) + - name: IMAGE_EXPIRES_AFTER + value: $(params.IMAGE_EXPIRES_AFTER) + volumeMounts: + - mountPath: /shared + name: shared + steps: + - computeResources: + limits: + cpu: "4" + memory: 8Gi + requests: + cpu: "1" + memory: 2Gi + image: quay.io/konflux-ci/appstudio-utils@sha256:426143910a9fe57a340143f8c19f1ad8e7103749be84096c3faacc20b260b15a + name: prepare + script: | + #!/bin/bash + set -euo pipefail + # Generate checksums for all maven artifact files. It will ignore the checksum files + # and signature files if they existed there + pkgpath="$(workspaces.source.path)/cachi2/output/deps/generic" + if [ -d "$pkgpath/${PKG_ROOT}" ]; then + echo "Generating checksums for artifacts" + while IFS= read -r -d '' f + do + md5sum "$f" | awk '{print $1}'> "$f.md5" + sha1sum "$f" | awk '{print $1}'> "$f.sha1" + sha256sum "$f" | awk '{print $1}'> "$f.sha256" + done < <(find "$pkgpath/${PKG_ROOT}" -type f ! -name "*.md5" \ + ! -name "*.sha1" ! -name "*.sha128" ! -name "*.sha256" \ + ! -name "*.sha512" ! -name "*.asc" -print0) + # Bundle the artifacts and checksums together into a zip file + cd "$pkgpath" + echo "create maven zip to $(workspaces.source.path)/cachi2/output/${FILE_NAME}.zip" + zip -rq "${FILE_NAME}.zip" "${PKG_ROOT}" + mv "${FILE_NAME}.zip" "/shared/${FILE_NAME}.zip" + else + echo "No ${PKG_ROOT} dir found, can not generate maven zip!" + exit 1 + fi + securityContext: + capabilities: + add: + - SETFCAP + workingDir: $(workspaces.source.path) + - computeResources: + limits: + cpu: "4" + memory: 8Gi + requests: + cpu: "1" + memory: 2Gi + image: quay.io/konflux-ci/oras:latest@sha256:66ccc8c3698304036a42739f6e1836f3399a46645be2d3c5d6d456b9c79fff40 + name: build + script: | + #!/bin/bash + set -euo pipefail + if [ -f "/shared/${FILE_NAME}.zip" ]; then + mv "/shared/${FILE_NAME}.zip" "./${FILE_NAME}.zip" + select-oci-auth "$IMAGE" > auth.json + [ -n "$IMAGE_EXPIRES_AFTER" ] && EXPIRE_LABEL=("--annotation" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + oras push "$IMAGE" \ + --registry-config auth.json \ + "${EXPIRE_LABEL[@]}" \ + --artifact-type application/vnd.maven+zip "${FILE_NAME}.zip" + RESULTING_DIGEST=$(oras resolve --registry-config auth.json "${IMAGE}") + echo -n "$IMAGE" | tee "$(results.IMAGE_URL.path)" + echo -n "$RESULTING_DIGEST" | tee "$(results.IMAGE_DIGEST.path)" + echo -n "${IMAGE}@${RESULTING_DIGEST}" | tee "$(results.IMAGE_REF.path)" + else + echo "The maven zip file is not found!" + exit 1 + fi + + # Save the SBOM produced by Cachi2 so it can be merged into the final SBOM later + if [ -f "$(workspaces.source.path)/cachi2/output/bom.json" ]; then + cp -vf "$(workspaces.source.path)/cachi2/output/bom.json" ./sbom-cyclonedx.json + else + echo "The SBOM file for fetched artifacts is not found!" + exit 1 + fi + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + - computeResources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + image: quay.io/konflux-ci/appstudio-utils:ab6b0b8e40e440158e7288c73aff1cf83a2cc8a9@sha256:24179f0efd06c65d16868c2d7eb82573cce8e43533de6cea14fec3b7446e0b14 + name: upload-sbom + script: | + #!/bin/bash + set -euo pipefail + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + cosign attach sbom --sbom sbom-cyclonedx.json --type cyclonedx "$IMAGE" + + # Remove tag from IMAGE while allowing registry to contain a port number. + sbom_repo="${IMAGE%:*}" + sbom_tag="sha256-$(< "$(results.IMAGE_DIGEST.path)" cut -d: -f2).sbom" + # The SBOM_BLOB_URL is created by `cosign attach sbom`. + echo -n "${sbom_repo}:${sbom_tag}" | tee "$(results.SBOM_BLOB_URL.path)" + volumeMounts: + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + volumes: + - emptyDir: {} + name: shared + - configMap: + items: + - key: $(params.caTrustConfigMapKey) + path: ca-bundle.crt + name: $(params.caTrustConfigMapName) + optional: true + name: trusted-ca + workspaces: + - description: Workspace containing the source code to build. + name: source diff --git a/auto-generated/task/buildah-10gb/0.1/tekton.dev_v1_task_buildah-10gb.yaml b/auto-generated/task/buildah-10gb/0.1/tekton.dev_v1_task_buildah-10gb.yaml new file mode 100644 index 0000000000..80cd69d1b2 --- /dev/null +++ b/auto-generated/task/buildah-10gb/0.1/tekton.dev_v1_task_buildah-10gb.yaml @@ -0,0 +1,585 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + annotations: + build.appstudio.redhat.com/expires-on: "2025-01-21T00:00:00Z" + build.appstudio.redhat.com/expiry-message: 'Instead of using this task, switch + to buildah task (you can find latest bundle reference here: https://quay.io/repository/konflux-ci/tekton-catalog/task-buildah) + and configure build step resources as described in the doc: https://konflux-ci.dev/docs/how-tos/configuring/overriding-compute-resources/' + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: image-build, konflux + labels: + app.kubernetes.io/version: "0.1" + build.appstudio.redhat.com/build_type: docker + name: buildah-10gb +spec: + description: |- + Buildah task builds source code into a container image and pushes the image into container registry using buildah tool. + In addition it generates a SBOM file, injects the SBOM file into final container image and pushes the SBOM file as separate image using cosign tool. + When [Java dependency rebuild](https://redhat-appstudio.github.io/docs.stonesoup.io/Documentation/main/cli/proc_enabled_java_dependencies.html) is enabled it triggers rebuilds of Java artifacts. + When prefetch-dependencies task was activated it is using its artifacts to run build in hermetic environment. + params: + - description: Reference of the image buildah will produce. + name: IMAGE + type: string + - default: "" + description: Deprecated. Has no effect. Will be removed in the future. + name: BUILDER_IMAGE + type: string + - default: ./Dockerfile + description: Path to the Dockerfile to build. + name: DOCKERFILE + type: string + - default: . + description: Path to the directory to use as context. + name: CONTEXT + type: string + - default: "true" + description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS + registry) + name: TLSVERIFY + type: string + - default: "" + description: unused, should be removed in next task version + name: DOCKER_AUTH + type: string + - default: "false" + description: Determines if build will be executed without network access. + name: HERMETIC + type: string + - default: "" + description: In case it is not empty, the prefetched content should be made available + to the build. + name: PREFETCH_INPUT + type: string + - default: "" + description: Delete image tag after specified time. Empty means to keep the image + tag. Time values could be something like 1h, 2d, 3w for hours, days, and weeks, + respectively. + name: IMAGE_EXPIRES_AFTER + type: string + - default: "" + description: The image is built from this commit. + name: COMMIT_SHA + type: string + - default: repos.d + description: Path in the git repository in which yum repository files are stored + name: YUM_REPOS_D_SRC + - default: fetched.repos.d + description: Path in source workspace where dynamically-fetched repos are present + name: YUM_REPOS_D_FETCHED + - default: /etc/yum.repos.d + description: Target path on the container in which yum repository files should + be made available + name: YUM_REPOS_D_TARGET + - default: "" + description: Target stage in Dockerfile to build. If not specified, the Dockerfile + is processed entirely to (and including) its last stage. + name: TARGET_STAGE + type: string + - default: etc-pki-entitlement + description: Name of secret which contains the entitlement certificates + name: ENTITLEMENT_SECRET + type: string + - default: activation-key + description: Name of secret which contains subscription activation key + name: ACTIVATION_KEY + type: string + - default: does-not-exist + description: Name of a secret which will be made available to the build with 'buildah + build --secret' at /run/secrets/$ADDITIONAL_SECRET + name: ADDITIONAL_SECRET + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) + name: BUILD_ARGS + type: array + - default: "" + description: Path to a file with build arguments, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: BUILD_ARGS_FILE + type: string + - default: trusted-ca + description: The name of the ConfigMap to read CA bundle data from. + name: caTrustConfigMapName + type: string + - default: ca-bundle.crt + description: The name of the key in the ConfigMap that contains the CA bundle + data. + name: caTrustConfigMapKey + type: string + - default: "" + description: Comma separated list of extra capabilities to add when running 'buildah + build' + name: ADD_CAPABILITIES + type: string + - default: "false" + description: Squash all new and previous layers added as a part of this build, + as per --squash + name: SQUASH + type: string + - default: vfs + description: Storage driver to configure for buildah + name: STORAGE_DRIVER + type: string + - default: "true" + description: Whether to skip stages in Containerfile that seem unused by subsequent + stages + name: SKIP_UNUSED_STAGES + type: string + results: + - description: Digest of the image just built + name: IMAGE_DIGEST + - description: Image repository and tag where the built image was pushed + name: IMAGE_URL + - description: Digests of the base images used for build + name: BASE_IMAGES_DIGESTS + - description: The counting of Java components by publisher in JSON format + name: SBOM_JAVA_COMPONENTS_COUNT + type: string + - description: The Java dependencies that came from community sources such as Maven + central. + name: JAVA_COMMUNITY_DEPENDENCIES + stepTemplate: + env: + - name: BUILDAH_FORMAT + value: oci + - name: STORAGE_DRIVER + value: $(params.STORAGE_DRIVER) + - name: HERMETIC + value: $(params.HERMETIC) + - name: CONTEXT + value: $(params.CONTEXT) + - name: DOCKERFILE + value: $(params.DOCKERFILE) + - name: IMAGE + value: $(params.IMAGE) + - name: TLSVERIFY + value: $(params.TLSVERIFY) + - name: IMAGE_EXPIRES_AFTER + value: $(params.IMAGE_EXPIRES_AFTER) + - name: YUM_REPOS_D_SRC + value: $(params.YUM_REPOS_D_SRC) + - name: YUM_REPOS_D_FETCHED + value: $(params.YUM_REPOS_D_FETCHED) + - name: YUM_REPOS_D_TARGET + value: $(params.YUM_REPOS_D_TARGET) + - name: TARGET_STAGE + value: $(params.TARGET_STAGE) + - name: PARAM_BUILDER_IMAGE + value: $(params.BUILDER_IMAGE) + - name: ENTITLEMENT_SECRET + value: $(params.ENTITLEMENT_SECRET) + - name: ADDITIONAL_SECRET + value: $(params.ADDITIONAL_SECRET) + - name: BUILD_ARGS_FILE + value: $(params.BUILD_ARGS_FILE) + - name: ADD_CAPABILITIES + value: $(params.ADD_CAPABILITIES) + - name: SQUASH + value: $(params.SQUASH) + - name: SKIP_UNUSED_STAGES + value: $(params.SKIP_UNUSED_STAGES) + volumeMounts: + - mountPath: /shared + name: shared + steps: + - args: + - $(params.BUILD_ARGS[*]) + computeResources: + limits: + memory: 10Gi + requests: + cpu: 250m + memory: 8Gi + env: + - name: COMMIT_SHA + value: $(params.COMMIT_SHA) + image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: build + script: | + if [ -n "${PARAM_BUILDER_IMAGE}" ]; then + echo "WARNING: provided deprecated BUILDER_IMAGE parameter has no effect." + fi + + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + SOURCE_CODE_DIR=source + if [ -e "$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" + elif [ -e "$SOURCE_CODE_DIR/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$DOCKERFILE" + elif echo "$DOCKERFILE" | grep -q "^https\?://"; then + echo "Fetch Dockerfile from $DOCKERFILE" + dockerfile_path=$(mktemp --suffix=-Dockerfile) + http_code=$(curl -s -L -w "%{http_code}" --output "$dockerfile_path" "$DOCKERFILE") + if [ $http_code != 200 ]; then + echo "No Dockerfile is fetched. Server responds $http_code" + exit 1 + fi + http_code=$(curl -s -L -w "%{http_code}" --output "$dockerfile_path.dockerignore.tmp" "$DOCKERFILE.dockerignore") + if [ $http_code = 200 ]; then + echo "Fetched .dockerignore from $DOCKERFILE.dockerignore" + mv "$dockerfile_path.dockerignore.tmp" $SOURCE_CODE_DIR/$CONTEXT/.dockerignore + fi + else + echo "Cannot find Dockerfile $DOCKERFILE" + exit 1 + fi + if [ -n "$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR" ] && grep -q '^\s*RUN \(./\)\?mvn' "$dockerfile_path"; then + sed -i -e "s|^\s*RUN \(\(./\)\?mvn\)\(.*\)|RUN echo \"mirror.defaulthttp://$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR/v1/cache/default/0/*\" > /tmp/settings.yaml; \1 -s /tmp/settings.yaml \3|g" "$dockerfile_path" + touch /var/lib/containers/java + fi + + # Fixing group permission on /var/lib/containers + chown root:root /var/lib/containers + + sed -i 's/^\s*short-name-mode\s*=\s*.*/short-name-mode = "disabled"/' /etc/containers/registries.conf + + # Setting new namespace to run buildah - 2^32-2 + echo 'root:1:4294967294' | tee -a /etc/subuid >> /etc/subgid + + BUILDAH_ARGS=() + + BASE_IMAGES=$(grep -i '^\s*FROM' "$dockerfile_path" | sed 's/--platform=\S*//' | awk '{print $2}' | (grep -v ^oci-archive: || true)) + if [ "${HERMETIC}" == "true" ]; then + BUILDAH_ARGS+=("--pull=never") + UNSHARE_ARGS="--net" + for image in $BASE_IMAGES; do + if [ "${image}" != "scratch" ]; then + unshare -Ufp --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -- buildah pull $image + fi + done + echo "Build will be executed with network isolation" + fi + + if [ -n "${TARGET_STAGE}" ]; then + BUILDAH_ARGS+=("--target=${TARGET_STAGE}") + fi + + if [ -n "${BUILD_ARGS_FILE}" ]; then + BUILDAH_ARGS+=("--build-arg-file=$(pwd)/$SOURCE_CODE_DIR/${BUILD_ARGS_FILE}") + fi + + for build_arg in "$@"; do + BUILDAH_ARGS+=("--build-arg=$build_arg") + done + + if [ -n "${ADD_CAPABILITIES}" ]; then + BUILDAH_ARGS+=("--cap-add=${ADD_CAPABILITIES}") + fi + + if [ "${SQUASH}" == "true" ]; then + BUILDAH_ARGS+=("--squash") + fi + + if [ "${SKIP_UNUSED_STAGES}" != "true" ] ; then + BUILDAH_ARGS+=("--skip-unused-stages=false") + fi + + if [ -f "$(workspaces.source.path)/cachi2/cachi2.env" ]; then + cp -r "$(workspaces.source.path)/cachi2" /tmp/ + chmod -R go+rwX /tmp/cachi2 + VOLUME_MOUNTS="--volume /tmp/cachi2:/cachi2" + # Read in the whole file (https://unix.stackexchange.com/questions/533277), then + # for each RUN ... line insert the cachi2.env command *after* any options like --mount + sed -E -i \ + -e 'H;1h;$!d;x' \ + -e 's@^\s*(run((\s|\\\n)+-\S+)*(\s|\\\n)+)@\1. /cachi2/cachi2.env \&\& \\\n @igM' \ + "$dockerfile_path" + echo "Prefetched content will be made available" + + prefetched_repo_for_my_arch="/tmp/cachi2/output/deps/rpm/$(uname -m)/repos.d/cachi2.repo" + if [ -f "$prefetched_repo_for_my_arch" ]; then + echo "Adding $prefetched_repo_for_my_arch to $YUM_REPOS_D_FETCHED" + mkdir -p "$YUM_REPOS_D_FETCHED" + cp --no-clobber "$prefetched_repo_for_my_arch" "$YUM_REPOS_D_FETCHED" + fi + fi + + # if yum repofiles stored in git, copy them to mount point outside the source dir + if [ -d "${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}" ]; then + mkdir -p ${YUM_REPOS_D_FETCHED} + cp -r ${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}/* ${YUM_REPOS_D_FETCHED} + fi + + # if anything in the repofiles mount point (either fetched or from git), mount it + if [ -d "${YUM_REPOS_D_FETCHED}" ]; then + chmod -R go+rwX ${YUM_REPOS_D_FETCHED} + mount_point=$(realpath ${YUM_REPOS_D_FETCHED}) + VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume ${mount_point}:${YUM_REPOS_D_TARGET}" + fi + + LABELS=( + "--label" "build-date=$(date -u +'%Y-%m-%dT%H:%M:%S')" + "--label" "architecture=$(uname -m)" + "--label" "vcs-type=git" + ) + [ -n "$COMMIT_SHA" ] && LABELS+=("--label" "vcs-ref=$COMMIT_SHA") + [ -n "$IMAGE_EXPIRES_AFTER" ] && LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + + ACTIVATION_KEY_PATH="/activation-key" + ENTITLEMENT_PATH="/entitlement" + + if [ -e /activation-key/org ]; then + cp -r --preserve=mode "$ACTIVATION_KEY_PATH" /tmp/activation-key + mkdir /shared/rhsm-tmp + VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume /tmp/activation-key:/activation-key -v /shared/rhsm-tmp:/etc/pki/entitlement:Z" + echo "Adding activation key to the build" + + elif find /entitlement -name "*.pem" >> null; then + cp -r --preserve=mode "$ENTITLEMENT_PATH" /tmp/entitlement + VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume /tmp/entitlement:/etc/pki/entitlement" + echo "Adding the entitlement to the build" + fi + + ADDITIONAL_SECRET_PATH="/additional-secret" + ADDITIONAL_SECRET_TMP="/tmp/additional-secret" + if [ -d "$ADDITIONAL_SECRET_PATH" ]; then + cp -r --preserve=mode -L "$ADDITIONAL_SECRET_PATH" $ADDITIONAL_SECRET_TMP + while read -r filename; do + echo "Adding the secret ${ADDITIONAL_SECRET}/${filename} to the build, available at /run/secrets/${ADDITIONAL_SECRET}/${filename}" + BUILDAH_ARGS+=("--secret=id=${ADDITIONAL_SECRET}/${filename},src=$ADDITIONAL_SECRET_TMP/${filename}") + done < <(find $ADDITIONAL_SECRET_TMP -maxdepth 1 -type f -exec basename {} \;) + fi + + unshare -Uf $UNSHARE_ARGS --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -w ${SOURCE_CODE_DIR}/$CONTEXT -- buildah build \ + $VOLUME_MOUNTS \ + "${BUILDAH_ARGS[@]}" \ + "${LABELS[@]}" \ + --tls-verify=$TLSVERIFY --no-cache \ + --ulimit nofile=4096:4096 \ + -f "$dockerfile_path" -t $IMAGE . + + container=$(buildah from --pull-never $IMAGE) + buildah mount $container | tee /shared/container_path + # delete symlinks - they may point outside the container rootfs, messing with SBOM scanners + find $(cat /shared/container_path) -xtype l -delete + echo $container > /shared/container_name + + # Save the SBOM produced by Cachi2 so it can be merged into the final SBOM later + if [ -f "/tmp/cachi2/output/bom.json" ]; then + cp /tmp/cachi2/output/bom.json ./sbom-cachi2.json + fi + + # Expose base image digests + touch $(results.BASE_IMAGES_DIGESTS.path) + for image in $BASE_IMAGES; do + if [ "${image}" != "scratch" ]; then + buildah images --format '{{ .Name }}:{{ .Tag }}@{{ .Digest }}' --filter reference="$image" >> $(results.BASE_IMAGES_DIGESTS.path) + fi + done + + # Needed to generate base images SBOM + echo "$BASE_IMAGES" > $(workspaces.source.path)/base_images_from_dockerfile + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /entitlement + name: etc-pki-entitlement + - mountPath: /activation-key + name: activation-key + - mountPath: /additional-secret + name: additional-secret + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + - image: registry.access.redhat.com/rh-syft-tech-preview/syft-rhel9:1.4.1@sha256:34d7065427085a31dc4949bd283c001b91794d427e1e4cdf1b21ea4faf9fee3f + name: sbom-syft-generate + script: | + echo "Running syft on the source directory" + syft dir:$(workspaces.source.path)/source --output cyclonedx-json=$(workspaces.source.path)/sbom-source.json + echo "Running syft on the image filesystem" + syft dir:$(cat /shared/container_path) --output cyclonedx-json=$(workspaces.source.path)/sbom-image.json + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + workingDir: $(workspaces.source.path)/source + - image: quay.io/redhat-appstudio/hacbs-jvm-build-request-processor:127ee0c223a2b56a9bd20a6f2eaeed3bd6015f77 + name: analyse-dependencies-java-sbom + script: | + if [ -f /var/lib/containers/java ]; then + /opt/jboss/container/java/run/run-java.sh analyse-dependencies path $(cat /shared/container_path) -s $(workspaces.source.path)/sbom-image.json --task-run-name $(context.taskRun.name) --publishers $(results.SBOM_JAVA_COMPONENTS_COUNT.path) + sed -i 's/^/ /' $(results.SBOM_JAVA_COMPONENTS_COUNT.path) # Workaround for SRVKP-2875 + else + touch $(results.JAVA_COMMUNITY_DEPENDENCIES.path) + fi + securityContext: + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + - image: registry.access.redhat.com/ubi9/python-39:9.5-1734610342@sha256:dde5068ba8fd81eef41a9128ddad2b99e2e02e5869ffe925c605b609a0ad7bbb + name: merge-syft-sboms + script: | + #!/bin/python3 + import json + + # load SBOMs + with open("./sbom-image.json") as f: + image_sbom = json.load(f) + + with open("./sbom-source.json") as f: + source_sbom = json.load(f) + + # fetch unique components from available SBOMs + def get_identifier(component): + return component["name"] + '@' + component.get("version", "") + + image_sbom_components = image_sbom.setdefault("components", []) + existing_components = [get_identifier(component) for component in image_sbom_components] + + source_sbom_components = source_sbom.get("components", []) + for component in source_sbom_components: + if get_identifier(component) not in existing_components: + image_sbom_components.append(component) + existing_components.append(get_identifier(component)) + + image_sbom_components.sort(key=lambda c: get_identifier(c)) + + # write the CycloneDX unified SBOM + with open("./sbom-cyclonedx.json", "w") as f: + json.dump(image_sbom, f, indent=4) + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - image: quay.io/redhat-appstudio/cachi2:0.16.0@sha256:55415cd8ded149f5d56d3fca46d93125b86b41e07ae5d3c03caa240b7b93b7d8 + name: merge-cachi2-sbom + script: | + if [ -f "sbom-cachi2.json" ]; then + echo "Merging contents of sbom-cachi2.json into sbom-cyclonedx.json" + merge_syft_sbom sbom-cachi2.json sbom-cyclonedx.json > sbom-temp.json + mv sbom-temp.json sbom-cyclonedx.json + else + echo "Skipping step since no Cachi2 SBOM was produced" + fi + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - image: registry.access.redhat.com/ubi9/python-39:9.5-1734610342@sha256:dde5068ba8fd81eef41a9128ddad2b99e2e02e5869ffe925c605b609a0ad7bbb + name: create-purl-sbom + script: | + #!/bin/python3 + import json + + with open("./sbom-cyclonedx.json") as f: + cyclonedx_sbom = json.load(f) + + purls = [{"purl": component["purl"]} for component in cyclonedx_sbom.get("components", []) if "purl" in component] + purl_content = {"image_contents": {"dependencies": purls}} + + with open("sbom-purl.json", "w") as output_file: + json.dump(purl_content, output_file, indent=4) + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - env: + - name: BASE_IMAGES_DIGESTS_PATH + value: $(results.BASE_IMAGES_DIGESTS.path) + image: quay.io/redhat-appstudio/base-images-sbom-script@sha256:667669e3def018f9dbb8eaf8868887a40bc07842221e9a98f6787edcff021840 + name: create-base-images-sbom + script: | + python3 /app/base_images_sbom_script.py --sbom=sbom-cyclonedx.json --base-images-from-dockerfile=base_images_from_dockerfile --base-images-digests=$BASE_IMAGES_DIGESTS_PATH + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - computeResources: {} + image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: inject-sbom-and-push + script: | + if [ -n "${PARAM_BUILDER_IMAGE}" ]; then + echo "WARNING: provided deprecated BUILDER_IMAGE parameter has no effect." + fi + + base_image_name=$(buildah inspect --format '{{ index .ImageAnnotations "org.opencontainers.image.base.name"}}' $IMAGE | cut -f1 -d'@') + base_image_digest=$(buildah inspect --format '{{ index .ImageAnnotations "org.opencontainers.image.base.digest"}}' $IMAGE) + container=$(buildah from --pull-never $IMAGE) + buildah copy $container sbom-cyclonedx.json sbom-purl.json /root/buildinfo/content_manifests/ + buildah config -a org.opencontainers.image.base.name=${base_image_name} -a org.opencontainers.image.base.digest=${base_image_digest} $container + + BUILDAH_ARGS=() + if [ "${SQUASH}" == "true" ]; then + BUILDAH_ARGS+=("--squash") + fi + + buildah commit "${BUILDAH_ARGS[@]}" $container $IMAGE + + status=-1 + max_run=5 + sleep_sec=10 + for run in $(seq 1 $max_run); do + status=0 + [ "$run" -gt 1 ] && sleep $sleep_sec + echo "Pushing sbom image to registry" + buildah push \ + --tls-verify=$TLSVERIFY \ + --digestfile $(workspaces.source.path)/image-digest $IMAGE \ + docker://$IMAGE && break || status=$? + done + if [ "$status" -ne 0 ]; then + echo "Failed to push sbom image to registry after ${max_run} tries" + exit 1 + fi + + cat "$(workspaces.source.path)"/image-digest | tee $(results.IMAGE_DIGEST.path) + echo -n "$IMAGE" | tee $(results.IMAGE_URL.path) + securityContext: + capabilities: + add: + - SETFCAP + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + workingDir: $(workspaces.source.path) + - args: + - attach + - sbom + - --sbom + - sbom-cyclonedx.json + - --type + - cyclonedx + - $(params.IMAGE) + image: quay.io/redhat-appstudio/cosign:v2.1.1@sha256:c883d6f8d39148f2cea71bff4622d196d89df3e510f36c140c097b932f0dd5d5 + name: upload-sbom + workingDir: $(workspaces.source.path) + volumes: + - emptyDir: {} + name: varlibcontainers + - emptyDir: {} + name: shared + - name: etc-pki-entitlement + secret: + optional: true + secretName: $(params.ENTITLEMENT_SECRET) + - name: activation-key + secret: + optional: true + secretName: $(params.ACTIVATION_KEY) + - name: additional-secret + secret: + optional: true + secretName: $(params.ADDITIONAL_SECRET) + - configMap: + items: + - key: $(params.caTrustConfigMapKey) + path: ca-bundle.crt + name: $(params.caTrustConfigMapName) + optional: true + name: trusted-ca + workspaces: + - description: Workspace containing the source code to build. + name: source diff --git a/auto-generated/task/buildah-10gb/0.2/tekton.dev_v1_task_buildah-10gb.yaml b/auto-generated/task/buildah-10gb/0.2/tekton.dev_v1_task_buildah-10gb.yaml new file mode 100644 index 0000000000..277e34d9b7 --- /dev/null +++ b/auto-generated/task/buildah-10gb/0.2/tekton.dev_v1_task_buildah-10gb.yaml @@ -0,0 +1,722 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + annotations: + build.appstudio.redhat.com/expires-on: "2025-01-21T00:00:00Z" + build.appstudio.redhat.com/expiry-message: 'Instead of using this task, switch + to buildah task (you can find latest bundle reference here: https://quay.io/repository/konflux-ci/tekton-catalog/task-buildah) + and configure build step resources as described in the doc: https://konflux-ci.dev/docs/how-tos/configuring/overriding-compute-resources/' + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: image-build, konflux + labels: + app.kubernetes.io/version: 0.2.1 + build.appstudio.redhat.com/build_type: docker + name: buildah-10gb +spec: + description: |- + Buildah task builds source code into a container image and pushes the image into container registry using buildah tool. + In addition it generates a SBOM file, injects the SBOM file into final container image and pushes the SBOM file as separate image using cosign tool. + When [Java dependency rebuild](https://redhat-appstudio.github.io/docs.stonesoup.io/Documentation/main/cli/proc_enabled_java_dependencies.html) is enabled it triggers rebuilds of Java artifacts. + When prefetch-dependencies task was activated it is using its artifacts to run build in hermetic environment. + params: + - description: Reference of the image buildah will produce. + name: IMAGE + type: string + - default: ./Dockerfile + description: Path to the Dockerfile to build. + name: DOCKERFILE + type: string + - default: . + description: Path to the directory to use as context. + name: CONTEXT + type: string + - default: "true" + description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS + registry) + name: TLSVERIFY + type: string + - default: "false" + description: Determines if build will be executed without network access. + name: HERMETIC + type: string + - default: "" + description: In case it is not empty, the prefetched content should be made available + to the build. + name: PREFETCH_INPUT + type: string + - default: "" + description: Delete image tag after specified time. Empty means to keep the image + tag. Time values could be something like 1h, 2d, 3w for hours, days, and weeks, + respectively. + name: IMAGE_EXPIRES_AFTER + type: string + - default: "" + description: The image is built from this commit. + name: COMMIT_SHA + type: string + - default: repos.d + description: Path in the git repository in which yum repository files are stored + name: YUM_REPOS_D_SRC + - default: fetched.repos.d + description: Path in source workspace where dynamically-fetched repos are present + name: YUM_REPOS_D_FETCHED + - default: /etc/yum.repos.d + description: Target path on the container in which yum repository files should + be made available + name: YUM_REPOS_D_TARGET + - default: "" + description: Target stage in Dockerfile to build. If not specified, the Dockerfile + is processed entirely to (and including) its last stage. + name: TARGET_STAGE + type: string + - default: etc-pki-entitlement + description: Name of secret which contains the entitlement certificates + name: ENTITLEMENT_SECRET + type: string + - default: activation-key + description: Name of secret which contains subscription activation key + name: ACTIVATION_KEY + type: string + - default: does-not-exist + description: Name of a secret which will be made available to the build with 'buildah + build --secret' at /run/secrets/$ADDITIONAL_SECRET + name: ADDITIONAL_SECRET + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) + name: BUILD_ARGS + type: array + - default: "" + description: Path to a file with build arguments, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: BUILD_ARGS_FILE + type: string + - default: trusted-ca + description: The name of the ConfigMap to read CA bundle data from. + name: caTrustConfigMapName + type: string + - default: ca-bundle.crt + description: The name of the key in the ConfigMap that contains the CA bundle + data. + name: caTrustConfigMapKey + type: string + - default: "" + description: Comma separated list of extra capabilities to add when running 'buildah + build' + name: ADD_CAPABILITIES + type: string + - default: "false" + description: Squash all new and previous layers added as a part of this build, + as per --squash + name: SQUASH + type: string + - default: vfs + description: Storage driver to configure for buildah + name: STORAGE_DRIVER + type: string + - default: "true" + description: Whether to skip stages in Containerfile that seem unused by subsequent + stages + name: SKIP_UNUSED_STAGES + type: string + - default: [] + description: Additional key=value labels that should be applied to the image + name: LABELS + type: array + - default: "false" + description: Whether to enable privileged mode + name: PRIVILEGED_NESTED + type: string + results: + - description: Digest of the image just built + name: IMAGE_DIGEST + - description: Image repository and tag where the built image was pushed + name: IMAGE_URL + - description: Image reference of the built image + name: IMAGE_REF + - description: Reference of SBOM blob digest to enable digest-based verification + from provenance + name: SBOM_BLOB_URL + type: string + - description: The counting of Java components by publisher in JSON format + name: SBOM_JAVA_COMPONENTS_COUNT + type: string + - description: The Java dependencies that came from community sources such as Maven + central. + name: JAVA_COMMUNITY_DEPENDENCIES + stepTemplate: + computeResources: + limits: + cpu: "4" + memory: 4Gi + requests: + cpu: "1" + memory: 1Gi + env: + - name: BUILDAH_FORMAT + value: oci + - name: STORAGE_DRIVER + value: $(params.STORAGE_DRIVER) + - name: HERMETIC + value: $(params.HERMETIC) + - name: SOURCE_CODE_DIR + value: source + - name: CONTEXT + value: $(params.CONTEXT) + - name: IMAGE + value: $(params.IMAGE) + - name: TLSVERIFY + value: $(params.TLSVERIFY) + - name: IMAGE_EXPIRES_AFTER + value: $(params.IMAGE_EXPIRES_AFTER) + - name: YUM_REPOS_D_SRC + value: $(params.YUM_REPOS_D_SRC) + - name: YUM_REPOS_D_FETCHED + value: $(params.YUM_REPOS_D_FETCHED) + - name: YUM_REPOS_D_TARGET + value: $(params.YUM_REPOS_D_TARGET) + - name: TARGET_STAGE + value: $(params.TARGET_STAGE) + - name: ENTITLEMENT_SECRET + value: $(params.ENTITLEMENT_SECRET) + - name: ACTIVATION_KEY + value: $(params.ACTIVATION_KEY) + - name: ADDITIONAL_SECRET + value: $(params.ADDITIONAL_SECRET) + - name: BUILD_ARGS_FILE + value: $(params.BUILD_ARGS_FILE) + - name: ADD_CAPABILITIES + value: $(params.ADD_CAPABILITIES) + - name: SQUASH + value: $(params.SQUASH) + - name: SKIP_UNUSED_STAGES + value: $(params.SKIP_UNUSED_STAGES) + - name: PRIVILEGED_NESTED + value: $(params.PRIVILEGED_NESTED) + volumeMounts: + - mountPath: /shared + name: shared + steps: + - args: + - --build-args + - $(params.BUILD_ARGS[*]) + - --labels + - $(params.LABELS[*]) + computeResources: + limits: + cpu: "4" + memory: 10Gi + requests: + cpu: "1" + memory: 8Gi + env: + - name: COMMIT_SHA + value: $(params.COMMIT_SHA) + - name: DOCKERFILE + value: $(params.DOCKERFILE) + image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: build + script: | + #!/bin/bash + set -euo pipefail + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + if [ -e "$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" + elif [ -e "$SOURCE_CODE_DIR/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$DOCKERFILE" + elif [ -e "$DOCKERFILE" ]; then + # Instrumented builds (SAST) use this custom dockerffile step as their base + dockerfile_path="$DOCKERFILE" + elif echo "$DOCKERFILE" | grep -q "^https\?://"; then + echo "Fetch Dockerfile from $DOCKERFILE" + dockerfile_path=$(mktemp --suffix=-Dockerfile) + http_code=$(curl -s -S -L -w "%{http_code}" --output "$dockerfile_path" "$DOCKERFILE") + if [ $http_code != 200 ]; then + echo "No Dockerfile is fetched. Server responds $http_code" + exit 1 + fi + http_code=$(curl -s -S -L -w "%{http_code}" --output "$dockerfile_path.dockerignore.tmp" "$DOCKERFILE.dockerignore") + if [ $http_code = 200 ]; then + echo "Fetched .dockerignore from $DOCKERFILE.dockerignore" + mv "$dockerfile_path.dockerignore.tmp" $SOURCE_CODE_DIR/$CONTEXT/.dockerignore + fi + else + echo "Cannot find Dockerfile $DOCKERFILE" + exit 1 + fi + + dockerfile_copy=$(mktemp --tmpdir "$(basename "$dockerfile_path").XXXXXX") + cp "$dockerfile_path" "$dockerfile_copy" + + if [ -n "${JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR-}" ] && grep -q '^\s*RUN \(./\)\?mvn' "$dockerfile_copy"; then + sed -i -e "s|^\s*RUN \(\(./\)\?mvn\)\(.*\)|RUN echo \"mirror.defaulthttp://$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR/v1/cache/default/0/*\" > /tmp/settings.yaml; \1 -s /tmp/settings.yaml \3|g" "$dockerfile_copy" + touch /var/lib/containers/java + fi + + # Fixing group permission on /var/lib/containers + chown root:root /var/lib/containers + + sed -i 's/^\s*short-name-mode\s*=\s*.*/short-name-mode = "disabled"/' /etc/containers/registries.conf + + # Setting new namespace to run buildah - 2^32-2 + echo 'root:1:4294967294' | tee -a /etc/subuid >> /etc/subgid + + build_args=() + if [ -n "${BUILD_ARGS_FILE}" ]; then + # Parse BUILD_ARGS_FILE ourselves because dockerfile-json doesn't support it + echo "Parsing ARGs from $BUILD_ARGS_FILE" + mapfile -t build_args < <( + # https://www.mankier.com/1/buildah-build#--build-arg-file + # delete lines that start with # + # delete blank lines + sed -e '/^#/d' -e '/^\s*$/d' "${SOURCE_CODE_DIR}/${BUILD_ARGS_FILE}" + ) + fi + + LABELS=() + # Split `args` into two sets of arguments. + while [[ $# -gt 0 ]]; do + case $1 in + --build-args) + shift + # Note: this may result in multiple --build-arg=KEY=value flags with the same KEY being + # passed to buildah. In that case, the *last* occurrence takes precedence. This is why + # we append BUILD_ARGS after the content of the BUILD_ARGS_FILE + while [[ $# -gt 0 && $1 != --* ]]; do build_args+=("$1"); shift; done + ;; + --labels) + shift + while [[ $# -gt 0 && $1 != --* ]]; do LABELS+=("--label" "$1"); shift; done + ;; + *) + echo "unexpected argument: $1" >&2 + exit 2 + ;; + esac + done + + BUILD_ARG_FLAGS=() + for build_arg in "${build_args[@]}"; do + BUILD_ARG_FLAGS+=("--build-arg=$build_arg") + done + + dockerfile-json "${BUILD_ARG_FLAGS[@]}" "$dockerfile_copy" > /shared/parsed_dockerfile.json + BASE_IMAGES=$( + jq -r '.Stages[] | select(.From | .Stage or .Scratch | not) | .BaseName | select(test("^oci-archive:") | not)' /shared/parsed_dockerfile.json + ) + + BUILDAH_ARGS=() + UNSHARE_ARGS=() + + if [ "${HERMETIC}" == "true" ]; then + BUILDAH_ARGS+=("--pull=never") + UNSHARE_ARGS+=("--net") + + for image in $BASE_IMAGES; do + unshare -Ufp --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -- buildah pull $image + done + echo "Build will be executed with network isolation" + fi + + if [ -n "${TARGET_STAGE}" ]; then + BUILDAH_ARGS+=("--target=${TARGET_STAGE}") + fi + + BUILDAH_ARGS+=("${BUILD_ARG_FLAGS[@]}") + + if [ "${PRIVILEGED_NESTED}" == "true" ]; then + BUILDAH_ARGS+=("--security-opt=label=disable") + BUILDAH_ARGS+=("--cap-add=all") + BUILDAH_ARGS+=("--device=/dev/fuse") + fi + + if [ -n "${ADD_CAPABILITIES}" ]; then + BUILDAH_ARGS+=("--cap-add=${ADD_CAPABILITIES}") + fi + + if [ "${SQUASH}" == "true" ]; then + BUILDAH_ARGS+=("--squash") + fi + + if [ "${SKIP_UNUSED_STAGES}" != "true" ] ; then + BUILDAH_ARGS+=("--skip-unused-stages=false") + fi + + VOLUME_MOUNTS=() + + if [ -f "$(workspaces.source.path)/cachi2/cachi2.env" ]; then + cp -r "$(workspaces.source.path)/cachi2" /tmp/ + chmod -R go+rwX /tmp/cachi2 + VOLUME_MOUNTS+=(--volume /tmp/cachi2:/cachi2) + # Read in the whole file (https://unix.stackexchange.com/questions/533277), then + # for each RUN ... line insert the cachi2.env command *after* any options like --mount + sed -E -i \ + -e 'H;1h;$!d;x' \ + -e 's@^\s*(run((\s|\\\n)+-\S+)*(\s|\\\n)+)@\1. /cachi2/cachi2.env \&\& \\\n @igM' \ + "$dockerfile_copy" + echo "Prefetched content will be made available" + + prefetched_repo_for_my_arch="/tmp/cachi2/output/deps/rpm/$(uname -m)/repos.d/cachi2.repo" + if [ -f "$prefetched_repo_for_my_arch" ]; then + echo "Adding $prefetched_repo_for_my_arch to $YUM_REPOS_D_FETCHED" + mkdir -p "$YUM_REPOS_D_FETCHED" + cp --no-clobber "$prefetched_repo_for_my_arch" "$YUM_REPOS_D_FETCHED" + fi + fi + + # if yum repofiles stored in git, copy them to mount point outside the source dir + if [ -d "${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}" ]; then + mkdir -p ${YUM_REPOS_D_FETCHED} + cp -r ${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}/* ${YUM_REPOS_D_FETCHED} + fi + + # if anything in the repofiles mount point (either fetched or from git), mount it + if [ -d "${YUM_REPOS_D_FETCHED}" ]; then + chmod -R go+rwX ${YUM_REPOS_D_FETCHED} + mount_point=$(realpath ${YUM_REPOS_D_FETCHED}) + VOLUME_MOUNTS+=(--volume "${mount_point}:${YUM_REPOS_D_TARGET}") + fi + + DEFAULT_LABELS=( + "--label" "build-date=$(date -u +'%Y-%m-%dT%H:%M:%S')" + "--label" "architecture=$(uname -m)" + "--label" "vcs-type=git" + ) + [ -n "$COMMIT_SHA" ] && DEFAULT_LABELS+=("--label" "vcs-ref=$COMMIT_SHA") + [ -n "$IMAGE_EXPIRES_AFTER" ] && DEFAULT_LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + + # Concatenate defaults and explicit labels. If a label appears twice, the last one wins. + LABELS=("${DEFAULT_LABELS[@]}" "${LABELS[@]}") + + ACTIVATION_KEY_PATH="/activation-key" + ENTITLEMENT_PATH="/entitlement" + + # 0. if hermetic=true, skip all subscription related stuff + # 1. do not enable activation key and entitlement at same time. If both vars are provided, prefer activation key. + # 2. Activation-keys will be used when the key 'org' exists in the activation key secret. + # 3. try to pre-register and mount files to the correct location so that users do no need to modify Dockerfiles. + # 3. If the Dockerfile contains the string "subcription-manager register", add the activation-keys volume + # to buildah but don't pre-register for backwards compatibility. Mount an empty directory on + # shared emptydir volume to "/etc/pki/entitlement" to prevent certificates from being included + + if [ "${HERMETIC}" != "true" ] && [ -e /activation-key/org ]; then + cp -r --preserve=mode "$ACTIVATION_KEY_PATH" /tmp/activation-key + mkdir -p /shared/rhsm/etc/pki/entitlement + mkdir -p /shared/rhsm/etc/pki/consumer + + VOLUME_MOUNTS+=(-v /tmp/activation-key:/activation-key \ + -v /shared/rhsm/etc/pki/entitlement:/etc/pki/entitlement:Z \ + -v /shared/rhsm/etc/pki/consumer:/etc/pki/consumer:Z) + echo "Adding activation key to the build" + + if ! grep -E "^[^#]*subscription-manager.[^#]*register" "$dockerfile_path"; then + # user is not running registration in the Containerfile: pre-register. + echo "Pre-registering with subscription manager." + subscription-manager register --org "$(cat /tmp/activation-key/org)" --activationkey "$(cat /tmp/activation-key/activationkey)" + trap 'subscription-manager unregister || true' EXIT + + # copy generated certificates to /shared volume + cp /etc/pki/entitlement/*.pem /shared/rhsm/etc/pki/entitlement + cp /etc/pki/consumer/*.pem /shared/rhsm/etc/pki/consumer + + # and then mount get /etc/rhsm/ca/redhat-uep.pem into /run/secrets/rhsm/ca + VOLUME_MOUNTS+=(--volume /etc/rhsm/ca/redhat-uep.pem:/etc/rhsm/ca/redhat-uep.pem:Z) + fi + + elif [ "${HERMETIC}" != "true" ] && find /entitlement -name "*.pem" >> null; then + cp -r --preserve=mode "$ENTITLEMENT_PATH" /tmp/entitlement + VOLUME_MOUNTS+=(--volume /tmp/entitlement:/etc/pki/entitlement) + echo "Adding the entitlement to the build" + fi + + if [ -n "${ADDITIONAL_VOLUME_MOUNTS-}" ]; then + # ADDITIONAL_VOLUME_MOUNTS allows to specify more volumes for the build. + # Instrumented builds (SAST) use this step as their base and add some other tools. + while read -r volume_mount; do + VOLUME_MOUNTS+=("--volume=$volume_mount") + done <<< "$ADDITIONAL_VOLUME_MOUNTS" + fi + + ADDITIONAL_SECRET_PATH="/additional-secret" + ADDITIONAL_SECRET_TMP="/tmp/additional-secret" + if [ -d "$ADDITIONAL_SECRET_PATH" ]; then + cp -r --preserve=mode -L "$ADDITIONAL_SECRET_PATH" $ADDITIONAL_SECRET_TMP + while read -r filename; do + echo "Adding the secret ${ADDITIONAL_SECRET}/${filename} to the build, available at /run/secrets/${ADDITIONAL_SECRET}/${filename}" + BUILDAH_ARGS+=("--secret=id=${ADDITIONAL_SECRET}/${filename},src=$ADDITIONAL_SECRET_TMP/${filename}") + done < <(find $ADDITIONAL_SECRET_TMP -maxdepth 1 -type f -exec basename {} \;) + fi + + # Prevent ShellCheck from giving a warning because 'image' is defined and 'IMAGE' is not. + declare IMAGE + + buildah_cmd_array=( + buildah build + "${VOLUME_MOUNTS[@]}" + "${BUILDAH_ARGS[@]}" + "${LABELS[@]}" + --tls-verify="$TLSVERIFY" --no-cache + --ulimit nofile=4096:4096 + -f "$dockerfile_copy" -t "$IMAGE" . + ) + buildah_cmd=$(printf "%q " "${buildah_cmd_array[@]}") + + if [ "${HERMETIC}" == "true" ]; then + # enabling loopback adapter enables Bazel builds to work in hermetic mode. + command="ip link set lo up && $buildah_cmd" + else + command="$buildah_cmd" + fi + + # disable host subcription manager integration + find /usr/share/rhel/secrets -type l -exec unlink {} \; + + unshare -Uf "${UNSHARE_ARGS[@]}" --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -w "${SOURCE_CODE_DIR}/$CONTEXT" -- sh -c "$command" + + container=$(buildah from --pull-never "$IMAGE") + + # Save the SBOM produced by Cachi2 so it can be merged into the final SBOM later + if [ -f "/tmp/cachi2/output/bom.json" ]; then + echo "Making copy of sbom-cachi2.json" + cp /tmp/cachi2/output/bom.json ./sbom-cachi2.json + fi + + buildah mount $container | tee /shared/container_path + # delete symlinks - they may point outside the container rootfs, messing with SBOM scanners + find $(cat /shared/container_path) -xtype l -delete + echo $container > /shared/container_name + + touch /shared/base_images_digests + for image in $BASE_IMAGES; do + base_image_digest=$(buildah images --format '{{ .Name }}:{{ .Tag }}@{{ .Digest }}' --filter reference="$image") + # In some cases, there might be BASE_IMAGES, but not any associated digest. This happens + # if buildah did not use that particular image during build because it was skipped + if [ -n "$base_image_digest" ]; then + echo "$image $base_image_digest" >> /shared/base_images_digests + fi + done + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /entitlement + name: etc-pki-entitlement + - mountPath: /activation-key + name: activation-key + - mountPath: /additional-secret + name: additional-secret + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + - image: quay.io/konflux-ci/icm-injection-scripts:latest@sha256:462980e94ba689b5f56c3d5dfb3358cd8c685300daf65a71532f11898935e7f1 + name: icm + script: | + #!/bin/bash + set -euo pipefail + /scripts/inject-icm.sh "$IMAGE" + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + workingDir: $(workspaces.source.path) + - image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: push + script: | + #!/bin/bash + set -e + + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + retries=5 + # Push to a unique tag based on the TaskRun name to avoid race conditions + echo "Pushing to ${IMAGE%:*}:${TASKRUN_NAME}" + if ! buildah push \ + --retry "$retries" \ + --tls-verify="$TLSVERIFY" \ + "$IMAGE" \ + "docker://${IMAGE%:*}:$(context.taskRun.name)"; + then + echo "Failed to push sbom image to ${IMAGE%:*}:$(context.taskRun.name) after ${retries} tries" + exit 1 + fi + + # Push to a tag based on the git revision + echo "Pushing to ${IMAGE}" + if ! buildah push \ + --retry "$retries" \ + --tls-verify="$TLSVERIFY" \ + --digestfile "$(workspaces.source.path)/image-digest" "$IMAGE" \ + "docker://$IMAGE"; + then + echo "Failed to push sbom image to $IMAGE after ${retries} tries" + exit 1 + fi + + cat "$(workspaces.source.path)"/image-digest | tee $(results.IMAGE_DIGEST.path) + echo -n "$IMAGE" | tee $(results.IMAGE_URL.path) + { + echo -n "${IMAGE}@" + cat "$(workspaces.source.path)/image-digest" + } > "$(results.IMAGE_REF.path)" + securityContext: + capabilities: + add: + - SETFCAP + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + - image: registry.access.redhat.com/rh-syft-tech-preview/syft-rhel9:1.4.1@sha256:34d7065427085a31dc4949bd283c001b91794d427e1e4cdf1b21ea4faf9fee3f + name: sbom-syft-generate + script: | + echo "Running syft on the source directory" + syft dir:"$(workspaces.source.path)/$SOURCE_CODE_DIR/$CONTEXT" --output cyclonedx-json="$(workspaces.source.path)/sbom-source.json" + echo "Running syft on the image filesystem" + syft dir:"$(cat /shared/container_path)" --output cyclonedx-json="$(workspaces.source.path)/sbom-image.json" + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + workingDir: $(workspaces.source.path)/source + - computeResources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + image: quay.io/redhat-appstudio/hacbs-jvm-build-request-processor:127ee0c223a2b56a9bd20a6f2eaeed3bd6015f77 + name: analyse-dependencies-java-sbom + script: | + if [ -f /var/lib/containers/java ]; then + /opt/jboss/container/java/run/run-java.sh analyse-dependencies path $(cat /shared/container_path) -s $(workspaces.source.path)/sbom-image.json --task-run-name $(context.taskRun.name) --publishers $(results.SBOM_JAVA_COMPONENTS_COUNT.path) + sed -i 's/^/ /' $(results.SBOM_JAVA_COMPONENTS_COUNT.path) # Workaround for SRVKP-2875 + else + touch $(results.JAVA_COMMUNITY_DEPENDENCIES.path) + fi + securityContext: + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + - computeResources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + image: quay.io/redhat-appstudio/sbom-utility-scripts-image@sha256:9f1fd11d9c3c517ecc112d192ad361d16ecf6ce00b83b109c93cf3d1c644a357 + name: prepare-sboms + script: | + echo "Merging contents of sbom-source.json and sbom-image.json into sbom-cyclonedx.json" + python3 /scripts/merge_syft_sboms.py + + if [ -f "sbom-cachi2.json" ]; then + echo "Merging contents of sbom-cachi2.json into sbom-cyclonedx.json" + python3 /scripts/merge_cachi2_sboms.py sbom-cachi2.json sbom-cyclonedx.json > sbom-temp.json + mv sbom-temp.json sbom-cyclonedx.json + fi + + echo "Adding base images data to sbom-cyclonedx.json" + python3 /scripts/base_images_sbom_script.py \ + --sbom=sbom-cyclonedx.json \ + --parsed-dockerfile=/shared/parsed_dockerfile.json \ + --base-images-digests=/shared/base_images_digests + + echo "Adding image reference to sbom" + IMAGE_URL="$(cat "$(results.IMAGE_URL.path)")" + IMAGE_DIGEST="$(cat "$(results.IMAGE_DIGEST.path)")" + + python3 /scripts/add_image_reference.py \ + --image-url "$IMAGE_URL" \ + --image-digest "$IMAGE_DIGEST" \ + --input-file sbom-cyclonedx.json \ + --output-file /tmp/sbom-cyclonedx.tmp.json + + mv /tmp/sbom-cyclonedx.tmp.json sbom-cyclonedx.json + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - computeResources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + image: quay.io/konflux-ci/appstudio-utils:48c311af02858e2422d6229600e9959e496ddef1@sha256:91ddd999271f65d8ec8487b10f3dd378f81aa894e11b9af4d10639fd52bba7e8 + name: upload-sbom + script: | + #!/bin/bash + + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + cosign attach sbom --sbom sbom-cyclonedx.json --type cyclonedx "$(cat "$(results.IMAGE_REF.path)")" + + # Remove tag from IMAGE while allowing registry to contain a port number. + sbom_repo="${IMAGE%:*}" + sbom_digest="$(sha256sum sbom-cyclonedx.json | cut -d' ' -f1)" + # The SBOM_BLOB_URL is created by `cosign attach sbom`. + echo -n "${sbom_repo}@sha256:${sbom_digest}" | tee "$(results.SBOM_BLOB_URL.path)" + volumeMounts: + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + volumes: + - emptyDir: {} + name: varlibcontainers + - emptyDir: {} + name: shared + - name: etc-pki-entitlement + secret: + optional: true + secretName: $(params.ENTITLEMENT_SECRET) + - name: activation-key + secret: + optional: true + secretName: $(params.ACTIVATION_KEY) + - name: additional-secret + secret: + optional: true + secretName: $(params.ADDITIONAL_SECRET) + - configMap: + items: + - key: $(params.caTrustConfigMapKey) + path: ca-bundle.crt + name: $(params.caTrustConfigMapName) + optional: true + name: trusted-ca + workspaces: + - description: Workspace containing the source code to build. + name: source diff --git a/auto-generated/task/buildah-20gb/0.1/tekton.dev_v1_task_buildah-20gb.yaml b/auto-generated/task/buildah-20gb/0.1/tekton.dev_v1_task_buildah-20gb.yaml new file mode 100644 index 0000000000..ae256ba88e --- /dev/null +++ b/auto-generated/task/buildah-20gb/0.1/tekton.dev_v1_task_buildah-20gb.yaml @@ -0,0 +1,585 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + annotations: + build.appstudio.redhat.com/expires-on: "2025-01-21T00:00:00Z" + build.appstudio.redhat.com/expiry-message: 'Instead of using this task, switch + to buildah task (you can find latest bundle reference here: https://quay.io/repository/konflux-ci/tekton-catalog/task-buildah) + and configure build step resources as described in the doc: https://konflux-ci.dev/docs/how-tos/configuring/overriding-compute-resources/' + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: image-build, konflux + labels: + app.kubernetes.io/version: "0.1" + build.appstudio.redhat.com/build_type: docker + name: buildah-20gb +spec: + description: |- + Buildah task builds source code into a container image and pushes the image into container registry using buildah tool. + In addition it generates a SBOM file, injects the SBOM file into final container image and pushes the SBOM file as separate image using cosign tool. + When [Java dependency rebuild](https://redhat-appstudio.github.io/docs.stonesoup.io/Documentation/main/cli/proc_enabled_java_dependencies.html) is enabled it triggers rebuilds of Java artifacts. + When prefetch-dependencies task was activated it is using its artifacts to run build in hermetic environment. + params: + - description: Reference of the image buildah will produce. + name: IMAGE + type: string + - default: "" + description: Deprecated. Has no effect. Will be removed in the future. + name: BUILDER_IMAGE + type: string + - default: ./Dockerfile + description: Path to the Dockerfile to build. + name: DOCKERFILE + type: string + - default: . + description: Path to the directory to use as context. + name: CONTEXT + type: string + - default: "true" + description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS + registry) + name: TLSVERIFY + type: string + - default: "" + description: unused, should be removed in next task version + name: DOCKER_AUTH + type: string + - default: "false" + description: Determines if build will be executed without network access. + name: HERMETIC + type: string + - default: "" + description: In case it is not empty, the prefetched content should be made available + to the build. + name: PREFETCH_INPUT + type: string + - default: "" + description: Delete image tag after specified time. Empty means to keep the image + tag. Time values could be something like 1h, 2d, 3w for hours, days, and weeks, + respectively. + name: IMAGE_EXPIRES_AFTER + type: string + - default: "" + description: The image is built from this commit. + name: COMMIT_SHA + type: string + - default: repos.d + description: Path in the git repository in which yum repository files are stored + name: YUM_REPOS_D_SRC + - default: fetched.repos.d + description: Path in source workspace where dynamically-fetched repos are present + name: YUM_REPOS_D_FETCHED + - default: /etc/yum.repos.d + description: Target path on the container in which yum repository files should + be made available + name: YUM_REPOS_D_TARGET + - default: "" + description: Target stage in Dockerfile to build. If not specified, the Dockerfile + is processed entirely to (and including) its last stage. + name: TARGET_STAGE + type: string + - default: etc-pki-entitlement + description: Name of secret which contains the entitlement certificates + name: ENTITLEMENT_SECRET + type: string + - default: activation-key + description: Name of secret which contains subscription activation key + name: ACTIVATION_KEY + type: string + - default: does-not-exist + description: Name of a secret which will be made available to the build with 'buildah + build --secret' at /run/secrets/$ADDITIONAL_SECRET + name: ADDITIONAL_SECRET + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) + name: BUILD_ARGS + type: array + - default: "" + description: Path to a file with build arguments, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: BUILD_ARGS_FILE + type: string + - default: trusted-ca + description: The name of the ConfigMap to read CA bundle data from. + name: caTrustConfigMapName + type: string + - default: ca-bundle.crt + description: The name of the key in the ConfigMap that contains the CA bundle + data. + name: caTrustConfigMapKey + type: string + - default: "" + description: Comma separated list of extra capabilities to add when running 'buildah + build' + name: ADD_CAPABILITIES + type: string + - default: "false" + description: Squash all new and previous layers added as a part of this build, + as per --squash + name: SQUASH + type: string + - default: vfs + description: Storage driver to configure for buildah + name: STORAGE_DRIVER + type: string + - default: "true" + description: Whether to skip stages in Containerfile that seem unused by subsequent + stages + name: SKIP_UNUSED_STAGES + type: string + results: + - description: Digest of the image just built + name: IMAGE_DIGEST + - description: Image repository and tag where the built image was pushed + name: IMAGE_URL + - description: Digests of the base images used for build + name: BASE_IMAGES_DIGESTS + - description: The counting of Java components by publisher in JSON format + name: SBOM_JAVA_COMPONENTS_COUNT + type: string + - description: The Java dependencies that came from community sources such as Maven + central. + name: JAVA_COMMUNITY_DEPENDENCIES + stepTemplate: + env: + - name: BUILDAH_FORMAT + value: oci + - name: STORAGE_DRIVER + value: $(params.STORAGE_DRIVER) + - name: HERMETIC + value: $(params.HERMETIC) + - name: CONTEXT + value: $(params.CONTEXT) + - name: DOCKERFILE + value: $(params.DOCKERFILE) + - name: IMAGE + value: $(params.IMAGE) + - name: TLSVERIFY + value: $(params.TLSVERIFY) + - name: IMAGE_EXPIRES_AFTER + value: $(params.IMAGE_EXPIRES_AFTER) + - name: YUM_REPOS_D_SRC + value: $(params.YUM_REPOS_D_SRC) + - name: YUM_REPOS_D_FETCHED + value: $(params.YUM_REPOS_D_FETCHED) + - name: YUM_REPOS_D_TARGET + value: $(params.YUM_REPOS_D_TARGET) + - name: TARGET_STAGE + value: $(params.TARGET_STAGE) + - name: PARAM_BUILDER_IMAGE + value: $(params.BUILDER_IMAGE) + - name: ENTITLEMENT_SECRET + value: $(params.ENTITLEMENT_SECRET) + - name: ADDITIONAL_SECRET + value: $(params.ADDITIONAL_SECRET) + - name: BUILD_ARGS_FILE + value: $(params.BUILD_ARGS_FILE) + - name: ADD_CAPABILITIES + value: $(params.ADD_CAPABILITIES) + - name: SQUASH + value: $(params.SQUASH) + - name: SKIP_UNUSED_STAGES + value: $(params.SKIP_UNUSED_STAGES) + volumeMounts: + - mountPath: /shared + name: shared + steps: + - args: + - $(params.BUILD_ARGS[*]) + computeResources: + limits: + memory: 20Gi + requests: + cpu: 250m + memory: 16Gi + env: + - name: COMMIT_SHA + value: $(params.COMMIT_SHA) + image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: build + script: | + if [ -n "${PARAM_BUILDER_IMAGE}" ]; then + echo "WARNING: provided deprecated BUILDER_IMAGE parameter has no effect." + fi + + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + SOURCE_CODE_DIR=source + if [ -e "$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" + elif [ -e "$SOURCE_CODE_DIR/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$DOCKERFILE" + elif echo "$DOCKERFILE" | grep -q "^https\?://"; then + echo "Fetch Dockerfile from $DOCKERFILE" + dockerfile_path=$(mktemp --suffix=-Dockerfile) + http_code=$(curl -s -L -w "%{http_code}" --output "$dockerfile_path" "$DOCKERFILE") + if [ $http_code != 200 ]; then + echo "No Dockerfile is fetched. Server responds $http_code" + exit 1 + fi + http_code=$(curl -s -L -w "%{http_code}" --output "$dockerfile_path.dockerignore.tmp" "$DOCKERFILE.dockerignore") + if [ $http_code = 200 ]; then + echo "Fetched .dockerignore from $DOCKERFILE.dockerignore" + mv "$dockerfile_path.dockerignore.tmp" $SOURCE_CODE_DIR/$CONTEXT/.dockerignore + fi + else + echo "Cannot find Dockerfile $DOCKERFILE" + exit 1 + fi + if [ -n "$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR" ] && grep -q '^\s*RUN \(./\)\?mvn' "$dockerfile_path"; then + sed -i -e "s|^\s*RUN \(\(./\)\?mvn\)\(.*\)|RUN echo \"mirror.defaulthttp://$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR/v1/cache/default/0/*\" > /tmp/settings.yaml; \1 -s /tmp/settings.yaml \3|g" "$dockerfile_path" + touch /var/lib/containers/java + fi + + # Fixing group permission on /var/lib/containers + chown root:root /var/lib/containers + + sed -i 's/^\s*short-name-mode\s*=\s*.*/short-name-mode = "disabled"/' /etc/containers/registries.conf + + # Setting new namespace to run buildah - 2^32-2 + echo 'root:1:4294967294' | tee -a /etc/subuid >> /etc/subgid + + BUILDAH_ARGS=() + + BASE_IMAGES=$(grep -i '^\s*FROM' "$dockerfile_path" | sed 's/--platform=\S*//' | awk '{print $2}' | (grep -v ^oci-archive: || true)) + if [ "${HERMETIC}" == "true" ]; then + BUILDAH_ARGS+=("--pull=never") + UNSHARE_ARGS="--net" + for image in $BASE_IMAGES; do + if [ "${image}" != "scratch" ]; then + unshare -Ufp --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -- buildah pull $image + fi + done + echo "Build will be executed with network isolation" + fi + + if [ -n "${TARGET_STAGE}" ]; then + BUILDAH_ARGS+=("--target=${TARGET_STAGE}") + fi + + if [ -n "${BUILD_ARGS_FILE}" ]; then + BUILDAH_ARGS+=("--build-arg-file=$(pwd)/$SOURCE_CODE_DIR/${BUILD_ARGS_FILE}") + fi + + for build_arg in "$@"; do + BUILDAH_ARGS+=("--build-arg=$build_arg") + done + + if [ -n "${ADD_CAPABILITIES}" ]; then + BUILDAH_ARGS+=("--cap-add=${ADD_CAPABILITIES}") + fi + + if [ "${SQUASH}" == "true" ]; then + BUILDAH_ARGS+=("--squash") + fi + + if [ "${SKIP_UNUSED_STAGES}" != "true" ] ; then + BUILDAH_ARGS+=("--skip-unused-stages=false") + fi + + if [ -f "$(workspaces.source.path)/cachi2/cachi2.env" ]; then + cp -r "$(workspaces.source.path)/cachi2" /tmp/ + chmod -R go+rwX /tmp/cachi2 + VOLUME_MOUNTS="--volume /tmp/cachi2:/cachi2" + # Read in the whole file (https://unix.stackexchange.com/questions/533277), then + # for each RUN ... line insert the cachi2.env command *after* any options like --mount + sed -E -i \ + -e 'H;1h;$!d;x' \ + -e 's@^\s*(run((\s|\\\n)+-\S+)*(\s|\\\n)+)@\1. /cachi2/cachi2.env \&\& \\\n @igM' \ + "$dockerfile_path" + echo "Prefetched content will be made available" + + prefetched_repo_for_my_arch="/tmp/cachi2/output/deps/rpm/$(uname -m)/repos.d/cachi2.repo" + if [ -f "$prefetched_repo_for_my_arch" ]; then + echo "Adding $prefetched_repo_for_my_arch to $YUM_REPOS_D_FETCHED" + mkdir -p "$YUM_REPOS_D_FETCHED" + cp --no-clobber "$prefetched_repo_for_my_arch" "$YUM_REPOS_D_FETCHED" + fi + fi + + # if yum repofiles stored in git, copy them to mount point outside the source dir + if [ -d "${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}" ]; then + mkdir -p ${YUM_REPOS_D_FETCHED} + cp -r ${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}/* ${YUM_REPOS_D_FETCHED} + fi + + # if anything in the repofiles mount point (either fetched or from git), mount it + if [ -d "${YUM_REPOS_D_FETCHED}" ]; then + chmod -R go+rwX ${YUM_REPOS_D_FETCHED} + mount_point=$(realpath ${YUM_REPOS_D_FETCHED}) + VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume ${mount_point}:${YUM_REPOS_D_TARGET}" + fi + + LABELS=( + "--label" "build-date=$(date -u +'%Y-%m-%dT%H:%M:%S')" + "--label" "architecture=$(uname -m)" + "--label" "vcs-type=git" + ) + [ -n "$COMMIT_SHA" ] && LABELS+=("--label" "vcs-ref=$COMMIT_SHA") + [ -n "$IMAGE_EXPIRES_AFTER" ] && LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + + ACTIVATION_KEY_PATH="/activation-key" + ENTITLEMENT_PATH="/entitlement" + + if [ -e /activation-key/org ]; then + cp -r --preserve=mode "$ACTIVATION_KEY_PATH" /tmp/activation-key + mkdir /shared/rhsm-tmp + VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume /tmp/activation-key:/activation-key -v /shared/rhsm-tmp:/etc/pki/entitlement:Z" + echo "Adding activation key to the build" + + elif find /entitlement -name "*.pem" >> null; then + cp -r --preserve=mode "$ENTITLEMENT_PATH" /tmp/entitlement + VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume /tmp/entitlement:/etc/pki/entitlement" + echo "Adding the entitlement to the build" + fi + + ADDITIONAL_SECRET_PATH="/additional-secret" + ADDITIONAL_SECRET_TMP="/tmp/additional-secret" + if [ -d "$ADDITIONAL_SECRET_PATH" ]; then + cp -r --preserve=mode -L "$ADDITIONAL_SECRET_PATH" $ADDITIONAL_SECRET_TMP + while read -r filename; do + echo "Adding the secret ${ADDITIONAL_SECRET}/${filename} to the build, available at /run/secrets/${ADDITIONAL_SECRET}/${filename}" + BUILDAH_ARGS+=("--secret=id=${ADDITIONAL_SECRET}/${filename},src=$ADDITIONAL_SECRET_TMP/${filename}") + done < <(find $ADDITIONAL_SECRET_TMP -maxdepth 1 -type f -exec basename {} \;) + fi + + unshare -Uf $UNSHARE_ARGS --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -w ${SOURCE_CODE_DIR}/$CONTEXT -- buildah build \ + $VOLUME_MOUNTS \ + "${BUILDAH_ARGS[@]}" \ + "${LABELS[@]}" \ + --tls-verify=$TLSVERIFY --no-cache \ + --ulimit nofile=4096:4096 \ + -f "$dockerfile_path" -t $IMAGE . + + container=$(buildah from --pull-never $IMAGE) + buildah mount $container | tee /shared/container_path + # delete symlinks - they may point outside the container rootfs, messing with SBOM scanners + find $(cat /shared/container_path) -xtype l -delete + echo $container > /shared/container_name + + # Save the SBOM produced by Cachi2 so it can be merged into the final SBOM later + if [ -f "/tmp/cachi2/output/bom.json" ]; then + cp /tmp/cachi2/output/bom.json ./sbom-cachi2.json + fi + + # Expose base image digests + touch $(results.BASE_IMAGES_DIGESTS.path) + for image in $BASE_IMAGES; do + if [ "${image}" != "scratch" ]; then + buildah images --format '{{ .Name }}:{{ .Tag }}@{{ .Digest }}' --filter reference="$image" >> $(results.BASE_IMAGES_DIGESTS.path) + fi + done + + # Needed to generate base images SBOM + echo "$BASE_IMAGES" > $(workspaces.source.path)/base_images_from_dockerfile + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /entitlement + name: etc-pki-entitlement + - mountPath: /activation-key + name: activation-key + - mountPath: /additional-secret + name: additional-secret + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + - image: registry.access.redhat.com/rh-syft-tech-preview/syft-rhel9:1.4.1@sha256:34d7065427085a31dc4949bd283c001b91794d427e1e4cdf1b21ea4faf9fee3f + name: sbom-syft-generate + script: | + echo "Running syft on the source directory" + syft dir:$(workspaces.source.path)/source --output cyclonedx-json=$(workspaces.source.path)/sbom-source.json + echo "Running syft on the image filesystem" + syft dir:$(cat /shared/container_path) --output cyclonedx-json=$(workspaces.source.path)/sbom-image.json + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + workingDir: $(workspaces.source.path)/source + - image: quay.io/redhat-appstudio/hacbs-jvm-build-request-processor:127ee0c223a2b56a9bd20a6f2eaeed3bd6015f77 + name: analyse-dependencies-java-sbom + script: | + if [ -f /var/lib/containers/java ]; then + /opt/jboss/container/java/run/run-java.sh analyse-dependencies path $(cat /shared/container_path) -s $(workspaces.source.path)/sbom-image.json --task-run-name $(context.taskRun.name) --publishers $(results.SBOM_JAVA_COMPONENTS_COUNT.path) + sed -i 's/^/ /' $(results.SBOM_JAVA_COMPONENTS_COUNT.path) # Workaround for SRVKP-2875 + else + touch $(results.JAVA_COMMUNITY_DEPENDENCIES.path) + fi + securityContext: + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + - image: registry.access.redhat.com/ubi9/python-39:9.5-1734610342@sha256:dde5068ba8fd81eef41a9128ddad2b99e2e02e5869ffe925c605b609a0ad7bbb + name: merge-syft-sboms + script: | + #!/bin/python3 + import json + + # load SBOMs + with open("./sbom-image.json") as f: + image_sbom = json.load(f) + + with open("./sbom-source.json") as f: + source_sbom = json.load(f) + + # fetch unique components from available SBOMs + def get_identifier(component): + return component["name"] + '@' + component.get("version", "") + + image_sbom_components = image_sbom.setdefault("components", []) + existing_components = [get_identifier(component) for component in image_sbom_components] + + source_sbom_components = source_sbom.get("components", []) + for component in source_sbom_components: + if get_identifier(component) not in existing_components: + image_sbom_components.append(component) + existing_components.append(get_identifier(component)) + + image_sbom_components.sort(key=lambda c: get_identifier(c)) + + # write the CycloneDX unified SBOM + with open("./sbom-cyclonedx.json", "w") as f: + json.dump(image_sbom, f, indent=4) + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - image: quay.io/redhat-appstudio/cachi2:0.16.0@sha256:55415cd8ded149f5d56d3fca46d93125b86b41e07ae5d3c03caa240b7b93b7d8 + name: merge-cachi2-sbom + script: | + if [ -f "sbom-cachi2.json" ]; then + echo "Merging contents of sbom-cachi2.json into sbom-cyclonedx.json" + merge_syft_sbom sbom-cachi2.json sbom-cyclonedx.json > sbom-temp.json + mv sbom-temp.json sbom-cyclonedx.json + else + echo "Skipping step since no Cachi2 SBOM was produced" + fi + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - image: registry.access.redhat.com/ubi9/python-39:9.5-1734610342@sha256:dde5068ba8fd81eef41a9128ddad2b99e2e02e5869ffe925c605b609a0ad7bbb + name: create-purl-sbom + script: | + #!/bin/python3 + import json + + with open("./sbom-cyclonedx.json") as f: + cyclonedx_sbom = json.load(f) + + purls = [{"purl": component["purl"]} for component in cyclonedx_sbom.get("components", []) if "purl" in component] + purl_content = {"image_contents": {"dependencies": purls}} + + with open("sbom-purl.json", "w") as output_file: + json.dump(purl_content, output_file, indent=4) + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - env: + - name: BASE_IMAGES_DIGESTS_PATH + value: $(results.BASE_IMAGES_DIGESTS.path) + image: quay.io/redhat-appstudio/base-images-sbom-script@sha256:667669e3def018f9dbb8eaf8868887a40bc07842221e9a98f6787edcff021840 + name: create-base-images-sbom + script: | + python3 /app/base_images_sbom_script.py --sbom=sbom-cyclonedx.json --base-images-from-dockerfile=base_images_from_dockerfile --base-images-digests=$BASE_IMAGES_DIGESTS_PATH + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - computeResources: {} + image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: inject-sbom-and-push + script: | + if [ -n "${PARAM_BUILDER_IMAGE}" ]; then + echo "WARNING: provided deprecated BUILDER_IMAGE parameter has no effect." + fi + + base_image_name=$(buildah inspect --format '{{ index .ImageAnnotations "org.opencontainers.image.base.name"}}' $IMAGE | cut -f1 -d'@') + base_image_digest=$(buildah inspect --format '{{ index .ImageAnnotations "org.opencontainers.image.base.digest"}}' $IMAGE) + container=$(buildah from --pull-never $IMAGE) + buildah copy $container sbom-cyclonedx.json sbom-purl.json /root/buildinfo/content_manifests/ + buildah config -a org.opencontainers.image.base.name=${base_image_name} -a org.opencontainers.image.base.digest=${base_image_digest} $container + + BUILDAH_ARGS=() + if [ "${SQUASH}" == "true" ]; then + BUILDAH_ARGS+=("--squash") + fi + + buildah commit "${BUILDAH_ARGS[@]}" $container $IMAGE + + status=-1 + max_run=5 + sleep_sec=10 + for run in $(seq 1 $max_run); do + status=0 + [ "$run" -gt 1 ] && sleep $sleep_sec + echo "Pushing sbom image to registry" + buildah push \ + --tls-verify=$TLSVERIFY \ + --digestfile $(workspaces.source.path)/image-digest $IMAGE \ + docker://$IMAGE && break || status=$? + done + if [ "$status" -ne 0 ]; then + echo "Failed to push sbom image to registry after ${max_run} tries" + exit 1 + fi + + cat "$(workspaces.source.path)"/image-digest | tee $(results.IMAGE_DIGEST.path) + echo -n "$IMAGE" | tee $(results.IMAGE_URL.path) + securityContext: + capabilities: + add: + - SETFCAP + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + workingDir: $(workspaces.source.path) + - args: + - attach + - sbom + - --sbom + - sbom-cyclonedx.json + - --type + - cyclonedx + - $(params.IMAGE) + image: quay.io/redhat-appstudio/cosign:v2.1.1@sha256:c883d6f8d39148f2cea71bff4622d196d89df3e510f36c140c097b932f0dd5d5 + name: upload-sbom + workingDir: $(workspaces.source.path) + volumes: + - emptyDir: {} + name: varlibcontainers + - emptyDir: {} + name: shared + - name: etc-pki-entitlement + secret: + optional: true + secretName: $(params.ENTITLEMENT_SECRET) + - name: activation-key + secret: + optional: true + secretName: $(params.ACTIVATION_KEY) + - name: additional-secret + secret: + optional: true + secretName: $(params.ADDITIONAL_SECRET) + - configMap: + items: + - key: $(params.caTrustConfigMapKey) + path: ca-bundle.crt + name: $(params.caTrustConfigMapName) + optional: true + name: trusted-ca + workspaces: + - description: Workspace containing the source code to build. + name: source diff --git a/auto-generated/task/buildah-20gb/0.2/tekton.dev_v1_task_buildah-20gb.yaml b/auto-generated/task/buildah-20gb/0.2/tekton.dev_v1_task_buildah-20gb.yaml new file mode 100644 index 0000000000..a866bfd817 --- /dev/null +++ b/auto-generated/task/buildah-20gb/0.2/tekton.dev_v1_task_buildah-20gb.yaml @@ -0,0 +1,722 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + annotations: + build.appstudio.redhat.com/expires-on: "2025-01-21T00:00:00Z" + build.appstudio.redhat.com/expiry-message: 'Instead of using this task, switch + to buildah task (you can find latest bundle reference here: https://quay.io/repository/konflux-ci/tekton-catalog/task-buildah) + and configure build step resources as described in the doc: https://konflux-ci.dev/docs/how-tos/configuring/overriding-compute-resources/' + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: image-build, konflux + labels: + app.kubernetes.io/version: 0.2.1 + build.appstudio.redhat.com/build_type: docker + name: buildah-20gb +spec: + description: |- + Buildah task builds source code into a container image and pushes the image into container registry using buildah tool. + In addition it generates a SBOM file, injects the SBOM file into final container image and pushes the SBOM file as separate image using cosign tool. + When [Java dependency rebuild](https://redhat-appstudio.github.io/docs.stonesoup.io/Documentation/main/cli/proc_enabled_java_dependencies.html) is enabled it triggers rebuilds of Java artifacts. + When prefetch-dependencies task was activated it is using its artifacts to run build in hermetic environment. + params: + - description: Reference of the image buildah will produce. + name: IMAGE + type: string + - default: ./Dockerfile + description: Path to the Dockerfile to build. + name: DOCKERFILE + type: string + - default: . + description: Path to the directory to use as context. + name: CONTEXT + type: string + - default: "true" + description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS + registry) + name: TLSVERIFY + type: string + - default: "false" + description: Determines if build will be executed without network access. + name: HERMETIC + type: string + - default: "" + description: In case it is not empty, the prefetched content should be made available + to the build. + name: PREFETCH_INPUT + type: string + - default: "" + description: Delete image tag after specified time. Empty means to keep the image + tag. Time values could be something like 1h, 2d, 3w for hours, days, and weeks, + respectively. + name: IMAGE_EXPIRES_AFTER + type: string + - default: "" + description: The image is built from this commit. + name: COMMIT_SHA + type: string + - default: repos.d + description: Path in the git repository in which yum repository files are stored + name: YUM_REPOS_D_SRC + - default: fetched.repos.d + description: Path in source workspace where dynamically-fetched repos are present + name: YUM_REPOS_D_FETCHED + - default: /etc/yum.repos.d + description: Target path on the container in which yum repository files should + be made available + name: YUM_REPOS_D_TARGET + - default: "" + description: Target stage in Dockerfile to build. If not specified, the Dockerfile + is processed entirely to (and including) its last stage. + name: TARGET_STAGE + type: string + - default: etc-pki-entitlement + description: Name of secret which contains the entitlement certificates + name: ENTITLEMENT_SECRET + type: string + - default: activation-key + description: Name of secret which contains subscription activation key + name: ACTIVATION_KEY + type: string + - default: does-not-exist + description: Name of a secret which will be made available to the build with 'buildah + build --secret' at /run/secrets/$ADDITIONAL_SECRET + name: ADDITIONAL_SECRET + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) + name: BUILD_ARGS + type: array + - default: "" + description: Path to a file with build arguments, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: BUILD_ARGS_FILE + type: string + - default: trusted-ca + description: The name of the ConfigMap to read CA bundle data from. + name: caTrustConfigMapName + type: string + - default: ca-bundle.crt + description: The name of the key in the ConfigMap that contains the CA bundle + data. + name: caTrustConfigMapKey + type: string + - default: "" + description: Comma separated list of extra capabilities to add when running 'buildah + build' + name: ADD_CAPABILITIES + type: string + - default: "false" + description: Squash all new and previous layers added as a part of this build, + as per --squash + name: SQUASH + type: string + - default: vfs + description: Storage driver to configure for buildah + name: STORAGE_DRIVER + type: string + - default: "true" + description: Whether to skip stages in Containerfile that seem unused by subsequent + stages + name: SKIP_UNUSED_STAGES + type: string + - default: [] + description: Additional key=value labels that should be applied to the image + name: LABELS + type: array + - default: "false" + description: Whether to enable privileged mode + name: PRIVILEGED_NESTED + type: string + results: + - description: Digest of the image just built + name: IMAGE_DIGEST + - description: Image repository and tag where the built image was pushed + name: IMAGE_URL + - description: Image reference of the built image + name: IMAGE_REF + - description: Reference of SBOM blob digest to enable digest-based verification + from provenance + name: SBOM_BLOB_URL + type: string + - description: The counting of Java components by publisher in JSON format + name: SBOM_JAVA_COMPONENTS_COUNT + type: string + - description: The Java dependencies that came from community sources such as Maven + central. + name: JAVA_COMMUNITY_DEPENDENCIES + stepTemplate: + computeResources: + limits: + cpu: "4" + memory: 4Gi + requests: + cpu: "1" + memory: 1Gi + env: + - name: BUILDAH_FORMAT + value: oci + - name: STORAGE_DRIVER + value: $(params.STORAGE_DRIVER) + - name: HERMETIC + value: $(params.HERMETIC) + - name: SOURCE_CODE_DIR + value: source + - name: CONTEXT + value: $(params.CONTEXT) + - name: IMAGE + value: $(params.IMAGE) + - name: TLSVERIFY + value: $(params.TLSVERIFY) + - name: IMAGE_EXPIRES_AFTER + value: $(params.IMAGE_EXPIRES_AFTER) + - name: YUM_REPOS_D_SRC + value: $(params.YUM_REPOS_D_SRC) + - name: YUM_REPOS_D_FETCHED + value: $(params.YUM_REPOS_D_FETCHED) + - name: YUM_REPOS_D_TARGET + value: $(params.YUM_REPOS_D_TARGET) + - name: TARGET_STAGE + value: $(params.TARGET_STAGE) + - name: ENTITLEMENT_SECRET + value: $(params.ENTITLEMENT_SECRET) + - name: ACTIVATION_KEY + value: $(params.ACTIVATION_KEY) + - name: ADDITIONAL_SECRET + value: $(params.ADDITIONAL_SECRET) + - name: BUILD_ARGS_FILE + value: $(params.BUILD_ARGS_FILE) + - name: ADD_CAPABILITIES + value: $(params.ADD_CAPABILITIES) + - name: SQUASH + value: $(params.SQUASH) + - name: SKIP_UNUSED_STAGES + value: $(params.SKIP_UNUSED_STAGES) + - name: PRIVILEGED_NESTED + value: $(params.PRIVILEGED_NESTED) + volumeMounts: + - mountPath: /shared + name: shared + steps: + - args: + - --build-args + - $(params.BUILD_ARGS[*]) + - --labels + - $(params.LABELS[*]) + computeResources: + limits: + cpu: "4" + memory: 20Gi + requests: + cpu: "1" + memory: 16Gi + env: + - name: COMMIT_SHA + value: $(params.COMMIT_SHA) + - name: DOCKERFILE + value: $(params.DOCKERFILE) + image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: build + script: | + #!/bin/bash + set -euo pipefail + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + if [ -e "$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" + elif [ -e "$SOURCE_CODE_DIR/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$DOCKERFILE" + elif [ -e "$DOCKERFILE" ]; then + # Instrumented builds (SAST) use this custom dockerffile step as their base + dockerfile_path="$DOCKERFILE" + elif echo "$DOCKERFILE" | grep -q "^https\?://"; then + echo "Fetch Dockerfile from $DOCKERFILE" + dockerfile_path=$(mktemp --suffix=-Dockerfile) + http_code=$(curl -s -S -L -w "%{http_code}" --output "$dockerfile_path" "$DOCKERFILE") + if [ $http_code != 200 ]; then + echo "No Dockerfile is fetched. Server responds $http_code" + exit 1 + fi + http_code=$(curl -s -S -L -w "%{http_code}" --output "$dockerfile_path.dockerignore.tmp" "$DOCKERFILE.dockerignore") + if [ $http_code = 200 ]; then + echo "Fetched .dockerignore from $DOCKERFILE.dockerignore" + mv "$dockerfile_path.dockerignore.tmp" $SOURCE_CODE_DIR/$CONTEXT/.dockerignore + fi + else + echo "Cannot find Dockerfile $DOCKERFILE" + exit 1 + fi + + dockerfile_copy=$(mktemp --tmpdir "$(basename "$dockerfile_path").XXXXXX") + cp "$dockerfile_path" "$dockerfile_copy" + + if [ -n "${JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR-}" ] && grep -q '^\s*RUN \(./\)\?mvn' "$dockerfile_copy"; then + sed -i -e "s|^\s*RUN \(\(./\)\?mvn\)\(.*\)|RUN echo \"mirror.defaulthttp://$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR/v1/cache/default/0/*\" > /tmp/settings.yaml; \1 -s /tmp/settings.yaml \3|g" "$dockerfile_copy" + touch /var/lib/containers/java + fi + + # Fixing group permission on /var/lib/containers + chown root:root /var/lib/containers + + sed -i 's/^\s*short-name-mode\s*=\s*.*/short-name-mode = "disabled"/' /etc/containers/registries.conf + + # Setting new namespace to run buildah - 2^32-2 + echo 'root:1:4294967294' | tee -a /etc/subuid >> /etc/subgid + + build_args=() + if [ -n "${BUILD_ARGS_FILE}" ]; then + # Parse BUILD_ARGS_FILE ourselves because dockerfile-json doesn't support it + echo "Parsing ARGs from $BUILD_ARGS_FILE" + mapfile -t build_args < <( + # https://www.mankier.com/1/buildah-build#--build-arg-file + # delete lines that start with # + # delete blank lines + sed -e '/^#/d' -e '/^\s*$/d' "${SOURCE_CODE_DIR}/${BUILD_ARGS_FILE}" + ) + fi + + LABELS=() + # Split `args` into two sets of arguments. + while [[ $# -gt 0 ]]; do + case $1 in + --build-args) + shift + # Note: this may result in multiple --build-arg=KEY=value flags with the same KEY being + # passed to buildah. In that case, the *last* occurrence takes precedence. This is why + # we append BUILD_ARGS after the content of the BUILD_ARGS_FILE + while [[ $# -gt 0 && $1 != --* ]]; do build_args+=("$1"); shift; done + ;; + --labels) + shift + while [[ $# -gt 0 && $1 != --* ]]; do LABELS+=("--label" "$1"); shift; done + ;; + *) + echo "unexpected argument: $1" >&2 + exit 2 + ;; + esac + done + + BUILD_ARG_FLAGS=() + for build_arg in "${build_args[@]}"; do + BUILD_ARG_FLAGS+=("--build-arg=$build_arg") + done + + dockerfile-json "${BUILD_ARG_FLAGS[@]}" "$dockerfile_copy" > /shared/parsed_dockerfile.json + BASE_IMAGES=$( + jq -r '.Stages[] | select(.From | .Stage or .Scratch | not) | .BaseName | select(test("^oci-archive:") | not)' /shared/parsed_dockerfile.json + ) + + BUILDAH_ARGS=() + UNSHARE_ARGS=() + + if [ "${HERMETIC}" == "true" ]; then + BUILDAH_ARGS+=("--pull=never") + UNSHARE_ARGS+=("--net") + + for image in $BASE_IMAGES; do + unshare -Ufp --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -- buildah pull $image + done + echo "Build will be executed with network isolation" + fi + + if [ -n "${TARGET_STAGE}" ]; then + BUILDAH_ARGS+=("--target=${TARGET_STAGE}") + fi + + BUILDAH_ARGS+=("${BUILD_ARG_FLAGS[@]}") + + if [ "${PRIVILEGED_NESTED}" == "true" ]; then + BUILDAH_ARGS+=("--security-opt=label=disable") + BUILDAH_ARGS+=("--cap-add=all") + BUILDAH_ARGS+=("--device=/dev/fuse") + fi + + if [ -n "${ADD_CAPABILITIES}" ]; then + BUILDAH_ARGS+=("--cap-add=${ADD_CAPABILITIES}") + fi + + if [ "${SQUASH}" == "true" ]; then + BUILDAH_ARGS+=("--squash") + fi + + if [ "${SKIP_UNUSED_STAGES}" != "true" ] ; then + BUILDAH_ARGS+=("--skip-unused-stages=false") + fi + + VOLUME_MOUNTS=() + + if [ -f "$(workspaces.source.path)/cachi2/cachi2.env" ]; then + cp -r "$(workspaces.source.path)/cachi2" /tmp/ + chmod -R go+rwX /tmp/cachi2 + VOLUME_MOUNTS+=(--volume /tmp/cachi2:/cachi2) + # Read in the whole file (https://unix.stackexchange.com/questions/533277), then + # for each RUN ... line insert the cachi2.env command *after* any options like --mount + sed -E -i \ + -e 'H;1h;$!d;x' \ + -e 's@^\s*(run((\s|\\\n)+-\S+)*(\s|\\\n)+)@\1. /cachi2/cachi2.env \&\& \\\n @igM' \ + "$dockerfile_copy" + echo "Prefetched content will be made available" + + prefetched_repo_for_my_arch="/tmp/cachi2/output/deps/rpm/$(uname -m)/repos.d/cachi2.repo" + if [ -f "$prefetched_repo_for_my_arch" ]; then + echo "Adding $prefetched_repo_for_my_arch to $YUM_REPOS_D_FETCHED" + mkdir -p "$YUM_REPOS_D_FETCHED" + cp --no-clobber "$prefetched_repo_for_my_arch" "$YUM_REPOS_D_FETCHED" + fi + fi + + # if yum repofiles stored in git, copy them to mount point outside the source dir + if [ -d "${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}" ]; then + mkdir -p ${YUM_REPOS_D_FETCHED} + cp -r ${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}/* ${YUM_REPOS_D_FETCHED} + fi + + # if anything in the repofiles mount point (either fetched or from git), mount it + if [ -d "${YUM_REPOS_D_FETCHED}" ]; then + chmod -R go+rwX ${YUM_REPOS_D_FETCHED} + mount_point=$(realpath ${YUM_REPOS_D_FETCHED}) + VOLUME_MOUNTS+=(--volume "${mount_point}:${YUM_REPOS_D_TARGET}") + fi + + DEFAULT_LABELS=( + "--label" "build-date=$(date -u +'%Y-%m-%dT%H:%M:%S')" + "--label" "architecture=$(uname -m)" + "--label" "vcs-type=git" + ) + [ -n "$COMMIT_SHA" ] && DEFAULT_LABELS+=("--label" "vcs-ref=$COMMIT_SHA") + [ -n "$IMAGE_EXPIRES_AFTER" ] && DEFAULT_LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + + # Concatenate defaults and explicit labels. If a label appears twice, the last one wins. + LABELS=("${DEFAULT_LABELS[@]}" "${LABELS[@]}") + + ACTIVATION_KEY_PATH="/activation-key" + ENTITLEMENT_PATH="/entitlement" + + # 0. if hermetic=true, skip all subscription related stuff + # 1. do not enable activation key and entitlement at same time. If both vars are provided, prefer activation key. + # 2. Activation-keys will be used when the key 'org' exists in the activation key secret. + # 3. try to pre-register and mount files to the correct location so that users do no need to modify Dockerfiles. + # 3. If the Dockerfile contains the string "subcription-manager register", add the activation-keys volume + # to buildah but don't pre-register for backwards compatibility. Mount an empty directory on + # shared emptydir volume to "/etc/pki/entitlement" to prevent certificates from being included + + if [ "${HERMETIC}" != "true" ] && [ -e /activation-key/org ]; then + cp -r --preserve=mode "$ACTIVATION_KEY_PATH" /tmp/activation-key + mkdir -p /shared/rhsm/etc/pki/entitlement + mkdir -p /shared/rhsm/etc/pki/consumer + + VOLUME_MOUNTS+=(-v /tmp/activation-key:/activation-key \ + -v /shared/rhsm/etc/pki/entitlement:/etc/pki/entitlement:Z \ + -v /shared/rhsm/etc/pki/consumer:/etc/pki/consumer:Z) + echo "Adding activation key to the build" + + if ! grep -E "^[^#]*subscription-manager.[^#]*register" "$dockerfile_path"; then + # user is not running registration in the Containerfile: pre-register. + echo "Pre-registering with subscription manager." + subscription-manager register --org "$(cat /tmp/activation-key/org)" --activationkey "$(cat /tmp/activation-key/activationkey)" + trap 'subscription-manager unregister || true' EXIT + + # copy generated certificates to /shared volume + cp /etc/pki/entitlement/*.pem /shared/rhsm/etc/pki/entitlement + cp /etc/pki/consumer/*.pem /shared/rhsm/etc/pki/consumer + + # and then mount get /etc/rhsm/ca/redhat-uep.pem into /run/secrets/rhsm/ca + VOLUME_MOUNTS+=(--volume /etc/rhsm/ca/redhat-uep.pem:/etc/rhsm/ca/redhat-uep.pem:Z) + fi + + elif [ "${HERMETIC}" != "true" ] && find /entitlement -name "*.pem" >> null; then + cp -r --preserve=mode "$ENTITLEMENT_PATH" /tmp/entitlement + VOLUME_MOUNTS+=(--volume /tmp/entitlement:/etc/pki/entitlement) + echo "Adding the entitlement to the build" + fi + + if [ -n "${ADDITIONAL_VOLUME_MOUNTS-}" ]; then + # ADDITIONAL_VOLUME_MOUNTS allows to specify more volumes for the build. + # Instrumented builds (SAST) use this step as their base and add some other tools. + while read -r volume_mount; do + VOLUME_MOUNTS+=("--volume=$volume_mount") + done <<< "$ADDITIONAL_VOLUME_MOUNTS" + fi + + ADDITIONAL_SECRET_PATH="/additional-secret" + ADDITIONAL_SECRET_TMP="/tmp/additional-secret" + if [ -d "$ADDITIONAL_SECRET_PATH" ]; then + cp -r --preserve=mode -L "$ADDITIONAL_SECRET_PATH" $ADDITIONAL_SECRET_TMP + while read -r filename; do + echo "Adding the secret ${ADDITIONAL_SECRET}/${filename} to the build, available at /run/secrets/${ADDITIONAL_SECRET}/${filename}" + BUILDAH_ARGS+=("--secret=id=${ADDITIONAL_SECRET}/${filename},src=$ADDITIONAL_SECRET_TMP/${filename}") + done < <(find $ADDITIONAL_SECRET_TMP -maxdepth 1 -type f -exec basename {} \;) + fi + + # Prevent ShellCheck from giving a warning because 'image' is defined and 'IMAGE' is not. + declare IMAGE + + buildah_cmd_array=( + buildah build + "${VOLUME_MOUNTS[@]}" + "${BUILDAH_ARGS[@]}" + "${LABELS[@]}" + --tls-verify="$TLSVERIFY" --no-cache + --ulimit nofile=4096:4096 + -f "$dockerfile_copy" -t "$IMAGE" . + ) + buildah_cmd=$(printf "%q " "${buildah_cmd_array[@]}") + + if [ "${HERMETIC}" == "true" ]; then + # enabling loopback adapter enables Bazel builds to work in hermetic mode. + command="ip link set lo up && $buildah_cmd" + else + command="$buildah_cmd" + fi + + # disable host subcription manager integration + find /usr/share/rhel/secrets -type l -exec unlink {} \; + + unshare -Uf "${UNSHARE_ARGS[@]}" --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -w "${SOURCE_CODE_DIR}/$CONTEXT" -- sh -c "$command" + + container=$(buildah from --pull-never "$IMAGE") + + # Save the SBOM produced by Cachi2 so it can be merged into the final SBOM later + if [ -f "/tmp/cachi2/output/bom.json" ]; then + echo "Making copy of sbom-cachi2.json" + cp /tmp/cachi2/output/bom.json ./sbom-cachi2.json + fi + + buildah mount $container | tee /shared/container_path + # delete symlinks - they may point outside the container rootfs, messing with SBOM scanners + find $(cat /shared/container_path) -xtype l -delete + echo $container > /shared/container_name + + touch /shared/base_images_digests + for image in $BASE_IMAGES; do + base_image_digest=$(buildah images --format '{{ .Name }}:{{ .Tag }}@{{ .Digest }}' --filter reference="$image") + # In some cases, there might be BASE_IMAGES, but not any associated digest. This happens + # if buildah did not use that particular image during build because it was skipped + if [ -n "$base_image_digest" ]; then + echo "$image $base_image_digest" >> /shared/base_images_digests + fi + done + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /entitlement + name: etc-pki-entitlement + - mountPath: /activation-key + name: activation-key + - mountPath: /additional-secret + name: additional-secret + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + - image: quay.io/konflux-ci/icm-injection-scripts:latest@sha256:462980e94ba689b5f56c3d5dfb3358cd8c685300daf65a71532f11898935e7f1 + name: icm + script: | + #!/bin/bash + set -euo pipefail + /scripts/inject-icm.sh "$IMAGE" + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + workingDir: $(workspaces.source.path) + - image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: push + script: | + #!/bin/bash + set -e + + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + retries=5 + # Push to a unique tag based on the TaskRun name to avoid race conditions + echo "Pushing to ${IMAGE%:*}:${TASKRUN_NAME}" + if ! buildah push \ + --retry "$retries" \ + --tls-verify="$TLSVERIFY" \ + "$IMAGE" \ + "docker://${IMAGE%:*}:$(context.taskRun.name)"; + then + echo "Failed to push sbom image to ${IMAGE%:*}:$(context.taskRun.name) after ${retries} tries" + exit 1 + fi + + # Push to a tag based on the git revision + echo "Pushing to ${IMAGE}" + if ! buildah push \ + --retry "$retries" \ + --tls-verify="$TLSVERIFY" \ + --digestfile "$(workspaces.source.path)/image-digest" "$IMAGE" \ + "docker://$IMAGE"; + then + echo "Failed to push sbom image to $IMAGE after ${retries} tries" + exit 1 + fi + + cat "$(workspaces.source.path)"/image-digest | tee $(results.IMAGE_DIGEST.path) + echo -n "$IMAGE" | tee $(results.IMAGE_URL.path) + { + echo -n "${IMAGE}@" + cat "$(workspaces.source.path)/image-digest" + } > "$(results.IMAGE_REF.path)" + securityContext: + capabilities: + add: + - SETFCAP + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + - image: registry.access.redhat.com/rh-syft-tech-preview/syft-rhel9:1.4.1@sha256:34d7065427085a31dc4949bd283c001b91794d427e1e4cdf1b21ea4faf9fee3f + name: sbom-syft-generate + script: | + echo "Running syft on the source directory" + syft dir:"$(workspaces.source.path)/$SOURCE_CODE_DIR/$CONTEXT" --output cyclonedx-json="$(workspaces.source.path)/sbom-source.json" + echo "Running syft on the image filesystem" + syft dir:"$(cat /shared/container_path)" --output cyclonedx-json="$(workspaces.source.path)/sbom-image.json" + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + workingDir: $(workspaces.source.path)/source + - computeResources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + image: quay.io/redhat-appstudio/hacbs-jvm-build-request-processor:127ee0c223a2b56a9bd20a6f2eaeed3bd6015f77 + name: analyse-dependencies-java-sbom + script: | + if [ -f /var/lib/containers/java ]; then + /opt/jboss/container/java/run/run-java.sh analyse-dependencies path $(cat /shared/container_path) -s $(workspaces.source.path)/sbom-image.json --task-run-name $(context.taskRun.name) --publishers $(results.SBOM_JAVA_COMPONENTS_COUNT.path) + sed -i 's/^/ /' $(results.SBOM_JAVA_COMPONENTS_COUNT.path) # Workaround for SRVKP-2875 + else + touch $(results.JAVA_COMMUNITY_DEPENDENCIES.path) + fi + securityContext: + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + - computeResources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + image: quay.io/redhat-appstudio/sbom-utility-scripts-image@sha256:9f1fd11d9c3c517ecc112d192ad361d16ecf6ce00b83b109c93cf3d1c644a357 + name: prepare-sboms + script: | + echo "Merging contents of sbom-source.json and sbom-image.json into sbom-cyclonedx.json" + python3 /scripts/merge_syft_sboms.py + + if [ -f "sbom-cachi2.json" ]; then + echo "Merging contents of sbom-cachi2.json into sbom-cyclonedx.json" + python3 /scripts/merge_cachi2_sboms.py sbom-cachi2.json sbom-cyclonedx.json > sbom-temp.json + mv sbom-temp.json sbom-cyclonedx.json + fi + + echo "Adding base images data to sbom-cyclonedx.json" + python3 /scripts/base_images_sbom_script.py \ + --sbom=sbom-cyclonedx.json \ + --parsed-dockerfile=/shared/parsed_dockerfile.json \ + --base-images-digests=/shared/base_images_digests + + echo "Adding image reference to sbom" + IMAGE_URL="$(cat "$(results.IMAGE_URL.path)")" + IMAGE_DIGEST="$(cat "$(results.IMAGE_DIGEST.path)")" + + python3 /scripts/add_image_reference.py \ + --image-url "$IMAGE_URL" \ + --image-digest "$IMAGE_DIGEST" \ + --input-file sbom-cyclonedx.json \ + --output-file /tmp/sbom-cyclonedx.tmp.json + + mv /tmp/sbom-cyclonedx.tmp.json sbom-cyclonedx.json + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - computeResources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + image: quay.io/konflux-ci/appstudio-utils:48c311af02858e2422d6229600e9959e496ddef1@sha256:91ddd999271f65d8ec8487b10f3dd378f81aa894e11b9af4d10639fd52bba7e8 + name: upload-sbom + script: | + #!/bin/bash + + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + cosign attach sbom --sbom sbom-cyclonedx.json --type cyclonedx "$(cat "$(results.IMAGE_REF.path)")" + + # Remove tag from IMAGE while allowing registry to contain a port number. + sbom_repo="${IMAGE%:*}" + sbom_digest="$(sha256sum sbom-cyclonedx.json | cut -d' ' -f1)" + # The SBOM_BLOB_URL is created by `cosign attach sbom`. + echo -n "${sbom_repo}@sha256:${sbom_digest}" | tee "$(results.SBOM_BLOB_URL.path)" + volumeMounts: + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + volumes: + - emptyDir: {} + name: varlibcontainers + - emptyDir: {} + name: shared + - name: etc-pki-entitlement + secret: + optional: true + secretName: $(params.ENTITLEMENT_SECRET) + - name: activation-key + secret: + optional: true + secretName: $(params.ACTIVATION_KEY) + - name: additional-secret + secret: + optional: true + secretName: $(params.ADDITIONAL_SECRET) + - configMap: + items: + - key: $(params.caTrustConfigMapKey) + path: ca-bundle.crt + name: $(params.caTrustConfigMapName) + optional: true + name: trusted-ca + workspaces: + - description: Workspace containing the source code to build. + name: source diff --git a/auto-generated/task/buildah-24gb/0.1/tekton.dev_v1_task_buildah-24gb.yaml b/auto-generated/task/buildah-24gb/0.1/tekton.dev_v1_task_buildah-24gb.yaml new file mode 100644 index 0000000000..a9f2a01865 --- /dev/null +++ b/auto-generated/task/buildah-24gb/0.1/tekton.dev_v1_task_buildah-24gb.yaml @@ -0,0 +1,586 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + annotations: + build.appstudio.redhat.com/expires-on: "2025-01-21T00:00:00Z" + build.appstudio.redhat.com/expiry-message: 'Instead of using this task, switch + to buildah task (you can find latest bundle reference here: https://quay.io/repository/konflux-ci/tekton-catalog/task-buildah) + and configure build step resources as described in the doc: https://konflux-ci.dev/docs/how-tos/configuring/overriding-compute-resources/' + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: image-build, konflux + labels: + app.kubernetes.io/version: "0.1" + build.appstudio.redhat.com/build_type: docker + name: buildah-24gb +spec: + description: |- + Buildah task builds source code into a container image and pushes the image into container registry using buildah tool. + In addition it generates a SBOM file, injects the SBOM file into final container image and pushes the SBOM file as separate image using cosign tool. + When [Java dependency rebuild](https://redhat-appstudio.github.io/docs.stonesoup.io/Documentation/main/cli/proc_enabled_java_dependencies.html) is enabled it triggers rebuilds of Java artifacts. + When prefetch-dependencies task was activated it is using its artifacts to run build in hermetic environment. + params: + - description: Reference of the image buildah will produce. + name: IMAGE + type: string + - default: "" + description: Deprecated. Has no effect. Will be removed in the future. + name: BUILDER_IMAGE + type: string + - default: ./Dockerfile + description: Path to the Dockerfile to build. + name: DOCKERFILE + type: string + - default: . + description: Path to the directory to use as context. + name: CONTEXT + type: string + - default: "true" + description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS + registry) + name: TLSVERIFY + type: string + - default: "" + description: unused, should be removed in next task version + name: DOCKER_AUTH + type: string + - default: "false" + description: Determines if build will be executed without network access. + name: HERMETIC + type: string + - default: "" + description: In case it is not empty, the prefetched content should be made available + to the build. + name: PREFETCH_INPUT + type: string + - default: "" + description: Delete image tag after specified time. Empty means to keep the image + tag. Time values could be something like 1h, 2d, 3w for hours, days, and weeks, + respectively. + name: IMAGE_EXPIRES_AFTER + type: string + - default: "" + description: The image is built from this commit. + name: COMMIT_SHA + type: string + - default: repos.d + description: Path in the git repository in which yum repository files are stored + name: YUM_REPOS_D_SRC + - default: fetched.repos.d + description: Path in source workspace where dynamically-fetched repos are present + name: YUM_REPOS_D_FETCHED + - default: /etc/yum.repos.d + description: Target path on the container in which yum repository files should + be made available + name: YUM_REPOS_D_TARGET + - default: "" + description: Target stage in Dockerfile to build. If not specified, the Dockerfile + is processed entirely to (and including) its last stage. + name: TARGET_STAGE + type: string + - default: etc-pki-entitlement + description: Name of secret which contains the entitlement certificates + name: ENTITLEMENT_SECRET + type: string + - default: activation-key + description: Name of secret which contains subscription activation key + name: ACTIVATION_KEY + type: string + - default: does-not-exist + description: Name of a secret which will be made available to the build with 'buildah + build --secret' at /run/secrets/$ADDITIONAL_SECRET + name: ADDITIONAL_SECRET + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) + name: BUILD_ARGS + type: array + - default: "" + description: Path to a file with build arguments, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: BUILD_ARGS_FILE + type: string + - default: trusted-ca + description: The name of the ConfigMap to read CA bundle data from. + name: caTrustConfigMapName + type: string + - default: ca-bundle.crt + description: The name of the key in the ConfigMap that contains the CA bundle + data. + name: caTrustConfigMapKey + type: string + - default: "" + description: Comma separated list of extra capabilities to add when running 'buildah + build' + name: ADD_CAPABILITIES + type: string + - default: "false" + description: Squash all new and previous layers added as a part of this build, + as per --squash + name: SQUASH + type: string + - default: vfs + description: Storage driver to configure for buildah + name: STORAGE_DRIVER + type: string + - default: "true" + description: Whether to skip stages in Containerfile that seem unused by subsequent + stages + name: SKIP_UNUSED_STAGES + type: string + results: + - description: Digest of the image just built + name: IMAGE_DIGEST + - description: Image repository and tag where the built image was pushed + name: IMAGE_URL + - description: Digests of the base images used for build + name: BASE_IMAGES_DIGESTS + - description: The counting of Java components by publisher in JSON format + name: SBOM_JAVA_COMPONENTS_COUNT + type: string + - description: The Java dependencies that came from community sources such as Maven + central. + name: JAVA_COMMUNITY_DEPENDENCIES + stepTemplate: + env: + - name: BUILDAH_FORMAT + value: oci + - name: STORAGE_DRIVER + value: $(params.STORAGE_DRIVER) + - name: HERMETIC + value: $(params.HERMETIC) + - name: CONTEXT + value: $(params.CONTEXT) + - name: DOCKERFILE + value: $(params.DOCKERFILE) + - name: IMAGE + value: $(params.IMAGE) + - name: TLSVERIFY + value: $(params.TLSVERIFY) + - name: IMAGE_EXPIRES_AFTER + value: $(params.IMAGE_EXPIRES_AFTER) + - name: YUM_REPOS_D_SRC + value: $(params.YUM_REPOS_D_SRC) + - name: YUM_REPOS_D_FETCHED + value: $(params.YUM_REPOS_D_FETCHED) + - name: YUM_REPOS_D_TARGET + value: $(params.YUM_REPOS_D_TARGET) + - name: TARGET_STAGE + value: $(params.TARGET_STAGE) + - name: PARAM_BUILDER_IMAGE + value: $(params.BUILDER_IMAGE) + - name: ENTITLEMENT_SECRET + value: $(params.ENTITLEMENT_SECRET) + - name: ADDITIONAL_SECRET + value: $(params.ADDITIONAL_SECRET) + - name: BUILD_ARGS_FILE + value: $(params.BUILD_ARGS_FILE) + - name: ADD_CAPABILITIES + value: $(params.ADD_CAPABILITIES) + - name: SQUASH + value: $(params.SQUASH) + - name: SKIP_UNUSED_STAGES + value: $(params.SKIP_UNUSED_STAGES) + volumeMounts: + - mountPath: /shared + name: shared + steps: + - args: + - $(params.BUILD_ARGS[*]) + computeResources: + limits: + cpu: "20" + memory: 24Gi + requests: + cpu: "10" + memory: 20Gi + env: + - name: COMMIT_SHA + value: $(params.COMMIT_SHA) + image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: build + script: | + if [ -n "${PARAM_BUILDER_IMAGE}" ]; then + echo "WARNING: provided deprecated BUILDER_IMAGE parameter has no effect." + fi + + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + SOURCE_CODE_DIR=source + if [ -e "$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" + elif [ -e "$SOURCE_CODE_DIR/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$DOCKERFILE" + elif echo "$DOCKERFILE" | grep -q "^https\?://"; then + echo "Fetch Dockerfile from $DOCKERFILE" + dockerfile_path=$(mktemp --suffix=-Dockerfile) + http_code=$(curl -s -L -w "%{http_code}" --output "$dockerfile_path" "$DOCKERFILE") + if [ $http_code != 200 ]; then + echo "No Dockerfile is fetched. Server responds $http_code" + exit 1 + fi + http_code=$(curl -s -L -w "%{http_code}" --output "$dockerfile_path.dockerignore.tmp" "$DOCKERFILE.dockerignore") + if [ $http_code = 200 ]; then + echo "Fetched .dockerignore from $DOCKERFILE.dockerignore" + mv "$dockerfile_path.dockerignore.tmp" $SOURCE_CODE_DIR/$CONTEXT/.dockerignore + fi + else + echo "Cannot find Dockerfile $DOCKERFILE" + exit 1 + fi + if [ -n "$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR" ] && grep -q '^\s*RUN \(./\)\?mvn' "$dockerfile_path"; then + sed -i -e "s|^\s*RUN \(\(./\)\?mvn\)\(.*\)|RUN echo \"mirror.defaulthttp://$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR/v1/cache/default/0/*\" > /tmp/settings.yaml; \1 -s /tmp/settings.yaml \3|g" "$dockerfile_path" + touch /var/lib/containers/java + fi + + # Fixing group permission on /var/lib/containers + chown root:root /var/lib/containers + + sed -i 's/^\s*short-name-mode\s*=\s*.*/short-name-mode = "disabled"/' /etc/containers/registries.conf + + # Setting new namespace to run buildah - 2^32-2 + echo 'root:1:4294967294' | tee -a /etc/subuid >> /etc/subgid + + BUILDAH_ARGS=() + + BASE_IMAGES=$(grep -i '^\s*FROM' "$dockerfile_path" | sed 's/--platform=\S*//' | awk '{print $2}' | (grep -v ^oci-archive: || true)) + if [ "${HERMETIC}" == "true" ]; then + BUILDAH_ARGS+=("--pull=never") + UNSHARE_ARGS="--net" + for image in $BASE_IMAGES; do + if [ "${image}" != "scratch" ]; then + unshare -Ufp --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -- buildah pull $image + fi + done + echo "Build will be executed with network isolation" + fi + + if [ -n "${TARGET_STAGE}" ]; then + BUILDAH_ARGS+=("--target=${TARGET_STAGE}") + fi + + if [ -n "${BUILD_ARGS_FILE}" ]; then + BUILDAH_ARGS+=("--build-arg-file=$(pwd)/$SOURCE_CODE_DIR/${BUILD_ARGS_FILE}") + fi + + for build_arg in "$@"; do + BUILDAH_ARGS+=("--build-arg=$build_arg") + done + + if [ -n "${ADD_CAPABILITIES}" ]; then + BUILDAH_ARGS+=("--cap-add=${ADD_CAPABILITIES}") + fi + + if [ "${SQUASH}" == "true" ]; then + BUILDAH_ARGS+=("--squash") + fi + + if [ "${SKIP_UNUSED_STAGES}" != "true" ] ; then + BUILDAH_ARGS+=("--skip-unused-stages=false") + fi + + if [ -f "$(workspaces.source.path)/cachi2/cachi2.env" ]; then + cp -r "$(workspaces.source.path)/cachi2" /tmp/ + chmod -R go+rwX /tmp/cachi2 + VOLUME_MOUNTS="--volume /tmp/cachi2:/cachi2" + # Read in the whole file (https://unix.stackexchange.com/questions/533277), then + # for each RUN ... line insert the cachi2.env command *after* any options like --mount + sed -E -i \ + -e 'H;1h;$!d;x' \ + -e 's@^\s*(run((\s|\\\n)+-\S+)*(\s|\\\n)+)@\1. /cachi2/cachi2.env \&\& \\\n @igM' \ + "$dockerfile_path" + echo "Prefetched content will be made available" + + prefetched_repo_for_my_arch="/tmp/cachi2/output/deps/rpm/$(uname -m)/repos.d/cachi2.repo" + if [ -f "$prefetched_repo_for_my_arch" ]; then + echo "Adding $prefetched_repo_for_my_arch to $YUM_REPOS_D_FETCHED" + mkdir -p "$YUM_REPOS_D_FETCHED" + cp --no-clobber "$prefetched_repo_for_my_arch" "$YUM_REPOS_D_FETCHED" + fi + fi + + # if yum repofiles stored in git, copy them to mount point outside the source dir + if [ -d "${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}" ]; then + mkdir -p ${YUM_REPOS_D_FETCHED} + cp -r ${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}/* ${YUM_REPOS_D_FETCHED} + fi + + # if anything in the repofiles mount point (either fetched or from git), mount it + if [ -d "${YUM_REPOS_D_FETCHED}" ]; then + chmod -R go+rwX ${YUM_REPOS_D_FETCHED} + mount_point=$(realpath ${YUM_REPOS_D_FETCHED}) + VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume ${mount_point}:${YUM_REPOS_D_TARGET}" + fi + + LABELS=( + "--label" "build-date=$(date -u +'%Y-%m-%dT%H:%M:%S')" + "--label" "architecture=$(uname -m)" + "--label" "vcs-type=git" + ) + [ -n "$COMMIT_SHA" ] && LABELS+=("--label" "vcs-ref=$COMMIT_SHA") + [ -n "$IMAGE_EXPIRES_AFTER" ] && LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + + ACTIVATION_KEY_PATH="/activation-key" + ENTITLEMENT_PATH="/entitlement" + + if [ -e /activation-key/org ]; then + cp -r --preserve=mode "$ACTIVATION_KEY_PATH" /tmp/activation-key + mkdir /shared/rhsm-tmp + VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume /tmp/activation-key:/activation-key -v /shared/rhsm-tmp:/etc/pki/entitlement:Z" + echo "Adding activation key to the build" + + elif find /entitlement -name "*.pem" >> null; then + cp -r --preserve=mode "$ENTITLEMENT_PATH" /tmp/entitlement + VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume /tmp/entitlement:/etc/pki/entitlement" + echo "Adding the entitlement to the build" + fi + + ADDITIONAL_SECRET_PATH="/additional-secret" + ADDITIONAL_SECRET_TMP="/tmp/additional-secret" + if [ -d "$ADDITIONAL_SECRET_PATH" ]; then + cp -r --preserve=mode -L "$ADDITIONAL_SECRET_PATH" $ADDITIONAL_SECRET_TMP + while read -r filename; do + echo "Adding the secret ${ADDITIONAL_SECRET}/${filename} to the build, available at /run/secrets/${ADDITIONAL_SECRET}/${filename}" + BUILDAH_ARGS+=("--secret=id=${ADDITIONAL_SECRET}/${filename},src=$ADDITIONAL_SECRET_TMP/${filename}") + done < <(find $ADDITIONAL_SECRET_TMP -maxdepth 1 -type f -exec basename {} \;) + fi + + unshare -Uf $UNSHARE_ARGS --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -w ${SOURCE_CODE_DIR}/$CONTEXT -- buildah build \ + $VOLUME_MOUNTS \ + "${BUILDAH_ARGS[@]}" \ + "${LABELS[@]}" \ + --tls-verify=$TLSVERIFY --no-cache \ + --ulimit nofile=4096:4096 \ + -f "$dockerfile_path" -t $IMAGE . + + container=$(buildah from --pull-never $IMAGE) + buildah mount $container | tee /shared/container_path + # delete symlinks - they may point outside the container rootfs, messing with SBOM scanners + find $(cat /shared/container_path) -xtype l -delete + echo $container > /shared/container_name + + # Save the SBOM produced by Cachi2 so it can be merged into the final SBOM later + if [ -f "/tmp/cachi2/output/bom.json" ]; then + cp /tmp/cachi2/output/bom.json ./sbom-cachi2.json + fi + + # Expose base image digests + touch $(results.BASE_IMAGES_DIGESTS.path) + for image in $BASE_IMAGES; do + if [ "${image}" != "scratch" ]; then + buildah images --format '{{ .Name }}:{{ .Tag }}@{{ .Digest }}' --filter reference="$image" >> $(results.BASE_IMAGES_DIGESTS.path) + fi + done + + # Needed to generate base images SBOM + echo "$BASE_IMAGES" > $(workspaces.source.path)/base_images_from_dockerfile + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /entitlement + name: etc-pki-entitlement + - mountPath: /activation-key + name: activation-key + - mountPath: /additional-secret + name: additional-secret + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + - image: registry.access.redhat.com/rh-syft-tech-preview/syft-rhel9:1.4.1@sha256:34d7065427085a31dc4949bd283c001b91794d427e1e4cdf1b21ea4faf9fee3f + name: sbom-syft-generate + script: | + echo "Running syft on the source directory" + syft dir:$(workspaces.source.path)/source --output cyclonedx-json=$(workspaces.source.path)/sbom-source.json + echo "Running syft on the image filesystem" + syft dir:$(cat /shared/container_path) --output cyclonedx-json=$(workspaces.source.path)/sbom-image.json + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + workingDir: $(workspaces.source.path)/source + - image: quay.io/redhat-appstudio/hacbs-jvm-build-request-processor:127ee0c223a2b56a9bd20a6f2eaeed3bd6015f77 + name: analyse-dependencies-java-sbom + script: | + if [ -f /var/lib/containers/java ]; then + /opt/jboss/container/java/run/run-java.sh analyse-dependencies path $(cat /shared/container_path) -s $(workspaces.source.path)/sbom-image.json --task-run-name $(context.taskRun.name) --publishers $(results.SBOM_JAVA_COMPONENTS_COUNT.path) + sed -i 's/^/ /' $(results.SBOM_JAVA_COMPONENTS_COUNT.path) # Workaround for SRVKP-2875 + else + touch $(results.JAVA_COMMUNITY_DEPENDENCIES.path) + fi + securityContext: + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + - image: registry.access.redhat.com/ubi9/python-39:9.5-1734610342@sha256:dde5068ba8fd81eef41a9128ddad2b99e2e02e5869ffe925c605b609a0ad7bbb + name: merge-syft-sboms + script: | + #!/bin/python3 + import json + + # load SBOMs + with open("./sbom-image.json") as f: + image_sbom = json.load(f) + + with open("./sbom-source.json") as f: + source_sbom = json.load(f) + + # fetch unique components from available SBOMs + def get_identifier(component): + return component["name"] + '@' + component.get("version", "") + + image_sbom_components = image_sbom.setdefault("components", []) + existing_components = [get_identifier(component) for component in image_sbom_components] + + source_sbom_components = source_sbom.get("components", []) + for component in source_sbom_components: + if get_identifier(component) not in existing_components: + image_sbom_components.append(component) + existing_components.append(get_identifier(component)) + + image_sbom_components.sort(key=lambda c: get_identifier(c)) + + # write the CycloneDX unified SBOM + with open("./sbom-cyclonedx.json", "w") as f: + json.dump(image_sbom, f, indent=4) + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - image: quay.io/redhat-appstudio/cachi2:0.16.0@sha256:55415cd8ded149f5d56d3fca46d93125b86b41e07ae5d3c03caa240b7b93b7d8 + name: merge-cachi2-sbom + script: | + if [ -f "sbom-cachi2.json" ]; then + echo "Merging contents of sbom-cachi2.json into sbom-cyclonedx.json" + merge_syft_sbom sbom-cachi2.json sbom-cyclonedx.json > sbom-temp.json + mv sbom-temp.json sbom-cyclonedx.json + else + echo "Skipping step since no Cachi2 SBOM was produced" + fi + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - image: registry.access.redhat.com/ubi9/python-39:9.5-1734610342@sha256:dde5068ba8fd81eef41a9128ddad2b99e2e02e5869ffe925c605b609a0ad7bbb + name: create-purl-sbom + script: | + #!/bin/python3 + import json + + with open("./sbom-cyclonedx.json") as f: + cyclonedx_sbom = json.load(f) + + purls = [{"purl": component["purl"]} for component in cyclonedx_sbom.get("components", []) if "purl" in component] + purl_content = {"image_contents": {"dependencies": purls}} + + with open("sbom-purl.json", "w") as output_file: + json.dump(purl_content, output_file, indent=4) + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - env: + - name: BASE_IMAGES_DIGESTS_PATH + value: $(results.BASE_IMAGES_DIGESTS.path) + image: quay.io/redhat-appstudio/base-images-sbom-script@sha256:667669e3def018f9dbb8eaf8868887a40bc07842221e9a98f6787edcff021840 + name: create-base-images-sbom + script: | + python3 /app/base_images_sbom_script.py --sbom=sbom-cyclonedx.json --base-images-from-dockerfile=base_images_from_dockerfile --base-images-digests=$BASE_IMAGES_DIGESTS_PATH + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - computeResources: {} + image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: inject-sbom-and-push + script: | + if [ -n "${PARAM_BUILDER_IMAGE}" ]; then + echo "WARNING: provided deprecated BUILDER_IMAGE parameter has no effect." + fi + + base_image_name=$(buildah inspect --format '{{ index .ImageAnnotations "org.opencontainers.image.base.name"}}' $IMAGE | cut -f1 -d'@') + base_image_digest=$(buildah inspect --format '{{ index .ImageAnnotations "org.opencontainers.image.base.digest"}}' $IMAGE) + container=$(buildah from --pull-never $IMAGE) + buildah copy $container sbom-cyclonedx.json sbom-purl.json /root/buildinfo/content_manifests/ + buildah config -a org.opencontainers.image.base.name=${base_image_name} -a org.opencontainers.image.base.digest=${base_image_digest} $container + + BUILDAH_ARGS=() + if [ "${SQUASH}" == "true" ]; then + BUILDAH_ARGS+=("--squash") + fi + + buildah commit "${BUILDAH_ARGS[@]}" $container $IMAGE + + status=-1 + max_run=5 + sleep_sec=10 + for run in $(seq 1 $max_run); do + status=0 + [ "$run" -gt 1 ] && sleep $sleep_sec + echo "Pushing sbom image to registry" + buildah push \ + --tls-verify=$TLSVERIFY \ + --digestfile $(workspaces.source.path)/image-digest $IMAGE \ + docker://$IMAGE && break || status=$? + done + if [ "$status" -ne 0 ]; then + echo "Failed to push sbom image to registry after ${max_run} tries" + exit 1 + fi + + cat "$(workspaces.source.path)"/image-digest | tee $(results.IMAGE_DIGEST.path) + echo -n "$IMAGE" | tee $(results.IMAGE_URL.path) + securityContext: + capabilities: + add: + - SETFCAP + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + workingDir: $(workspaces.source.path) + - args: + - attach + - sbom + - --sbom + - sbom-cyclonedx.json + - --type + - cyclonedx + - $(params.IMAGE) + image: quay.io/redhat-appstudio/cosign:v2.1.1@sha256:c883d6f8d39148f2cea71bff4622d196d89df3e510f36c140c097b932f0dd5d5 + name: upload-sbom + workingDir: $(workspaces.source.path) + volumes: + - emptyDir: {} + name: varlibcontainers + - emptyDir: {} + name: shared + - name: etc-pki-entitlement + secret: + optional: true + secretName: $(params.ENTITLEMENT_SECRET) + - name: activation-key + secret: + optional: true + secretName: $(params.ACTIVATION_KEY) + - name: additional-secret + secret: + optional: true + secretName: $(params.ADDITIONAL_SECRET) + - configMap: + items: + - key: $(params.caTrustConfigMapKey) + path: ca-bundle.crt + name: $(params.caTrustConfigMapName) + optional: true + name: trusted-ca + workspaces: + - description: Workspace containing the source code to build. + name: source diff --git a/auto-generated/task/buildah-24gb/0.2/tekton.dev_v1_task_buildah-24gb.yaml b/auto-generated/task/buildah-24gb/0.2/tekton.dev_v1_task_buildah-24gb.yaml new file mode 100644 index 0000000000..3e618f81b0 --- /dev/null +++ b/auto-generated/task/buildah-24gb/0.2/tekton.dev_v1_task_buildah-24gb.yaml @@ -0,0 +1,722 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + annotations: + build.appstudio.redhat.com/expires-on: "2025-01-21T00:00:00Z" + build.appstudio.redhat.com/expiry-message: 'Instead of using this task, switch + to buildah task (you can find latest bundle reference here: https://quay.io/repository/konflux-ci/tekton-catalog/task-buildah) + and configure build step resources as described in the doc: https://konflux-ci.dev/docs/how-tos/configuring/overriding-compute-resources/' + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: image-build, konflux + labels: + app.kubernetes.io/version: 0.2.1 + build.appstudio.redhat.com/build_type: docker + name: buildah-24gb +spec: + description: |- + Buildah task builds source code into a container image and pushes the image into container registry using buildah tool. + In addition it generates a SBOM file, injects the SBOM file into final container image and pushes the SBOM file as separate image using cosign tool. + When [Java dependency rebuild](https://redhat-appstudio.github.io/docs.stonesoup.io/Documentation/main/cli/proc_enabled_java_dependencies.html) is enabled it triggers rebuilds of Java artifacts. + When prefetch-dependencies task was activated it is using its artifacts to run build in hermetic environment. + params: + - description: Reference of the image buildah will produce. + name: IMAGE + type: string + - default: ./Dockerfile + description: Path to the Dockerfile to build. + name: DOCKERFILE + type: string + - default: . + description: Path to the directory to use as context. + name: CONTEXT + type: string + - default: "true" + description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS + registry) + name: TLSVERIFY + type: string + - default: "false" + description: Determines if build will be executed without network access. + name: HERMETIC + type: string + - default: "" + description: In case it is not empty, the prefetched content should be made available + to the build. + name: PREFETCH_INPUT + type: string + - default: "" + description: Delete image tag after specified time. Empty means to keep the image + tag. Time values could be something like 1h, 2d, 3w for hours, days, and weeks, + respectively. + name: IMAGE_EXPIRES_AFTER + type: string + - default: "" + description: The image is built from this commit. + name: COMMIT_SHA + type: string + - default: repos.d + description: Path in the git repository in which yum repository files are stored + name: YUM_REPOS_D_SRC + - default: fetched.repos.d + description: Path in source workspace where dynamically-fetched repos are present + name: YUM_REPOS_D_FETCHED + - default: /etc/yum.repos.d + description: Target path on the container in which yum repository files should + be made available + name: YUM_REPOS_D_TARGET + - default: "" + description: Target stage in Dockerfile to build. If not specified, the Dockerfile + is processed entirely to (and including) its last stage. + name: TARGET_STAGE + type: string + - default: etc-pki-entitlement + description: Name of secret which contains the entitlement certificates + name: ENTITLEMENT_SECRET + type: string + - default: activation-key + description: Name of secret which contains subscription activation key + name: ACTIVATION_KEY + type: string + - default: does-not-exist + description: Name of a secret which will be made available to the build with 'buildah + build --secret' at /run/secrets/$ADDITIONAL_SECRET + name: ADDITIONAL_SECRET + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) + name: BUILD_ARGS + type: array + - default: "" + description: Path to a file with build arguments, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: BUILD_ARGS_FILE + type: string + - default: trusted-ca + description: The name of the ConfigMap to read CA bundle data from. + name: caTrustConfigMapName + type: string + - default: ca-bundle.crt + description: The name of the key in the ConfigMap that contains the CA bundle + data. + name: caTrustConfigMapKey + type: string + - default: "" + description: Comma separated list of extra capabilities to add when running 'buildah + build' + name: ADD_CAPABILITIES + type: string + - default: "false" + description: Squash all new and previous layers added as a part of this build, + as per --squash + name: SQUASH + type: string + - default: vfs + description: Storage driver to configure for buildah + name: STORAGE_DRIVER + type: string + - default: "true" + description: Whether to skip stages in Containerfile that seem unused by subsequent + stages + name: SKIP_UNUSED_STAGES + type: string + - default: [] + description: Additional key=value labels that should be applied to the image + name: LABELS + type: array + - default: "false" + description: Whether to enable privileged mode + name: PRIVILEGED_NESTED + type: string + results: + - description: Digest of the image just built + name: IMAGE_DIGEST + - description: Image repository and tag where the built image was pushed + name: IMAGE_URL + - description: Image reference of the built image + name: IMAGE_REF + - description: Reference of SBOM blob digest to enable digest-based verification + from provenance + name: SBOM_BLOB_URL + type: string + - description: The counting of Java components by publisher in JSON format + name: SBOM_JAVA_COMPONENTS_COUNT + type: string + - description: The Java dependencies that came from community sources such as Maven + central. + name: JAVA_COMMUNITY_DEPENDENCIES + stepTemplate: + computeResources: + limits: + cpu: "4" + memory: 4Gi + requests: + cpu: "1" + memory: 1Gi + env: + - name: BUILDAH_FORMAT + value: oci + - name: STORAGE_DRIVER + value: $(params.STORAGE_DRIVER) + - name: HERMETIC + value: $(params.HERMETIC) + - name: SOURCE_CODE_DIR + value: source + - name: CONTEXT + value: $(params.CONTEXT) + - name: IMAGE + value: $(params.IMAGE) + - name: TLSVERIFY + value: $(params.TLSVERIFY) + - name: IMAGE_EXPIRES_AFTER + value: $(params.IMAGE_EXPIRES_AFTER) + - name: YUM_REPOS_D_SRC + value: $(params.YUM_REPOS_D_SRC) + - name: YUM_REPOS_D_FETCHED + value: $(params.YUM_REPOS_D_FETCHED) + - name: YUM_REPOS_D_TARGET + value: $(params.YUM_REPOS_D_TARGET) + - name: TARGET_STAGE + value: $(params.TARGET_STAGE) + - name: ENTITLEMENT_SECRET + value: $(params.ENTITLEMENT_SECRET) + - name: ACTIVATION_KEY + value: $(params.ACTIVATION_KEY) + - name: ADDITIONAL_SECRET + value: $(params.ADDITIONAL_SECRET) + - name: BUILD_ARGS_FILE + value: $(params.BUILD_ARGS_FILE) + - name: ADD_CAPABILITIES + value: $(params.ADD_CAPABILITIES) + - name: SQUASH + value: $(params.SQUASH) + - name: SKIP_UNUSED_STAGES + value: $(params.SKIP_UNUSED_STAGES) + - name: PRIVILEGED_NESTED + value: $(params.PRIVILEGED_NESTED) + volumeMounts: + - mountPath: /shared + name: shared + steps: + - args: + - --build-args + - $(params.BUILD_ARGS[*]) + - --labels + - $(params.LABELS[*]) + computeResources: + limits: + cpu: "20" + memory: 24Gi + requests: + cpu: "10" + memory: 20Gi + env: + - name: COMMIT_SHA + value: $(params.COMMIT_SHA) + - name: DOCKERFILE + value: $(params.DOCKERFILE) + image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: build + script: | + #!/bin/bash + set -euo pipefail + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + if [ -e "$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" + elif [ -e "$SOURCE_CODE_DIR/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$DOCKERFILE" + elif [ -e "$DOCKERFILE" ]; then + # Instrumented builds (SAST) use this custom dockerffile step as their base + dockerfile_path="$DOCKERFILE" + elif echo "$DOCKERFILE" | grep -q "^https\?://"; then + echo "Fetch Dockerfile from $DOCKERFILE" + dockerfile_path=$(mktemp --suffix=-Dockerfile) + http_code=$(curl -s -S -L -w "%{http_code}" --output "$dockerfile_path" "$DOCKERFILE") + if [ $http_code != 200 ]; then + echo "No Dockerfile is fetched. Server responds $http_code" + exit 1 + fi + http_code=$(curl -s -S -L -w "%{http_code}" --output "$dockerfile_path.dockerignore.tmp" "$DOCKERFILE.dockerignore") + if [ $http_code = 200 ]; then + echo "Fetched .dockerignore from $DOCKERFILE.dockerignore" + mv "$dockerfile_path.dockerignore.tmp" $SOURCE_CODE_DIR/$CONTEXT/.dockerignore + fi + else + echo "Cannot find Dockerfile $DOCKERFILE" + exit 1 + fi + + dockerfile_copy=$(mktemp --tmpdir "$(basename "$dockerfile_path").XXXXXX") + cp "$dockerfile_path" "$dockerfile_copy" + + if [ -n "${JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR-}" ] && grep -q '^\s*RUN \(./\)\?mvn' "$dockerfile_copy"; then + sed -i -e "s|^\s*RUN \(\(./\)\?mvn\)\(.*\)|RUN echo \"mirror.defaulthttp://$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR/v1/cache/default/0/*\" > /tmp/settings.yaml; \1 -s /tmp/settings.yaml \3|g" "$dockerfile_copy" + touch /var/lib/containers/java + fi + + # Fixing group permission on /var/lib/containers + chown root:root /var/lib/containers + + sed -i 's/^\s*short-name-mode\s*=\s*.*/short-name-mode = "disabled"/' /etc/containers/registries.conf + + # Setting new namespace to run buildah - 2^32-2 + echo 'root:1:4294967294' | tee -a /etc/subuid >> /etc/subgid + + build_args=() + if [ -n "${BUILD_ARGS_FILE}" ]; then + # Parse BUILD_ARGS_FILE ourselves because dockerfile-json doesn't support it + echo "Parsing ARGs from $BUILD_ARGS_FILE" + mapfile -t build_args < <( + # https://www.mankier.com/1/buildah-build#--build-arg-file + # delete lines that start with # + # delete blank lines + sed -e '/^#/d' -e '/^\s*$/d' "${SOURCE_CODE_DIR}/${BUILD_ARGS_FILE}" + ) + fi + + LABELS=() + # Split `args` into two sets of arguments. + while [[ $# -gt 0 ]]; do + case $1 in + --build-args) + shift + # Note: this may result in multiple --build-arg=KEY=value flags with the same KEY being + # passed to buildah. In that case, the *last* occurrence takes precedence. This is why + # we append BUILD_ARGS after the content of the BUILD_ARGS_FILE + while [[ $# -gt 0 && $1 != --* ]]; do build_args+=("$1"); shift; done + ;; + --labels) + shift + while [[ $# -gt 0 && $1 != --* ]]; do LABELS+=("--label" "$1"); shift; done + ;; + *) + echo "unexpected argument: $1" >&2 + exit 2 + ;; + esac + done + + BUILD_ARG_FLAGS=() + for build_arg in "${build_args[@]}"; do + BUILD_ARG_FLAGS+=("--build-arg=$build_arg") + done + + dockerfile-json "${BUILD_ARG_FLAGS[@]}" "$dockerfile_copy" > /shared/parsed_dockerfile.json + BASE_IMAGES=$( + jq -r '.Stages[] | select(.From | .Stage or .Scratch | not) | .BaseName | select(test("^oci-archive:") | not)' /shared/parsed_dockerfile.json + ) + + BUILDAH_ARGS=() + UNSHARE_ARGS=() + + if [ "${HERMETIC}" == "true" ]; then + BUILDAH_ARGS+=("--pull=never") + UNSHARE_ARGS+=("--net") + + for image in $BASE_IMAGES; do + unshare -Ufp --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -- buildah pull $image + done + echo "Build will be executed with network isolation" + fi + + if [ -n "${TARGET_STAGE}" ]; then + BUILDAH_ARGS+=("--target=${TARGET_STAGE}") + fi + + BUILDAH_ARGS+=("${BUILD_ARG_FLAGS[@]}") + + if [ "${PRIVILEGED_NESTED}" == "true" ]; then + BUILDAH_ARGS+=("--security-opt=label=disable") + BUILDAH_ARGS+=("--cap-add=all") + BUILDAH_ARGS+=("--device=/dev/fuse") + fi + + if [ -n "${ADD_CAPABILITIES}" ]; then + BUILDAH_ARGS+=("--cap-add=${ADD_CAPABILITIES}") + fi + + if [ "${SQUASH}" == "true" ]; then + BUILDAH_ARGS+=("--squash") + fi + + if [ "${SKIP_UNUSED_STAGES}" != "true" ] ; then + BUILDAH_ARGS+=("--skip-unused-stages=false") + fi + + VOLUME_MOUNTS=() + + if [ -f "$(workspaces.source.path)/cachi2/cachi2.env" ]; then + cp -r "$(workspaces.source.path)/cachi2" /tmp/ + chmod -R go+rwX /tmp/cachi2 + VOLUME_MOUNTS+=(--volume /tmp/cachi2:/cachi2) + # Read in the whole file (https://unix.stackexchange.com/questions/533277), then + # for each RUN ... line insert the cachi2.env command *after* any options like --mount + sed -E -i \ + -e 'H;1h;$!d;x' \ + -e 's@^\s*(run((\s|\\\n)+-\S+)*(\s|\\\n)+)@\1. /cachi2/cachi2.env \&\& \\\n @igM' \ + "$dockerfile_copy" + echo "Prefetched content will be made available" + + prefetched_repo_for_my_arch="/tmp/cachi2/output/deps/rpm/$(uname -m)/repos.d/cachi2.repo" + if [ -f "$prefetched_repo_for_my_arch" ]; then + echo "Adding $prefetched_repo_for_my_arch to $YUM_REPOS_D_FETCHED" + mkdir -p "$YUM_REPOS_D_FETCHED" + cp --no-clobber "$prefetched_repo_for_my_arch" "$YUM_REPOS_D_FETCHED" + fi + fi + + # if yum repofiles stored in git, copy them to mount point outside the source dir + if [ -d "${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}" ]; then + mkdir -p ${YUM_REPOS_D_FETCHED} + cp -r ${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}/* ${YUM_REPOS_D_FETCHED} + fi + + # if anything in the repofiles mount point (either fetched or from git), mount it + if [ -d "${YUM_REPOS_D_FETCHED}" ]; then + chmod -R go+rwX ${YUM_REPOS_D_FETCHED} + mount_point=$(realpath ${YUM_REPOS_D_FETCHED}) + VOLUME_MOUNTS+=(--volume "${mount_point}:${YUM_REPOS_D_TARGET}") + fi + + DEFAULT_LABELS=( + "--label" "build-date=$(date -u +'%Y-%m-%dT%H:%M:%S')" + "--label" "architecture=$(uname -m)" + "--label" "vcs-type=git" + ) + [ -n "$COMMIT_SHA" ] && DEFAULT_LABELS+=("--label" "vcs-ref=$COMMIT_SHA") + [ -n "$IMAGE_EXPIRES_AFTER" ] && DEFAULT_LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + + # Concatenate defaults and explicit labels. If a label appears twice, the last one wins. + LABELS=("${DEFAULT_LABELS[@]}" "${LABELS[@]}") + + ACTIVATION_KEY_PATH="/activation-key" + ENTITLEMENT_PATH="/entitlement" + + # 0. if hermetic=true, skip all subscription related stuff + # 1. do not enable activation key and entitlement at same time. If both vars are provided, prefer activation key. + # 2. Activation-keys will be used when the key 'org' exists in the activation key secret. + # 3. try to pre-register and mount files to the correct location so that users do no need to modify Dockerfiles. + # 3. If the Dockerfile contains the string "subcription-manager register", add the activation-keys volume + # to buildah but don't pre-register for backwards compatibility. Mount an empty directory on + # shared emptydir volume to "/etc/pki/entitlement" to prevent certificates from being included + + if [ "${HERMETIC}" != "true" ] && [ -e /activation-key/org ]; then + cp -r --preserve=mode "$ACTIVATION_KEY_PATH" /tmp/activation-key + mkdir -p /shared/rhsm/etc/pki/entitlement + mkdir -p /shared/rhsm/etc/pki/consumer + + VOLUME_MOUNTS+=(-v /tmp/activation-key:/activation-key \ + -v /shared/rhsm/etc/pki/entitlement:/etc/pki/entitlement:Z \ + -v /shared/rhsm/etc/pki/consumer:/etc/pki/consumer:Z) + echo "Adding activation key to the build" + + if ! grep -E "^[^#]*subscription-manager.[^#]*register" "$dockerfile_path"; then + # user is not running registration in the Containerfile: pre-register. + echo "Pre-registering with subscription manager." + subscription-manager register --org "$(cat /tmp/activation-key/org)" --activationkey "$(cat /tmp/activation-key/activationkey)" + trap 'subscription-manager unregister || true' EXIT + + # copy generated certificates to /shared volume + cp /etc/pki/entitlement/*.pem /shared/rhsm/etc/pki/entitlement + cp /etc/pki/consumer/*.pem /shared/rhsm/etc/pki/consumer + + # and then mount get /etc/rhsm/ca/redhat-uep.pem into /run/secrets/rhsm/ca + VOLUME_MOUNTS+=(--volume /etc/rhsm/ca/redhat-uep.pem:/etc/rhsm/ca/redhat-uep.pem:Z) + fi + + elif [ "${HERMETIC}" != "true" ] && find /entitlement -name "*.pem" >> null; then + cp -r --preserve=mode "$ENTITLEMENT_PATH" /tmp/entitlement + VOLUME_MOUNTS+=(--volume /tmp/entitlement:/etc/pki/entitlement) + echo "Adding the entitlement to the build" + fi + + if [ -n "${ADDITIONAL_VOLUME_MOUNTS-}" ]; then + # ADDITIONAL_VOLUME_MOUNTS allows to specify more volumes for the build. + # Instrumented builds (SAST) use this step as their base and add some other tools. + while read -r volume_mount; do + VOLUME_MOUNTS+=("--volume=$volume_mount") + done <<< "$ADDITIONAL_VOLUME_MOUNTS" + fi + + ADDITIONAL_SECRET_PATH="/additional-secret" + ADDITIONAL_SECRET_TMP="/tmp/additional-secret" + if [ -d "$ADDITIONAL_SECRET_PATH" ]; then + cp -r --preserve=mode -L "$ADDITIONAL_SECRET_PATH" $ADDITIONAL_SECRET_TMP + while read -r filename; do + echo "Adding the secret ${ADDITIONAL_SECRET}/${filename} to the build, available at /run/secrets/${ADDITIONAL_SECRET}/${filename}" + BUILDAH_ARGS+=("--secret=id=${ADDITIONAL_SECRET}/${filename},src=$ADDITIONAL_SECRET_TMP/${filename}") + done < <(find $ADDITIONAL_SECRET_TMP -maxdepth 1 -type f -exec basename {} \;) + fi + + # Prevent ShellCheck from giving a warning because 'image' is defined and 'IMAGE' is not. + declare IMAGE + + buildah_cmd_array=( + buildah build + "${VOLUME_MOUNTS[@]}" + "${BUILDAH_ARGS[@]}" + "${LABELS[@]}" + --tls-verify="$TLSVERIFY" --no-cache + --ulimit nofile=4096:4096 + -f "$dockerfile_copy" -t "$IMAGE" . + ) + buildah_cmd=$(printf "%q " "${buildah_cmd_array[@]}") + + if [ "${HERMETIC}" == "true" ]; then + # enabling loopback adapter enables Bazel builds to work in hermetic mode. + command="ip link set lo up && $buildah_cmd" + else + command="$buildah_cmd" + fi + + # disable host subcription manager integration + find /usr/share/rhel/secrets -type l -exec unlink {} \; + + unshare -Uf "${UNSHARE_ARGS[@]}" --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -w "${SOURCE_CODE_DIR}/$CONTEXT" -- sh -c "$command" + + container=$(buildah from --pull-never "$IMAGE") + + # Save the SBOM produced by Cachi2 so it can be merged into the final SBOM later + if [ -f "/tmp/cachi2/output/bom.json" ]; then + echo "Making copy of sbom-cachi2.json" + cp /tmp/cachi2/output/bom.json ./sbom-cachi2.json + fi + + buildah mount $container | tee /shared/container_path + # delete symlinks - they may point outside the container rootfs, messing with SBOM scanners + find $(cat /shared/container_path) -xtype l -delete + echo $container > /shared/container_name + + touch /shared/base_images_digests + for image in $BASE_IMAGES; do + base_image_digest=$(buildah images --format '{{ .Name }}:{{ .Tag }}@{{ .Digest }}' --filter reference="$image") + # In some cases, there might be BASE_IMAGES, but not any associated digest. This happens + # if buildah did not use that particular image during build because it was skipped + if [ -n "$base_image_digest" ]; then + echo "$image $base_image_digest" >> /shared/base_images_digests + fi + done + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /entitlement + name: etc-pki-entitlement + - mountPath: /activation-key + name: activation-key + - mountPath: /additional-secret + name: additional-secret + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + - image: quay.io/konflux-ci/icm-injection-scripts:latest@sha256:462980e94ba689b5f56c3d5dfb3358cd8c685300daf65a71532f11898935e7f1 + name: icm + script: | + #!/bin/bash + set -euo pipefail + /scripts/inject-icm.sh "$IMAGE" + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + workingDir: $(workspaces.source.path) + - image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: push + script: | + #!/bin/bash + set -e + + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + retries=5 + # Push to a unique tag based on the TaskRun name to avoid race conditions + echo "Pushing to ${IMAGE%:*}:${TASKRUN_NAME}" + if ! buildah push \ + --retry "$retries" \ + --tls-verify="$TLSVERIFY" \ + "$IMAGE" \ + "docker://${IMAGE%:*}:$(context.taskRun.name)"; + then + echo "Failed to push sbom image to ${IMAGE%:*}:$(context.taskRun.name) after ${retries} tries" + exit 1 + fi + + # Push to a tag based on the git revision + echo "Pushing to ${IMAGE}" + if ! buildah push \ + --retry "$retries" \ + --tls-verify="$TLSVERIFY" \ + --digestfile "$(workspaces.source.path)/image-digest" "$IMAGE" \ + "docker://$IMAGE"; + then + echo "Failed to push sbom image to $IMAGE after ${retries} tries" + exit 1 + fi + + cat "$(workspaces.source.path)"/image-digest | tee $(results.IMAGE_DIGEST.path) + echo -n "$IMAGE" | tee $(results.IMAGE_URL.path) + { + echo -n "${IMAGE}@" + cat "$(workspaces.source.path)/image-digest" + } > "$(results.IMAGE_REF.path)" + securityContext: + capabilities: + add: + - SETFCAP + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + - image: registry.access.redhat.com/rh-syft-tech-preview/syft-rhel9:1.4.1@sha256:34d7065427085a31dc4949bd283c001b91794d427e1e4cdf1b21ea4faf9fee3f + name: sbom-syft-generate + script: | + echo "Running syft on the source directory" + syft dir:"$(workspaces.source.path)/$SOURCE_CODE_DIR/$CONTEXT" --output cyclonedx-json="$(workspaces.source.path)/sbom-source.json" + echo "Running syft on the image filesystem" + syft dir:"$(cat /shared/container_path)" --output cyclonedx-json="$(workspaces.source.path)/sbom-image.json" + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + workingDir: $(workspaces.source.path)/source + - computeResources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + image: quay.io/redhat-appstudio/hacbs-jvm-build-request-processor:127ee0c223a2b56a9bd20a6f2eaeed3bd6015f77 + name: analyse-dependencies-java-sbom + script: | + if [ -f /var/lib/containers/java ]; then + /opt/jboss/container/java/run/run-java.sh analyse-dependencies path $(cat /shared/container_path) -s $(workspaces.source.path)/sbom-image.json --task-run-name $(context.taskRun.name) --publishers $(results.SBOM_JAVA_COMPONENTS_COUNT.path) + sed -i 's/^/ /' $(results.SBOM_JAVA_COMPONENTS_COUNT.path) # Workaround for SRVKP-2875 + else + touch $(results.JAVA_COMMUNITY_DEPENDENCIES.path) + fi + securityContext: + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + - computeResources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + image: quay.io/redhat-appstudio/sbom-utility-scripts-image@sha256:9f1fd11d9c3c517ecc112d192ad361d16ecf6ce00b83b109c93cf3d1c644a357 + name: prepare-sboms + script: | + echo "Merging contents of sbom-source.json and sbom-image.json into sbom-cyclonedx.json" + python3 /scripts/merge_syft_sboms.py + + if [ -f "sbom-cachi2.json" ]; then + echo "Merging contents of sbom-cachi2.json into sbom-cyclonedx.json" + python3 /scripts/merge_cachi2_sboms.py sbom-cachi2.json sbom-cyclonedx.json > sbom-temp.json + mv sbom-temp.json sbom-cyclonedx.json + fi + + echo "Adding base images data to sbom-cyclonedx.json" + python3 /scripts/base_images_sbom_script.py \ + --sbom=sbom-cyclonedx.json \ + --parsed-dockerfile=/shared/parsed_dockerfile.json \ + --base-images-digests=/shared/base_images_digests + + echo "Adding image reference to sbom" + IMAGE_URL="$(cat "$(results.IMAGE_URL.path)")" + IMAGE_DIGEST="$(cat "$(results.IMAGE_DIGEST.path)")" + + python3 /scripts/add_image_reference.py \ + --image-url "$IMAGE_URL" \ + --image-digest "$IMAGE_DIGEST" \ + --input-file sbom-cyclonedx.json \ + --output-file /tmp/sbom-cyclonedx.tmp.json + + mv /tmp/sbom-cyclonedx.tmp.json sbom-cyclonedx.json + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - computeResources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + image: quay.io/konflux-ci/appstudio-utils:48c311af02858e2422d6229600e9959e496ddef1@sha256:91ddd999271f65d8ec8487b10f3dd378f81aa894e11b9af4d10639fd52bba7e8 + name: upload-sbom + script: | + #!/bin/bash + + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + cosign attach sbom --sbom sbom-cyclonedx.json --type cyclonedx "$(cat "$(results.IMAGE_REF.path)")" + + # Remove tag from IMAGE while allowing registry to contain a port number. + sbom_repo="${IMAGE%:*}" + sbom_digest="$(sha256sum sbom-cyclonedx.json | cut -d' ' -f1)" + # The SBOM_BLOB_URL is created by `cosign attach sbom`. + echo -n "${sbom_repo}@sha256:${sbom_digest}" | tee "$(results.SBOM_BLOB_URL.path)" + volumeMounts: + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + volumes: + - emptyDir: {} + name: varlibcontainers + - emptyDir: {} + name: shared + - name: etc-pki-entitlement + secret: + optional: true + secretName: $(params.ENTITLEMENT_SECRET) + - name: activation-key + secret: + optional: true + secretName: $(params.ACTIVATION_KEY) + - name: additional-secret + secret: + optional: true + secretName: $(params.ADDITIONAL_SECRET) + - configMap: + items: + - key: $(params.caTrustConfigMapKey) + path: ca-bundle.crt + name: $(params.caTrustConfigMapName) + optional: true + name: trusted-ca + workspaces: + - description: Workspace containing the source code to build. + name: source diff --git a/auto-generated/task/buildah-6gb/0.1/tekton.dev_v1_task_buildah-6gb.yaml b/auto-generated/task/buildah-6gb/0.1/tekton.dev_v1_task_buildah-6gb.yaml new file mode 100644 index 0000000000..23d1ee3e88 --- /dev/null +++ b/auto-generated/task/buildah-6gb/0.1/tekton.dev_v1_task_buildah-6gb.yaml @@ -0,0 +1,585 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + annotations: + build.appstudio.redhat.com/expires-on: "2025-01-21T00:00:00Z" + build.appstudio.redhat.com/expiry-message: 'Instead of using this task, switch + to buildah task (you can find latest bundle reference here: https://quay.io/repository/konflux-ci/tekton-catalog/task-buildah) + and configure build step resources as described in the doc: https://konflux-ci.dev/docs/how-tos/configuring/overriding-compute-resources/' + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: image-build, konflux + labels: + app.kubernetes.io/version: "0.1" + build.appstudio.redhat.com/build_type: docker + name: buildah-6gb +spec: + description: |- + Buildah task builds source code into a container image and pushes the image into container registry using buildah tool. + In addition it generates a SBOM file, injects the SBOM file into final container image and pushes the SBOM file as separate image using cosign tool. + When [Java dependency rebuild](https://redhat-appstudio.github.io/docs.stonesoup.io/Documentation/main/cli/proc_enabled_java_dependencies.html) is enabled it triggers rebuilds of Java artifacts. + When prefetch-dependencies task was activated it is using its artifacts to run build in hermetic environment. + params: + - description: Reference of the image buildah will produce. + name: IMAGE + type: string + - default: "" + description: Deprecated. Has no effect. Will be removed in the future. + name: BUILDER_IMAGE + type: string + - default: ./Dockerfile + description: Path to the Dockerfile to build. + name: DOCKERFILE + type: string + - default: . + description: Path to the directory to use as context. + name: CONTEXT + type: string + - default: "true" + description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS + registry) + name: TLSVERIFY + type: string + - default: "" + description: unused, should be removed in next task version + name: DOCKER_AUTH + type: string + - default: "false" + description: Determines if build will be executed without network access. + name: HERMETIC + type: string + - default: "" + description: In case it is not empty, the prefetched content should be made available + to the build. + name: PREFETCH_INPUT + type: string + - default: "" + description: Delete image tag after specified time. Empty means to keep the image + tag. Time values could be something like 1h, 2d, 3w for hours, days, and weeks, + respectively. + name: IMAGE_EXPIRES_AFTER + type: string + - default: "" + description: The image is built from this commit. + name: COMMIT_SHA + type: string + - default: repos.d + description: Path in the git repository in which yum repository files are stored + name: YUM_REPOS_D_SRC + - default: fetched.repos.d + description: Path in source workspace where dynamically-fetched repos are present + name: YUM_REPOS_D_FETCHED + - default: /etc/yum.repos.d + description: Target path on the container in which yum repository files should + be made available + name: YUM_REPOS_D_TARGET + - default: "" + description: Target stage in Dockerfile to build. If not specified, the Dockerfile + is processed entirely to (and including) its last stage. + name: TARGET_STAGE + type: string + - default: etc-pki-entitlement + description: Name of secret which contains the entitlement certificates + name: ENTITLEMENT_SECRET + type: string + - default: activation-key + description: Name of secret which contains subscription activation key + name: ACTIVATION_KEY + type: string + - default: does-not-exist + description: Name of a secret which will be made available to the build with 'buildah + build --secret' at /run/secrets/$ADDITIONAL_SECRET + name: ADDITIONAL_SECRET + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) + name: BUILD_ARGS + type: array + - default: "" + description: Path to a file with build arguments, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: BUILD_ARGS_FILE + type: string + - default: trusted-ca + description: The name of the ConfigMap to read CA bundle data from. + name: caTrustConfigMapName + type: string + - default: ca-bundle.crt + description: The name of the key in the ConfigMap that contains the CA bundle + data. + name: caTrustConfigMapKey + type: string + - default: "" + description: Comma separated list of extra capabilities to add when running 'buildah + build' + name: ADD_CAPABILITIES + type: string + - default: "false" + description: Squash all new and previous layers added as a part of this build, + as per --squash + name: SQUASH + type: string + - default: vfs + description: Storage driver to configure for buildah + name: STORAGE_DRIVER + type: string + - default: "true" + description: Whether to skip stages in Containerfile that seem unused by subsequent + stages + name: SKIP_UNUSED_STAGES + type: string + results: + - description: Digest of the image just built + name: IMAGE_DIGEST + - description: Image repository and tag where the built image was pushed + name: IMAGE_URL + - description: Digests of the base images used for build + name: BASE_IMAGES_DIGESTS + - description: The counting of Java components by publisher in JSON format + name: SBOM_JAVA_COMPONENTS_COUNT + type: string + - description: The Java dependencies that came from community sources such as Maven + central. + name: JAVA_COMMUNITY_DEPENDENCIES + stepTemplate: + env: + - name: BUILDAH_FORMAT + value: oci + - name: STORAGE_DRIVER + value: $(params.STORAGE_DRIVER) + - name: HERMETIC + value: $(params.HERMETIC) + - name: CONTEXT + value: $(params.CONTEXT) + - name: DOCKERFILE + value: $(params.DOCKERFILE) + - name: IMAGE + value: $(params.IMAGE) + - name: TLSVERIFY + value: $(params.TLSVERIFY) + - name: IMAGE_EXPIRES_AFTER + value: $(params.IMAGE_EXPIRES_AFTER) + - name: YUM_REPOS_D_SRC + value: $(params.YUM_REPOS_D_SRC) + - name: YUM_REPOS_D_FETCHED + value: $(params.YUM_REPOS_D_FETCHED) + - name: YUM_REPOS_D_TARGET + value: $(params.YUM_REPOS_D_TARGET) + - name: TARGET_STAGE + value: $(params.TARGET_STAGE) + - name: PARAM_BUILDER_IMAGE + value: $(params.BUILDER_IMAGE) + - name: ENTITLEMENT_SECRET + value: $(params.ENTITLEMENT_SECRET) + - name: ADDITIONAL_SECRET + value: $(params.ADDITIONAL_SECRET) + - name: BUILD_ARGS_FILE + value: $(params.BUILD_ARGS_FILE) + - name: ADD_CAPABILITIES + value: $(params.ADD_CAPABILITIES) + - name: SQUASH + value: $(params.SQUASH) + - name: SKIP_UNUSED_STAGES + value: $(params.SKIP_UNUSED_STAGES) + volumeMounts: + - mountPath: /shared + name: shared + steps: + - args: + - $(params.BUILD_ARGS[*]) + computeResources: + limits: + memory: 6Gi + requests: + cpu: 250m + memory: 4Gi + env: + - name: COMMIT_SHA + value: $(params.COMMIT_SHA) + image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: build + script: | + if [ -n "${PARAM_BUILDER_IMAGE}" ]; then + echo "WARNING: provided deprecated BUILDER_IMAGE parameter has no effect." + fi + + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + SOURCE_CODE_DIR=source + if [ -e "$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" + elif [ -e "$SOURCE_CODE_DIR/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$DOCKERFILE" + elif echo "$DOCKERFILE" | grep -q "^https\?://"; then + echo "Fetch Dockerfile from $DOCKERFILE" + dockerfile_path=$(mktemp --suffix=-Dockerfile) + http_code=$(curl -s -L -w "%{http_code}" --output "$dockerfile_path" "$DOCKERFILE") + if [ $http_code != 200 ]; then + echo "No Dockerfile is fetched. Server responds $http_code" + exit 1 + fi + http_code=$(curl -s -L -w "%{http_code}" --output "$dockerfile_path.dockerignore.tmp" "$DOCKERFILE.dockerignore") + if [ $http_code = 200 ]; then + echo "Fetched .dockerignore from $DOCKERFILE.dockerignore" + mv "$dockerfile_path.dockerignore.tmp" $SOURCE_CODE_DIR/$CONTEXT/.dockerignore + fi + else + echo "Cannot find Dockerfile $DOCKERFILE" + exit 1 + fi + if [ -n "$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR" ] && grep -q '^\s*RUN \(./\)\?mvn' "$dockerfile_path"; then + sed -i -e "s|^\s*RUN \(\(./\)\?mvn\)\(.*\)|RUN echo \"mirror.defaulthttp://$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR/v1/cache/default/0/*\" > /tmp/settings.yaml; \1 -s /tmp/settings.yaml \3|g" "$dockerfile_path" + touch /var/lib/containers/java + fi + + # Fixing group permission on /var/lib/containers + chown root:root /var/lib/containers + + sed -i 's/^\s*short-name-mode\s*=\s*.*/short-name-mode = "disabled"/' /etc/containers/registries.conf + + # Setting new namespace to run buildah - 2^32-2 + echo 'root:1:4294967294' | tee -a /etc/subuid >> /etc/subgid + + BUILDAH_ARGS=() + + BASE_IMAGES=$(grep -i '^\s*FROM' "$dockerfile_path" | sed 's/--platform=\S*//' | awk '{print $2}' | (grep -v ^oci-archive: || true)) + if [ "${HERMETIC}" == "true" ]; then + BUILDAH_ARGS+=("--pull=never") + UNSHARE_ARGS="--net" + for image in $BASE_IMAGES; do + if [ "${image}" != "scratch" ]; then + unshare -Ufp --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -- buildah pull $image + fi + done + echo "Build will be executed with network isolation" + fi + + if [ -n "${TARGET_STAGE}" ]; then + BUILDAH_ARGS+=("--target=${TARGET_STAGE}") + fi + + if [ -n "${BUILD_ARGS_FILE}" ]; then + BUILDAH_ARGS+=("--build-arg-file=$(pwd)/$SOURCE_CODE_DIR/${BUILD_ARGS_FILE}") + fi + + for build_arg in "$@"; do + BUILDAH_ARGS+=("--build-arg=$build_arg") + done + + if [ -n "${ADD_CAPABILITIES}" ]; then + BUILDAH_ARGS+=("--cap-add=${ADD_CAPABILITIES}") + fi + + if [ "${SQUASH}" == "true" ]; then + BUILDAH_ARGS+=("--squash") + fi + + if [ "${SKIP_UNUSED_STAGES}" != "true" ] ; then + BUILDAH_ARGS+=("--skip-unused-stages=false") + fi + + if [ -f "$(workspaces.source.path)/cachi2/cachi2.env" ]; then + cp -r "$(workspaces.source.path)/cachi2" /tmp/ + chmod -R go+rwX /tmp/cachi2 + VOLUME_MOUNTS="--volume /tmp/cachi2:/cachi2" + # Read in the whole file (https://unix.stackexchange.com/questions/533277), then + # for each RUN ... line insert the cachi2.env command *after* any options like --mount + sed -E -i \ + -e 'H;1h;$!d;x' \ + -e 's@^\s*(run((\s|\\\n)+-\S+)*(\s|\\\n)+)@\1. /cachi2/cachi2.env \&\& \\\n @igM' \ + "$dockerfile_path" + echo "Prefetched content will be made available" + + prefetched_repo_for_my_arch="/tmp/cachi2/output/deps/rpm/$(uname -m)/repos.d/cachi2.repo" + if [ -f "$prefetched_repo_for_my_arch" ]; then + echo "Adding $prefetched_repo_for_my_arch to $YUM_REPOS_D_FETCHED" + mkdir -p "$YUM_REPOS_D_FETCHED" + cp --no-clobber "$prefetched_repo_for_my_arch" "$YUM_REPOS_D_FETCHED" + fi + fi + + # if yum repofiles stored in git, copy them to mount point outside the source dir + if [ -d "${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}" ]; then + mkdir -p ${YUM_REPOS_D_FETCHED} + cp -r ${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}/* ${YUM_REPOS_D_FETCHED} + fi + + # if anything in the repofiles mount point (either fetched or from git), mount it + if [ -d "${YUM_REPOS_D_FETCHED}" ]; then + chmod -R go+rwX ${YUM_REPOS_D_FETCHED} + mount_point=$(realpath ${YUM_REPOS_D_FETCHED}) + VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume ${mount_point}:${YUM_REPOS_D_TARGET}" + fi + + LABELS=( + "--label" "build-date=$(date -u +'%Y-%m-%dT%H:%M:%S')" + "--label" "architecture=$(uname -m)" + "--label" "vcs-type=git" + ) + [ -n "$COMMIT_SHA" ] && LABELS+=("--label" "vcs-ref=$COMMIT_SHA") + [ -n "$IMAGE_EXPIRES_AFTER" ] && LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + + ACTIVATION_KEY_PATH="/activation-key" + ENTITLEMENT_PATH="/entitlement" + + if [ -e /activation-key/org ]; then + cp -r --preserve=mode "$ACTIVATION_KEY_PATH" /tmp/activation-key + mkdir /shared/rhsm-tmp + VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume /tmp/activation-key:/activation-key -v /shared/rhsm-tmp:/etc/pki/entitlement:Z" + echo "Adding activation key to the build" + + elif find /entitlement -name "*.pem" >> null; then + cp -r --preserve=mode "$ENTITLEMENT_PATH" /tmp/entitlement + VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume /tmp/entitlement:/etc/pki/entitlement" + echo "Adding the entitlement to the build" + fi + + ADDITIONAL_SECRET_PATH="/additional-secret" + ADDITIONAL_SECRET_TMP="/tmp/additional-secret" + if [ -d "$ADDITIONAL_SECRET_PATH" ]; then + cp -r --preserve=mode -L "$ADDITIONAL_SECRET_PATH" $ADDITIONAL_SECRET_TMP + while read -r filename; do + echo "Adding the secret ${ADDITIONAL_SECRET}/${filename} to the build, available at /run/secrets/${ADDITIONAL_SECRET}/${filename}" + BUILDAH_ARGS+=("--secret=id=${ADDITIONAL_SECRET}/${filename},src=$ADDITIONAL_SECRET_TMP/${filename}") + done < <(find $ADDITIONAL_SECRET_TMP -maxdepth 1 -type f -exec basename {} \;) + fi + + unshare -Uf $UNSHARE_ARGS --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -w ${SOURCE_CODE_DIR}/$CONTEXT -- buildah build \ + $VOLUME_MOUNTS \ + "${BUILDAH_ARGS[@]}" \ + "${LABELS[@]}" \ + --tls-verify=$TLSVERIFY --no-cache \ + --ulimit nofile=4096:4096 \ + -f "$dockerfile_path" -t $IMAGE . + + container=$(buildah from --pull-never $IMAGE) + buildah mount $container | tee /shared/container_path + # delete symlinks - they may point outside the container rootfs, messing with SBOM scanners + find $(cat /shared/container_path) -xtype l -delete + echo $container > /shared/container_name + + # Save the SBOM produced by Cachi2 so it can be merged into the final SBOM later + if [ -f "/tmp/cachi2/output/bom.json" ]; then + cp /tmp/cachi2/output/bom.json ./sbom-cachi2.json + fi + + # Expose base image digests + touch $(results.BASE_IMAGES_DIGESTS.path) + for image in $BASE_IMAGES; do + if [ "${image}" != "scratch" ]; then + buildah images --format '{{ .Name }}:{{ .Tag }}@{{ .Digest }}' --filter reference="$image" >> $(results.BASE_IMAGES_DIGESTS.path) + fi + done + + # Needed to generate base images SBOM + echo "$BASE_IMAGES" > $(workspaces.source.path)/base_images_from_dockerfile + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /entitlement + name: etc-pki-entitlement + - mountPath: /activation-key + name: activation-key + - mountPath: /additional-secret + name: additional-secret + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + - image: registry.access.redhat.com/rh-syft-tech-preview/syft-rhel9:1.4.1@sha256:34d7065427085a31dc4949bd283c001b91794d427e1e4cdf1b21ea4faf9fee3f + name: sbom-syft-generate + script: | + echo "Running syft on the source directory" + syft dir:$(workspaces.source.path)/source --output cyclonedx-json=$(workspaces.source.path)/sbom-source.json + echo "Running syft on the image filesystem" + syft dir:$(cat /shared/container_path) --output cyclonedx-json=$(workspaces.source.path)/sbom-image.json + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + workingDir: $(workspaces.source.path)/source + - image: quay.io/redhat-appstudio/hacbs-jvm-build-request-processor:127ee0c223a2b56a9bd20a6f2eaeed3bd6015f77 + name: analyse-dependencies-java-sbom + script: | + if [ -f /var/lib/containers/java ]; then + /opt/jboss/container/java/run/run-java.sh analyse-dependencies path $(cat /shared/container_path) -s $(workspaces.source.path)/sbom-image.json --task-run-name $(context.taskRun.name) --publishers $(results.SBOM_JAVA_COMPONENTS_COUNT.path) + sed -i 's/^/ /' $(results.SBOM_JAVA_COMPONENTS_COUNT.path) # Workaround for SRVKP-2875 + else + touch $(results.JAVA_COMMUNITY_DEPENDENCIES.path) + fi + securityContext: + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + - image: registry.access.redhat.com/ubi9/python-39:9.5-1734610342@sha256:dde5068ba8fd81eef41a9128ddad2b99e2e02e5869ffe925c605b609a0ad7bbb + name: merge-syft-sboms + script: | + #!/bin/python3 + import json + + # load SBOMs + with open("./sbom-image.json") as f: + image_sbom = json.load(f) + + with open("./sbom-source.json") as f: + source_sbom = json.load(f) + + # fetch unique components from available SBOMs + def get_identifier(component): + return component["name"] + '@' + component.get("version", "") + + image_sbom_components = image_sbom.setdefault("components", []) + existing_components = [get_identifier(component) for component in image_sbom_components] + + source_sbom_components = source_sbom.get("components", []) + for component in source_sbom_components: + if get_identifier(component) not in existing_components: + image_sbom_components.append(component) + existing_components.append(get_identifier(component)) + + image_sbom_components.sort(key=lambda c: get_identifier(c)) + + # write the CycloneDX unified SBOM + with open("./sbom-cyclonedx.json", "w") as f: + json.dump(image_sbom, f, indent=4) + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - image: quay.io/redhat-appstudio/cachi2:0.16.0@sha256:55415cd8ded149f5d56d3fca46d93125b86b41e07ae5d3c03caa240b7b93b7d8 + name: merge-cachi2-sbom + script: | + if [ -f "sbom-cachi2.json" ]; then + echo "Merging contents of sbom-cachi2.json into sbom-cyclonedx.json" + merge_syft_sbom sbom-cachi2.json sbom-cyclonedx.json > sbom-temp.json + mv sbom-temp.json sbom-cyclonedx.json + else + echo "Skipping step since no Cachi2 SBOM was produced" + fi + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - image: registry.access.redhat.com/ubi9/python-39:9.5-1734610342@sha256:dde5068ba8fd81eef41a9128ddad2b99e2e02e5869ffe925c605b609a0ad7bbb + name: create-purl-sbom + script: | + #!/bin/python3 + import json + + with open("./sbom-cyclonedx.json") as f: + cyclonedx_sbom = json.load(f) + + purls = [{"purl": component["purl"]} for component in cyclonedx_sbom.get("components", []) if "purl" in component] + purl_content = {"image_contents": {"dependencies": purls}} + + with open("sbom-purl.json", "w") as output_file: + json.dump(purl_content, output_file, indent=4) + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - env: + - name: BASE_IMAGES_DIGESTS_PATH + value: $(results.BASE_IMAGES_DIGESTS.path) + image: quay.io/redhat-appstudio/base-images-sbom-script@sha256:667669e3def018f9dbb8eaf8868887a40bc07842221e9a98f6787edcff021840 + name: create-base-images-sbom + script: | + python3 /app/base_images_sbom_script.py --sbom=sbom-cyclonedx.json --base-images-from-dockerfile=base_images_from_dockerfile --base-images-digests=$BASE_IMAGES_DIGESTS_PATH + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - computeResources: {} + image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: inject-sbom-and-push + script: | + if [ -n "${PARAM_BUILDER_IMAGE}" ]; then + echo "WARNING: provided deprecated BUILDER_IMAGE parameter has no effect." + fi + + base_image_name=$(buildah inspect --format '{{ index .ImageAnnotations "org.opencontainers.image.base.name"}}' $IMAGE | cut -f1 -d'@') + base_image_digest=$(buildah inspect --format '{{ index .ImageAnnotations "org.opencontainers.image.base.digest"}}' $IMAGE) + container=$(buildah from --pull-never $IMAGE) + buildah copy $container sbom-cyclonedx.json sbom-purl.json /root/buildinfo/content_manifests/ + buildah config -a org.opencontainers.image.base.name=${base_image_name} -a org.opencontainers.image.base.digest=${base_image_digest} $container + + BUILDAH_ARGS=() + if [ "${SQUASH}" == "true" ]; then + BUILDAH_ARGS+=("--squash") + fi + + buildah commit "${BUILDAH_ARGS[@]}" $container $IMAGE + + status=-1 + max_run=5 + sleep_sec=10 + for run in $(seq 1 $max_run); do + status=0 + [ "$run" -gt 1 ] && sleep $sleep_sec + echo "Pushing sbom image to registry" + buildah push \ + --tls-verify=$TLSVERIFY \ + --digestfile $(workspaces.source.path)/image-digest $IMAGE \ + docker://$IMAGE && break || status=$? + done + if [ "$status" -ne 0 ]; then + echo "Failed to push sbom image to registry after ${max_run} tries" + exit 1 + fi + + cat "$(workspaces.source.path)"/image-digest | tee $(results.IMAGE_DIGEST.path) + echo -n "$IMAGE" | tee $(results.IMAGE_URL.path) + securityContext: + capabilities: + add: + - SETFCAP + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + workingDir: $(workspaces.source.path) + - args: + - attach + - sbom + - --sbom + - sbom-cyclonedx.json + - --type + - cyclonedx + - $(params.IMAGE) + image: quay.io/redhat-appstudio/cosign:v2.1.1@sha256:c883d6f8d39148f2cea71bff4622d196d89df3e510f36c140c097b932f0dd5d5 + name: upload-sbom + workingDir: $(workspaces.source.path) + volumes: + - emptyDir: {} + name: varlibcontainers + - emptyDir: {} + name: shared + - name: etc-pki-entitlement + secret: + optional: true + secretName: $(params.ENTITLEMENT_SECRET) + - name: activation-key + secret: + optional: true + secretName: $(params.ACTIVATION_KEY) + - name: additional-secret + secret: + optional: true + secretName: $(params.ADDITIONAL_SECRET) + - configMap: + items: + - key: $(params.caTrustConfigMapKey) + path: ca-bundle.crt + name: $(params.caTrustConfigMapName) + optional: true + name: trusted-ca + workspaces: + - description: Workspace containing the source code to build. + name: source diff --git a/auto-generated/task/buildah-6gb/0.2/tekton.dev_v1_task_buildah-6gb.yaml b/auto-generated/task/buildah-6gb/0.2/tekton.dev_v1_task_buildah-6gb.yaml new file mode 100644 index 0000000000..bff9cee1a3 --- /dev/null +++ b/auto-generated/task/buildah-6gb/0.2/tekton.dev_v1_task_buildah-6gb.yaml @@ -0,0 +1,722 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + annotations: + build.appstudio.redhat.com/expires-on: "2025-01-21T00:00:00Z" + build.appstudio.redhat.com/expiry-message: 'Instead of using this task, switch + to buildah task (you can find latest bundle reference here: https://quay.io/repository/konflux-ci/tekton-catalog/task-buildah) + and configure build step resources as described in the doc: https://konflux-ci.dev/docs/how-tos/configuring/overriding-compute-resources/' + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: image-build, konflux + labels: + app.kubernetes.io/version: 0.2.1 + build.appstudio.redhat.com/build_type: docker + name: buildah-6gb +spec: + description: |- + Buildah task builds source code into a container image and pushes the image into container registry using buildah tool. + In addition it generates a SBOM file, injects the SBOM file into final container image and pushes the SBOM file as separate image using cosign tool. + When [Java dependency rebuild](https://redhat-appstudio.github.io/docs.stonesoup.io/Documentation/main/cli/proc_enabled_java_dependencies.html) is enabled it triggers rebuilds of Java artifacts. + When prefetch-dependencies task was activated it is using its artifacts to run build in hermetic environment. + params: + - description: Reference of the image buildah will produce. + name: IMAGE + type: string + - default: ./Dockerfile + description: Path to the Dockerfile to build. + name: DOCKERFILE + type: string + - default: . + description: Path to the directory to use as context. + name: CONTEXT + type: string + - default: "true" + description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS + registry) + name: TLSVERIFY + type: string + - default: "false" + description: Determines if build will be executed without network access. + name: HERMETIC + type: string + - default: "" + description: In case it is not empty, the prefetched content should be made available + to the build. + name: PREFETCH_INPUT + type: string + - default: "" + description: Delete image tag after specified time. Empty means to keep the image + tag. Time values could be something like 1h, 2d, 3w for hours, days, and weeks, + respectively. + name: IMAGE_EXPIRES_AFTER + type: string + - default: "" + description: The image is built from this commit. + name: COMMIT_SHA + type: string + - default: repos.d + description: Path in the git repository in which yum repository files are stored + name: YUM_REPOS_D_SRC + - default: fetched.repos.d + description: Path in source workspace where dynamically-fetched repos are present + name: YUM_REPOS_D_FETCHED + - default: /etc/yum.repos.d + description: Target path on the container in which yum repository files should + be made available + name: YUM_REPOS_D_TARGET + - default: "" + description: Target stage in Dockerfile to build. If not specified, the Dockerfile + is processed entirely to (and including) its last stage. + name: TARGET_STAGE + type: string + - default: etc-pki-entitlement + description: Name of secret which contains the entitlement certificates + name: ENTITLEMENT_SECRET + type: string + - default: activation-key + description: Name of secret which contains subscription activation key + name: ACTIVATION_KEY + type: string + - default: does-not-exist + description: Name of a secret which will be made available to the build with 'buildah + build --secret' at /run/secrets/$ADDITIONAL_SECRET + name: ADDITIONAL_SECRET + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) + name: BUILD_ARGS + type: array + - default: "" + description: Path to a file with build arguments, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: BUILD_ARGS_FILE + type: string + - default: trusted-ca + description: The name of the ConfigMap to read CA bundle data from. + name: caTrustConfigMapName + type: string + - default: ca-bundle.crt + description: The name of the key in the ConfigMap that contains the CA bundle + data. + name: caTrustConfigMapKey + type: string + - default: "" + description: Comma separated list of extra capabilities to add when running 'buildah + build' + name: ADD_CAPABILITIES + type: string + - default: "false" + description: Squash all new and previous layers added as a part of this build, + as per --squash + name: SQUASH + type: string + - default: vfs + description: Storage driver to configure for buildah + name: STORAGE_DRIVER + type: string + - default: "true" + description: Whether to skip stages in Containerfile that seem unused by subsequent + stages + name: SKIP_UNUSED_STAGES + type: string + - default: [] + description: Additional key=value labels that should be applied to the image + name: LABELS + type: array + - default: "false" + description: Whether to enable privileged mode + name: PRIVILEGED_NESTED + type: string + results: + - description: Digest of the image just built + name: IMAGE_DIGEST + - description: Image repository and tag where the built image was pushed + name: IMAGE_URL + - description: Image reference of the built image + name: IMAGE_REF + - description: Reference of SBOM blob digest to enable digest-based verification + from provenance + name: SBOM_BLOB_URL + type: string + - description: The counting of Java components by publisher in JSON format + name: SBOM_JAVA_COMPONENTS_COUNT + type: string + - description: The Java dependencies that came from community sources such as Maven + central. + name: JAVA_COMMUNITY_DEPENDENCIES + stepTemplate: + computeResources: + limits: + cpu: "4" + memory: 4Gi + requests: + cpu: "1" + memory: 1Gi + env: + - name: BUILDAH_FORMAT + value: oci + - name: STORAGE_DRIVER + value: $(params.STORAGE_DRIVER) + - name: HERMETIC + value: $(params.HERMETIC) + - name: SOURCE_CODE_DIR + value: source + - name: CONTEXT + value: $(params.CONTEXT) + - name: IMAGE + value: $(params.IMAGE) + - name: TLSVERIFY + value: $(params.TLSVERIFY) + - name: IMAGE_EXPIRES_AFTER + value: $(params.IMAGE_EXPIRES_AFTER) + - name: YUM_REPOS_D_SRC + value: $(params.YUM_REPOS_D_SRC) + - name: YUM_REPOS_D_FETCHED + value: $(params.YUM_REPOS_D_FETCHED) + - name: YUM_REPOS_D_TARGET + value: $(params.YUM_REPOS_D_TARGET) + - name: TARGET_STAGE + value: $(params.TARGET_STAGE) + - name: ENTITLEMENT_SECRET + value: $(params.ENTITLEMENT_SECRET) + - name: ACTIVATION_KEY + value: $(params.ACTIVATION_KEY) + - name: ADDITIONAL_SECRET + value: $(params.ADDITIONAL_SECRET) + - name: BUILD_ARGS_FILE + value: $(params.BUILD_ARGS_FILE) + - name: ADD_CAPABILITIES + value: $(params.ADD_CAPABILITIES) + - name: SQUASH + value: $(params.SQUASH) + - name: SKIP_UNUSED_STAGES + value: $(params.SKIP_UNUSED_STAGES) + - name: PRIVILEGED_NESTED + value: $(params.PRIVILEGED_NESTED) + volumeMounts: + - mountPath: /shared + name: shared + steps: + - args: + - --build-args + - $(params.BUILD_ARGS[*]) + - --labels + - $(params.LABELS[*]) + computeResources: + limits: + cpu: "4" + memory: 6Gi + requests: + cpu: "1" + memory: 4Gi + env: + - name: COMMIT_SHA + value: $(params.COMMIT_SHA) + - name: DOCKERFILE + value: $(params.DOCKERFILE) + image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: build + script: | + #!/bin/bash + set -euo pipefail + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + if [ -e "$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" + elif [ -e "$SOURCE_CODE_DIR/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$DOCKERFILE" + elif [ -e "$DOCKERFILE" ]; then + # Instrumented builds (SAST) use this custom dockerffile step as their base + dockerfile_path="$DOCKERFILE" + elif echo "$DOCKERFILE" | grep -q "^https\?://"; then + echo "Fetch Dockerfile from $DOCKERFILE" + dockerfile_path=$(mktemp --suffix=-Dockerfile) + http_code=$(curl -s -S -L -w "%{http_code}" --output "$dockerfile_path" "$DOCKERFILE") + if [ $http_code != 200 ]; then + echo "No Dockerfile is fetched. Server responds $http_code" + exit 1 + fi + http_code=$(curl -s -S -L -w "%{http_code}" --output "$dockerfile_path.dockerignore.tmp" "$DOCKERFILE.dockerignore") + if [ $http_code = 200 ]; then + echo "Fetched .dockerignore from $DOCKERFILE.dockerignore" + mv "$dockerfile_path.dockerignore.tmp" $SOURCE_CODE_DIR/$CONTEXT/.dockerignore + fi + else + echo "Cannot find Dockerfile $DOCKERFILE" + exit 1 + fi + + dockerfile_copy=$(mktemp --tmpdir "$(basename "$dockerfile_path").XXXXXX") + cp "$dockerfile_path" "$dockerfile_copy" + + if [ -n "${JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR-}" ] && grep -q '^\s*RUN \(./\)\?mvn' "$dockerfile_copy"; then + sed -i -e "s|^\s*RUN \(\(./\)\?mvn\)\(.*\)|RUN echo \"mirror.defaulthttp://$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR/v1/cache/default/0/*\" > /tmp/settings.yaml; \1 -s /tmp/settings.yaml \3|g" "$dockerfile_copy" + touch /var/lib/containers/java + fi + + # Fixing group permission on /var/lib/containers + chown root:root /var/lib/containers + + sed -i 's/^\s*short-name-mode\s*=\s*.*/short-name-mode = "disabled"/' /etc/containers/registries.conf + + # Setting new namespace to run buildah - 2^32-2 + echo 'root:1:4294967294' | tee -a /etc/subuid >> /etc/subgid + + build_args=() + if [ -n "${BUILD_ARGS_FILE}" ]; then + # Parse BUILD_ARGS_FILE ourselves because dockerfile-json doesn't support it + echo "Parsing ARGs from $BUILD_ARGS_FILE" + mapfile -t build_args < <( + # https://www.mankier.com/1/buildah-build#--build-arg-file + # delete lines that start with # + # delete blank lines + sed -e '/^#/d' -e '/^\s*$/d' "${SOURCE_CODE_DIR}/${BUILD_ARGS_FILE}" + ) + fi + + LABELS=() + # Split `args` into two sets of arguments. + while [[ $# -gt 0 ]]; do + case $1 in + --build-args) + shift + # Note: this may result in multiple --build-arg=KEY=value flags with the same KEY being + # passed to buildah. In that case, the *last* occurrence takes precedence. This is why + # we append BUILD_ARGS after the content of the BUILD_ARGS_FILE + while [[ $# -gt 0 && $1 != --* ]]; do build_args+=("$1"); shift; done + ;; + --labels) + shift + while [[ $# -gt 0 && $1 != --* ]]; do LABELS+=("--label" "$1"); shift; done + ;; + *) + echo "unexpected argument: $1" >&2 + exit 2 + ;; + esac + done + + BUILD_ARG_FLAGS=() + for build_arg in "${build_args[@]}"; do + BUILD_ARG_FLAGS+=("--build-arg=$build_arg") + done + + dockerfile-json "${BUILD_ARG_FLAGS[@]}" "$dockerfile_copy" > /shared/parsed_dockerfile.json + BASE_IMAGES=$( + jq -r '.Stages[] | select(.From | .Stage or .Scratch | not) | .BaseName | select(test("^oci-archive:") | not)' /shared/parsed_dockerfile.json + ) + + BUILDAH_ARGS=() + UNSHARE_ARGS=() + + if [ "${HERMETIC}" == "true" ]; then + BUILDAH_ARGS+=("--pull=never") + UNSHARE_ARGS+=("--net") + + for image in $BASE_IMAGES; do + unshare -Ufp --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -- buildah pull $image + done + echo "Build will be executed with network isolation" + fi + + if [ -n "${TARGET_STAGE}" ]; then + BUILDAH_ARGS+=("--target=${TARGET_STAGE}") + fi + + BUILDAH_ARGS+=("${BUILD_ARG_FLAGS[@]}") + + if [ "${PRIVILEGED_NESTED}" == "true" ]; then + BUILDAH_ARGS+=("--security-opt=label=disable") + BUILDAH_ARGS+=("--cap-add=all") + BUILDAH_ARGS+=("--device=/dev/fuse") + fi + + if [ -n "${ADD_CAPABILITIES}" ]; then + BUILDAH_ARGS+=("--cap-add=${ADD_CAPABILITIES}") + fi + + if [ "${SQUASH}" == "true" ]; then + BUILDAH_ARGS+=("--squash") + fi + + if [ "${SKIP_UNUSED_STAGES}" != "true" ] ; then + BUILDAH_ARGS+=("--skip-unused-stages=false") + fi + + VOLUME_MOUNTS=() + + if [ -f "$(workspaces.source.path)/cachi2/cachi2.env" ]; then + cp -r "$(workspaces.source.path)/cachi2" /tmp/ + chmod -R go+rwX /tmp/cachi2 + VOLUME_MOUNTS+=(--volume /tmp/cachi2:/cachi2) + # Read in the whole file (https://unix.stackexchange.com/questions/533277), then + # for each RUN ... line insert the cachi2.env command *after* any options like --mount + sed -E -i \ + -e 'H;1h;$!d;x' \ + -e 's@^\s*(run((\s|\\\n)+-\S+)*(\s|\\\n)+)@\1. /cachi2/cachi2.env \&\& \\\n @igM' \ + "$dockerfile_copy" + echo "Prefetched content will be made available" + + prefetched_repo_for_my_arch="/tmp/cachi2/output/deps/rpm/$(uname -m)/repos.d/cachi2.repo" + if [ -f "$prefetched_repo_for_my_arch" ]; then + echo "Adding $prefetched_repo_for_my_arch to $YUM_REPOS_D_FETCHED" + mkdir -p "$YUM_REPOS_D_FETCHED" + cp --no-clobber "$prefetched_repo_for_my_arch" "$YUM_REPOS_D_FETCHED" + fi + fi + + # if yum repofiles stored in git, copy them to mount point outside the source dir + if [ -d "${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}" ]; then + mkdir -p ${YUM_REPOS_D_FETCHED} + cp -r ${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}/* ${YUM_REPOS_D_FETCHED} + fi + + # if anything in the repofiles mount point (either fetched or from git), mount it + if [ -d "${YUM_REPOS_D_FETCHED}" ]; then + chmod -R go+rwX ${YUM_REPOS_D_FETCHED} + mount_point=$(realpath ${YUM_REPOS_D_FETCHED}) + VOLUME_MOUNTS+=(--volume "${mount_point}:${YUM_REPOS_D_TARGET}") + fi + + DEFAULT_LABELS=( + "--label" "build-date=$(date -u +'%Y-%m-%dT%H:%M:%S')" + "--label" "architecture=$(uname -m)" + "--label" "vcs-type=git" + ) + [ -n "$COMMIT_SHA" ] && DEFAULT_LABELS+=("--label" "vcs-ref=$COMMIT_SHA") + [ -n "$IMAGE_EXPIRES_AFTER" ] && DEFAULT_LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + + # Concatenate defaults and explicit labels. If a label appears twice, the last one wins. + LABELS=("${DEFAULT_LABELS[@]}" "${LABELS[@]}") + + ACTIVATION_KEY_PATH="/activation-key" + ENTITLEMENT_PATH="/entitlement" + + # 0. if hermetic=true, skip all subscription related stuff + # 1. do not enable activation key and entitlement at same time. If both vars are provided, prefer activation key. + # 2. Activation-keys will be used when the key 'org' exists in the activation key secret. + # 3. try to pre-register and mount files to the correct location so that users do no need to modify Dockerfiles. + # 3. If the Dockerfile contains the string "subcription-manager register", add the activation-keys volume + # to buildah but don't pre-register for backwards compatibility. Mount an empty directory on + # shared emptydir volume to "/etc/pki/entitlement" to prevent certificates from being included + + if [ "${HERMETIC}" != "true" ] && [ -e /activation-key/org ]; then + cp -r --preserve=mode "$ACTIVATION_KEY_PATH" /tmp/activation-key + mkdir -p /shared/rhsm/etc/pki/entitlement + mkdir -p /shared/rhsm/etc/pki/consumer + + VOLUME_MOUNTS+=(-v /tmp/activation-key:/activation-key \ + -v /shared/rhsm/etc/pki/entitlement:/etc/pki/entitlement:Z \ + -v /shared/rhsm/etc/pki/consumer:/etc/pki/consumer:Z) + echo "Adding activation key to the build" + + if ! grep -E "^[^#]*subscription-manager.[^#]*register" "$dockerfile_path"; then + # user is not running registration in the Containerfile: pre-register. + echo "Pre-registering with subscription manager." + subscription-manager register --org "$(cat /tmp/activation-key/org)" --activationkey "$(cat /tmp/activation-key/activationkey)" + trap 'subscription-manager unregister || true' EXIT + + # copy generated certificates to /shared volume + cp /etc/pki/entitlement/*.pem /shared/rhsm/etc/pki/entitlement + cp /etc/pki/consumer/*.pem /shared/rhsm/etc/pki/consumer + + # and then mount get /etc/rhsm/ca/redhat-uep.pem into /run/secrets/rhsm/ca + VOLUME_MOUNTS+=(--volume /etc/rhsm/ca/redhat-uep.pem:/etc/rhsm/ca/redhat-uep.pem:Z) + fi + + elif [ "${HERMETIC}" != "true" ] && find /entitlement -name "*.pem" >> null; then + cp -r --preserve=mode "$ENTITLEMENT_PATH" /tmp/entitlement + VOLUME_MOUNTS+=(--volume /tmp/entitlement:/etc/pki/entitlement) + echo "Adding the entitlement to the build" + fi + + if [ -n "${ADDITIONAL_VOLUME_MOUNTS-}" ]; then + # ADDITIONAL_VOLUME_MOUNTS allows to specify more volumes for the build. + # Instrumented builds (SAST) use this step as their base and add some other tools. + while read -r volume_mount; do + VOLUME_MOUNTS+=("--volume=$volume_mount") + done <<< "$ADDITIONAL_VOLUME_MOUNTS" + fi + + ADDITIONAL_SECRET_PATH="/additional-secret" + ADDITIONAL_SECRET_TMP="/tmp/additional-secret" + if [ -d "$ADDITIONAL_SECRET_PATH" ]; then + cp -r --preserve=mode -L "$ADDITIONAL_SECRET_PATH" $ADDITIONAL_SECRET_TMP + while read -r filename; do + echo "Adding the secret ${ADDITIONAL_SECRET}/${filename} to the build, available at /run/secrets/${ADDITIONAL_SECRET}/${filename}" + BUILDAH_ARGS+=("--secret=id=${ADDITIONAL_SECRET}/${filename},src=$ADDITIONAL_SECRET_TMP/${filename}") + done < <(find $ADDITIONAL_SECRET_TMP -maxdepth 1 -type f -exec basename {} \;) + fi + + # Prevent ShellCheck from giving a warning because 'image' is defined and 'IMAGE' is not. + declare IMAGE + + buildah_cmd_array=( + buildah build + "${VOLUME_MOUNTS[@]}" + "${BUILDAH_ARGS[@]}" + "${LABELS[@]}" + --tls-verify="$TLSVERIFY" --no-cache + --ulimit nofile=4096:4096 + -f "$dockerfile_copy" -t "$IMAGE" . + ) + buildah_cmd=$(printf "%q " "${buildah_cmd_array[@]}") + + if [ "${HERMETIC}" == "true" ]; then + # enabling loopback adapter enables Bazel builds to work in hermetic mode. + command="ip link set lo up && $buildah_cmd" + else + command="$buildah_cmd" + fi + + # disable host subcription manager integration + find /usr/share/rhel/secrets -type l -exec unlink {} \; + + unshare -Uf "${UNSHARE_ARGS[@]}" --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -w "${SOURCE_CODE_DIR}/$CONTEXT" -- sh -c "$command" + + container=$(buildah from --pull-never "$IMAGE") + + # Save the SBOM produced by Cachi2 so it can be merged into the final SBOM later + if [ -f "/tmp/cachi2/output/bom.json" ]; then + echo "Making copy of sbom-cachi2.json" + cp /tmp/cachi2/output/bom.json ./sbom-cachi2.json + fi + + buildah mount $container | tee /shared/container_path + # delete symlinks - they may point outside the container rootfs, messing with SBOM scanners + find $(cat /shared/container_path) -xtype l -delete + echo $container > /shared/container_name + + touch /shared/base_images_digests + for image in $BASE_IMAGES; do + base_image_digest=$(buildah images --format '{{ .Name }}:{{ .Tag }}@{{ .Digest }}' --filter reference="$image") + # In some cases, there might be BASE_IMAGES, but not any associated digest. This happens + # if buildah did not use that particular image during build because it was skipped + if [ -n "$base_image_digest" ]; then + echo "$image $base_image_digest" >> /shared/base_images_digests + fi + done + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /entitlement + name: etc-pki-entitlement + - mountPath: /activation-key + name: activation-key + - mountPath: /additional-secret + name: additional-secret + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + - image: quay.io/konflux-ci/icm-injection-scripts:latest@sha256:462980e94ba689b5f56c3d5dfb3358cd8c685300daf65a71532f11898935e7f1 + name: icm + script: | + #!/bin/bash + set -euo pipefail + /scripts/inject-icm.sh "$IMAGE" + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + workingDir: $(workspaces.source.path) + - image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: push + script: | + #!/bin/bash + set -e + + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + retries=5 + # Push to a unique tag based on the TaskRun name to avoid race conditions + echo "Pushing to ${IMAGE%:*}:${TASKRUN_NAME}" + if ! buildah push \ + --retry "$retries" \ + --tls-verify="$TLSVERIFY" \ + "$IMAGE" \ + "docker://${IMAGE%:*}:$(context.taskRun.name)"; + then + echo "Failed to push sbom image to ${IMAGE%:*}:$(context.taskRun.name) after ${retries} tries" + exit 1 + fi + + # Push to a tag based on the git revision + echo "Pushing to ${IMAGE}" + if ! buildah push \ + --retry "$retries" \ + --tls-verify="$TLSVERIFY" \ + --digestfile "$(workspaces.source.path)/image-digest" "$IMAGE" \ + "docker://$IMAGE"; + then + echo "Failed to push sbom image to $IMAGE after ${retries} tries" + exit 1 + fi + + cat "$(workspaces.source.path)"/image-digest | tee $(results.IMAGE_DIGEST.path) + echo -n "$IMAGE" | tee $(results.IMAGE_URL.path) + { + echo -n "${IMAGE}@" + cat "$(workspaces.source.path)/image-digest" + } > "$(results.IMAGE_REF.path)" + securityContext: + capabilities: + add: + - SETFCAP + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + - image: registry.access.redhat.com/rh-syft-tech-preview/syft-rhel9:1.4.1@sha256:34d7065427085a31dc4949bd283c001b91794d427e1e4cdf1b21ea4faf9fee3f + name: sbom-syft-generate + script: | + echo "Running syft on the source directory" + syft dir:"$(workspaces.source.path)/$SOURCE_CODE_DIR/$CONTEXT" --output cyclonedx-json="$(workspaces.source.path)/sbom-source.json" + echo "Running syft on the image filesystem" + syft dir:"$(cat /shared/container_path)" --output cyclonedx-json="$(workspaces.source.path)/sbom-image.json" + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + workingDir: $(workspaces.source.path)/source + - computeResources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + image: quay.io/redhat-appstudio/hacbs-jvm-build-request-processor:127ee0c223a2b56a9bd20a6f2eaeed3bd6015f77 + name: analyse-dependencies-java-sbom + script: | + if [ -f /var/lib/containers/java ]; then + /opt/jboss/container/java/run/run-java.sh analyse-dependencies path $(cat /shared/container_path) -s $(workspaces.source.path)/sbom-image.json --task-run-name $(context.taskRun.name) --publishers $(results.SBOM_JAVA_COMPONENTS_COUNT.path) + sed -i 's/^/ /' $(results.SBOM_JAVA_COMPONENTS_COUNT.path) # Workaround for SRVKP-2875 + else + touch $(results.JAVA_COMMUNITY_DEPENDENCIES.path) + fi + securityContext: + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + - computeResources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + image: quay.io/redhat-appstudio/sbom-utility-scripts-image@sha256:9f1fd11d9c3c517ecc112d192ad361d16ecf6ce00b83b109c93cf3d1c644a357 + name: prepare-sboms + script: | + echo "Merging contents of sbom-source.json and sbom-image.json into sbom-cyclonedx.json" + python3 /scripts/merge_syft_sboms.py + + if [ -f "sbom-cachi2.json" ]; then + echo "Merging contents of sbom-cachi2.json into sbom-cyclonedx.json" + python3 /scripts/merge_cachi2_sboms.py sbom-cachi2.json sbom-cyclonedx.json > sbom-temp.json + mv sbom-temp.json sbom-cyclonedx.json + fi + + echo "Adding base images data to sbom-cyclonedx.json" + python3 /scripts/base_images_sbom_script.py \ + --sbom=sbom-cyclonedx.json \ + --parsed-dockerfile=/shared/parsed_dockerfile.json \ + --base-images-digests=/shared/base_images_digests + + echo "Adding image reference to sbom" + IMAGE_URL="$(cat "$(results.IMAGE_URL.path)")" + IMAGE_DIGEST="$(cat "$(results.IMAGE_DIGEST.path)")" + + python3 /scripts/add_image_reference.py \ + --image-url "$IMAGE_URL" \ + --image-digest "$IMAGE_DIGEST" \ + --input-file sbom-cyclonedx.json \ + --output-file /tmp/sbom-cyclonedx.tmp.json + + mv /tmp/sbom-cyclonedx.tmp.json sbom-cyclonedx.json + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - computeResources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + image: quay.io/konflux-ci/appstudio-utils:48c311af02858e2422d6229600e9959e496ddef1@sha256:91ddd999271f65d8ec8487b10f3dd378f81aa894e11b9af4d10639fd52bba7e8 + name: upload-sbom + script: | + #!/bin/bash + + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + cosign attach sbom --sbom sbom-cyclonedx.json --type cyclonedx "$(cat "$(results.IMAGE_REF.path)")" + + # Remove tag from IMAGE while allowing registry to contain a port number. + sbom_repo="${IMAGE%:*}" + sbom_digest="$(sha256sum sbom-cyclonedx.json | cut -d' ' -f1)" + # The SBOM_BLOB_URL is created by `cosign attach sbom`. + echo -n "${sbom_repo}@sha256:${sbom_digest}" | tee "$(results.SBOM_BLOB_URL.path)" + volumeMounts: + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + volumes: + - emptyDir: {} + name: varlibcontainers + - emptyDir: {} + name: shared + - name: etc-pki-entitlement + secret: + optional: true + secretName: $(params.ENTITLEMENT_SECRET) + - name: activation-key + secret: + optional: true + secretName: $(params.ACTIVATION_KEY) + - name: additional-secret + secret: + optional: true + secretName: $(params.ADDITIONAL_SECRET) + - configMap: + items: + - key: $(params.caTrustConfigMapKey) + path: ca-bundle.crt + name: $(params.caTrustConfigMapName) + optional: true + name: trusted-ca + workspaces: + - description: Workspace containing the source code to build. + name: source diff --git a/auto-generated/task/buildah-8gb/0.1/tekton.dev_v1_task_buildah-8gb.yaml b/auto-generated/task/buildah-8gb/0.1/tekton.dev_v1_task_buildah-8gb.yaml new file mode 100644 index 0000000000..d463d51043 --- /dev/null +++ b/auto-generated/task/buildah-8gb/0.1/tekton.dev_v1_task_buildah-8gb.yaml @@ -0,0 +1,585 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + annotations: + build.appstudio.redhat.com/expires-on: "2025-01-21T00:00:00Z" + build.appstudio.redhat.com/expiry-message: 'Instead of using this task, switch + to buildah task (you can find latest bundle reference here: https://quay.io/repository/konflux-ci/tekton-catalog/task-buildah) + and configure build step resources as described in the doc: https://konflux-ci.dev/docs/how-tos/configuring/overriding-compute-resources/' + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: image-build, konflux + labels: + app.kubernetes.io/version: "0.1" + build.appstudio.redhat.com/build_type: docker + name: buildah-8gb +spec: + description: |- + Buildah task builds source code into a container image and pushes the image into container registry using buildah tool. + In addition it generates a SBOM file, injects the SBOM file into final container image and pushes the SBOM file as separate image using cosign tool. + When [Java dependency rebuild](https://redhat-appstudio.github.io/docs.stonesoup.io/Documentation/main/cli/proc_enabled_java_dependencies.html) is enabled it triggers rebuilds of Java artifacts. + When prefetch-dependencies task was activated it is using its artifacts to run build in hermetic environment. + params: + - description: Reference of the image buildah will produce. + name: IMAGE + type: string + - default: "" + description: Deprecated. Has no effect. Will be removed in the future. + name: BUILDER_IMAGE + type: string + - default: ./Dockerfile + description: Path to the Dockerfile to build. + name: DOCKERFILE + type: string + - default: . + description: Path to the directory to use as context. + name: CONTEXT + type: string + - default: "true" + description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS + registry) + name: TLSVERIFY + type: string + - default: "" + description: unused, should be removed in next task version + name: DOCKER_AUTH + type: string + - default: "false" + description: Determines if build will be executed without network access. + name: HERMETIC + type: string + - default: "" + description: In case it is not empty, the prefetched content should be made available + to the build. + name: PREFETCH_INPUT + type: string + - default: "" + description: Delete image tag after specified time. Empty means to keep the image + tag. Time values could be something like 1h, 2d, 3w for hours, days, and weeks, + respectively. + name: IMAGE_EXPIRES_AFTER + type: string + - default: "" + description: The image is built from this commit. + name: COMMIT_SHA + type: string + - default: repos.d + description: Path in the git repository in which yum repository files are stored + name: YUM_REPOS_D_SRC + - default: fetched.repos.d + description: Path in source workspace where dynamically-fetched repos are present + name: YUM_REPOS_D_FETCHED + - default: /etc/yum.repos.d + description: Target path on the container in which yum repository files should + be made available + name: YUM_REPOS_D_TARGET + - default: "" + description: Target stage in Dockerfile to build. If not specified, the Dockerfile + is processed entirely to (and including) its last stage. + name: TARGET_STAGE + type: string + - default: etc-pki-entitlement + description: Name of secret which contains the entitlement certificates + name: ENTITLEMENT_SECRET + type: string + - default: activation-key + description: Name of secret which contains subscription activation key + name: ACTIVATION_KEY + type: string + - default: does-not-exist + description: Name of a secret which will be made available to the build with 'buildah + build --secret' at /run/secrets/$ADDITIONAL_SECRET + name: ADDITIONAL_SECRET + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) + name: BUILD_ARGS + type: array + - default: "" + description: Path to a file with build arguments, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: BUILD_ARGS_FILE + type: string + - default: trusted-ca + description: The name of the ConfigMap to read CA bundle data from. + name: caTrustConfigMapName + type: string + - default: ca-bundle.crt + description: The name of the key in the ConfigMap that contains the CA bundle + data. + name: caTrustConfigMapKey + type: string + - default: "" + description: Comma separated list of extra capabilities to add when running 'buildah + build' + name: ADD_CAPABILITIES + type: string + - default: "false" + description: Squash all new and previous layers added as a part of this build, + as per --squash + name: SQUASH + type: string + - default: vfs + description: Storage driver to configure for buildah + name: STORAGE_DRIVER + type: string + - default: "true" + description: Whether to skip stages in Containerfile that seem unused by subsequent + stages + name: SKIP_UNUSED_STAGES + type: string + results: + - description: Digest of the image just built + name: IMAGE_DIGEST + - description: Image repository and tag where the built image was pushed + name: IMAGE_URL + - description: Digests of the base images used for build + name: BASE_IMAGES_DIGESTS + - description: The counting of Java components by publisher in JSON format + name: SBOM_JAVA_COMPONENTS_COUNT + type: string + - description: The Java dependencies that came from community sources such as Maven + central. + name: JAVA_COMMUNITY_DEPENDENCIES + stepTemplate: + env: + - name: BUILDAH_FORMAT + value: oci + - name: STORAGE_DRIVER + value: $(params.STORAGE_DRIVER) + - name: HERMETIC + value: $(params.HERMETIC) + - name: CONTEXT + value: $(params.CONTEXT) + - name: DOCKERFILE + value: $(params.DOCKERFILE) + - name: IMAGE + value: $(params.IMAGE) + - name: TLSVERIFY + value: $(params.TLSVERIFY) + - name: IMAGE_EXPIRES_AFTER + value: $(params.IMAGE_EXPIRES_AFTER) + - name: YUM_REPOS_D_SRC + value: $(params.YUM_REPOS_D_SRC) + - name: YUM_REPOS_D_FETCHED + value: $(params.YUM_REPOS_D_FETCHED) + - name: YUM_REPOS_D_TARGET + value: $(params.YUM_REPOS_D_TARGET) + - name: TARGET_STAGE + value: $(params.TARGET_STAGE) + - name: PARAM_BUILDER_IMAGE + value: $(params.BUILDER_IMAGE) + - name: ENTITLEMENT_SECRET + value: $(params.ENTITLEMENT_SECRET) + - name: ADDITIONAL_SECRET + value: $(params.ADDITIONAL_SECRET) + - name: BUILD_ARGS_FILE + value: $(params.BUILD_ARGS_FILE) + - name: ADD_CAPABILITIES + value: $(params.ADD_CAPABILITIES) + - name: SQUASH + value: $(params.SQUASH) + - name: SKIP_UNUSED_STAGES + value: $(params.SKIP_UNUSED_STAGES) + volumeMounts: + - mountPath: /shared + name: shared + steps: + - args: + - $(params.BUILD_ARGS[*]) + computeResources: + limits: + memory: 8Gi + requests: + cpu: 250m + memory: 6Gi + env: + - name: COMMIT_SHA + value: $(params.COMMIT_SHA) + image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: build + script: | + if [ -n "${PARAM_BUILDER_IMAGE}" ]; then + echo "WARNING: provided deprecated BUILDER_IMAGE parameter has no effect." + fi + + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + SOURCE_CODE_DIR=source + if [ -e "$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" + elif [ -e "$SOURCE_CODE_DIR/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$DOCKERFILE" + elif echo "$DOCKERFILE" | grep -q "^https\?://"; then + echo "Fetch Dockerfile from $DOCKERFILE" + dockerfile_path=$(mktemp --suffix=-Dockerfile) + http_code=$(curl -s -L -w "%{http_code}" --output "$dockerfile_path" "$DOCKERFILE") + if [ $http_code != 200 ]; then + echo "No Dockerfile is fetched. Server responds $http_code" + exit 1 + fi + http_code=$(curl -s -L -w "%{http_code}" --output "$dockerfile_path.dockerignore.tmp" "$DOCKERFILE.dockerignore") + if [ $http_code = 200 ]; then + echo "Fetched .dockerignore from $DOCKERFILE.dockerignore" + mv "$dockerfile_path.dockerignore.tmp" $SOURCE_CODE_DIR/$CONTEXT/.dockerignore + fi + else + echo "Cannot find Dockerfile $DOCKERFILE" + exit 1 + fi + if [ -n "$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR" ] && grep -q '^\s*RUN \(./\)\?mvn' "$dockerfile_path"; then + sed -i -e "s|^\s*RUN \(\(./\)\?mvn\)\(.*\)|RUN echo \"mirror.defaulthttp://$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR/v1/cache/default/0/*\" > /tmp/settings.yaml; \1 -s /tmp/settings.yaml \3|g" "$dockerfile_path" + touch /var/lib/containers/java + fi + + # Fixing group permission on /var/lib/containers + chown root:root /var/lib/containers + + sed -i 's/^\s*short-name-mode\s*=\s*.*/short-name-mode = "disabled"/' /etc/containers/registries.conf + + # Setting new namespace to run buildah - 2^32-2 + echo 'root:1:4294967294' | tee -a /etc/subuid >> /etc/subgid + + BUILDAH_ARGS=() + + BASE_IMAGES=$(grep -i '^\s*FROM' "$dockerfile_path" | sed 's/--platform=\S*//' | awk '{print $2}' | (grep -v ^oci-archive: || true)) + if [ "${HERMETIC}" == "true" ]; then + BUILDAH_ARGS+=("--pull=never") + UNSHARE_ARGS="--net" + for image in $BASE_IMAGES; do + if [ "${image}" != "scratch" ]; then + unshare -Ufp --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -- buildah pull $image + fi + done + echo "Build will be executed with network isolation" + fi + + if [ -n "${TARGET_STAGE}" ]; then + BUILDAH_ARGS+=("--target=${TARGET_STAGE}") + fi + + if [ -n "${BUILD_ARGS_FILE}" ]; then + BUILDAH_ARGS+=("--build-arg-file=$(pwd)/$SOURCE_CODE_DIR/${BUILD_ARGS_FILE}") + fi + + for build_arg in "$@"; do + BUILDAH_ARGS+=("--build-arg=$build_arg") + done + + if [ -n "${ADD_CAPABILITIES}" ]; then + BUILDAH_ARGS+=("--cap-add=${ADD_CAPABILITIES}") + fi + + if [ "${SQUASH}" == "true" ]; then + BUILDAH_ARGS+=("--squash") + fi + + if [ "${SKIP_UNUSED_STAGES}" != "true" ] ; then + BUILDAH_ARGS+=("--skip-unused-stages=false") + fi + + if [ -f "$(workspaces.source.path)/cachi2/cachi2.env" ]; then + cp -r "$(workspaces.source.path)/cachi2" /tmp/ + chmod -R go+rwX /tmp/cachi2 + VOLUME_MOUNTS="--volume /tmp/cachi2:/cachi2" + # Read in the whole file (https://unix.stackexchange.com/questions/533277), then + # for each RUN ... line insert the cachi2.env command *after* any options like --mount + sed -E -i \ + -e 'H;1h;$!d;x' \ + -e 's@^\s*(run((\s|\\\n)+-\S+)*(\s|\\\n)+)@\1. /cachi2/cachi2.env \&\& \\\n @igM' \ + "$dockerfile_path" + echo "Prefetched content will be made available" + + prefetched_repo_for_my_arch="/tmp/cachi2/output/deps/rpm/$(uname -m)/repos.d/cachi2.repo" + if [ -f "$prefetched_repo_for_my_arch" ]; then + echo "Adding $prefetched_repo_for_my_arch to $YUM_REPOS_D_FETCHED" + mkdir -p "$YUM_REPOS_D_FETCHED" + cp --no-clobber "$prefetched_repo_for_my_arch" "$YUM_REPOS_D_FETCHED" + fi + fi + + # if yum repofiles stored in git, copy them to mount point outside the source dir + if [ -d "${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}" ]; then + mkdir -p ${YUM_REPOS_D_FETCHED} + cp -r ${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}/* ${YUM_REPOS_D_FETCHED} + fi + + # if anything in the repofiles mount point (either fetched or from git), mount it + if [ -d "${YUM_REPOS_D_FETCHED}" ]; then + chmod -R go+rwX ${YUM_REPOS_D_FETCHED} + mount_point=$(realpath ${YUM_REPOS_D_FETCHED}) + VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume ${mount_point}:${YUM_REPOS_D_TARGET}" + fi + + LABELS=( + "--label" "build-date=$(date -u +'%Y-%m-%dT%H:%M:%S')" + "--label" "architecture=$(uname -m)" + "--label" "vcs-type=git" + ) + [ -n "$COMMIT_SHA" ] && LABELS+=("--label" "vcs-ref=$COMMIT_SHA") + [ -n "$IMAGE_EXPIRES_AFTER" ] && LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + + ACTIVATION_KEY_PATH="/activation-key" + ENTITLEMENT_PATH="/entitlement" + + if [ -e /activation-key/org ]; then + cp -r --preserve=mode "$ACTIVATION_KEY_PATH" /tmp/activation-key + mkdir /shared/rhsm-tmp + VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume /tmp/activation-key:/activation-key -v /shared/rhsm-tmp:/etc/pki/entitlement:Z" + echo "Adding activation key to the build" + + elif find /entitlement -name "*.pem" >> null; then + cp -r --preserve=mode "$ENTITLEMENT_PATH" /tmp/entitlement + VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume /tmp/entitlement:/etc/pki/entitlement" + echo "Adding the entitlement to the build" + fi + + ADDITIONAL_SECRET_PATH="/additional-secret" + ADDITIONAL_SECRET_TMP="/tmp/additional-secret" + if [ -d "$ADDITIONAL_SECRET_PATH" ]; then + cp -r --preserve=mode -L "$ADDITIONAL_SECRET_PATH" $ADDITIONAL_SECRET_TMP + while read -r filename; do + echo "Adding the secret ${ADDITIONAL_SECRET}/${filename} to the build, available at /run/secrets/${ADDITIONAL_SECRET}/${filename}" + BUILDAH_ARGS+=("--secret=id=${ADDITIONAL_SECRET}/${filename},src=$ADDITIONAL_SECRET_TMP/${filename}") + done < <(find $ADDITIONAL_SECRET_TMP -maxdepth 1 -type f -exec basename {} \;) + fi + + unshare -Uf $UNSHARE_ARGS --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -w ${SOURCE_CODE_DIR}/$CONTEXT -- buildah build \ + $VOLUME_MOUNTS \ + "${BUILDAH_ARGS[@]}" \ + "${LABELS[@]}" \ + --tls-verify=$TLSVERIFY --no-cache \ + --ulimit nofile=4096:4096 \ + -f "$dockerfile_path" -t $IMAGE . + + container=$(buildah from --pull-never $IMAGE) + buildah mount $container | tee /shared/container_path + # delete symlinks - they may point outside the container rootfs, messing with SBOM scanners + find $(cat /shared/container_path) -xtype l -delete + echo $container > /shared/container_name + + # Save the SBOM produced by Cachi2 so it can be merged into the final SBOM later + if [ -f "/tmp/cachi2/output/bom.json" ]; then + cp /tmp/cachi2/output/bom.json ./sbom-cachi2.json + fi + + # Expose base image digests + touch $(results.BASE_IMAGES_DIGESTS.path) + for image in $BASE_IMAGES; do + if [ "${image}" != "scratch" ]; then + buildah images --format '{{ .Name }}:{{ .Tag }}@{{ .Digest }}' --filter reference="$image" >> $(results.BASE_IMAGES_DIGESTS.path) + fi + done + + # Needed to generate base images SBOM + echo "$BASE_IMAGES" > $(workspaces.source.path)/base_images_from_dockerfile + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /entitlement + name: etc-pki-entitlement + - mountPath: /activation-key + name: activation-key + - mountPath: /additional-secret + name: additional-secret + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + - image: registry.access.redhat.com/rh-syft-tech-preview/syft-rhel9:1.4.1@sha256:34d7065427085a31dc4949bd283c001b91794d427e1e4cdf1b21ea4faf9fee3f + name: sbom-syft-generate + script: | + echo "Running syft on the source directory" + syft dir:$(workspaces.source.path)/source --output cyclonedx-json=$(workspaces.source.path)/sbom-source.json + echo "Running syft on the image filesystem" + syft dir:$(cat /shared/container_path) --output cyclonedx-json=$(workspaces.source.path)/sbom-image.json + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + workingDir: $(workspaces.source.path)/source + - image: quay.io/redhat-appstudio/hacbs-jvm-build-request-processor:127ee0c223a2b56a9bd20a6f2eaeed3bd6015f77 + name: analyse-dependencies-java-sbom + script: | + if [ -f /var/lib/containers/java ]; then + /opt/jboss/container/java/run/run-java.sh analyse-dependencies path $(cat /shared/container_path) -s $(workspaces.source.path)/sbom-image.json --task-run-name $(context.taskRun.name) --publishers $(results.SBOM_JAVA_COMPONENTS_COUNT.path) + sed -i 's/^/ /' $(results.SBOM_JAVA_COMPONENTS_COUNT.path) # Workaround for SRVKP-2875 + else + touch $(results.JAVA_COMMUNITY_DEPENDENCIES.path) + fi + securityContext: + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + - image: registry.access.redhat.com/ubi9/python-39:9.5-1734610342@sha256:dde5068ba8fd81eef41a9128ddad2b99e2e02e5869ffe925c605b609a0ad7bbb + name: merge-syft-sboms + script: | + #!/bin/python3 + import json + + # load SBOMs + with open("./sbom-image.json") as f: + image_sbom = json.load(f) + + with open("./sbom-source.json") as f: + source_sbom = json.load(f) + + # fetch unique components from available SBOMs + def get_identifier(component): + return component["name"] + '@' + component.get("version", "") + + image_sbom_components = image_sbom.setdefault("components", []) + existing_components = [get_identifier(component) for component in image_sbom_components] + + source_sbom_components = source_sbom.get("components", []) + for component in source_sbom_components: + if get_identifier(component) not in existing_components: + image_sbom_components.append(component) + existing_components.append(get_identifier(component)) + + image_sbom_components.sort(key=lambda c: get_identifier(c)) + + # write the CycloneDX unified SBOM + with open("./sbom-cyclonedx.json", "w") as f: + json.dump(image_sbom, f, indent=4) + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - image: quay.io/redhat-appstudio/cachi2:0.16.0@sha256:55415cd8ded149f5d56d3fca46d93125b86b41e07ae5d3c03caa240b7b93b7d8 + name: merge-cachi2-sbom + script: | + if [ -f "sbom-cachi2.json" ]; then + echo "Merging contents of sbom-cachi2.json into sbom-cyclonedx.json" + merge_syft_sbom sbom-cachi2.json sbom-cyclonedx.json > sbom-temp.json + mv sbom-temp.json sbom-cyclonedx.json + else + echo "Skipping step since no Cachi2 SBOM was produced" + fi + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - image: registry.access.redhat.com/ubi9/python-39:9.5-1734610342@sha256:dde5068ba8fd81eef41a9128ddad2b99e2e02e5869ffe925c605b609a0ad7bbb + name: create-purl-sbom + script: | + #!/bin/python3 + import json + + with open("./sbom-cyclonedx.json") as f: + cyclonedx_sbom = json.load(f) + + purls = [{"purl": component["purl"]} for component in cyclonedx_sbom.get("components", []) if "purl" in component] + purl_content = {"image_contents": {"dependencies": purls}} + + with open("sbom-purl.json", "w") as output_file: + json.dump(purl_content, output_file, indent=4) + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - env: + - name: BASE_IMAGES_DIGESTS_PATH + value: $(results.BASE_IMAGES_DIGESTS.path) + image: quay.io/redhat-appstudio/base-images-sbom-script@sha256:667669e3def018f9dbb8eaf8868887a40bc07842221e9a98f6787edcff021840 + name: create-base-images-sbom + script: | + python3 /app/base_images_sbom_script.py --sbom=sbom-cyclonedx.json --base-images-from-dockerfile=base_images_from_dockerfile --base-images-digests=$BASE_IMAGES_DIGESTS_PATH + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - computeResources: {} + image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: inject-sbom-and-push + script: | + if [ -n "${PARAM_BUILDER_IMAGE}" ]; then + echo "WARNING: provided deprecated BUILDER_IMAGE parameter has no effect." + fi + + base_image_name=$(buildah inspect --format '{{ index .ImageAnnotations "org.opencontainers.image.base.name"}}' $IMAGE | cut -f1 -d'@') + base_image_digest=$(buildah inspect --format '{{ index .ImageAnnotations "org.opencontainers.image.base.digest"}}' $IMAGE) + container=$(buildah from --pull-never $IMAGE) + buildah copy $container sbom-cyclonedx.json sbom-purl.json /root/buildinfo/content_manifests/ + buildah config -a org.opencontainers.image.base.name=${base_image_name} -a org.opencontainers.image.base.digest=${base_image_digest} $container + + BUILDAH_ARGS=() + if [ "${SQUASH}" == "true" ]; then + BUILDAH_ARGS+=("--squash") + fi + + buildah commit "${BUILDAH_ARGS[@]}" $container $IMAGE + + status=-1 + max_run=5 + sleep_sec=10 + for run in $(seq 1 $max_run); do + status=0 + [ "$run" -gt 1 ] && sleep $sleep_sec + echo "Pushing sbom image to registry" + buildah push \ + --tls-verify=$TLSVERIFY \ + --digestfile $(workspaces.source.path)/image-digest $IMAGE \ + docker://$IMAGE && break || status=$? + done + if [ "$status" -ne 0 ]; then + echo "Failed to push sbom image to registry after ${max_run} tries" + exit 1 + fi + + cat "$(workspaces.source.path)"/image-digest | tee $(results.IMAGE_DIGEST.path) + echo -n "$IMAGE" | tee $(results.IMAGE_URL.path) + securityContext: + capabilities: + add: + - SETFCAP + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + workingDir: $(workspaces.source.path) + - args: + - attach + - sbom + - --sbom + - sbom-cyclonedx.json + - --type + - cyclonedx + - $(params.IMAGE) + image: quay.io/redhat-appstudio/cosign:v2.1.1@sha256:c883d6f8d39148f2cea71bff4622d196d89df3e510f36c140c097b932f0dd5d5 + name: upload-sbom + workingDir: $(workspaces.source.path) + volumes: + - emptyDir: {} + name: varlibcontainers + - emptyDir: {} + name: shared + - name: etc-pki-entitlement + secret: + optional: true + secretName: $(params.ENTITLEMENT_SECRET) + - name: activation-key + secret: + optional: true + secretName: $(params.ACTIVATION_KEY) + - name: additional-secret + secret: + optional: true + secretName: $(params.ADDITIONAL_SECRET) + - configMap: + items: + - key: $(params.caTrustConfigMapKey) + path: ca-bundle.crt + name: $(params.caTrustConfigMapName) + optional: true + name: trusted-ca + workspaces: + - description: Workspace containing the source code to build. + name: source diff --git a/auto-generated/task/buildah-8gb/0.2/tekton.dev_v1_task_buildah-8gb.yaml b/auto-generated/task/buildah-8gb/0.2/tekton.dev_v1_task_buildah-8gb.yaml new file mode 100644 index 0000000000..071e850027 --- /dev/null +++ b/auto-generated/task/buildah-8gb/0.2/tekton.dev_v1_task_buildah-8gb.yaml @@ -0,0 +1,722 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + annotations: + build.appstudio.redhat.com/expires-on: "2025-01-21T00:00:00Z" + build.appstudio.redhat.com/expiry-message: 'Instead of using this task, switch + to buildah task (you can find latest bundle reference here: https://quay.io/repository/konflux-ci/tekton-catalog/task-buildah) + and configure build step resources as described in the doc: https://konflux-ci.dev/docs/how-tos/configuring/overriding-compute-resources/' + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: image-build, konflux + labels: + app.kubernetes.io/version: 0.2.1 + build.appstudio.redhat.com/build_type: docker + name: buildah-8gb +spec: + description: |- + Buildah task builds source code into a container image and pushes the image into container registry using buildah tool. + In addition it generates a SBOM file, injects the SBOM file into final container image and pushes the SBOM file as separate image using cosign tool. + When [Java dependency rebuild](https://redhat-appstudio.github.io/docs.stonesoup.io/Documentation/main/cli/proc_enabled_java_dependencies.html) is enabled it triggers rebuilds of Java artifacts. + When prefetch-dependencies task was activated it is using its artifacts to run build in hermetic environment. + params: + - description: Reference of the image buildah will produce. + name: IMAGE + type: string + - default: ./Dockerfile + description: Path to the Dockerfile to build. + name: DOCKERFILE + type: string + - default: . + description: Path to the directory to use as context. + name: CONTEXT + type: string + - default: "true" + description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS + registry) + name: TLSVERIFY + type: string + - default: "false" + description: Determines if build will be executed without network access. + name: HERMETIC + type: string + - default: "" + description: In case it is not empty, the prefetched content should be made available + to the build. + name: PREFETCH_INPUT + type: string + - default: "" + description: Delete image tag after specified time. Empty means to keep the image + tag. Time values could be something like 1h, 2d, 3w for hours, days, and weeks, + respectively. + name: IMAGE_EXPIRES_AFTER + type: string + - default: "" + description: The image is built from this commit. + name: COMMIT_SHA + type: string + - default: repos.d + description: Path in the git repository in which yum repository files are stored + name: YUM_REPOS_D_SRC + - default: fetched.repos.d + description: Path in source workspace where dynamically-fetched repos are present + name: YUM_REPOS_D_FETCHED + - default: /etc/yum.repos.d + description: Target path on the container in which yum repository files should + be made available + name: YUM_REPOS_D_TARGET + - default: "" + description: Target stage in Dockerfile to build. If not specified, the Dockerfile + is processed entirely to (and including) its last stage. + name: TARGET_STAGE + type: string + - default: etc-pki-entitlement + description: Name of secret which contains the entitlement certificates + name: ENTITLEMENT_SECRET + type: string + - default: activation-key + description: Name of secret which contains subscription activation key + name: ACTIVATION_KEY + type: string + - default: does-not-exist + description: Name of a secret which will be made available to the build with 'buildah + build --secret' at /run/secrets/$ADDITIONAL_SECRET + name: ADDITIONAL_SECRET + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) + name: BUILD_ARGS + type: array + - default: "" + description: Path to a file with build arguments, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: BUILD_ARGS_FILE + type: string + - default: trusted-ca + description: The name of the ConfigMap to read CA bundle data from. + name: caTrustConfigMapName + type: string + - default: ca-bundle.crt + description: The name of the key in the ConfigMap that contains the CA bundle + data. + name: caTrustConfigMapKey + type: string + - default: "" + description: Comma separated list of extra capabilities to add when running 'buildah + build' + name: ADD_CAPABILITIES + type: string + - default: "false" + description: Squash all new and previous layers added as a part of this build, + as per --squash + name: SQUASH + type: string + - default: vfs + description: Storage driver to configure for buildah + name: STORAGE_DRIVER + type: string + - default: "true" + description: Whether to skip stages in Containerfile that seem unused by subsequent + stages + name: SKIP_UNUSED_STAGES + type: string + - default: [] + description: Additional key=value labels that should be applied to the image + name: LABELS + type: array + - default: "false" + description: Whether to enable privileged mode + name: PRIVILEGED_NESTED + type: string + results: + - description: Digest of the image just built + name: IMAGE_DIGEST + - description: Image repository and tag where the built image was pushed + name: IMAGE_URL + - description: Image reference of the built image + name: IMAGE_REF + - description: Reference of SBOM blob digest to enable digest-based verification + from provenance + name: SBOM_BLOB_URL + type: string + - description: The counting of Java components by publisher in JSON format + name: SBOM_JAVA_COMPONENTS_COUNT + type: string + - description: The Java dependencies that came from community sources such as Maven + central. + name: JAVA_COMMUNITY_DEPENDENCIES + stepTemplate: + computeResources: + limits: + cpu: "4" + memory: 4Gi + requests: + cpu: "1" + memory: 1Gi + env: + - name: BUILDAH_FORMAT + value: oci + - name: STORAGE_DRIVER + value: $(params.STORAGE_DRIVER) + - name: HERMETIC + value: $(params.HERMETIC) + - name: SOURCE_CODE_DIR + value: source + - name: CONTEXT + value: $(params.CONTEXT) + - name: IMAGE + value: $(params.IMAGE) + - name: TLSVERIFY + value: $(params.TLSVERIFY) + - name: IMAGE_EXPIRES_AFTER + value: $(params.IMAGE_EXPIRES_AFTER) + - name: YUM_REPOS_D_SRC + value: $(params.YUM_REPOS_D_SRC) + - name: YUM_REPOS_D_FETCHED + value: $(params.YUM_REPOS_D_FETCHED) + - name: YUM_REPOS_D_TARGET + value: $(params.YUM_REPOS_D_TARGET) + - name: TARGET_STAGE + value: $(params.TARGET_STAGE) + - name: ENTITLEMENT_SECRET + value: $(params.ENTITLEMENT_SECRET) + - name: ACTIVATION_KEY + value: $(params.ACTIVATION_KEY) + - name: ADDITIONAL_SECRET + value: $(params.ADDITIONAL_SECRET) + - name: BUILD_ARGS_FILE + value: $(params.BUILD_ARGS_FILE) + - name: ADD_CAPABILITIES + value: $(params.ADD_CAPABILITIES) + - name: SQUASH + value: $(params.SQUASH) + - name: SKIP_UNUSED_STAGES + value: $(params.SKIP_UNUSED_STAGES) + - name: PRIVILEGED_NESTED + value: $(params.PRIVILEGED_NESTED) + volumeMounts: + - mountPath: /shared + name: shared + steps: + - args: + - --build-args + - $(params.BUILD_ARGS[*]) + - --labels + - $(params.LABELS[*]) + computeResources: + limits: + cpu: "4" + memory: 8Gi + requests: + cpu: "1" + memory: 6Gi + env: + - name: COMMIT_SHA + value: $(params.COMMIT_SHA) + - name: DOCKERFILE + value: $(params.DOCKERFILE) + image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: build + script: | + #!/bin/bash + set -euo pipefail + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + if [ -e "$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" + elif [ -e "$SOURCE_CODE_DIR/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$DOCKERFILE" + elif [ -e "$DOCKERFILE" ]; then + # Instrumented builds (SAST) use this custom dockerffile step as their base + dockerfile_path="$DOCKERFILE" + elif echo "$DOCKERFILE" | grep -q "^https\?://"; then + echo "Fetch Dockerfile from $DOCKERFILE" + dockerfile_path=$(mktemp --suffix=-Dockerfile) + http_code=$(curl -s -S -L -w "%{http_code}" --output "$dockerfile_path" "$DOCKERFILE") + if [ $http_code != 200 ]; then + echo "No Dockerfile is fetched. Server responds $http_code" + exit 1 + fi + http_code=$(curl -s -S -L -w "%{http_code}" --output "$dockerfile_path.dockerignore.tmp" "$DOCKERFILE.dockerignore") + if [ $http_code = 200 ]; then + echo "Fetched .dockerignore from $DOCKERFILE.dockerignore" + mv "$dockerfile_path.dockerignore.tmp" $SOURCE_CODE_DIR/$CONTEXT/.dockerignore + fi + else + echo "Cannot find Dockerfile $DOCKERFILE" + exit 1 + fi + + dockerfile_copy=$(mktemp --tmpdir "$(basename "$dockerfile_path").XXXXXX") + cp "$dockerfile_path" "$dockerfile_copy" + + if [ -n "${JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR-}" ] && grep -q '^\s*RUN \(./\)\?mvn' "$dockerfile_copy"; then + sed -i -e "s|^\s*RUN \(\(./\)\?mvn\)\(.*\)|RUN echo \"mirror.defaulthttp://$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR/v1/cache/default/0/*\" > /tmp/settings.yaml; \1 -s /tmp/settings.yaml \3|g" "$dockerfile_copy" + touch /var/lib/containers/java + fi + + # Fixing group permission on /var/lib/containers + chown root:root /var/lib/containers + + sed -i 's/^\s*short-name-mode\s*=\s*.*/short-name-mode = "disabled"/' /etc/containers/registries.conf + + # Setting new namespace to run buildah - 2^32-2 + echo 'root:1:4294967294' | tee -a /etc/subuid >> /etc/subgid + + build_args=() + if [ -n "${BUILD_ARGS_FILE}" ]; then + # Parse BUILD_ARGS_FILE ourselves because dockerfile-json doesn't support it + echo "Parsing ARGs from $BUILD_ARGS_FILE" + mapfile -t build_args < <( + # https://www.mankier.com/1/buildah-build#--build-arg-file + # delete lines that start with # + # delete blank lines + sed -e '/^#/d' -e '/^\s*$/d' "${SOURCE_CODE_DIR}/${BUILD_ARGS_FILE}" + ) + fi + + LABELS=() + # Split `args` into two sets of arguments. + while [[ $# -gt 0 ]]; do + case $1 in + --build-args) + shift + # Note: this may result in multiple --build-arg=KEY=value flags with the same KEY being + # passed to buildah. In that case, the *last* occurrence takes precedence. This is why + # we append BUILD_ARGS after the content of the BUILD_ARGS_FILE + while [[ $# -gt 0 && $1 != --* ]]; do build_args+=("$1"); shift; done + ;; + --labels) + shift + while [[ $# -gt 0 && $1 != --* ]]; do LABELS+=("--label" "$1"); shift; done + ;; + *) + echo "unexpected argument: $1" >&2 + exit 2 + ;; + esac + done + + BUILD_ARG_FLAGS=() + for build_arg in "${build_args[@]}"; do + BUILD_ARG_FLAGS+=("--build-arg=$build_arg") + done + + dockerfile-json "${BUILD_ARG_FLAGS[@]}" "$dockerfile_copy" > /shared/parsed_dockerfile.json + BASE_IMAGES=$( + jq -r '.Stages[] | select(.From | .Stage or .Scratch | not) | .BaseName | select(test("^oci-archive:") | not)' /shared/parsed_dockerfile.json + ) + + BUILDAH_ARGS=() + UNSHARE_ARGS=() + + if [ "${HERMETIC}" == "true" ]; then + BUILDAH_ARGS+=("--pull=never") + UNSHARE_ARGS+=("--net") + + for image in $BASE_IMAGES; do + unshare -Ufp --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -- buildah pull $image + done + echo "Build will be executed with network isolation" + fi + + if [ -n "${TARGET_STAGE}" ]; then + BUILDAH_ARGS+=("--target=${TARGET_STAGE}") + fi + + BUILDAH_ARGS+=("${BUILD_ARG_FLAGS[@]}") + + if [ "${PRIVILEGED_NESTED}" == "true" ]; then + BUILDAH_ARGS+=("--security-opt=label=disable") + BUILDAH_ARGS+=("--cap-add=all") + BUILDAH_ARGS+=("--device=/dev/fuse") + fi + + if [ -n "${ADD_CAPABILITIES}" ]; then + BUILDAH_ARGS+=("--cap-add=${ADD_CAPABILITIES}") + fi + + if [ "${SQUASH}" == "true" ]; then + BUILDAH_ARGS+=("--squash") + fi + + if [ "${SKIP_UNUSED_STAGES}" != "true" ] ; then + BUILDAH_ARGS+=("--skip-unused-stages=false") + fi + + VOLUME_MOUNTS=() + + if [ -f "$(workspaces.source.path)/cachi2/cachi2.env" ]; then + cp -r "$(workspaces.source.path)/cachi2" /tmp/ + chmod -R go+rwX /tmp/cachi2 + VOLUME_MOUNTS+=(--volume /tmp/cachi2:/cachi2) + # Read in the whole file (https://unix.stackexchange.com/questions/533277), then + # for each RUN ... line insert the cachi2.env command *after* any options like --mount + sed -E -i \ + -e 'H;1h;$!d;x' \ + -e 's@^\s*(run((\s|\\\n)+-\S+)*(\s|\\\n)+)@\1. /cachi2/cachi2.env \&\& \\\n @igM' \ + "$dockerfile_copy" + echo "Prefetched content will be made available" + + prefetched_repo_for_my_arch="/tmp/cachi2/output/deps/rpm/$(uname -m)/repos.d/cachi2.repo" + if [ -f "$prefetched_repo_for_my_arch" ]; then + echo "Adding $prefetched_repo_for_my_arch to $YUM_REPOS_D_FETCHED" + mkdir -p "$YUM_REPOS_D_FETCHED" + cp --no-clobber "$prefetched_repo_for_my_arch" "$YUM_REPOS_D_FETCHED" + fi + fi + + # if yum repofiles stored in git, copy them to mount point outside the source dir + if [ -d "${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}" ]; then + mkdir -p ${YUM_REPOS_D_FETCHED} + cp -r ${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}/* ${YUM_REPOS_D_FETCHED} + fi + + # if anything in the repofiles mount point (either fetched or from git), mount it + if [ -d "${YUM_REPOS_D_FETCHED}" ]; then + chmod -R go+rwX ${YUM_REPOS_D_FETCHED} + mount_point=$(realpath ${YUM_REPOS_D_FETCHED}) + VOLUME_MOUNTS+=(--volume "${mount_point}:${YUM_REPOS_D_TARGET}") + fi + + DEFAULT_LABELS=( + "--label" "build-date=$(date -u +'%Y-%m-%dT%H:%M:%S')" + "--label" "architecture=$(uname -m)" + "--label" "vcs-type=git" + ) + [ -n "$COMMIT_SHA" ] && DEFAULT_LABELS+=("--label" "vcs-ref=$COMMIT_SHA") + [ -n "$IMAGE_EXPIRES_AFTER" ] && DEFAULT_LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + + # Concatenate defaults and explicit labels. If a label appears twice, the last one wins. + LABELS=("${DEFAULT_LABELS[@]}" "${LABELS[@]}") + + ACTIVATION_KEY_PATH="/activation-key" + ENTITLEMENT_PATH="/entitlement" + + # 0. if hermetic=true, skip all subscription related stuff + # 1. do not enable activation key and entitlement at same time. If both vars are provided, prefer activation key. + # 2. Activation-keys will be used when the key 'org' exists in the activation key secret. + # 3. try to pre-register and mount files to the correct location so that users do no need to modify Dockerfiles. + # 3. If the Dockerfile contains the string "subcription-manager register", add the activation-keys volume + # to buildah but don't pre-register for backwards compatibility. Mount an empty directory on + # shared emptydir volume to "/etc/pki/entitlement" to prevent certificates from being included + + if [ "${HERMETIC}" != "true" ] && [ -e /activation-key/org ]; then + cp -r --preserve=mode "$ACTIVATION_KEY_PATH" /tmp/activation-key + mkdir -p /shared/rhsm/etc/pki/entitlement + mkdir -p /shared/rhsm/etc/pki/consumer + + VOLUME_MOUNTS+=(-v /tmp/activation-key:/activation-key \ + -v /shared/rhsm/etc/pki/entitlement:/etc/pki/entitlement:Z \ + -v /shared/rhsm/etc/pki/consumer:/etc/pki/consumer:Z) + echo "Adding activation key to the build" + + if ! grep -E "^[^#]*subscription-manager.[^#]*register" "$dockerfile_path"; then + # user is not running registration in the Containerfile: pre-register. + echo "Pre-registering with subscription manager." + subscription-manager register --org "$(cat /tmp/activation-key/org)" --activationkey "$(cat /tmp/activation-key/activationkey)" + trap 'subscription-manager unregister || true' EXIT + + # copy generated certificates to /shared volume + cp /etc/pki/entitlement/*.pem /shared/rhsm/etc/pki/entitlement + cp /etc/pki/consumer/*.pem /shared/rhsm/etc/pki/consumer + + # and then mount get /etc/rhsm/ca/redhat-uep.pem into /run/secrets/rhsm/ca + VOLUME_MOUNTS+=(--volume /etc/rhsm/ca/redhat-uep.pem:/etc/rhsm/ca/redhat-uep.pem:Z) + fi + + elif [ "${HERMETIC}" != "true" ] && find /entitlement -name "*.pem" >> null; then + cp -r --preserve=mode "$ENTITLEMENT_PATH" /tmp/entitlement + VOLUME_MOUNTS+=(--volume /tmp/entitlement:/etc/pki/entitlement) + echo "Adding the entitlement to the build" + fi + + if [ -n "${ADDITIONAL_VOLUME_MOUNTS-}" ]; then + # ADDITIONAL_VOLUME_MOUNTS allows to specify more volumes for the build. + # Instrumented builds (SAST) use this step as their base and add some other tools. + while read -r volume_mount; do + VOLUME_MOUNTS+=("--volume=$volume_mount") + done <<< "$ADDITIONAL_VOLUME_MOUNTS" + fi + + ADDITIONAL_SECRET_PATH="/additional-secret" + ADDITIONAL_SECRET_TMP="/tmp/additional-secret" + if [ -d "$ADDITIONAL_SECRET_PATH" ]; then + cp -r --preserve=mode -L "$ADDITIONAL_SECRET_PATH" $ADDITIONAL_SECRET_TMP + while read -r filename; do + echo "Adding the secret ${ADDITIONAL_SECRET}/${filename} to the build, available at /run/secrets/${ADDITIONAL_SECRET}/${filename}" + BUILDAH_ARGS+=("--secret=id=${ADDITIONAL_SECRET}/${filename},src=$ADDITIONAL_SECRET_TMP/${filename}") + done < <(find $ADDITIONAL_SECRET_TMP -maxdepth 1 -type f -exec basename {} \;) + fi + + # Prevent ShellCheck from giving a warning because 'image' is defined and 'IMAGE' is not. + declare IMAGE + + buildah_cmd_array=( + buildah build + "${VOLUME_MOUNTS[@]}" + "${BUILDAH_ARGS[@]}" + "${LABELS[@]}" + --tls-verify="$TLSVERIFY" --no-cache + --ulimit nofile=4096:4096 + -f "$dockerfile_copy" -t "$IMAGE" . + ) + buildah_cmd=$(printf "%q " "${buildah_cmd_array[@]}") + + if [ "${HERMETIC}" == "true" ]; then + # enabling loopback adapter enables Bazel builds to work in hermetic mode. + command="ip link set lo up && $buildah_cmd" + else + command="$buildah_cmd" + fi + + # disable host subcription manager integration + find /usr/share/rhel/secrets -type l -exec unlink {} \; + + unshare -Uf "${UNSHARE_ARGS[@]}" --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -w "${SOURCE_CODE_DIR}/$CONTEXT" -- sh -c "$command" + + container=$(buildah from --pull-never "$IMAGE") + + # Save the SBOM produced by Cachi2 so it can be merged into the final SBOM later + if [ -f "/tmp/cachi2/output/bom.json" ]; then + echo "Making copy of sbom-cachi2.json" + cp /tmp/cachi2/output/bom.json ./sbom-cachi2.json + fi + + buildah mount $container | tee /shared/container_path + # delete symlinks - they may point outside the container rootfs, messing with SBOM scanners + find $(cat /shared/container_path) -xtype l -delete + echo $container > /shared/container_name + + touch /shared/base_images_digests + for image in $BASE_IMAGES; do + base_image_digest=$(buildah images --format '{{ .Name }}:{{ .Tag }}@{{ .Digest }}' --filter reference="$image") + # In some cases, there might be BASE_IMAGES, but not any associated digest. This happens + # if buildah did not use that particular image during build because it was skipped + if [ -n "$base_image_digest" ]; then + echo "$image $base_image_digest" >> /shared/base_images_digests + fi + done + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /entitlement + name: etc-pki-entitlement + - mountPath: /activation-key + name: activation-key + - mountPath: /additional-secret + name: additional-secret + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + - image: quay.io/konflux-ci/icm-injection-scripts:latest@sha256:462980e94ba689b5f56c3d5dfb3358cd8c685300daf65a71532f11898935e7f1 + name: icm + script: | + #!/bin/bash + set -euo pipefail + /scripts/inject-icm.sh "$IMAGE" + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + workingDir: $(workspaces.source.path) + - image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: push + script: | + #!/bin/bash + set -e + + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + retries=5 + # Push to a unique tag based on the TaskRun name to avoid race conditions + echo "Pushing to ${IMAGE%:*}:${TASKRUN_NAME}" + if ! buildah push \ + --retry "$retries" \ + --tls-verify="$TLSVERIFY" \ + "$IMAGE" \ + "docker://${IMAGE%:*}:$(context.taskRun.name)"; + then + echo "Failed to push sbom image to ${IMAGE%:*}:$(context.taskRun.name) after ${retries} tries" + exit 1 + fi + + # Push to a tag based on the git revision + echo "Pushing to ${IMAGE}" + if ! buildah push \ + --retry "$retries" \ + --tls-verify="$TLSVERIFY" \ + --digestfile "$(workspaces.source.path)/image-digest" "$IMAGE" \ + "docker://$IMAGE"; + then + echo "Failed to push sbom image to $IMAGE after ${retries} tries" + exit 1 + fi + + cat "$(workspaces.source.path)"/image-digest | tee $(results.IMAGE_DIGEST.path) + echo -n "$IMAGE" | tee $(results.IMAGE_URL.path) + { + echo -n "${IMAGE}@" + cat "$(workspaces.source.path)/image-digest" + } > "$(results.IMAGE_REF.path)" + securityContext: + capabilities: + add: + - SETFCAP + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + - image: registry.access.redhat.com/rh-syft-tech-preview/syft-rhel9:1.4.1@sha256:34d7065427085a31dc4949bd283c001b91794d427e1e4cdf1b21ea4faf9fee3f + name: sbom-syft-generate + script: | + echo "Running syft on the source directory" + syft dir:"$(workspaces.source.path)/$SOURCE_CODE_DIR/$CONTEXT" --output cyclonedx-json="$(workspaces.source.path)/sbom-source.json" + echo "Running syft on the image filesystem" + syft dir:"$(cat /shared/container_path)" --output cyclonedx-json="$(workspaces.source.path)/sbom-image.json" + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + workingDir: $(workspaces.source.path)/source + - computeResources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + image: quay.io/redhat-appstudio/hacbs-jvm-build-request-processor:127ee0c223a2b56a9bd20a6f2eaeed3bd6015f77 + name: analyse-dependencies-java-sbom + script: | + if [ -f /var/lib/containers/java ]; then + /opt/jboss/container/java/run/run-java.sh analyse-dependencies path $(cat /shared/container_path) -s $(workspaces.source.path)/sbom-image.json --task-run-name $(context.taskRun.name) --publishers $(results.SBOM_JAVA_COMPONENTS_COUNT.path) + sed -i 's/^/ /' $(results.SBOM_JAVA_COMPONENTS_COUNT.path) # Workaround for SRVKP-2875 + else + touch $(results.JAVA_COMMUNITY_DEPENDENCIES.path) + fi + securityContext: + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + - computeResources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + image: quay.io/redhat-appstudio/sbom-utility-scripts-image@sha256:9f1fd11d9c3c517ecc112d192ad361d16ecf6ce00b83b109c93cf3d1c644a357 + name: prepare-sboms + script: | + echo "Merging contents of sbom-source.json and sbom-image.json into sbom-cyclonedx.json" + python3 /scripts/merge_syft_sboms.py + + if [ -f "sbom-cachi2.json" ]; then + echo "Merging contents of sbom-cachi2.json into sbom-cyclonedx.json" + python3 /scripts/merge_cachi2_sboms.py sbom-cachi2.json sbom-cyclonedx.json > sbom-temp.json + mv sbom-temp.json sbom-cyclonedx.json + fi + + echo "Adding base images data to sbom-cyclonedx.json" + python3 /scripts/base_images_sbom_script.py \ + --sbom=sbom-cyclonedx.json \ + --parsed-dockerfile=/shared/parsed_dockerfile.json \ + --base-images-digests=/shared/base_images_digests + + echo "Adding image reference to sbom" + IMAGE_URL="$(cat "$(results.IMAGE_URL.path)")" + IMAGE_DIGEST="$(cat "$(results.IMAGE_DIGEST.path)")" + + python3 /scripts/add_image_reference.py \ + --image-url "$IMAGE_URL" \ + --image-digest "$IMAGE_DIGEST" \ + --input-file sbom-cyclonedx.json \ + --output-file /tmp/sbom-cyclonedx.tmp.json + + mv /tmp/sbom-cyclonedx.tmp.json sbom-cyclonedx.json + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - computeResources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + image: quay.io/konflux-ci/appstudio-utils:48c311af02858e2422d6229600e9959e496ddef1@sha256:91ddd999271f65d8ec8487b10f3dd378f81aa894e11b9af4d10639fd52bba7e8 + name: upload-sbom + script: | + #!/bin/bash + + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + cosign attach sbom --sbom sbom-cyclonedx.json --type cyclonedx "$(cat "$(results.IMAGE_REF.path)")" + + # Remove tag from IMAGE while allowing registry to contain a port number. + sbom_repo="${IMAGE%:*}" + sbom_digest="$(sha256sum sbom-cyclonedx.json | cut -d' ' -f1)" + # The SBOM_BLOB_URL is created by `cosign attach sbom`. + echo -n "${sbom_repo}@sha256:${sbom_digest}" | tee "$(results.SBOM_BLOB_URL.path)" + volumeMounts: + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + volumes: + - emptyDir: {} + name: varlibcontainers + - emptyDir: {} + name: shared + - name: etc-pki-entitlement + secret: + optional: true + secretName: $(params.ENTITLEMENT_SECRET) + - name: activation-key + secret: + optional: true + secretName: $(params.ACTIVATION_KEY) + - name: additional-secret + secret: + optional: true + secretName: $(params.ADDITIONAL_SECRET) + - configMap: + items: + - key: $(params.caTrustConfigMapKey) + path: ca-bundle.crt + name: $(params.caTrustConfigMapName) + optional: true + name: trusted-ca + workspaces: + - description: Workspace containing the source code to build. + name: source diff --git a/auto-generated/task/buildah-min/0.1/tekton.dev_v1_task_buildah-min.yaml b/auto-generated/task/buildah-min/0.1/tekton.dev_v1_task_buildah-min.yaml new file mode 100644 index 0000000000..d10af8b1c6 --- /dev/null +++ b/auto-generated/task/buildah-min/0.1/tekton.dev_v1_task_buildah-min.yaml @@ -0,0 +1,582 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + annotations: + build.appstudio.redhat.com/expires-on: "2024-11-13T00:00:00Z" + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: image-build, konflux + labels: + app.kubernetes.io/version: "0.1" + build.appstudio.redhat.com/build_type: docker + name: buildah-min +spec: + description: |- + Buildah task builds source code into a container image and pushes the image into container registry using buildah tool. + In addition it generates a SBOM file, injects the SBOM file into final container image and pushes the SBOM file as separate image using cosign tool. + When [Java dependency rebuild](https://redhat-appstudio.github.io/docs.stonesoup.io/Documentation/main/cli/proc_enabled_java_dependencies.html) is enabled it triggers rebuilds of Java artifacts. + When prefetch-dependencies task was activated it is using its artifacts to run build in hermetic environment. + params: + - description: Reference of the image buildah will produce. + name: IMAGE + type: string + - default: "" + description: Deprecated. Has no effect. Will be removed in the future. + name: BUILDER_IMAGE + type: string + - default: ./Dockerfile + description: Path to the Dockerfile to build. + name: DOCKERFILE + type: string + - default: . + description: Path to the directory to use as context. + name: CONTEXT + type: string + - default: "true" + description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS + registry) + name: TLSVERIFY + type: string + - default: "" + description: unused, should be removed in next task version + name: DOCKER_AUTH + type: string + - default: "false" + description: Determines if build will be executed without network access. + name: HERMETIC + type: string + - default: "" + description: In case it is not empty, the prefetched content should be made available + to the build. + name: PREFETCH_INPUT + type: string + - default: "" + description: Delete image tag after specified time. Empty means to keep the image + tag. Time values could be something like 1h, 2d, 3w for hours, days, and weeks, + respectively. + name: IMAGE_EXPIRES_AFTER + type: string + - default: "" + description: The image is built from this commit. + name: COMMIT_SHA + type: string + - default: repos.d + description: Path in the git repository in which yum repository files are stored + name: YUM_REPOS_D_SRC + - default: fetched.repos.d + description: Path in source workspace where dynamically-fetched repos are present + name: YUM_REPOS_D_FETCHED + - default: /etc/yum.repos.d + description: Target path on the container in which yum repository files should + be made available + name: YUM_REPOS_D_TARGET + - default: "" + description: Target stage in Dockerfile to build. If not specified, the Dockerfile + is processed entirely to (and including) its last stage. + name: TARGET_STAGE + type: string + - default: etc-pki-entitlement + description: Name of secret which contains the entitlement certificates + name: ENTITLEMENT_SECRET + type: string + - default: activation-key + description: Name of secret which contains subscription activation key + name: ACTIVATION_KEY + type: string + - default: does-not-exist + description: Name of a secret which will be made available to the build with 'buildah + build --secret' at /run/secrets/$ADDITIONAL_SECRET + name: ADDITIONAL_SECRET + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) + name: BUILD_ARGS + type: array + - default: "" + description: Path to a file with build arguments, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: BUILD_ARGS_FILE + type: string + - default: trusted-ca + description: The name of the ConfigMap to read CA bundle data from. + name: caTrustConfigMapName + type: string + - default: ca-bundle.crt + description: The name of the key in the ConfigMap that contains the CA bundle + data. + name: caTrustConfigMapKey + type: string + - default: "" + description: Comma separated list of extra capabilities to add when running 'buildah + build' + name: ADD_CAPABILITIES + type: string + - default: "false" + description: Squash all new and previous layers added as a part of this build, + as per --squash + name: SQUASH + type: string + - default: vfs + description: Storage driver to configure for buildah + name: STORAGE_DRIVER + type: string + - default: "true" + description: Whether to skip stages in Containerfile that seem unused by subsequent + stages + name: SKIP_UNUSED_STAGES + type: string + results: + - description: Digest of the image just built + name: IMAGE_DIGEST + - description: Image repository and tag where the built image was pushed + name: IMAGE_URL + - description: Digests of the base images used for build + name: BASE_IMAGES_DIGESTS + - description: The counting of Java components by publisher in JSON format + name: SBOM_JAVA_COMPONENTS_COUNT + type: string + - description: The Java dependencies that came from community sources such as Maven + central. + name: JAVA_COMMUNITY_DEPENDENCIES + stepTemplate: + env: + - name: BUILDAH_FORMAT + value: oci + - name: STORAGE_DRIVER + value: $(params.STORAGE_DRIVER) + - name: HERMETIC + value: $(params.HERMETIC) + - name: CONTEXT + value: $(params.CONTEXT) + - name: DOCKERFILE + value: $(params.DOCKERFILE) + - name: IMAGE + value: $(params.IMAGE) + - name: TLSVERIFY + value: $(params.TLSVERIFY) + - name: IMAGE_EXPIRES_AFTER + value: $(params.IMAGE_EXPIRES_AFTER) + - name: YUM_REPOS_D_SRC + value: $(params.YUM_REPOS_D_SRC) + - name: YUM_REPOS_D_FETCHED + value: $(params.YUM_REPOS_D_FETCHED) + - name: YUM_REPOS_D_TARGET + value: $(params.YUM_REPOS_D_TARGET) + - name: TARGET_STAGE + value: $(params.TARGET_STAGE) + - name: PARAM_BUILDER_IMAGE + value: $(params.BUILDER_IMAGE) + - name: ENTITLEMENT_SECRET + value: $(params.ENTITLEMENT_SECRET) + - name: ADDITIONAL_SECRET + value: $(params.ADDITIONAL_SECRET) + - name: BUILD_ARGS_FILE + value: $(params.BUILD_ARGS_FILE) + - name: ADD_CAPABILITIES + value: $(params.ADD_CAPABILITIES) + - name: SQUASH + value: $(params.SQUASH) + - name: SKIP_UNUSED_STAGES + value: $(params.SKIP_UNUSED_STAGES) + volumeMounts: + - mountPath: /shared + name: shared + steps: + - args: + - $(params.BUILD_ARGS[*]) + computeResources: + limits: + memory: 4Gi + requests: + cpu: 100m + memory: 1Gi + env: + - name: COMMIT_SHA + value: $(params.COMMIT_SHA) + image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: build + script: | + if [ -n "${PARAM_BUILDER_IMAGE}" ]; then + echo "WARNING: provided deprecated BUILDER_IMAGE parameter has no effect." + fi + + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + SOURCE_CODE_DIR=source + if [ -e "$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" + elif [ -e "$SOURCE_CODE_DIR/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$DOCKERFILE" + elif echo "$DOCKERFILE" | grep -q "^https\?://"; then + echo "Fetch Dockerfile from $DOCKERFILE" + dockerfile_path=$(mktemp --suffix=-Dockerfile) + http_code=$(curl -s -L -w "%{http_code}" --output "$dockerfile_path" "$DOCKERFILE") + if [ $http_code != 200 ]; then + echo "No Dockerfile is fetched. Server responds $http_code" + exit 1 + fi + http_code=$(curl -s -L -w "%{http_code}" --output "$dockerfile_path.dockerignore.tmp" "$DOCKERFILE.dockerignore") + if [ $http_code = 200 ]; then + echo "Fetched .dockerignore from $DOCKERFILE.dockerignore" + mv "$dockerfile_path.dockerignore.tmp" $SOURCE_CODE_DIR/$CONTEXT/.dockerignore + fi + else + echo "Cannot find Dockerfile $DOCKERFILE" + exit 1 + fi + if [ -n "$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR" ] && grep -q '^\s*RUN \(./\)\?mvn' "$dockerfile_path"; then + sed -i -e "s|^\s*RUN \(\(./\)\?mvn\)\(.*\)|RUN echo \"mirror.defaulthttp://$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR/v1/cache/default/0/*\" > /tmp/settings.yaml; \1 -s /tmp/settings.yaml \3|g" "$dockerfile_path" + touch /var/lib/containers/java + fi + + # Fixing group permission on /var/lib/containers + chown root:root /var/lib/containers + + sed -i 's/^\s*short-name-mode\s*=\s*.*/short-name-mode = "disabled"/' /etc/containers/registries.conf + + # Setting new namespace to run buildah - 2^32-2 + echo 'root:1:4294967294' | tee -a /etc/subuid >> /etc/subgid + + BUILDAH_ARGS=() + + BASE_IMAGES=$(grep -i '^\s*FROM' "$dockerfile_path" | sed 's/--platform=\S*//' | awk '{print $2}' | (grep -v ^oci-archive: || true)) + if [ "${HERMETIC}" == "true" ]; then + BUILDAH_ARGS+=("--pull=never") + UNSHARE_ARGS="--net" + for image in $BASE_IMAGES; do + if [ "${image}" != "scratch" ]; then + unshare -Ufp --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -- buildah pull $image + fi + done + echo "Build will be executed with network isolation" + fi + + if [ -n "${TARGET_STAGE}" ]; then + BUILDAH_ARGS+=("--target=${TARGET_STAGE}") + fi + + if [ -n "${BUILD_ARGS_FILE}" ]; then + BUILDAH_ARGS+=("--build-arg-file=$(pwd)/$SOURCE_CODE_DIR/${BUILD_ARGS_FILE}") + fi + + for build_arg in "$@"; do + BUILDAH_ARGS+=("--build-arg=$build_arg") + done + + if [ -n "${ADD_CAPABILITIES}" ]; then + BUILDAH_ARGS+=("--cap-add=${ADD_CAPABILITIES}") + fi + + if [ "${SQUASH}" == "true" ]; then + BUILDAH_ARGS+=("--squash") + fi + + if [ "${SKIP_UNUSED_STAGES}" != "true" ] ; then + BUILDAH_ARGS+=("--skip-unused-stages=false") + fi + + if [ -f "$(workspaces.source.path)/cachi2/cachi2.env" ]; then + cp -r "$(workspaces.source.path)/cachi2" /tmp/ + chmod -R go+rwX /tmp/cachi2 + VOLUME_MOUNTS="--volume /tmp/cachi2:/cachi2" + # Read in the whole file (https://unix.stackexchange.com/questions/533277), then + # for each RUN ... line insert the cachi2.env command *after* any options like --mount + sed -E -i \ + -e 'H;1h;$!d;x' \ + -e 's@^\s*(run((\s|\\\n)+-\S+)*(\s|\\\n)+)@\1. /cachi2/cachi2.env \&\& \\\n @igM' \ + "$dockerfile_path" + echo "Prefetched content will be made available" + + prefetched_repo_for_my_arch="/tmp/cachi2/output/deps/rpm/$(uname -m)/repos.d/cachi2.repo" + if [ -f "$prefetched_repo_for_my_arch" ]; then + echo "Adding $prefetched_repo_for_my_arch to $YUM_REPOS_D_FETCHED" + mkdir -p "$YUM_REPOS_D_FETCHED" + cp --no-clobber "$prefetched_repo_for_my_arch" "$YUM_REPOS_D_FETCHED" + fi + fi + + # if yum repofiles stored in git, copy them to mount point outside the source dir + if [ -d "${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}" ]; then + mkdir -p ${YUM_REPOS_D_FETCHED} + cp -r ${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}/* ${YUM_REPOS_D_FETCHED} + fi + + # if anything in the repofiles mount point (either fetched or from git), mount it + if [ -d "${YUM_REPOS_D_FETCHED}" ]; then + chmod -R go+rwX ${YUM_REPOS_D_FETCHED} + mount_point=$(realpath ${YUM_REPOS_D_FETCHED}) + VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume ${mount_point}:${YUM_REPOS_D_TARGET}" + fi + + LABELS=( + "--label" "build-date=$(date -u +'%Y-%m-%dT%H:%M:%S')" + "--label" "architecture=$(uname -m)" + "--label" "vcs-type=git" + ) + [ -n "$COMMIT_SHA" ] && LABELS+=("--label" "vcs-ref=$COMMIT_SHA") + [ -n "$IMAGE_EXPIRES_AFTER" ] && LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + + ACTIVATION_KEY_PATH="/activation-key" + ENTITLEMENT_PATH="/entitlement" + + if [ -e /activation-key/org ]; then + cp -r --preserve=mode "$ACTIVATION_KEY_PATH" /tmp/activation-key + mkdir /shared/rhsm-tmp + VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume /tmp/activation-key:/activation-key -v /shared/rhsm-tmp:/etc/pki/entitlement:Z" + echo "Adding activation key to the build" + + elif find /entitlement -name "*.pem" >> null; then + cp -r --preserve=mode "$ENTITLEMENT_PATH" /tmp/entitlement + VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume /tmp/entitlement:/etc/pki/entitlement" + echo "Adding the entitlement to the build" + fi + + ADDITIONAL_SECRET_PATH="/additional-secret" + ADDITIONAL_SECRET_TMP="/tmp/additional-secret" + if [ -d "$ADDITIONAL_SECRET_PATH" ]; then + cp -r --preserve=mode -L "$ADDITIONAL_SECRET_PATH" $ADDITIONAL_SECRET_TMP + while read -r filename; do + echo "Adding the secret ${ADDITIONAL_SECRET}/${filename} to the build, available at /run/secrets/${ADDITIONAL_SECRET}/${filename}" + BUILDAH_ARGS+=("--secret=id=${ADDITIONAL_SECRET}/${filename},src=$ADDITIONAL_SECRET_TMP/${filename}") + done < <(find $ADDITIONAL_SECRET_TMP -maxdepth 1 -type f -exec basename {} \;) + fi + + unshare -Uf $UNSHARE_ARGS --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -w ${SOURCE_CODE_DIR}/$CONTEXT -- buildah build \ + $VOLUME_MOUNTS \ + "${BUILDAH_ARGS[@]}" \ + "${LABELS[@]}" \ + --tls-verify=$TLSVERIFY --no-cache \ + --ulimit nofile=4096:4096 \ + -f "$dockerfile_path" -t $IMAGE . + + container=$(buildah from --pull-never $IMAGE) + buildah mount $container | tee /shared/container_path + # delete symlinks - they may point outside the container rootfs, messing with SBOM scanners + find $(cat /shared/container_path) -xtype l -delete + echo $container > /shared/container_name + + # Save the SBOM produced by Cachi2 so it can be merged into the final SBOM later + if [ -f "/tmp/cachi2/output/bom.json" ]; then + cp /tmp/cachi2/output/bom.json ./sbom-cachi2.json + fi + + # Expose base image digests + touch $(results.BASE_IMAGES_DIGESTS.path) + for image in $BASE_IMAGES; do + if [ "${image}" != "scratch" ]; then + buildah images --format '{{ .Name }}:{{ .Tag }}@{{ .Digest }}' --filter reference="$image" >> $(results.BASE_IMAGES_DIGESTS.path) + fi + done + + # Needed to generate base images SBOM + echo "$BASE_IMAGES" > $(workspaces.source.path)/base_images_from_dockerfile + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /entitlement + name: etc-pki-entitlement + - mountPath: /activation-key + name: activation-key + - mountPath: /additional-secret + name: additional-secret + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + - image: registry.access.redhat.com/rh-syft-tech-preview/syft-rhel9:1.4.1@sha256:34d7065427085a31dc4949bd283c001b91794d427e1e4cdf1b21ea4faf9fee3f + name: sbom-syft-generate + script: | + echo "Running syft on the source directory" + syft dir:$(workspaces.source.path)/source --output cyclonedx-json=$(workspaces.source.path)/sbom-source.json + echo "Running syft on the image filesystem" + syft dir:$(cat /shared/container_path) --output cyclonedx-json=$(workspaces.source.path)/sbom-image.json + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + workingDir: $(workspaces.source.path)/source + - image: quay.io/redhat-appstudio/hacbs-jvm-build-request-processor:127ee0c223a2b56a9bd20a6f2eaeed3bd6015f77 + name: analyse-dependencies-java-sbom + script: | + if [ -f /var/lib/containers/java ]; then + /opt/jboss/container/java/run/run-java.sh analyse-dependencies path $(cat /shared/container_path) -s $(workspaces.source.path)/sbom-image.json --task-run-name $(context.taskRun.name) --publishers $(results.SBOM_JAVA_COMPONENTS_COUNT.path) + sed -i 's/^/ /' $(results.SBOM_JAVA_COMPONENTS_COUNT.path) # Workaround for SRVKP-2875 + else + touch $(results.JAVA_COMMUNITY_DEPENDENCIES.path) + fi + securityContext: + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + - image: registry.access.redhat.com/ubi9/python-39:9.5-1734610342@sha256:dde5068ba8fd81eef41a9128ddad2b99e2e02e5869ffe925c605b609a0ad7bbb + name: merge-syft-sboms + script: | + #!/bin/python3 + import json + + # load SBOMs + with open("./sbom-image.json") as f: + image_sbom = json.load(f) + + with open("./sbom-source.json") as f: + source_sbom = json.load(f) + + # fetch unique components from available SBOMs + def get_identifier(component): + return component["name"] + '@' + component.get("version", "") + + image_sbom_components = image_sbom.setdefault("components", []) + existing_components = [get_identifier(component) for component in image_sbom_components] + + source_sbom_components = source_sbom.get("components", []) + for component in source_sbom_components: + if get_identifier(component) not in existing_components: + image_sbom_components.append(component) + existing_components.append(get_identifier(component)) + + image_sbom_components.sort(key=lambda c: get_identifier(c)) + + # write the CycloneDX unified SBOM + with open("./sbom-cyclonedx.json", "w") as f: + json.dump(image_sbom, f, indent=4) + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - image: quay.io/redhat-appstudio/cachi2:0.16.0@sha256:55415cd8ded149f5d56d3fca46d93125b86b41e07ae5d3c03caa240b7b93b7d8 + name: merge-cachi2-sbom + script: | + if [ -f "sbom-cachi2.json" ]; then + echo "Merging contents of sbom-cachi2.json into sbom-cyclonedx.json" + merge_syft_sbom sbom-cachi2.json sbom-cyclonedx.json > sbom-temp.json + mv sbom-temp.json sbom-cyclonedx.json + else + echo "Skipping step since no Cachi2 SBOM was produced" + fi + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - image: registry.access.redhat.com/ubi9/python-39:9.5-1734610342@sha256:dde5068ba8fd81eef41a9128ddad2b99e2e02e5869ffe925c605b609a0ad7bbb + name: create-purl-sbom + script: | + #!/bin/python3 + import json + + with open("./sbom-cyclonedx.json") as f: + cyclonedx_sbom = json.load(f) + + purls = [{"purl": component["purl"]} for component in cyclonedx_sbom.get("components", []) if "purl" in component] + purl_content = {"image_contents": {"dependencies": purls}} + + with open("sbom-purl.json", "w") as output_file: + json.dump(purl_content, output_file, indent=4) + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - env: + - name: BASE_IMAGES_DIGESTS_PATH + value: $(results.BASE_IMAGES_DIGESTS.path) + image: quay.io/redhat-appstudio/base-images-sbom-script@sha256:667669e3def018f9dbb8eaf8868887a40bc07842221e9a98f6787edcff021840 + name: create-base-images-sbom + script: | + python3 /app/base_images_sbom_script.py --sbom=sbom-cyclonedx.json --base-images-from-dockerfile=base_images_from_dockerfile --base-images-digests=$BASE_IMAGES_DIGESTS_PATH + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - computeResources: {} + image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: inject-sbom-and-push + script: | + if [ -n "${PARAM_BUILDER_IMAGE}" ]; then + echo "WARNING: provided deprecated BUILDER_IMAGE parameter has no effect." + fi + + base_image_name=$(buildah inspect --format '{{ index .ImageAnnotations "org.opencontainers.image.base.name"}}' $IMAGE | cut -f1 -d'@') + base_image_digest=$(buildah inspect --format '{{ index .ImageAnnotations "org.opencontainers.image.base.digest"}}' $IMAGE) + container=$(buildah from --pull-never $IMAGE) + buildah copy $container sbom-cyclonedx.json sbom-purl.json /root/buildinfo/content_manifests/ + buildah config -a org.opencontainers.image.base.name=${base_image_name} -a org.opencontainers.image.base.digest=${base_image_digest} $container + + BUILDAH_ARGS=() + if [ "${SQUASH}" == "true" ]; then + BUILDAH_ARGS+=("--squash") + fi + + buildah commit "${BUILDAH_ARGS[@]}" $container $IMAGE + + status=-1 + max_run=5 + sleep_sec=10 + for run in $(seq 1 $max_run); do + status=0 + [ "$run" -gt 1 ] && sleep $sleep_sec + echo "Pushing sbom image to registry" + buildah push \ + --tls-verify=$TLSVERIFY \ + --digestfile $(workspaces.source.path)/image-digest $IMAGE \ + docker://$IMAGE && break || status=$? + done + if [ "$status" -ne 0 ]; then + echo "Failed to push sbom image to registry after ${max_run} tries" + exit 1 + fi + + cat "$(workspaces.source.path)"/image-digest | tee $(results.IMAGE_DIGEST.path) + echo -n "$IMAGE" | tee $(results.IMAGE_URL.path) + securityContext: + capabilities: + add: + - SETFCAP + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + workingDir: $(workspaces.source.path) + - args: + - attach + - sbom + - --sbom + - sbom-cyclonedx.json + - --type + - cyclonedx + - $(params.IMAGE) + image: quay.io/redhat-appstudio/cosign:v2.1.1@sha256:c883d6f8d39148f2cea71bff4622d196d89df3e510f36c140c097b932f0dd5d5 + name: upload-sbom + workingDir: $(workspaces.source.path) + volumes: + - emptyDir: {} + name: varlibcontainers + - emptyDir: {} + name: shared + - name: etc-pki-entitlement + secret: + optional: true + secretName: $(params.ENTITLEMENT_SECRET) + - name: activation-key + secret: + optional: true + secretName: $(params.ACTIVATION_KEY) + - name: additional-secret + secret: + optional: true + secretName: $(params.ADDITIONAL_SECRET) + - configMap: + items: + - key: $(params.caTrustConfigMapKey) + path: ca-bundle.crt + name: $(params.caTrustConfigMapName) + optional: true + name: trusted-ca + workspaces: + - description: Workspace containing the source code to build. + name: source diff --git a/auto-generated/task/buildah-min/0.2/tekton.dev_v1_task_buildah-min.yaml b/auto-generated/task/buildah-min/0.2/tekton.dev_v1_task_buildah-min.yaml new file mode 100644 index 0000000000..72c40d6db7 --- /dev/null +++ b/auto-generated/task/buildah-min/0.2/tekton.dev_v1_task_buildah-min.yaml @@ -0,0 +1,718 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + annotations: + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: image-build, konflux + labels: + app.kubernetes.io/version: 0.2.1 + build.appstudio.redhat.com/build_type: docker + name: buildah-min +spec: + description: |- + Buildah task builds source code into a container image and pushes the image into container registry using buildah tool. + In addition it generates a SBOM file, injects the SBOM file into final container image and pushes the SBOM file as separate image using cosign tool. + When [Java dependency rebuild](https://redhat-appstudio.github.io/docs.stonesoup.io/Documentation/main/cli/proc_enabled_java_dependencies.html) is enabled it triggers rebuilds of Java artifacts. + When prefetch-dependencies task was activated it is using its artifacts to run build in hermetic environment. + params: + - description: Reference of the image buildah will produce. + name: IMAGE + type: string + - default: ./Dockerfile + description: Path to the Dockerfile to build. + name: DOCKERFILE + type: string + - default: . + description: Path to the directory to use as context. + name: CONTEXT + type: string + - default: "true" + description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS + registry) + name: TLSVERIFY + type: string + - default: "false" + description: Determines if build will be executed without network access. + name: HERMETIC + type: string + - default: "" + description: In case it is not empty, the prefetched content should be made available + to the build. + name: PREFETCH_INPUT + type: string + - default: "" + description: Delete image tag after specified time. Empty means to keep the image + tag. Time values could be something like 1h, 2d, 3w for hours, days, and weeks, + respectively. + name: IMAGE_EXPIRES_AFTER + type: string + - default: "" + description: The image is built from this commit. + name: COMMIT_SHA + type: string + - default: repos.d + description: Path in the git repository in which yum repository files are stored + name: YUM_REPOS_D_SRC + - default: fetched.repos.d + description: Path in source workspace where dynamically-fetched repos are present + name: YUM_REPOS_D_FETCHED + - default: /etc/yum.repos.d + description: Target path on the container in which yum repository files should + be made available + name: YUM_REPOS_D_TARGET + - default: "" + description: Target stage in Dockerfile to build. If not specified, the Dockerfile + is processed entirely to (and including) its last stage. + name: TARGET_STAGE + type: string + - default: etc-pki-entitlement + description: Name of secret which contains the entitlement certificates + name: ENTITLEMENT_SECRET + type: string + - default: activation-key + description: Name of secret which contains subscription activation key + name: ACTIVATION_KEY + type: string + - default: does-not-exist + description: Name of a secret which will be made available to the build with 'buildah + build --secret' at /run/secrets/$ADDITIONAL_SECRET + name: ADDITIONAL_SECRET + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) + name: BUILD_ARGS + type: array + - default: "" + description: Path to a file with build arguments, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: BUILD_ARGS_FILE + type: string + - default: trusted-ca + description: The name of the ConfigMap to read CA bundle data from. + name: caTrustConfigMapName + type: string + - default: ca-bundle.crt + description: The name of the key in the ConfigMap that contains the CA bundle + data. + name: caTrustConfigMapKey + type: string + - default: "" + description: Comma separated list of extra capabilities to add when running 'buildah + build' + name: ADD_CAPABILITIES + type: string + - default: "false" + description: Squash all new and previous layers added as a part of this build, + as per --squash + name: SQUASH + type: string + - default: vfs + description: Storage driver to configure for buildah + name: STORAGE_DRIVER + type: string + - default: "true" + description: Whether to skip stages in Containerfile that seem unused by subsequent + stages + name: SKIP_UNUSED_STAGES + type: string + - default: [] + description: Additional key=value labels that should be applied to the image + name: LABELS + type: array + - default: "false" + description: Whether to enable privileged mode + name: PRIVILEGED_NESTED + type: string + results: + - description: Digest of the image just built + name: IMAGE_DIGEST + - description: Image repository and tag where the built image was pushed + name: IMAGE_URL + - description: Image reference of the built image + name: IMAGE_REF + - description: Reference of SBOM blob digest to enable digest-based verification + from provenance + name: SBOM_BLOB_URL + type: string + - description: The counting of Java components by publisher in JSON format + name: SBOM_JAVA_COMPONENTS_COUNT + type: string + - description: The Java dependencies that came from community sources such as Maven + central. + name: JAVA_COMMUNITY_DEPENDENCIES + stepTemplate: + computeResources: + limits: + cpu: 500m + memory: 2Gi + requests: + cpu: 100m + memory: 512Mi + env: + - name: BUILDAH_FORMAT + value: oci + - name: STORAGE_DRIVER + value: $(params.STORAGE_DRIVER) + - name: HERMETIC + value: $(params.HERMETIC) + - name: SOURCE_CODE_DIR + value: source + - name: CONTEXT + value: $(params.CONTEXT) + - name: IMAGE + value: $(params.IMAGE) + - name: TLSVERIFY + value: $(params.TLSVERIFY) + - name: IMAGE_EXPIRES_AFTER + value: $(params.IMAGE_EXPIRES_AFTER) + - name: YUM_REPOS_D_SRC + value: $(params.YUM_REPOS_D_SRC) + - name: YUM_REPOS_D_FETCHED + value: $(params.YUM_REPOS_D_FETCHED) + - name: YUM_REPOS_D_TARGET + value: $(params.YUM_REPOS_D_TARGET) + - name: TARGET_STAGE + value: $(params.TARGET_STAGE) + - name: ENTITLEMENT_SECRET + value: $(params.ENTITLEMENT_SECRET) + - name: ACTIVATION_KEY + value: $(params.ACTIVATION_KEY) + - name: ADDITIONAL_SECRET + value: $(params.ADDITIONAL_SECRET) + - name: BUILD_ARGS_FILE + value: $(params.BUILD_ARGS_FILE) + - name: ADD_CAPABILITIES + value: $(params.ADD_CAPABILITIES) + - name: SQUASH + value: $(params.SQUASH) + - name: SKIP_UNUSED_STAGES + value: $(params.SKIP_UNUSED_STAGES) + - name: PRIVILEGED_NESTED + value: $(params.PRIVILEGED_NESTED) + volumeMounts: + - mountPath: /shared + name: shared + steps: + - args: + - --build-args + - $(params.BUILD_ARGS[*]) + - --labels + - $(params.LABELS[*]) + computeResources: + limits: + cpu: 2 + memory: 4Gi + requests: + cpu: 100m + memory: 1Gi + env: + - name: COMMIT_SHA + value: $(params.COMMIT_SHA) + - name: DOCKERFILE + value: $(params.DOCKERFILE) + image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: build + script: | + #!/bin/bash + set -euo pipefail + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + if [ -e "$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" + elif [ -e "$SOURCE_CODE_DIR/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$DOCKERFILE" + elif [ -e "$DOCKERFILE" ]; then + # Instrumented builds (SAST) use this custom dockerffile step as their base + dockerfile_path="$DOCKERFILE" + elif echo "$DOCKERFILE" | grep -q "^https\?://"; then + echo "Fetch Dockerfile from $DOCKERFILE" + dockerfile_path=$(mktemp --suffix=-Dockerfile) + http_code=$(curl -s -S -L -w "%{http_code}" --output "$dockerfile_path" "$DOCKERFILE") + if [ $http_code != 200 ]; then + echo "No Dockerfile is fetched. Server responds $http_code" + exit 1 + fi + http_code=$(curl -s -S -L -w "%{http_code}" --output "$dockerfile_path.dockerignore.tmp" "$DOCKERFILE.dockerignore") + if [ $http_code = 200 ]; then + echo "Fetched .dockerignore from $DOCKERFILE.dockerignore" + mv "$dockerfile_path.dockerignore.tmp" $SOURCE_CODE_DIR/$CONTEXT/.dockerignore + fi + else + echo "Cannot find Dockerfile $DOCKERFILE" + exit 1 + fi + + dockerfile_copy=$(mktemp --tmpdir "$(basename "$dockerfile_path").XXXXXX") + cp "$dockerfile_path" "$dockerfile_copy" + + if [ -n "${JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR-}" ] && grep -q '^\s*RUN \(./\)\?mvn' "$dockerfile_copy"; then + sed -i -e "s|^\s*RUN \(\(./\)\?mvn\)\(.*\)|RUN echo \"mirror.defaulthttp://$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR/v1/cache/default/0/*\" > /tmp/settings.yaml; \1 -s /tmp/settings.yaml \3|g" "$dockerfile_copy" + touch /var/lib/containers/java + fi + + # Fixing group permission on /var/lib/containers + chown root:root /var/lib/containers + + sed -i 's/^\s*short-name-mode\s*=\s*.*/short-name-mode = "disabled"/' /etc/containers/registries.conf + + # Setting new namespace to run buildah - 2^32-2 + echo 'root:1:4294967294' | tee -a /etc/subuid >> /etc/subgid + + build_args=() + if [ -n "${BUILD_ARGS_FILE}" ]; then + # Parse BUILD_ARGS_FILE ourselves because dockerfile-json doesn't support it + echo "Parsing ARGs from $BUILD_ARGS_FILE" + mapfile -t build_args < <( + # https://www.mankier.com/1/buildah-build#--build-arg-file + # delete lines that start with # + # delete blank lines + sed -e '/^#/d' -e '/^\s*$/d' "${SOURCE_CODE_DIR}/${BUILD_ARGS_FILE}" + ) + fi + + LABELS=() + # Split `args` into two sets of arguments. + while [[ $# -gt 0 ]]; do + case $1 in + --build-args) + shift + # Note: this may result in multiple --build-arg=KEY=value flags with the same KEY being + # passed to buildah. In that case, the *last* occurrence takes precedence. This is why + # we append BUILD_ARGS after the content of the BUILD_ARGS_FILE + while [[ $# -gt 0 && $1 != --* ]]; do build_args+=("$1"); shift; done + ;; + --labels) + shift + while [[ $# -gt 0 && $1 != --* ]]; do LABELS+=("--label" "$1"); shift; done + ;; + *) + echo "unexpected argument: $1" >&2 + exit 2 + ;; + esac + done + + BUILD_ARG_FLAGS=() + for build_arg in "${build_args[@]}"; do + BUILD_ARG_FLAGS+=("--build-arg=$build_arg") + done + + dockerfile-json "${BUILD_ARG_FLAGS[@]}" "$dockerfile_copy" > /shared/parsed_dockerfile.json + BASE_IMAGES=$( + jq -r '.Stages[] | select(.From | .Stage or .Scratch | not) | .BaseName | select(test("^oci-archive:") | not)' /shared/parsed_dockerfile.json + ) + + BUILDAH_ARGS=() + UNSHARE_ARGS=() + + if [ "${HERMETIC}" == "true" ]; then + BUILDAH_ARGS+=("--pull=never") + UNSHARE_ARGS+=("--net") + + for image in $BASE_IMAGES; do + unshare -Ufp --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -- buildah pull $image + done + echo "Build will be executed with network isolation" + fi + + if [ -n "${TARGET_STAGE}" ]; then + BUILDAH_ARGS+=("--target=${TARGET_STAGE}") + fi + + BUILDAH_ARGS+=("${BUILD_ARG_FLAGS[@]}") + + if [ "${PRIVILEGED_NESTED}" == "true" ]; then + BUILDAH_ARGS+=("--security-opt=label=disable") + BUILDAH_ARGS+=("--cap-add=all") + BUILDAH_ARGS+=("--device=/dev/fuse") + fi + + if [ -n "${ADD_CAPABILITIES}" ]; then + BUILDAH_ARGS+=("--cap-add=${ADD_CAPABILITIES}") + fi + + if [ "${SQUASH}" == "true" ]; then + BUILDAH_ARGS+=("--squash") + fi + + if [ "${SKIP_UNUSED_STAGES}" != "true" ] ; then + BUILDAH_ARGS+=("--skip-unused-stages=false") + fi + + VOLUME_MOUNTS=() + + if [ -f "$(workspaces.source.path)/cachi2/cachi2.env" ]; then + cp -r "$(workspaces.source.path)/cachi2" /tmp/ + chmod -R go+rwX /tmp/cachi2 + VOLUME_MOUNTS+=(--volume /tmp/cachi2:/cachi2) + # Read in the whole file (https://unix.stackexchange.com/questions/533277), then + # for each RUN ... line insert the cachi2.env command *after* any options like --mount + sed -E -i \ + -e 'H;1h;$!d;x' \ + -e 's@^\s*(run((\s|\\\n)+-\S+)*(\s|\\\n)+)@\1. /cachi2/cachi2.env \&\& \\\n @igM' \ + "$dockerfile_copy" + echo "Prefetched content will be made available" + + prefetched_repo_for_my_arch="/tmp/cachi2/output/deps/rpm/$(uname -m)/repos.d/cachi2.repo" + if [ -f "$prefetched_repo_for_my_arch" ]; then + echo "Adding $prefetched_repo_for_my_arch to $YUM_REPOS_D_FETCHED" + mkdir -p "$YUM_REPOS_D_FETCHED" + cp --no-clobber "$prefetched_repo_for_my_arch" "$YUM_REPOS_D_FETCHED" + fi + fi + + # if yum repofiles stored in git, copy them to mount point outside the source dir + if [ -d "${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}" ]; then + mkdir -p ${YUM_REPOS_D_FETCHED} + cp -r ${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}/* ${YUM_REPOS_D_FETCHED} + fi + + # if anything in the repofiles mount point (either fetched or from git), mount it + if [ -d "${YUM_REPOS_D_FETCHED}" ]; then + chmod -R go+rwX ${YUM_REPOS_D_FETCHED} + mount_point=$(realpath ${YUM_REPOS_D_FETCHED}) + VOLUME_MOUNTS+=(--volume "${mount_point}:${YUM_REPOS_D_TARGET}") + fi + + DEFAULT_LABELS=( + "--label" "build-date=$(date -u +'%Y-%m-%dT%H:%M:%S')" + "--label" "architecture=$(uname -m)" + "--label" "vcs-type=git" + ) + [ -n "$COMMIT_SHA" ] && DEFAULT_LABELS+=("--label" "vcs-ref=$COMMIT_SHA") + [ -n "$IMAGE_EXPIRES_AFTER" ] && DEFAULT_LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + + # Concatenate defaults and explicit labels. If a label appears twice, the last one wins. + LABELS=("${DEFAULT_LABELS[@]}" "${LABELS[@]}") + + ACTIVATION_KEY_PATH="/activation-key" + ENTITLEMENT_PATH="/entitlement" + + # 0. if hermetic=true, skip all subscription related stuff + # 1. do not enable activation key and entitlement at same time. If both vars are provided, prefer activation key. + # 2. Activation-keys will be used when the key 'org' exists in the activation key secret. + # 3. try to pre-register and mount files to the correct location so that users do no need to modify Dockerfiles. + # 3. If the Dockerfile contains the string "subcription-manager register", add the activation-keys volume + # to buildah but don't pre-register for backwards compatibility. Mount an empty directory on + # shared emptydir volume to "/etc/pki/entitlement" to prevent certificates from being included + + if [ "${HERMETIC}" != "true" ] && [ -e /activation-key/org ]; then + cp -r --preserve=mode "$ACTIVATION_KEY_PATH" /tmp/activation-key + mkdir -p /shared/rhsm/etc/pki/entitlement + mkdir -p /shared/rhsm/etc/pki/consumer + + VOLUME_MOUNTS+=(-v /tmp/activation-key:/activation-key \ + -v /shared/rhsm/etc/pki/entitlement:/etc/pki/entitlement:Z \ + -v /shared/rhsm/etc/pki/consumer:/etc/pki/consumer:Z) + echo "Adding activation key to the build" + + if ! grep -E "^[^#]*subscription-manager.[^#]*register" "$dockerfile_path"; then + # user is not running registration in the Containerfile: pre-register. + echo "Pre-registering with subscription manager." + subscription-manager register --org "$(cat /tmp/activation-key/org)" --activationkey "$(cat /tmp/activation-key/activationkey)" + trap 'subscription-manager unregister || true' EXIT + + # copy generated certificates to /shared volume + cp /etc/pki/entitlement/*.pem /shared/rhsm/etc/pki/entitlement + cp /etc/pki/consumer/*.pem /shared/rhsm/etc/pki/consumer + + # and then mount get /etc/rhsm/ca/redhat-uep.pem into /run/secrets/rhsm/ca + VOLUME_MOUNTS+=(--volume /etc/rhsm/ca/redhat-uep.pem:/etc/rhsm/ca/redhat-uep.pem:Z) + fi + + elif [ "${HERMETIC}" != "true" ] && find /entitlement -name "*.pem" >> null; then + cp -r --preserve=mode "$ENTITLEMENT_PATH" /tmp/entitlement + VOLUME_MOUNTS+=(--volume /tmp/entitlement:/etc/pki/entitlement) + echo "Adding the entitlement to the build" + fi + + if [ -n "${ADDITIONAL_VOLUME_MOUNTS-}" ]; then + # ADDITIONAL_VOLUME_MOUNTS allows to specify more volumes for the build. + # Instrumented builds (SAST) use this step as their base and add some other tools. + while read -r volume_mount; do + VOLUME_MOUNTS+=("--volume=$volume_mount") + done <<< "$ADDITIONAL_VOLUME_MOUNTS" + fi + + ADDITIONAL_SECRET_PATH="/additional-secret" + ADDITIONAL_SECRET_TMP="/tmp/additional-secret" + if [ -d "$ADDITIONAL_SECRET_PATH" ]; then + cp -r --preserve=mode -L "$ADDITIONAL_SECRET_PATH" $ADDITIONAL_SECRET_TMP + while read -r filename; do + echo "Adding the secret ${ADDITIONAL_SECRET}/${filename} to the build, available at /run/secrets/${ADDITIONAL_SECRET}/${filename}" + BUILDAH_ARGS+=("--secret=id=${ADDITIONAL_SECRET}/${filename},src=$ADDITIONAL_SECRET_TMP/${filename}") + done < <(find $ADDITIONAL_SECRET_TMP -maxdepth 1 -type f -exec basename {} \;) + fi + + # Prevent ShellCheck from giving a warning because 'image' is defined and 'IMAGE' is not. + declare IMAGE + + buildah_cmd_array=( + buildah build + "${VOLUME_MOUNTS[@]}" + "${BUILDAH_ARGS[@]}" + "${LABELS[@]}" + --tls-verify="$TLSVERIFY" --no-cache + --ulimit nofile=4096:4096 + -f "$dockerfile_copy" -t "$IMAGE" . + ) + buildah_cmd=$(printf "%q " "${buildah_cmd_array[@]}") + + if [ "${HERMETIC}" == "true" ]; then + # enabling loopback adapter enables Bazel builds to work in hermetic mode. + command="ip link set lo up && $buildah_cmd" + else + command="$buildah_cmd" + fi + + # disable host subcription manager integration + find /usr/share/rhel/secrets -type l -exec unlink {} \; + + unshare -Uf "${UNSHARE_ARGS[@]}" --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -w "${SOURCE_CODE_DIR}/$CONTEXT" -- sh -c "$command" + + container=$(buildah from --pull-never "$IMAGE") + + # Save the SBOM produced by Cachi2 so it can be merged into the final SBOM later + if [ -f "/tmp/cachi2/output/bom.json" ]; then + echo "Making copy of sbom-cachi2.json" + cp /tmp/cachi2/output/bom.json ./sbom-cachi2.json + fi + + buildah mount $container | tee /shared/container_path + # delete symlinks - they may point outside the container rootfs, messing with SBOM scanners + find $(cat /shared/container_path) -xtype l -delete + echo $container > /shared/container_name + + touch /shared/base_images_digests + for image in $BASE_IMAGES; do + base_image_digest=$(buildah images --format '{{ .Name }}:{{ .Tag }}@{{ .Digest }}' --filter reference="$image") + # In some cases, there might be BASE_IMAGES, but not any associated digest. This happens + # if buildah did not use that particular image during build because it was skipped + if [ -n "$base_image_digest" ]; then + echo "$image $base_image_digest" >> /shared/base_images_digests + fi + done + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /entitlement + name: etc-pki-entitlement + - mountPath: /activation-key + name: activation-key + - mountPath: /additional-secret + name: additional-secret + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + - image: quay.io/konflux-ci/icm-injection-scripts:latest@sha256:462980e94ba689b5f56c3d5dfb3358cd8c685300daf65a71532f11898935e7f1 + name: icm + script: | + #!/bin/bash + set -euo pipefail + /scripts/inject-icm.sh "$IMAGE" + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + workingDir: $(workspaces.source.path) + - image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: push + script: | + #!/bin/bash + set -e + + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + retries=5 + # Push to a unique tag based on the TaskRun name to avoid race conditions + echo "Pushing to ${IMAGE%:*}:${TASKRUN_NAME}" + if ! buildah push \ + --retry "$retries" \ + --tls-verify="$TLSVERIFY" \ + "$IMAGE" \ + "docker://${IMAGE%:*}:$(context.taskRun.name)"; + then + echo "Failed to push sbom image to ${IMAGE%:*}:$(context.taskRun.name) after ${retries} tries" + exit 1 + fi + + # Push to a tag based on the git revision + echo "Pushing to ${IMAGE}" + if ! buildah push \ + --retry "$retries" \ + --tls-verify="$TLSVERIFY" \ + --digestfile "$(workspaces.source.path)/image-digest" "$IMAGE" \ + "docker://$IMAGE"; + then + echo "Failed to push sbom image to $IMAGE after ${retries} tries" + exit 1 + fi + + cat "$(workspaces.source.path)"/image-digest | tee $(results.IMAGE_DIGEST.path) + echo -n "$IMAGE" | tee $(results.IMAGE_URL.path) + { + echo -n "${IMAGE}@" + cat "$(workspaces.source.path)/image-digest" + } > "$(results.IMAGE_REF.path)" + securityContext: + capabilities: + add: + - SETFCAP + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + - image: registry.access.redhat.com/rh-syft-tech-preview/syft-rhel9:1.4.1@sha256:34d7065427085a31dc4949bd283c001b91794d427e1e4cdf1b21ea4faf9fee3f + name: sbom-syft-generate + script: | + echo "Running syft on the source directory" + syft dir:"$(workspaces.source.path)/$SOURCE_CODE_DIR/$CONTEXT" --output cyclonedx-json="$(workspaces.source.path)/sbom-source.json" + echo "Running syft on the image filesystem" + syft dir:"$(cat /shared/container_path)" --output cyclonedx-json="$(workspaces.source.path)/sbom-image.json" + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + workingDir: $(workspaces.source.path)/source + - computeResources: + limits: + cpu: 100m + memory: 256Mi + requests: + cpu: 10m + memory: 128Mi + image: quay.io/redhat-appstudio/hacbs-jvm-build-request-processor:127ee0c223a2b56a9bd20a6f2eaeed3bd6015f77 + name: analyse-dependencies-java-sbom + script: | + if [ -f /var/lib/containers/java ]; then + /opt/jboss/container/java/run/run-java.sh analyse-dependencies path $(cat /shared/container_path) -s $(workspaces.source.path)/sbom-image.json --task-run-name $(context.taskRun.name) --publishers $(results.SBOM_JAVA_COMPONENTS_COUNT.path) + sed -i 's/^/ /' $(results.SBOM_JAVA_COMPONENTS_COUNT.path) # Workaround for SRVKP-2875 + else + touch $(results.JAVA_COMMUNITY_DEPENDENCIES.path) + fi + securityContext: + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + - computeResources: + limits: + cpu: 100m + memory: 256Mi + requests: + cpu: 10m + memory: 128Mi + image: quay.io/redhat-appstudio/sbom-utility-scripts-image@sha256:9f1fd11d9c3c517ecc112d192ad361d16ecf6ce00b83b109c93cf3d1c644a357 + name: prepare-sboms + script: | + echo "Merging contents of sbom-source.json and sbom-image.json into sbom-cyclonedx.json" + python3 /scripts/merge_syft_sboms.py + + if [ -f "sbom-cachi2.json" ]; then + echo "Merging contents of sbom-cachi2.json into sbom-cyclonedx.json" + python3 /scripts/merge_cachi2_sboms.py sbom-cachi2.json sbom-cyclonedx.json > sbom-temp.json + mv sbom-temp.json sbom-cyclonedx.json + fi + + echo "Adding base images data to sbom-cyclonedx.json" + python3 /scripts/base_images_sbom_script.py \ + --sbom=sbom-cyclonedx.json \ + --parsed-dockerfile=/shared/parsed_dockerfile.json \ + --base-images-digests=/shared/base_images_digests + + echo "Adding image reference to sbom" + IMAGE_URL="$(cat "$(results.IMAGE_URL.path)")" + IMAGE_DIGEST="$(cat "$(results.IMAGE_DIGEST.path)")" + + python3 /scripts/add_image_reference.py \ + --image-url "$IMAGE_URL" \ + --image-digest "$IMAGE_DIGEST" \ + --input-file sbom-cyclonedx.json \ + --output-file /tmp/sbom-cyclonedx.tmp.json + + mv /tmp/sbom-cyclonedx.tmp.json sbom-cyclonedx.json + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - computeResources: + limits: + cpu: 2 + memory: 2Gi + requests: + cpu: 100m + memory: 512Mi + image: quay.io/konflux-ci/appstudio-utils:48c311af02858e2422d6229600e9959e496ddef1@sha256:91ddd999271f65d8ec8487b10f3dd378f81aa894e11b9af4d10639fd52bba7e8 + name: upload-sbom + script: | + #!/bin/bash + + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + cosign attach sbom --sbom sbom-cyclonedx.json --type cyclonedx "$(cat "$(results.IMAGE_REF.path)")" + + # Remove tag from IMAGE while allowing registry to contain a port number. + sbom_repo="${IMAGE%:*}" + sbom_digest="$(sha256sum sbom-cyclonedx.json | cut -d' ' -f1)" + # The SBOM_BLOB_URL is created by `cosign attach sbom`. + echo -n "${sbom_repo}@sha256:${sbom_digest}" | tee "$(results.SBOM_BLOB_URL.path)" + volumeMounts: + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + volumes: + - emptyDir: {} + name: varlibcontainers + - emptyDir: {} + name: shared + - name: etc-pki-entitlement + secret: + optional: true + secretName: $(params.ENTITLEMENT_SECRET) + - name: activation-key + secret: + optional: true + secretName: $(params.ACTIVATION_KEY) + - name: additional-secret + secret: + optional: true + secretName: $(params.ADDITIONAL_SECRET) + - configMap: + items: + - key: $(params.caTrustConfigMapKey) + path: ca-bundle.crt + name: $(params.caTrustConfigMapName) + optional: true + name: trusted-ca + workspaces: + - description: Workspace containing the source code to build. + name: source diff --git a/auto-generated/task/buildah-oci-ta/0.1/tekton.dev_v1_task_buildah-oci-ta.yaml b/auto-generated/task/buildah-oci-ta/0.1/tekton.dev_v1_task_buildah-oci-ta.yaml new file mode 100644 index 0000000000..62496810f3 --- /dev/null +++ b/auto-generated/task/buildah-oci-ta/0.1/tekton.dev_v1_task_buildah-oci-ta.yaml @@ -0,0 +1,583 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + annotations: + build.appstudio.redhat.com/expires-on: "2024-11-13T00:00:00Z" + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: image-build, konflux + labels: + app.kubernetes.io/version: "0.1" + build.appstudio.redhat.com/build_type: docker + name: buildah-oci-ta +spec: + description: |- + Buildah task builds source code into a container image and pushes the image into container registry using buildah tool. + In addition it generates a SBOM file, injects the SBOM file into final container image and pushes the SBOM file as separate image using cosign tool. + When [Java dependency rebuild](https://redhat-appstudio.github.io/docs.stonesoup.io/Documentation/main/cli/proc_enabled_java_dependencies.html) is enabled it triggers rebuilds of Java artifacts. + When prefetch-dependencies task was activated it is using its artifacts to run build in hermetic environment. + params: + - default: activation-key + description: Name of secret which contains subscription activation key + name: ACTIVATION_KEY + type: string + - default: does-not-exist + description: Name of a secret which will be made available to the build with 'buildah + build --secret' at /run/secrets/$ADDITIONAL_SECRET + name: ADDITIONAL_SECRET + type: string + - default: "" + description: Comma separated list of extra capabilities to add when running 'buildah + build' + name: ADD_CAPABILITIES + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) + name: BUILD_ARGS + type: array + - default: "" + description: Path to a file with build arguments, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: BUILD_ARGS_FILE + type: string + - default: "" + description: The Trusted Artifact URI pointing to the artifact with the prefetched + dependencies. + name: CACHI2_ARTIFACT + type: string + - default: "" + description: The image is built from this commit. + name: COMMIT_SHA + type: string + - default: . + description: Path to the directory to use as context. + name: CONTEXT + type: string + - default: ./Dockerfile + description: Path to the Dockerfile to build. + name: DOCKERFILE + type: string + - default: "" + description: unused, should be removed in next task version + name: DOCKER_AUTH + type: string + - default: etc-pki-entitlement + description: Name of secret which contains the entitlement certificates + name: ENTITLEMENT_SECRET + type: string + - default: "false" + description: Determines if build will be executed without network access. + name: HERMETIC + type: string + - description: Reference of the image buildah will produce. + name: IMAGE + type: string + - default: "" + description: Delete image tag after specified time. Empty means to keep the image + tag. Time values could be something like 1h, 2d, 3w for hours, days, and weeks, + respectively. + name: IMAGE_EXPIRES_AFTER + type: string + - default: "" + description: In case it is not empty, the prefetched content should be made available + to the build. + name: PREFETCH_INPUT + type: string + - default: "true" + description: Whether to skip stages in Containerfile that seem unused by subsequent + stages + name: SKIP_UNUSED_STAGES + type: string + - description: The Trusted Artifact URI pointing to the artifact with the application + source code. + name: SOURCE_ARTIFACT + type: string + - default: "false" + description: Squash all new and previous layers added as a part of this build, + as per --squash + name: SQUASH + type: string + - default: vfs + description: Storage driver to configure for buildah + name: STORAGE_DRIVER + type: string + - default: "" + description: Target stage in Dockerfile to build. If not specified, the Dockerfile + is processed entirely to (and including) its last stage. + name: TARGET_STAGE + type: string + - default: "true" + description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS + registry) + name: TLSVERIFY + type: string + - default: fetched.repos.d + description: Path in source workspace where dynamically-fetched repos are present + name: YUM_REPOS_D_FETCHED + - default: repos.d + description: Path in the git repository in which yum repository files are stored + name: YUM_REPOS_D_SRC + - default: /etc/yum.repos.d + description: Target path on the container in which yum repository files should + be made available + name: YUM_REPOS_D_TARGET + - default: ca-bundle.crt + description: The name of the key in the ConfigMap that contains the CA bundle + data. + name: caTrustConfigMapKey + type: string + - default: trusted-ca + description: The name of the ConfigMap to read CA bundle data from. + name: caTrustConfigMapName + type: string + results: + - description: Digests of the base images used for build + name: BASE_IMAGES_DIGESTS + - description: Digest of the image just built + name: IMAGE_DIGEST + - description: Image repository and tag where the built image was pushed + name: IMAGE_URL + - description: The Java dependencies that came from community sources such as Maven + central. + name: JAVA_COMMUNITY_DEPENDENCIES + - description: The counting of Java components by publisher in JSON format + name: SBOM_JAVA_COMPONENTS_COUNT + type: string + stepTemplate: + env: + - name: ADDITIONAL_SECRET + value: $(params.ADDITIONAL_SECRET) + - name: ADD_CAPABILITIES + value: $(params.ADD_CAPABILITIES) + - name: BUILDAH_FORMAT + value: oci + - name: BUILD_ARGS_FILE + value: $(params.BUILD_ARGS_FILE) + - name: CONTEXT + value: $(params.CONTEXT) + - name: DOCKERFILE + value: $(params.DOCKERFILE) + - name: ENTITLEMENT_SECRET + value: $(params.ENTITLEMENT_SECRET) + - name: HERMETIC + value: $(params.HERMETIC) + - name: IMAGE + value: $(params.IMAGE) + - name: IMAGE_EXPIRES_AFTER + value: $(params.IMAGE_EXPIRES_AFTER) + - name: SKIP_UNUSED_STAGES + value: $(params.SKIP_UNUSED_STAGES) + - name: SQUASH + value: $(params.SQUASH) + - name: STORAGE_DRIVER + value: $(params.STORAGE_DRIVER) + - name: TARGET_STAGE + value: $(params.TARGET_STAGE) + - name: TLSVERIFY + value: $(params.TLSVERIFY) + - name: YUM_REPOS_D_FETCHED + value: $(params.YUM_REPOS_D_FETCHED) + - name: YUM_REPOS_D_SRC + value: $(params.YUM_REPOS_D_SRC) + - name: YUM_REPOS_D_TARGET + value: $(params.YUM_REPOS_D_TARGET) + volumeMounts: + - mountPath: /shared + name: shared + - mountPath: /var/workdir + name: workdir + steps: + - args: + - use + - $(params.SOURCE_ARTIFACT)=/var/workdir/source + - $(params.CACHI2_ARTIFACT)=/var/workdir/cachi2 + image: quay.io/redhat-appstudio/build-trusted-artifacts:latest@sha256:ff35e09ff5c89e54538b50abae241a765b2b7868f05d62c4835bebf0978f3659 + name: use-trusted-artifact + - args: + - $(params.BUILD_ARGS[*]) + computeResources: + limits: + memory: 4Gi + requests: + cpu: 250m + memory: 512Mi + env: + - name: COMMIT_SHA + value: $(params.COMMIT_SHA) + image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: build + script: | + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + SOURCE_CODE_DIR=source + if [ -e "$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" + elif [ -e "$SOURCE_CODE_DIR/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$DOCKERFILE" + elif echo "$DOCKERFILE" | grep -q "^https\?://"; then + echo "Fetch Dockerfile from $DOCKERFILE" + dockerfile_path=$(mktemp --suffix=-Dockerfile) + http_code=$(curl -s -L -w "%{http_code}" --output "$dockerfile_path" "$DOCKERFILE") + if [ $http_code != 200 ]; then + echo "No Dockerfile is fetched. Server responds $http_code" + exit 1 + fi + http_code=$(curl -s -L -w "%{http_code}" --output "$dockerfile_path.dockerignore.tmp" "$DOCKERFILE.dockerignore") + if [ $http_code = 200 ]; then + echo "Fetched .dockerignore from $DOCKERFILE.dockerignore" + mv "$dockerfile_path.dockerignore.tmp" $SOURCE_CODE_DIR/$CONTEXT/.dockerignore + fi + else + echo "Cannot find Dockerfile $DOCKERFILE" + exit 1 + fi + if [ -n "$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR" ] && grep -q '^\s*RUN \(./\)\?mvn' "$dockerfile_path"; then + sed -i -e "s|^\s*RUN \(\(./\)\?mvn\)\(.*\)|RUN echo \"mirror.defaulthttp://$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR/v1/cache/default/0/*\" > /tmp/settings.yaml; \1 -s /tmp/settings.yaml \3|g" "$dockerfile_path" + touch /var/lib/containers/java + fi + + # Fixing group permission on /var/lib/containers + chown root:root /var/lib/containers + + sed -i 's/^\s*short-name-mode\s*=\s*.*/short-name-mode = "disabled"/' /etc/containers/registries.conf + + # Setting new namespace to run buildah - 2^32-2 + echo 'root:1:4294967294' | tee -a /etc/subuid >>/etc/subgid + + BUILDAH_ARGS=() + + BASE_IMAGES=$(grep -i '^\s*FROM' "$dockerfile_path" | sed 's/--platform=\S*//' | awk '{print $2}' | (grep -v ^oci-archive: || true)) + if [ "${HERMETIC}" == "true" ]; then + BUILDAH_ARGS+=("--pull=never") + UNSHARE_ARGS="--net" + for image in $BASE_IMAGES; do + if [ "${image}" != "scratch" ]; then + unshare -Ufp --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -- buildah pull $image + fi + done + echo "Build will be executed with network isolation" + fi + + if [ -n "${TARGET_STAGE}" ]; then + BUILDAH_ARGS+=("--target=${TARGET_STAGE}") + fi + + if [ -n "${BUILD_ARGS_FILE}" ]; then + BUILDAH_ARGS+=("--build-arg-file=$(pwd)/$SOURCE_CODE_DIR/${BUILD_ARGS_FILE}") + fi + + for build_arg in "$@"; do + BUILDAH_ARGS+=("--build-arg=$build_arg") + done + + if [ -n "${ADD_CAPABILITIES}" ]; then + BUILDAH_ARGS+=("--cap-add=${ADD_CAPABILITIES}") + fi + + if [ "${SQUASH}" == "true" ]; then + BUILDAH_ARGS+=("--squash") + fi + + if [ "${SKIP_UNUSED_STAGES}" != "true" ]; then + BUILDAH_ARGS+=("--skip-unused-stages=false") + fi + + if [ -f "/var/workdir/cachi2/cachi2.env" ]; then + cp -r "/var/workdir/cachi2" /tmp/ + chmod -R go+rwX /tmp/cachi2 + VOLUME_MOUNTS="--volume /tmp/cachi2:/cachi2" + # Read in the whole file (https://unix.stackexchange.com/questions/533277), then + # for each RUN ... line insert the cachi2.env command *after* any options like --mount + sed -E -i \ + -e 'H;1h;$!d;x' \ + -e 's@^\s*(run((\s|\\\n)+-\S+)*(\s|\\\n)+)@\1. /cachi2/cachi2.env \&\& \\\n @igM' \ + "$dockerfile_path" + echo "Prefetched content will be made available" + + prefetched_repo_for_my_arch="/tmp/cachi2/output/deps/rpm/$(uname -m)/repos.d/cachi2.repo" + if [ -f "$prefetched_repo_for_my_arch" ]; then + echo "Adding $prefetched_repo_for_my_arch to $YUM_REPOS_D_FETCHED" + mkdir -p "$YUM_REPOS_D_FETCHED" + cp --no-clobber "$prefetched_repo_for_my_arch" "$YUM_REPOS_D_FETCHED" + fi + fi + + # if yum repofiles stored in git, copy them to mount point outside the source dir + if [ -d "${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}" ]; then + mkdir -p ${YUM_REPOS_D_FETCHED} + cp -r ${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}/* ${YUM_REPOS_D_FETCHED} + fi + + # if anything in the repofiles mount point (either fetched or from git), mount it + if [ -d "${YUM_REPOS_D_FETCHED}" ]; then + chmod -R go+rwX ${YUM_REPOS_D_FETCHED} + mount_point=$(realpath ${YUM_REPOS_D_FETCHED}) + VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume ${mount_point}:${YUM_REPOS_D_TARGET}" + fi + + LABELS=( + "--label" "build-date=$(date -u +'%Y-%m-%dT%H:%M:%S')" + "--label" "architecture=$(uname -m)" + "--label" "vcs-type=git" + ) + [ -n "$COMMIT_SHA" ] && LABELS+=("--label" "vcs-ref=$COMMIT_SHA") + [ -n "$IMAGE_EXPIRES_AFTER" ] && LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + + ACTIVATION_KEY_PATH="/activation-key" + ENTITLEMENT_PATH="/entitlement" + + if [ -e /activation-key/org ]; then + cp -r --preserve=mode "$ACTIVATION_KEY_PATH" /tmp/activation-key + mkdir /shared/rhsm-tmp + VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume /tmp/activation-key:/activation-key -v /shared/rhsm-tmp:/etc/pki/entitlement:Z" + echo "Adding activation key to the build" + + elif find /entitlement -name "*.pem" >>null; then + cp -r --preserve=mode "$ENTITLEMENT_PATH" /tmp/entitlement + VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume /tmp/entitlement:/etc/pki/entitlement" + echo "Adding the entitlement to the build" + fi + + ADDITIONAL_SECRET_PATH="/additional-secret" + ADDITIONAL_SECRET_TMP="/tmp/additional-secret" + if [ -d "$ADDITIONAL_SECRET_PATH" ]; then + cp -r --preserve=mode -L "$ADDITIONAL_SECRET_PATH" $ADDITIONAL_SECRET_TMP + while read -r filename; do + echo "Adding the secret ${ADDITIONAL_SECRET}/${filename} to the build, available at /run/secrets/${ADDITIONAL_SECRET}/${filename}" + BUILDAH_ARGS+=("--secret=id=${ADDITIONAL_SECRET}/${filename},src=$ADDITIONAL_SECRET_TMP/${filename}") + done < <(find $ADDITIONAL_SECRET_TMP -maxdepth 1 -type f -exec basename {} \;) + fi + + unshare -Uf $UNSHARE_ARGS --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -w ${SOURCE_CODE_DIR}/$CONTEXT -- buildah build \ + $VOLUME_MOUNTS \ + "${BUILDAH_ARGS[@]}" \ + "${LABELS[@]}" \ + --tls-verify=$TLSVERIFY --no-cache \ + --ulimit nofile=4096:4096 \ + -f "$dockerfile_path" -t $IMAGE . + + container=$(buildah from --pull-never $IMAGE) + buildah mount $container | tee /shared/container_path + # delete symlinks - they may point outside the container rootfs, messing with SBOM scanners + find $(cat /shared/container_path) -xtype l -delete + echo $container >/shared/container_name + + # Save the SBOM produced by Cachi2 so it can be merged into the final SBOM later + if [ -f "/tmp/cachi2/output/bom.json" ]; then + cp /tmp/cachi2/output/bom.json ./sbom-cachi2.json + fi + + # Expose base image digests + touch $(results.BASE_IMAGES_DIGESTS.path) + for image in $BASE_IMAGES; do + if [ "${image}" != "scratch" ]; then + buildah images --format '{{ .Name }}:{{ .Tag }}@{{ .Digest }}' --filter reference="$image" >>$(results.BASE_IMAGES_DIGESTS.path) + fi + done + + # Needed to generate base images SBOM + echo "$BASE_IMAGES" >/var/workdir/base_images_from_dockerfile + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /entitlement + name: etc-pki-entitlement + - mountPath: /activation-key + name: activation-key + - mountPath: /additional-secret + name: additional-secret + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: /var/workdir + - image: registry.access.redhat.com/rh-syft-tech-preview/syft-rhel9:1.4.1@sha256:34d7065427085a31dc4949bd283c001b91794d427e1e4cdf1b21ea4faf9fee3f + name: sbom-syft-generate + script: | + echo "Running syft on the source directory" + syft dir:/var/workdir/source --output cyclonedx-json=/var/workdir/sbom-source.json + echo "Running syft on the image filesystem" + syft dir:$(cat /shared/container_path) --output cyclonedx-json=/var/workdir/sbom-image.json + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + workingDir: /var/workdir/source + - image: quay.io/redhat-appstudio/hacbs-jvm-build-request-processor:127ee0c223a2b56a9bd20a6f2eaeed3bd6015f77 + name: analyse-dependencies-java-sbom + script: | + if [ -f /var/lib/containers/java ]; then + /opt/jboss/container/java/run/run-java.sh analyse-dependencies path $(cat /shared/container_path) -s /var/workdir/sbom-image.json --task-run-name $(context.taskRun.name) --publishers $(results.SBOM_JAVA_COMPONENTS_COUNT.path) + sed -i 's/^/ /' $(results.SBOM_JAVA_COMPONENTS_COUNT.path) # Workaround for SRVKP-2875 + else + touch $(results.JAVA_COMMUNITY_DEPENDENCIES.path) + fi + securityContext: + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + - image: registry.access.redhat.com/ubi9/python-39:9.5-1734610342@sha256:dde5068ba8fd81eef41a9128ddad2b99e2e02e5869ffe925c605b609a0ad7bbb + name: merge-syft-sboms + script: | + #!/bin/python3 + import json + + # load SBOMs + with open("./sbom-image.json") as f: + image_sbom = json.load(f) + + with open("./sbom-source.json") as f: + source_sbom = json.load(f) + + # fetch unique components from available SBOMs + def get_identifier(component): + return component["name"] + '@' + component.get("version", "") + + image_sbom_components = image_sbom.setdefault("components", []) + existing_components = [get_identifier(component) for component in image_sbom_components] + + source_sbom_components = source_sbom.get("components", []) + for component in source_sbom_components: + if get_identifier(component) not in existing_components: + image_sbom_components.append(component) + existing_components.append(get_identifier(component)) + + image_sbom_components.sort(key=lambda c: get_identifier(c)) + + # write the CycloneDX unified SBOM + with open("./sbom-cyclonedx.json", "w") as f: + json.dump(image_sbom, f, indent=4) + securityContext: + runAsUser: 0 + workingDir: /var/workdir + - image: quay.io/redhat-appstudio/cachi2:0.16.0@sha256:55415cd8ded149f5d56d3fca46d93125b86b41e07ae5d3c03caa240b7b93b7d8 + name: merge-cachi2-sbom + script: | + if [ -f "sbom-cachi2.json" ]; then + echo "Merging contents of sbom-cachi2.json into sbom-cyclonedx.json" + merge_syft_sbom sbom-cachi2.json sbom-cyclonedx.json >sbom-temp.json + mv sbom-temp.json sbom-cyclonedx.json + else + echo "Skipping step since no Cachi2 SBOM was produced" + fi + securityContext: + runAsUser: 0 + workingDir: /var/workdir + - image: registry.access.redhat.com/ubi9/python-39:9.5-1734610342@sha256:dde5068ba8fd81eef41a9128ddad2b99e2e02e5869ffe925c605b609a0ad7bbb + name: create-purl-sbom + script: | + #!/bin/python3 + import json + + with open("./sbom-cyclonedx.json") as f: + cyclonedx_sbom = json.load(f) + + purls = [{"purl": component["purl"]} for component in cyclonedx_sbom.get("components", []) if "purl" in component] + purl_content = {"image_contents": {"dependencies": purls}} + + with open("sbom-purl.json", "w") as output_file: + json.dump(purl_content, output_file, indent=4) + securityContext: + runAsUser: 0 + workingDir: /var/workdir + - env: + - name: BASE_IMAGES_DIGESTS_PATH + value: $(results.BASE_IMAGES_DIGESTS.path) + image: quay.io/redhat-appstudio/base-images-sbom-script@sha256:667669e3def018f9dbb8eaf8868887a40bc07842221e9a98f6787edcff021840 + name: create-base-images-sbom + script: | + python3 /app/base_images_sbom_script.py --sbom=sbom-cyclonedx.json --base-images-from-dockerfile=base_images_from_dockerfile --base-images-digests=$BASE_IMAGES_DIGESTS_PATH + securityContext: + runAsUser: 0 + workingDir: /var/workdir + - image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: inject-sbom-and-push + script: | + base_image_name=$(buildah inspect --format '{{ index .ImageAnnotations "org.opencontainers.image.base.name"}}' $IMAGE | cut -f1 -d'@') + base_image_digest=$(buildah inspect --format '{{ index .ImageAnnotations "org.opencontainers.image.base.digest"}}' $IMAGE) + container=$(buildah from --pull-never $IMAGE) + buildah copy $container sbom-cyclonedx.json sbom-purl.json /root/buildinfo/content_manifests/ + buildah config -a org.opencontainers.image.base.name=${base_image_name} -a org.opencontainers.image.base.digest=${base_image_digest} $container + + BUILDAH_ARGS=() + if [ "${SQUASH}" == "true" ]; then + BUILDAH_ARGS+=("--squash") + fi + + buildah commit "${BUILDAH_ARGS[@]}" $container $IMAGE + + status=-1 + max_run=5 + sleep_sec=10 + for run in $(seq 1 $max_run); do + status=0 + [ "$run" -gt 1 ] && sleep $sleep_sec + echo "Pushing sbom image to registry" + buildah push \ + --tls-verify=$TLSVERIFY \ + --digestfile /var/workdir/image-digest $IMAGE \ + docker://$IMAGE && break || status=$? + done + if [ "$status" -ne 0 ]; then + echo "Failed to push sbom image to registry after ${max_run} tries" + exit 1 + fi + + cat "/var/workdir"/image-digest | tee $(results.IMAGE_DIGEST.path) + echo -n "$IMAGE" | tee $(results.IMAGE_URL.path) + securityContext: + capabilities: + add: + - SETFCAP + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + workingDir: /var/workdir + - args: + - attach + - sbom + - --sbom + - sbom-cyclonedx.json + - --type + - cyclonedx + - $(params.IMAGE) + image: quay.io/redhat-appstudio/cosign:v2.1.1@sha256:c883d6f8d39148f2cea71bff4622d196d89df3e510f36c140c097b932f0dd5d5 + name: upload-sbom + workingDir: /var/workdir + volumes: + - name: activation-key + secret: + optional: true + secretName: $(params.ACTIVATION_KEY) + - name: additional-secret + secret: + optional: true + secretName: $(params.ADDITIONAL_SECRET) + - name: etc-pki-entitlement + secret: + optional: true + secretName: $(params.ENTITLEMENT_SECRET) + - emptyDir: {} + name: shared + - configMap: + items: + - key: $(params.caTrustConfigMapKey) + path: ca-bundle.crt + name: $(params.caTrustConfigMapName) + optional: true + name: trusted-ca + - emptyDir: {} + name: varlibcontainers + - emptyDir: {} + name: workdir diff --git a/auto-generated/task/buildah/0.1/tekton.dev_v1_task_buildah.yaml b/auto-generated/task/buildah/0.1/tekton.dev_v1_task_buildah.yaml new file mode 100644 index 0000000000..87fdba4ee6 --- /dev/null +++ b/auto-generated/task/buildah/0.1/tekton.dev_v1_task_buildah.yaml @@ -0,0 +1,582 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + annotations: + build.appstudio.redhat.com/expires-on: "2024-11-13T00:00:00Z" + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: image-build, konflux + labels: + app.kubernetes.io/version: "0.1" + build.appstudio.redhat.com/build_type: docker + name: buildah +spec: + description: |- + Buildah task builds source code into a container image and pushes the image into container registry using buildah tool. + In addition it generates a SBOM file, injects the SBOM file into final container image and pushes the SBOM file as separate image using cosign tool. + When [Java dependency rebuild](https://redhat-appstudio.github.io/docs.stonesoup.io/Documentation/main/cli/proc_enabled_java_dependencies.html) is enabled it triggers rebuilds of Java artifacts. + When prefetch-dependencies task was activated it is using its artifacts to run build in hermetic environment. + params: + - description: Reference of the image buildah will produce. + name: IMAGE + type: string + - default: "" + description: Deprecated. Has no effect. Will be removed in the future. + name: BUILDER_IMAGE + type: string + - default: ./Dockerfile + description: Path to the Dockerfile to build. + name: DOCKERFILE + type: string + - default: . + description: Path to the directory to use as context. + name: CONTEXT + type: string + - default: "true" + description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS + registry) + name: TLSVERIFY + type: string + - default: "" + description: unused, should be removed in next task version + name: DOCKER_AUTH + type: string + - default: "false" + description: Determines if build will be executed without network access. + name: HERMETIC + type: string + - default: "" + description: In case it is not empty, the prefetched content should be made available + to the build. + name: PREFETCH_INPUT + type: string + - default: "" + description: Delete image tag after specified time. Empty means to keep the image + tag. Time values could be something like 1h, 2d, 3w for hours, days, and weeks, + respectively. + name: IMAGE_EXPIRES_AFTER + type: string + - default: "" + description: The image is built from this commit. + name: COMMIT_SHA + type: string + - default: repos.d + description: Path in the git repository in which yum repository files are stored + name: YUM_REPOS_D_SRC + - default: fetched.repos.d + description: Path in source workspace where dynamically-fetched repos are present + name: YUM_REPOS_D_FETCHED + - default: /etc/yum.repos.d + description: Target path on the container in which yum repository files should + be made available + name: YUM_REPOS_D_TARGET + - default: "" + description: Target stage in Dockerfile to build. If not specified, the Dockerfile + is processed entirely to (and including) its last stage. + name: TARGET_STAGE + type: string + - default: etc-pki-entitlement + description: Name of secret which contains the entitlement certificates + name: ENTITLEMENT_SECRET + type: string + - default: activation-key + description: Name of secret which contains subscription activation key + name: ACTIVATION_KEY + type: string + - default: does-not-exist + description: Name of a secret which will be made available to the build with 'buildah + build --secret' at /run/secrets/$ADDITIONAL_SECRET + name: ADDITIONAL_SECRET + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) + name: BUILD_ARGS + type: array + - default: "" + description: Path to a file with build arguments, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: BUILD_ARGS_FILE + type: string + - default: trusted-ca + description: The name of the ConfigMap to read CA bundle data from. + name: caTrustConfigMapName + type: string + - default: ca-bundle.crt + description: The name of the key in the ConfigMap that contains the CA bundle + data. + name: caTrustConfigMapKey + type: string + - default: "" + description: Comma separated list of extra capabilities to add when running 'buildah + build' + name: ADD_CAPABILITIES + type: string + - default: "false" + description: Squash all new and previous layers added as a part of this build, + as per --squash + name: SQUASH + type: string + - default: vfs + description: Storage driver to configure for buildah + name: STORAGE_DRIVER + type: string + - default: "true" + description: Whether to skip stages in Containerfile that seem unused by subsequent + stages + name: SKIP_UNUSED_STAGES + type: string + results: + - description: Digest of the image just built + name: IMAGE_DIGEST + - description: Image repository and tag where the built image was pushed + name: IMAGE_URL + - description: Digests of the base images used for build + name: BASE_IMAGES_DIGESTS + - description: The counting of Java components by publisher in JSON format + name: SBOM_JAVA_COMPONENTS_COUNT + type: string + - description: The Java dependencies that came from community sources such as Maven + central. + name: JAVA_COMMUNITY_DEPENDENCIES + stepTemplate: + env: + - name: BUILDAH_FORMAT + value: oci + - name: STORAGE_DRIVER + value: $(params.STORAGE_DRIVER) + - name: HERMETIC + value: $(params.HERMETIC) + - name: CONTEXT + value: $(params.CONTEXT) + - name: DOCKERFILE + value: $(params.DOCKERFILE) + - name: IMAGE + value: $(params.IMAGE) + - name: TLSVERIFY + value: $(params.TLSVERIFY) + - name: IMAGE_EXPIRES_AFTER + value: $(params.IMAGE_EXPIRES_AFTER) + - name: YUM_REPOS_D_SRC + value: $(params.YUM_REPOS_D_SRC) + - name: YUM_REPOS_D_FETCHED + value: $(params.YUM_REPOS_D_FETCHED) + - name: YUM_REPOS_D_TARGET + value: $(params.YUM_REPOS_D_TARGET) + - name: TARGET_STAGE + value: $(params.TARGET_STAGE) + - name: PARAM_BUILDER_IMAGE + value: $(params.BUILDER_IMAGE) + - name: ENTITLEMENT_SECRET + value: $(params.ENTITLEMENT_SECRET) + - name: ADDITIONAL_SECRET + value: $(params.ADDITIONAL_SECRET) + - name: BUILD_ARGS_FILE + value: $(params.BUILD_ARGS_FILE) + - name: ADD_CAPABILITIES + value: $(params.ADD_CAPABILITIES) + - name: SQUASH + value: $(params.SQUASH) + - name: SKIP_UNUSED_STAGES + value: $(params.SKIP_UNUSED_STAGES) + volumeMounts: + - mountPath: /shared + name: shared + steps: + - args: + - $(params.BUILD_ARGS[*]) + computeResources: + limits: + memory: 4Gi + requests: + cpu: 250m + memory: 512Mi + env: + - name: COMMIT_SHA + value: $(params.COMMIT_SHA) + image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: build + script: | + if [ -n "${PARAM_BUILDER_IMAGE}" ]; then + echo "WARNING: provided deprecated BUILDER_IMAGE parameter has no effect." + fi + + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + SOURCE_CODE_DIR=source + if [ -e "$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" + elif [ -e "$SOURCE_CODE_DIR/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$DOCKERFILE" + elif echo "$DOCKERFILE" | grep -q "^https\?://"; then + echo "Fetch Dockerfile from $DOCKERFILE" + dockerfile_path=$(mktemp --suffix=-Dockerfile) + http_code=$(curl -s -L -w "%{http_code}" --output "$dockerfile_path" "$DOCKERFILE") + if [ $http_code != 200 ]; then + echo "No Dockerfile is fetched. Server responds $http_code" + exit 1 + fi + http_code=$(curl -s -L -w "%{http_code}" --output "$dockerfile_path.dockerignore.tmp" "$DOCKERFILE.dockerignore") + if [ $http_code = 200 ]; then + echo "Fetched .dockerignore from $DOCKERFILE.dockerignore" + mv "$dockerfile_path.dockerignore.tmp" $SOURCE_CODE_DIR/$CONTEXT/.dockerignore + fi + else + echo "Cannot find Dockerfile $DOCKERFILE" + exit 1 + fi + if [ -n "$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR" ] && grep -q '^\s*RUN \(./\)\?mvn' "$dockerfile_path"; then + sed -i -e "s|^\s*RUN \(\(./\)\?mvn\)\(.*\)|RUN echo \"mirror.defaulthttp://$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR/v1/cache/default/0/*\" > /tmp/settings.yaml; \1 -s /tmp/settings.yaml \3|g" "$dockerfile_path" + touch /var/lib/containers/java + fi + + # Fixing group permission on /var/lib/containers + chown root:root /var/lib/containers + + sed -i 's/^\s*short-name-mode\s*=\s*.*/short-name-mode = "disabled"/' /etc/containers/registries.conf + + # Setting new namespace to run buildah - 2^32-2 + echo 'root:1:4294967294' | tee -a /etc/subuid >> /etc/subgid + + BUILDAH_ARGS=() + + BASE_IMAGES=$(grep -i '^\s*FROM' "$dockerfile_path" | sed 's/--platform=\S*//' | awk '{print $2}' | (grep -v ^oci-archive: || true)) + if [ "${HERMETIC}" == "true" ]; then + BUILDAH_ARGS+=("--pull=never") + UNSHARE_ARGS="--net" + for image in $BASE_IMAGES; do + if [ "${image}" != "scratch" ]; then + unshare -Ufp --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -- buildah pull $image + fi + done + echo "Build will be executed with network isolation" + fi + + if [ -n "${TARGET_STAGE}" ]; then + BUILDAH_ARGS+=("--target=${TARGET_STAGE}") + fi + + if [ -n "${BUILD_ARGS_FILE}" ]; then + BUILDAH_ARGS+=("--build-arg-file=$(pwd)/$SOURCE_CODE_DIR/${BUILD_ARGS_FILE}") + fi + + for build_arg in "$@"; do + BUILDAH_ARGS+=("--build-arg=$build_arg") + done + + if [ -n "${ADD_CAPABILITIES}" ]; then + BUILDAH_ARGS+=("--cap-add=${ADD_CAPABILITIES}") + fi + + if [ "${SQUASH}" == "true" ]; then + BUILDAH_ARGS+=("--squash") + fi + + if [ "${SKIP_UNUSED_STAGES}" != "true" ] ; then + BUILDAH_ARGS+=("--skip-unused-stages=false") + fi + + if [ -f "$(workspaces.source.path)/cachi2/cachi2.env" ]; then + cp -r "$(workspaces.source.path)/cachi2" /tmp/ + chmod -R go+rwX /tmp/cachi2 + VOLUME_MOUNTS="--volume /tmp/cachi2:/cachi2" + # Read in the whole file (https://unix.stackexchange.com/questions/533277), then + # for each RUN ... line insert the cachi2.env command *after* any options like --mount + sed -E -i \ + -e 'H;1h;$!d;x' \ + -e 's@^\s*(run((\s|\\\n)+-\S+)*(\s|\\\n)+)@\1. /cachi2/cachi2.env \&\& \\\n @igM' \ + "$dockerfile_path" + echo "Prefetched content will be made available" + + prefetched_repo_for_my_arch="/tmp/cachi2/output/deps/rpm/$(uname -m)/repos.d/cachi2.repo" + if [ -f "$prefetched_repo_for_my_arch" ]; then + echo "Adding $prefetched_repo_for_my_arch to $YUM_REPOS_D_FETCHED" + mkdir -p "$YUM_REPOS_D_FETCHED" + cp --no-clobber "$prefetched_repo_for_my_arch" "$YUM_REPOS_D_FETCHED" + fi + fi + + # if yum repofiles stored in git, copy them to mount point outside the source dir + if [ -d "${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}" ]; then + mkdir -p ${YUM_REPOS_D_FETCHED} + cp -r ${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}/* ${YUM_REPOS_D_FETCHED} + fi + + # if anything in the repofiles mount point (either fetched or from git), mount it + if [ -d "${YUM_REPOS_D_FETCHED}" ]; then + chmod -R go+rwX ${YUM_REPOS_D_FETCHED} + mount_point=$(realpath ${YUM_REPOS_D_FETCHED}) + VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume ${mount_point}:${YUM_REPOS_D_TARGET}" + fi + + LABELS=( + "--label" "build-date=$(date -u +'%Y-%m-%dT%H:%M:%S')" + "--label" "architecture=$(uname -m)" + "--label" "vcs-type=git" + ) + [ -n "$COMMIT_SHA" ] && LABELS+=("--label" "vcs-ref=$COMMIT_SHA") + [ -n "$IMAGE_EXPIRES_AFTER" ] && LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + + ACTIVATION_KEY_PATH="/activation-key" + ENTITLEMENT_PATH="/entitlement" + + if [ -e /activation-key/org ]; then + cp -r --preserve=mode "$ACTIVATION_KEY_PATH" /tmp/activation-key + mkdir /shared/rhsm-tmp + VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume /tmp/activation-key:/activation-key -v /shared/rhsm-tmp:/etc/pki/entitlement:Z" + echo "Adding activation key to the build" + + elif find /entitlement -name "*.pem" >> null; then + cp -r --preserve=mode "$ENTITLEMENT_PATH" /tmp/entitlement + VOLUME_MOUNTS="${VOLUME_MOUNTS} --volume /tmp/entitlement:/etc/pki/entitlement" + echo "Adding the entitlement to the build" + fi + + ADDITIONAL_SECRET_PATH="/additional-secret" + ADDITIONAL_SECRET_TMP="/tmp/additional-secret" + if [ -d "$ADDITIONAL_SECRET_PATH" ]; then + cp -r --preserve=mode -L "$ADDITIONAL_SECRET_PATH" $ADDITIONAL_SECRET_TMP + while read -r filename; do + echo "Adding the secret ${ADDITIONAL_SECRET}/${filename} to the build, available at /run/secrets/${ADDITIONAL_SECRET}/${filename}" + BUILDAH_ARGS+=("--secret=id=${ADDITIONAL_SECRET}/${filename},src=$ADDITIONAL_SECRET_TMP/${filename}") + done < <(find $ADDITIONAL_SECRET_TMP -maxdepth 1 -type f -exec basename {} \;) + fi + + unshare -Uf $UNSHARE_ARGS --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -w ${SOURCE_CODE_DIR}/$CONTEXT -- buildah build \ + $VOLUME_MOUNTS \ + "${BUILDAH_ARGS[@]}" \ + "${LABELS[@]}" \ + --tls-verify=$TLSVERIFY --no-cache \ + --ulimit nofile=4096:4096 \ + -f "$dockerfile_path" -t $IMAGE . + + container=$(buildah from --pull-never $IMAGE) + buildah mount $container | tee /shared/container_path + # delete symlinks - they may point outside the container rootfs, messing with SBOM scanners + find $(cat /shared/container_path) -xtype l -delete + echo $container > /shared/container_name + + # Save the SBOM produced by Cachi2 so it can be merged into the final SBOM later + if [ -f "/tmp/cachi2/output/bom.json" ]; then + cp /tmp/cachi2/output/bom.json ./sbom-cachi2.json + fi + + # Expose base image digests + touch $(results.BASE_IMAGES_DIGESTS.path) + for image in $BASE_IMAGES; do + if [ "${image}" != "scratch" ]; then + buildah images --format '{{ .Name }}:{{ .Tag }}@{{ .Digest }}' --filter reference="$image" >> $(results.BASE_IMAGES_DIGESTS.path) + fi + done + + # Needed to generate base images SBOM + echo "$BASE_IMAGES" > $(workspaces.source.path)/base_images_from_dockerfile + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /entitlement + name: etc-pki-entitlement + - mountPath: /activation-key + name: activation-key + - mountPath: /additional-secret + name: additional-secret + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + - image: registry.access.redhat.com/rh-syft-tech-preview/syft-rhel9:1.4.1@sha256:34d7065427085a31dc4949bd283c001b91794d427e1e4cdf1b21ea4faf9fee3f + name: sbom-syft-generate + script: | + echo "Running syft on the source directory" + syft dir:$(workspaces.source.path)/source --output cyclonedx-json=$(workspaces.source.path)/sbom-source.json + echo "Running syft on the image filesystem" + syft dir:$(cat /shared/container_path) --output cyclonedx-json=$(workspaces.source.path)/sbom-image.json + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + workingDir: $(workspaces.source.path)/source + - image: quay.io/redhat-appstudio/hacbs-jvm-build-request-processor:127ee0c223a2b56a9bd20a6f2eaeed3bd6015f77 + name: analyse-dependencies-java-sbom + script: | + if [ -f /var/lib/containers/java ]; then + /opt/jboss/container/java/run/run-java.sh analyse-dependencies path $(cat /shared/container_path) -s $(workspaces.source.path)/sbom-image.json --task-run-name $(context.taskRun.name) --publishers $(results.SBOM_JAVA_COMPONENTS_COUNT.path) + sed -i 's/^/ /' $(results.SBOM_JAVA_COMPONENTS_COUNT.path) # Workaround for SRVKP-2875 + else + touch $(results.JAVA_COMMUNITY_DEPENDENCIES.path) + fi + securityContext: + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + - image: registry.access.redhat.com/ubi9/python-39:9.5-1734610342@sha256:dde5068ba8fd81eef41a9128ddad2b99e2e02e5869ffe925c605b609a0ad7bbb + name: merge-syft-sboms + script: | + #!/bin/python3 + import json + + # load SBOMs + with open("./sbom-image.json") as f: + image_sbom = json.load(f) + + with open("./sbom-source.json") as f: + source_sbom = json.load(f) + + # fetch unique components from available SBOMs + def get_identifier(component): + return component["name"] + '@' + component.get("version", "") + + image_sbom_components = image_sbom.setdefault("components", []) + existing_components = [get_identifier(component) for component in image_sbom_components] + + source_sbom_components = source_sbom.get("components", []) + for component in source_sbom_components: + if get_identifier(component) not in existing_components: + image_sbom_components.append(component) + existing_components.append(get_identifier(component)) + + image_sbom_components.sort(key=lambda c: get_identifier(c)) + + # write the CycloneDX unified SBOM + with open("./sbom-cyclonedx.json", "w") as f: + json.dump(image_sbom, f, indent=4) + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - image: quay.io/redhat-appstudio/cachi2:0.16.0@sha256:55415cd8ded149f5d56d3fca46d93125b86b41e07ae5d3c03caa240b7b93b7d8 + name: merge-cachi2-sbom + script: | + if [ -f "sbom-cachi2.json" ]; then + echo "Merging contents of sbom-cachi2.json into sbom-cyclonedx.json" + merge_syft_sbom sbom-cachi2.json sbom-cyclonedx.json > sbom-temp.json + mv sbom-temp.json sbom-cyclonedx.json + else + echo "Skipping step since no Cachi2 SBOM was produced" + fi + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - image: registry.access.redhat.com/ubi9/python-39:9.5-1734610342@sha256:dde5068ba8fd81eef41a9128ddad2b99e2e02e5869ffe925c605b609a0ad7bbb + name: create-purl-sbom + script: | + #!/bin/python3 + import json + + with open("./sbom-cyclonedx.json") as f: + cyclonedx_sbom = json.load(f) + + purls = [{"purl": component["purl"]} for component in cyclonedx_sbom.get("components", []) if "purl" in component] + purl_content = {"image_contents": {"dependencies": purls}} + + with open("sbom-purl.json", "w") as output_file: + json.dump(purl_content, output_file, indent=4) + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - env: + - name: BASE_IMAGES_DIGESTS_PATH + value: $(results.BASE_IMAGES_DIGESTS.path) + image: quay.io/redhat-appstudio/base-images-sbom-script@sha256:667669e3def018f9dbb8eaf8868887a40bc07842221e9a98f6787edcff021840 + name: create-base-images-sbom + script: | + python3 /app/base_images_sbom_script.py --sbom=sbom-cyclonedx.json --base-images-from-dockerfile=base_images_from_dockerfile --base-images-digests=$BASE_IMAGES_DIGESTS_PATH + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - computeResources: {} + image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: inject-sbom-and-push + script: | + if [ -n "${PARAM_BUILDER_IMAGE}" ]; then + echo "WARNING: provided deprecated BUILDER_IMAGE parameter has no effect." + fi + + base_image_name=$(buildah inspect --format '{{ index .ImageAnnotations "org.opencontainers.image.base.name"}}' $IMAGE | cut -f1 -d'@') + base_image_digest=$(buildah inspect --format '{{ index .ImageAnnotations "org.opencontainers.image.base.digest"}}' $IMAGE) + container=$(buildah from --pull-never $IMAGE) + buildah copy $container sbom-cyclonedx.json sbom-purl.json /root/buildinfo/content_manifests/ + buildah config -a org.opencontainers.image.base.name=${base_image_name} -a org.opencontainers.image.base.digest=${base_image_digest} $container + + BUILDAH_ARGS=() + if [ "${SQUASH}" == "true" ]; then + BUILDAH_ARGS+=("--squash") + fi + + buildah commit "${BUILDAH_ARGS[@]}" $container $IMAGE + + status=-1 + max_run=5 + sleep_sec=10 + for run in $(seq 1 $max_run); do + status=0 + [ "$run" -gt 1 ] && sleep $sleep_sec + echo "Pushing sbom image to registry" + buildah push \ + --tls-verify=$TLSVERIFY \ + --digestfile $(workspaces.source.path)/image-digest $IMAGE \ + docker://$IMAGE && break || status=$? + done + if [ "$status" -ne 0 ]; then + echo "Failed to push sbom image to registry after ${max_run} tries" + exit 1 + fi + + cat "$(workspaces.source.path)"/image-digest | tee $(results.IMAGE_DIGEST.path) + echo -n "$IMAGE" | tee $(results.IMAGE_URL.path) + securityContext: + capabilities: + add: + - SETFCAP + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + workingDir: $(workspaces.source.path) + - args: + - attach + - sbom + - --sbom + - sbom-cyclonedx.json + - --type + - cyclonedx + - $(params.IMAGE) + image: quay.io/redhat-appstudio/cosign:v2.1.1@sha256:c883d6f8d39148f2cea71bff4622d196d89df3e510f36c140c097b932f0dd5d5 + name: upload-sbom + workingDir: $(workspaces.source.path) + volumes: + - emptyDir: {} + name: varlibcontainers + - emptyDir: {} + name: shared + - name: etc-pki-entitlement + secret: + optional: true + secretName: $(params.ENTITLEMENT_SECRET) + - name: activation-key + secret: + optional: true + secretName: $(params.ACTIVATION_KEY) + - name: additional-secret + secret: + optional: true + secretName: $(params.ADDITIONAL_SECRET) + - configMap: + items: + - key: $(params.caTrustConfigMapKey) + path: ca-bundle.crt + name: $(params.caTrustConfigMapName) + optional: true + name: trusted-ca + workspaces: + - description: Workspace containing the source code to build. + name: source diff --git a/auto-generated/task/buildah/0.2/tekton.dev_v1_task_buildah.yaml b/auto-generated/task/buildah/0.2/tekton.dev_v1_task_buildah.yaml new file mode 100644 index 0000000000..4e4fb22c5a --- /dev/null +++ b/auto-generated/task/buildah/0.2/tekton.dev_v1_task_buildah.yaml @@ -0,0 +1,718 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + annotations: + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: image-build, konflux + labels: + app.kubernetes.io/version: 0.2.1 + build.appstudio.redhat.com/build_type: docker + name: buildah +spec: + description: |- + Buildah task builds source code into a container image and pushes the image into container registry using buildah tool. + In addition it generates a SBOM file, injects the SBOM file into final container image and pushes the SBOM file as separate image using cosign tool. + When [Java dependency rebuild](https://redhat-appstudio.github.io/docs.stonesoup.io/Documentation/main/cli/proc_enabled_java_dependencies.html) is enabled it triggers rebuilds of Java artifacts. + When prefetch-dependencies task was activated it is using its artifacts to run build in hermetic environment. + params: + - description: Reference of the image buildah will produce. + name: IMAGE + type: string + - default: ./Dockerfile + description: Path to the Dockerfile to build. + name: DOCKERFILE + type: string + - default: . + description: Path to the directory to use as context. + name: CONTEXT + type: string + - default: "true" + description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS + registry) + name: TLSVERIFY + type: string + - default: "false" + description: Determines if build will be executed without network access. + name: HERMETIC + type: string + - default: "" + description: In case it is not empty, the prefetched content should be made available + to the build. + name: PREFETCH_INPUT + type: string + - default: "" + description: Delete image tag after specified time. Empty means to keep the image + tag. Time values could be something like 1h, 2d, 3w for hours, days, and weeks, + respectively. + name: IMAGE_EXPIRES_AFTER + type: string + - default: "" + description: The image is built from this commit. + name: COMMIT_SHA + type: string + - default: repos.d + description: Path in the git repository in which yum repository files are stored + name: YUM_REPOS_D_SRC + - default: fetched.repos.d + description: Path in source workspace where dynamically-fetched repos are present + name: YUM_REPOS_D_FETCHED + - default: /etc/yum.repos.d + description: Target path on the container in which yum repository files should + be made available + name: YUM_REPOS_D_TARGET + - default: "" + description: Target stage in Dockerfile to build. If not specified, the Dockerfile + is processed entirely to (and including) its last stage. + name: TARGET_STAGE + type: string + - default: etc-pki-entitlement + description: Name of secret which contains the entitlement certificates + name: ENTITLEMENT_SECRET + type: string + - default: activation-key + description: Name of secret which contains subscription activation key + name: ACTIVATION_KEY + type: string + - default: does-not-exist + description: Name of a secret which will be made available to the build with 'buildah + build --secret' at /run/secrets/$ADDITIONAL_SECRET + name: ADDITIONAL_SECRET + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) + name: BUILD_ARGS + type: array + - default: "" + description: Path to a file with build arguments, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: BUILD_ARGS_FILE + type: string + - default: trusted-ca + description: The name of the ConfigMap to read CA bundle data from. + name: caTrustConfigMapName + type: string + - default: ca-bundle.crt + description: The name of the key in the ConfigMap that contains the CA bundle + data. + name: caTrustConfigMapKey + type: string + - default: "" + description: Comma separated list of extra capabilities to add when running 'buildah + build' + name: ADD_CAPABILITIES + type: string + - default: "false" + description: Squash all new and previous layers added as a part of this build, + as per --squash + name: SQUASH + type: string + - default: vfs + description: Storage driver to configure for buildah + name: STORAGE_DRIVER + type: string + - default: "true" + description: Whether to skip stages in Containerfile that seem unused by subsequent + stages + name: SKIP_UNUSED_STAGES + type: string + - default: [] + description: Additional key=value labels that should be applied to the image + name: LABELS + type: array + - default: "false" + description: Whether to enable privileged mode + name: PRIVILEGED_NESTED + type: string + results: + - description: Digest of the image just built + name: IMAGE_DIGEST + - description: Image repository and tag where the built image was pushed + name: IMAGE_URL + - description: Image reference of the built image + name: IMAGE_REF + - description: Reference of SBOM blob digest to enable digest-based verification + from provenance + name: SBOM_BLOB_URL + type: string + - description: The counting of Java components by publisher in JSON format + name: SBOM_JAVA_COMPONENTS_COUNT + type: string + - description: The Java dependencies that came from community sources such as Maven + central. + name: JAVA_COMMUNITY_DEPENDENCIES + stepTemplate: + computeResources: + limits: + cpu: "4" + memory: 4Gi + requests: + cpu: "1" + memory: 1Gi + env: + - name: BUILDAH_FORMAT + value: oci + - name: STORAGE_DRIVER + value: $(params.STORAGE_DRIVER) + - name: HERMETIC + value: $(params.HERMETIC) + - name: SOURCE_CODE_DIR + value: source + - name: CONTEXT + value: $(params.CONTEXT) + - name: IMAGE + value: $(params.IMAGE) + - name: TLSVERIFY + value: $(params.TLSVERIFY) + - name: IMAGE_EXPIRES_AFTER + value: $(params.IMAGE_EXPIRES_AFTER) + - name: YUM_REPOS_D_SRC + value: $(params.YUM_REPOS_D_SRC) + - name: YUM_REPOS_D_FETCHED + value: $(params.YUM_REPOS_D_FETCHED) + - name: YUM_REPOS_D_TARGET + value: $(params.YUM_REPOS_D_TARGET) + - name: TARGET_STAGE + value: $(params.TARGET_STAGE) + - name: ENTITLEMENT_SECRET + value: $(params.ENTITLEMENT_SECRET) + - name: ACTIVATION_KEY + value: $(params.ACTIVATION_KEY) + - name: ADDITIONAL_SECRET + value: $(params.ADDITIONAL_SECRET) + - name: BUILD_ARGS_FILE + value: $(params.BUILD_ARGS_FILE) + - name: ADD_CAPABILITIES + value: $(params.ADD_CAPABILITIES) + - name: SQUASH + value: $(params.SQUASH) + - name: SKIP_UNUSED_STAGES + value: $(params.SKIP_UNUSED_STAGES) + - name: PRIVILEGED_NESTED + value: $(params.PRIVILEGED_NESTED) + volumeMounts: + - mountPath: /shared + name: shared + steps: + - args: + - --build-args + - $(params.BUILD_ARGS[*]) + - --labels + - $(params.LABELS[*]) + computeResources: + limits: + cpu: "4" + memory: 8Gi + requests: + cpu: "1" + memory: 2Gi + env: + - name: COMMIT_SHA + value: $(params.COMMIT_SHA) + - name: DOCKERFILE + value: $(params.DOCKERFILE) + image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: build + script: | + #!/bin/bash + set -euo pipefail + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + if [ -e "$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" + elif [ -e "$SOURCE_CODE_DIR/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$DOCKERFILE" + elif [ -e "$DOCKERFILE" ]; then + # Instrumented builds (SAST) use this custom dockerffile step as their base + dockerfile_path="$DOCKERFILE" + elif echo "$DOCKERFILE" | grep -q "^https\?://"; then + echo "Fetch Dockerfile from $DOCKERFILE" + dockerfile_path=$(mktemp --suffix=-Dockerfile) + http_code=$(curl -s -S -L -w "%{http_code}" --output "$dockerfile_path" "$DOCKERFILE") + if [ $http_code != 200 ]; then + echo "No Dockerfile is fetched. Server responds $http_code" + exit 1 + fi + http_code=$(curl -s -S -L -w "%{http_code}" --output "$dockerfile_path.dockerignore.tmp" "$DOCKERFILE.dockerignore") + if [ $http_code = 200 ]; then + echo "Fetched .dockerignore from $DOCKERFILE.dockerignore" + mv "$dockerfile_path.dockerignore.tmp" $SOURCE_CODE_DIR/$CONTEXT/.dockerignore + fi + else + echo "Cannot find Dockerfile $DOCKERFILE" + exit 1 + fi + + dockerfile_copy=$(mktemp --tmpdir "$(basename "$dockerfile_path").XXXXXX") + cp "$dockerfile_path" "$dockerfile_copy" + + if [ -n "${JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR-}" ] && grep -q '^\s*RUN \(./\)\?mvn' "$dockerfile_copy"; then + sed -i -e "s|^\s*RUN \(\(./\)\?mvn\)\(.*\)|RUN echo \"mirror.defaulthttp://$JVM_BUILD_WORKSPACE_ARTIFACT_CACHE_PORT_80_TCP_ADDR/v1/cache/default/0/*\" > /tmp/settings.yaml; \1 -s /tmp/settings.yaml \3|g" "$dockerfile_copy" + touch /var/lib/containers/java + fi + + # Fixing group permission on /var/lib/containers + chown root:root /var/lib/containers + + sed -i 's/^\s*short-name-mode\s*=\s*.*/short-name-mode = "disabled"/' /etc/containers/registries.conf + + # Setting new namespace to run buildah - 2^32-2 + echo 'root:1:4294967294' | tee -a /etc/subuid >> /etc/subgid + + build_args=() + if [ -n "${BUILD_ARGS_FILE}" ]; then + # Parse BUILD_ARGS_FILE ourselves because dockerfile-json doesn't support it + echo "Parsing ARGs from $BUILD_ARGS_FILE" + mapfile -t build_args < <( + # https://www.mankier.com/1/buildah-build#--build-arg-file + # delete lines that start with # + # delete blank lines + sed -e '/^#/d' -e '/^\s*$/d' "${SOURCE_CODE_DIR}/${BUILD_ARGS_FILE}" + ) + fi + + LABELS=() + # Split `args` into two sets of arguments. + while [[ $# -gt 0 ]]; do + case $1 in + --build-args) + shift + # Note: this may result in multiple --build-arg=KEY=value flags with the same KEY being + # passed to buildah. In that case, the *last* occurrence takes precedence. This is why + # we append BUILD_ARGS after the content of the BUILD_ARGS_FILE + while [[ $# -gt 0 && $1 != --* ]]; do build_args+=("$1"); shift; done + ;; + --labels) + shift + while [[ $# -gt 0 && $1 != --* ]]; do LABELS+=("--label" "$1"); shift; done + ;; + *) + echo "unexpected argument: $1" >&2 + exit 2 + ;; + esac + done + + BUILD_ARG_FLAGS=() + for build_arg in "${build_args[@]}"; do + BUILD_ARG_FLAGS+=("--build-arg=$build_arg") + done + + dockerfile-json "${BUILD_ARG_FLAGS[@]}" "$dockerfile_copy" > /shared/parsed_dockerfile.json + BASE_IMAGES=$( + jq -r '.Stages[] | select(.From | .Stage or .Scratch | not) | .BaseName | select(test("^oci-archive:") | not)' /shared/parsed_dockerfile.json + ) + + BUILDAH_ARGS=() + UNSHARE_ARGS=() + + if [ "${HERMETIC}" == "true" ]; then + BUILDAH_ARGS+=("--pull=never") + UNSHARE_ARGS+=("--net") + + for image in $BASE_IMAGES; do + unshare -Ufp --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -- buildah pull $image + done + echo "Build will be executed with network isolation" + fi + + if [ -n "${TARGET_STAGE}" ]; then + BUILDAH_ARGS+=("--target=${TARGET_STAGE}") + fi + + BUILDAH_ARGS+=("${BUILD_ARG_FLAGS[@]}") + + if [ "${PRIVILEGED_NESTED}" == "true" ]; then + BUILDAH_ARGS+=("--security-opt=label=disable") + BUILDAH_ARGS+=("--cap-add=all") + BUILDAH_ARGS+=("--device=/dev/fuse") + fi + + if [ -n "${ADD_CAPABILITIES}" ]; then + BUILDAH_ARGS+=("--cap-add=${ADD_CAPABILITIES}") + fi + + if [ "${SQUASH}" == "true" ]; then + BUILDAH_ARGS+=("--squash") + fi + + if [ "${SKIP_UNUSED_STAGES}" != "true" ] ; then + BUILDAH_ARGS+=("--skip-unused-stages=false") + fi + + VOLUME_MOUNTS=() + + if [ -f "$(workspaces.source.path)/cachi2/cachi2.env" ]; then + cp -r "$(workspaces.source.path)/cachi2" /tmp/ + chmod -R go+rwX /tmp/cachi2 + VOLUME_MOUNTS+=(--volume /tmp/cachi2:/cachi2) + # Read in the whole file (https://unix.stackexchange.com/questions/533277), then + # for each RUN ... line insert the cachi2.env command *after* any options like --mount + sed -E -i \ + -e 'H;1h;$!d;x' \ + -e 's@^\s*(run((\s|\\\n)+-\S+)*(\s|\\\n)+)@\1. /cachi2/cachi2.env \&\& \\\n @igM' \ + "$dockerfile_copy" + echo "Prefetched content will be made available" + + prefetched_repo_for_my_arch="/tmp/cachi2/output/deps/rpm/$(uname -m)/repos.d/cachi2.repo" + if [ -f "$prefetched_repo_for_my_arch" ]; then + echo "Adding $prefetched_repo_for_my_arch to $YUM_REPOS_D_FETCHED" + mkdir -p "$YUM_REPOS_D_FETCHED" + cp --no-clobber "$prefetched_repo_for_my_arch" "$YUM_REPOS_D_FETCHED" + fi + fi + + # if yum repofiles stored in git, copy them to mount point outside the source dir + if [ -d "${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}" ]; then + mkdir -p ${YUM_REPOS_D_FETCHED} + cp -r ${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}/* ${YUM_REPOS_D_FETCHED} + fi + + # if anything in the repofiles mount point (either fetched or from git), mount it + if [ -d "${YUM_REPOS_D_FETCHED}" ]; then + chmod -R go+rwX ${YUM_REPOS_D_FETCHED} + mount_point=$(realpath ${YUM_REPOS_D_FETCHED}) + VOLUME_MOUNTS+=(--volume "${mount_point}:${YUM_REPOS_D_TARGET}") + fi + + DEFAULT_LABELS=( + "--label" "build-date=$(date -u +'%Y-%m-%dT%H:%M:%S')" + "--label" "architecture=$(uname -m)" + "--label" "vcs-type=git" + ) + [ -n "$COMMIT_SHA" ] && DEFAULT_LABELS+=("--label" "vcs-ref=$COMMIT_SHA") + [ -n "$IMAGE_EXPIRES_AFTER" ] && DEFAULT_LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + + # Concatenate defaults and explicit labels. If a label appears twice, the last one wins. + LABELS=("${DEFAULT_LABELS[@]}" "${LABELS[@]}") + + ACTIVATION_KEY_PATH="/activation-key" + ENTITLEMENT_PATH="/entitlement" + + # 0. if hermetic=true, skip all subscription related stuff + # 1. do not enable activation key and entitlement at same time. If both vars are provided, prefer activation key. + # 2. Activation-keys will be used when the key 'org' exists in the activation key secret. + # 3. try to pre-register and mount files to the correct location so that users do no need to modify Dockerfiles. + # 3. If the Dockerfile contains the string "subcription-manager register", add the activation-keys volume + # to buildah but don't pre-register for backwards compatibility. Mount an empty directory on + # shared emptydir volume to "/etc/pki/entitlement" to prevent certificates from being included + + if [ "${HERMETIC}" != "true" ] && [ -e /activation-key/org ]; then + cp -r --preserve=mode "$ACTIVATION_KEY_PATH" /tmp/activation-key + mkdir -p /shared/rhsm/etc/pki/entitlement + mkdir -p /shared/rhsm/etc/pki/consumer + + VOLUME_MOUNTS+=(-v /tmp/activation-key:/activation-key \ + -v /shared/rhsm/etc/pki/entitlement:/etc/pki/entitlement:Z \ + -v /shared/rhsm/etc/pki/consumer:/etc/pki/consumer:Z) + echo "Adding activation key to the build" + + if ! grep -E "^[^#]*subscription-manager.[^#]*register" "$dockerfile_path"; then + # user is not running registration in the Containerfile: pre-register. + echo "Pre-registering with subscription manager." + subscription-manager register --org "$(cat /tmp/activation-key/org)" --activationkey "$(cat /tmp/activation-key/activationkey)" + trap 'subscription-manager unregister || true' EXIT + + # copy generated certificates to /shared volume + cp /etc/pki/entitlement/*.pem /shared/rhsm/etc/pki/entitlement + cp /etc/pki/consumer/*.pem /shared/rhsm/etc/pki/consumer + + # and then mount get /etc/rhsm/ca/redhat-uep.pem into /run/secrets/rhsm/ca + VOLUME_MOUNTS+=(--volume /etc/rhsm/ca/redhat-uep.pem:/etc/rhsm/ca/redhat-uep.pem:Z) + fi + + elif [ "${HERMETIC}" != "true" ] && find /entitlement -name "*.pem" >> null; then + cp -r --preserve=mode "$ENTITLEMENT_PATH" /tmp/entitlement + VOLUME_MOUNTS+=(--volume /tmp/entitlement:/etc/pki/entitlement) + echo "Adding the entitlement to the build" + fi + + if [ -n "${ADDITIONAL_VOLUME_MOUNTS-}" ]; then + # ADDITIONAL_VOLUME_MOUNTS allows to specify more volumes for the build. + # Instrumented builds (SAST) use this step as their base and add some other tools. + while read -r volume_mount; do + VOLUME_MOUNTS+=("--volume=$volume_mount") + done <<< "$ADDITIONAL_VOLUME_MOUNTS" + fi + + ADDITIONAL_SECRET_PATH="/additional-secret" + ADDITIONAL_SECRET_TMP="/tmp/additional-secret" + if [ -d "$ADDITIONAL_SECRET_PATH" ]; then + cp -r --preserve=mode -L "$ADDITIONAL_SECRET_PATH" $ADDITIONAL_SECRET_TMP + while read -r filename; do + echo "Adding the secret ${ADDITIONAL_SECRET}/${filename} to the build, available at /run/secrets/${ADDITIONAL_SECRET}/${filename}" + BUILDAH_ARGS+=("--secret=id=${ADDITIONAL_SECRET}/${filename},src=$ADDITIONAL_SECRET_TMP/${filename}") + done < <(find $ADDITIONAL_SECRET_TMP -maxdepth 1 -type f -exec basename {} \;) + fi + + # Prevent ShellCheck from giving a warning because 'image' is defined and 'IMAGE' is not. + declare IMAGE + + buildah_cmd_array=( + buildah build + "${VOLUME_MOUNTS[@]}" + "${BUILDAH_ARGS[@]}" + "${LABELS[@]}" + --tls-verify="$TLSVERIFY" --no-cache + --ulimit nofile=4096:4096 + -f "$dockerfile_copy" -t "$IMAGE" . + ) + buildah_cmd=$(printf "%q " "${buildah_cmd_array[@]}") + + if [ "${HERMETIC}" == "true" ]; then + # enabling loopback adapter enables Bazel builds to work in hermetic mode. + command="ip link set lo up && $buildah_cmd" + else + command="$buildah_cmd" + fi + + # disable host subcription manager integration + find /usr/share/rhel/secrets -type l -exec unlink {} \; + + unshare -Uf "${UNSHARE_ARGS[@]}" --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -w "${SOURCE_CODE_DIR}/$CONTEXT" -- sh -c "$command" + + container=$(buildah from --pull-never "$IMAGE") + + # Save the SBOM produced by Cachi2 so it can be merged into the final SBOM later + if [ -f "/tmp/cachi2/output/bom.json" ]; then + echo "Making copy of sbom-cachi2.json" + cp /tmp/cachi2/output/bom.json ./sbom-cachi2.json + fi + + buildah mount $container | tee /shared/container_path + # delete symlinks - they may point outside the container rootfs, messing with SBOM scanners + find $(cat /shared/container_path) -xtype l -delete + echo $container > /shared/container_name + + touch /shared/base_images_digests + for image in $BASE_IMAGES; do + base_image_digest=$(buildah images --format '{{ .Name }}:{{ .Tag }}@{{ .Digest }}' --filter reference="$image") + # In some cases, there might be BASE_IMAGES, but not any associated digest. This happens + # if buildah did not use that particular image during build because it was skipped + if [ -n "$base_image_digest" ]; then + echo "$image $base_image_digest" >> /shared/base_images_digests + fi + done + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /entitlement + name: etc-pki-entitlement + - mountPath: /activation-key + name: activation-key + - mountPath: /additional-secret + name: additional-secret + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + - image: quay.io/konflux-ci/icm-injection-scripts:latest@sha256:462980e94ba689b5f56c3d5dfb3358cd8c685300daf65a71532f11898935e7f1 + name: icm + script: | + #!/bin/bash + set -euo pipefail + /scripts/inject-icm.sh "$IMAGE" + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + workingDir: $(workspaces.source.path) + - image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: push + script: | + #!/bin/bash + set -e + + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + retries=5 + # Push to a unique tag based on the TaskRun name to avoid race conditions + echo "Pushing to ${IMAGE%:*}:${TASKRUN_NAME}" + if ! buildah push \ + --retry "$retries" \ + --tls-verify="$TLSVERIFY" \ + "$IMAGE" \ + "docker://${IMAGE%:*}:$(context.taskRun.name)"; + then + echo "Failed to push sbom image to ${IMAGE%:*}:$(context.taskRun.name) after ${retries} tries" + exit 1 + fi + + # Push to a tag based on the git revision + echo "Pushing to ${IMAGE}" + if ! buildah push \ + --retry "$retries" \ + --tls-verify="$TLSVERIFY" \ + --digestfile "$(workspaces.source.path)/image-digest" "$IMAGE" \ + "docker://$IMAGE"; + then + echo "Failed to push sbom image to $IMAGE after ${retries} tries" + exit 1 + fi + + cat "$(workspaces.source.path)"/image-digest | tee $(results.IMAGE_DIGEST.path) + echo -n "$IMAGE" | tee $(results.IMAGE_URL.path) + { + echo -n "${IMAGE}@" + cat "$(workspaces.source.path)/image-digest" + } > "$(results.IMAGE_REF.path)" + securityContext: + capabilities: + add: + - SETFCAP + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + - image: registry.access.redhat.com/rh-syft-tech-preview/syft-rhel9:1.4.1@sha256:34d7065427085a31dc4949bd283c001b91794d427e1e4cdf1b21ea4faf9fee3f + name: sbom-syft-generate + script: | + echo "Running syft on the source directory" + syft dir:"$(workspaces.source.path)/$SOURCE_CODE_DIR/$CONTEXT" --output cyclonedx-json="$(workspaces.source.path)/sbom-source.json" + echo "Running syft on the image filesystem" + syft dir:"$(cat /shared/container_path)" --output cyclonedx-json="$(workspaces.source.path)/sbom-image.json" + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + workingDir: $(workspaces.source.path)/source + - computeResources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + image: quay.io/redhat-appstudio/hacbs-jvm-build-request-processor:127ee0c223a2b56a9bd20a6f2eaeed3bd6015f77 + name: analyse-dependencies-java-sbom + script: | + if [ -f /var/lib/containers/java ]; then + /opt/jboss/container/java/run/run-java.sh analyse-dependencies path $(cat /shared/container_path) -s $(workspaces.source.path)/sbom-image.json --task-run-name $(context.taskRun.name) --publishers $(results.SBOM_JAVA_COMPONENTS_COUNT.path) + sed -i 's/^/ /' $(results.SBOM_JAVA_COMPONENTS_COUNT.path) # Workaround for SRVKP-2875 + else + touch $(results.JAVA_COMMUNITY_DEPENDENCIES.path) + fi + securityContext: + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + - computeResources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + image: quay.io/redhat-appstudio/sbom-utility-scripts-image@sha256:9f1fd11d9c3c517ecc112d192ad361d16ecf6ce00b83b109c93cf3d1c644a357 + name: prepare-sboms + script: | + echo "Merging contents of sbom-source.json and sbom-image.json into sbom-cyclonedx.json" + python3 /scripts/merge_syft_sboms.py + + if [ -f "sbom-cachi2.json" ]; then + echo "Merging contents of sbom-cachi2.json into sbom-cyclonedx.json" + python3 /scripts/merge_cachi2_sboms.py sbom-cachi2.json sbom-cyclonedx.json > sbom-temp.json + mv sbom-temp.json sbom-cyclonedx.json + fi + + echo "Adding base images data to sbom-cyclonedx.json" + python3 /scripts/base_images_sbom_script.py \ + --sbom=sbom-cyclonedx.json \ + --parsed-dockerfile=/shared/parsed_dockerfile.json \ + --base-images-digests=/shared/base_images_digests + + echo "Adding image reference to sbom" + IMAGE_URL="$(cat "$(results.IMAGE_URL.path)")" + IMAGE_DIGEST="$(cat "$(results.IMAGE_DIGEST.path)")" + + python3 /scripts/add_image_reference.py \ + --image-url "$IMAGE_URL" \ + --image-digest "$IMAGE_DIGEST" \ + --input-file sbom-cyclonedx.json \ + --output-file /tmp/sbom-cyclonedx.tmp.json + + mv /tmp/sbom-cyclonedx.tmp.json sbom-cyclonedx.json + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - computeResources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + image: quay.io/konflux-ci/appstudio-utils:48c311af02858e2422d6229600e9959e496ddef1@sha256:91ddd999271f65d8ec8487b10f3dd378f81aa894e11b9af4d10639fd52bba7e8 + name: upload-sbom + script: | + #!/bin/bash + + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + cosign attach sbom --sbom sbom-cyclonedx.json --type cyclonedx "$(cat "$(results.IMAGE_REF.path)")" + + # Remove tag from IMAGE while allowing registry to contain a port number. + sbom_repo="${IMAGE%:*}" + sbom_digest="$(sha256sum sbom-cyclonedx.json | cut -d' ' -f1)" + # The SBOM_BLOB_URL is created by `cosign attach sbom`. + echo -n "${sbom_repo}@sha256:${sbom_digest}" | tee "$(results.SBOM_BLOB_URL.path)" + volumeMounts: + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + volumes: + - emptyDir: {} + name: varlibcontainers + - emptyDir: {} + name: shared + - name: etc-pki-entitlement + secret: + optional: true + secretName: $(params.ENTITLEMENT_SECRET) + - name: activation-key + secret: + optional: true + secretName: $(params.ACTIVATION_KEY) + - name: additional-secret + secret: + optional: true + secretName: $(params.ADDITIONAL_SECRET) + - configMap: + items: + - key: $(params.caTrustConfigMapKey) + path: ca-bundle.crt + name: $(params.caTrustConfigMapName) + optional: true + name: trusted-ca + workspaces: + - description: Workspace containing the source code to build. + name: source diff --git a/auto-generated/task/buildah/0.3/tekton.dev_v1_task_buildah.yaml b/auto-generated/task/buildah/0.3/tekton.dev_v1_task_buildah.yaml new file mode 100644 index 0000000000..20a6cc90dc --- /dev/null +++ b/auto-generated/task/buildah/0.3/tekton.dev_v1_task_buildah.yaml @@ -0,0 +1,681 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + annotations: + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: image-build, konflux + labels: + app.kubernetes.io/version: 0.2.1 + build.appstudio.redhat.com/build_type: docker + name: buildah +spec: + description: |- + Buildah task builds source code into a container image and pushes the image into container registry using buildah tool. + In addition, it generates a SBOM file, injects the SBOM file into final container image and pushes the SBOM file as separate image using cosign tool. + When prefetch-dependencies task is activated it is using its artifacts to run build in hermetic environment. + params: + - description: Reference of the image buildah will produce. + name: IMAGE + type: string + - default: ./Dockerfile + description: Path to the Dockerfile to build. + name: DOCKERFILE + type: string + - default: . + description: Path to the directory to use as context. + name: CONTEXT + type: string + - default: "true" + description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS + registry) + name: TLSVERIFY + type: string + - default: "false" + description: Determines if build will be executed without network access. + name: HERMETIC + type: string + - default: "" + description: In case it is not empty, the prefetched content should be made available + to the build. + name: PREFETCH_INPUT + type: string + - default: "" + description: Delete image tag after specified time. Empty means to keep the image + tag. Time values could be something like 1h, 2d, 3w for hours, days, and weeks, + respectively. + name: IMAGE_EXPIRES_AFTER + type: string + - default: "" + description: The image is built from this commit. + name: COMMIT_SHA + type: string + - default: repos.d + description: Path in the git repository in which yum repository files are stored + name: YUM_REPOS_D_SRC + - default: fetched.repos.d + description: Path in source workspace where dynamically-fetched repos are present + name: YUM_REPOS_D_FETCHED + - default: /etc/yum.repos.d + description: Target path on the container in which yum repository files should + be made available + name: YUM_REPOS_D_TARGET + - default: "" + description: Target stage in Dockerfile to build. If not specified, the Dockerfile + is processed entirely to (and including) its last stage. + name: TARGET_STAGE + type: string + - default: etc-pki-entitlement + description: Name of secret which contains the entitlement certificates + name: ENTITLEMENT_SECRET + type: string + - default: activation-key + description: Name of secret which contains subscription activation key + name: ACTIVATION_KEY + type: string + - default: does-not-exist + description: Name of a secret which will be made available to the build with 'buildah + build --secret' at /run/secrets/$ADDITIONAL_SECRET + name: ADDITIONAL_SECRET + type: string + - default: [] + description: Array of --build-arg values ("arg=value" strings) + name: BUILD_ARGS + type: array + - default: "" + description: Path to a file with build arguments, see https://www.mankier.com/1/buildah-build#--build-arg-file + name: BUILD_ARGS_FILE + type: string + - default: trusted-ca + description: The name of the ConfigMap to read CA bundle data from. + name: caTrustConfigMapName + type: string + - default: ca-bundle.crt + description: The name of the key in the ConfigMap that contains the CA bundle + data. + name: caTrustConfigMapKey + type: string + - default: "" + description: Comma separated list of extra capabilities to add when running 'buildah + build' + name: ADD_CAPABILITIES + type: string + - default: "false" + description: Squash all new and previous layers added as a part of this build, + as per --squash + name: SQUASH + type: string + - default: vfs + description: Storage driver to configure for buildah + name: STORAGE_DRIVER + type: string + - default: "true" + description: Whether to skip stages in Containerfile that seem unused by subsequent + stages + name: SKIP_UNUSED_STAGES + type: string + - default: [] + description: Additional key=value labels that should be applied to the image + name: LABELS + type: array + - default: "false" + description: Whether to enable privileged mode + name: PRIVILEGED_NESTED + type: string + results: + - description: Digest of the image just built + name: IMAGE_DIGEST + - description: Image repository and tag where the built image was pushed + name: IMAGE_URL + - description: Image reference of the built image + name: IMAGE_REF + - description: Reference of SBOM blob digest to enable digest-based verification + from provenance + name: SBOM_BLOB_URL + type: string + stepTemplate: + computeResources: + limits: + cpu: "4" + memory: 4Gi + requests: + cpu: "1" + memory: 1Gi + env: + - name: BUILDAH_FORMAT + value: oci + - name: STORAGE_DRIVER + value: $(params.STORAGE_DRIVER) + - name: HERMETIC + value: $(params.HERMETIC) + - name: SOURCE_CODE_DIR + value: source + - name: CONTEXT + value: $(params.CONTEXT) + - name: IMAGE + value: $(params.IMAGE) + - name: TLSVERIFY + value: $(params.TLSVERIFY) + - name: IMAGE_EXPIRES_AFTER + value: $(params.IMAGE_EXPIRES_AFTER) + - name: YUM_REPOS_D_SRC + value: $(params.YUM_REPOS_D_SRC) + - name: YUM_REPOS_D_FETCHED + value: $(params.YUM_REPOS_D_FETCHED) + - name: YUM_REPOS_D_TARGET + value: $(params.YUM_REPOS_D_TARGET) + - name: TARGET_STAGE + value: $(params.TARGET_STAGE) + - name: ENTITLEMENT_SECRET + value: $(params.ENTITLEMENT_SECRET) + - name: ACTIVATION_KEY + value: $(params.ACTIVATION_KEY) + - name: ADDITIONAL_SECRET + value: $(params.ADDITIONAL_SECRET) + - name: BUILD_ARGS_FILE + value: $(params.BUILD_ARGS_FILE) + - name: ADD_CAPABILITIES + value: $(params.ADD_CAPABILITIES) + - name: SQUASH + value: $(params.SQUASH) + - name: SKIP_UNUSED_STAGES + value: $(params.SKIP_UNUSED_STAGES) + - name: PRIVILEGED_NESTED + value: $(params.PRIVILEGED_NESTED) + volumeMounts: + - mountPath: /shared + name: shared + steps: + - args: + - --build-args + - $(params.BUILD_ARGS[*]) + - --labels + - $(params.LABELS[*]) + computeResources: + limits: + cpu: "4" + memory: 8Gi + requests: + cpu: "1" + memory: 2Gi + env: + - name: COMMIT_SHA + value: $(params.COMMIT_SHA) + - name: DOCKERFILE + value: $(params.DOCKERFILE) + image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: build + script: | + #!/bin/bash + set -euo pipefail + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + if [ -e "$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$CONTEXT/$DOCKERFILE" + elif [ -e "$SOURCE_CODE_DIR/$DOCKERFILE" ]; then + dockerfile_path="$(pwd)/$SOURCE_CODE_DIR/$DOCKERFILE" + elif [ -e "$DOCKERFILE" ]; then + # Instrumented builds (SAST) use this custom dockerffile step as their base + dockerfile_path="$DOCKERFILE" + elif echo "$DOCKERFILE" | grep -q "^https\?://"; then + echo "Fetch Dockerfile from $DOCKERFILE" + dockerfile_path=$(mktemp --suffix=-Dockerfile) + http_code=$(curl -s -S -L -w "%{http_code}" --output "$dockerfile_path" "$DOCKERFILE") + if [ $http_code != 200 ]; then + echo "No Dockerfile is fetched. Server responds $http_code" + exit 1 + fi + http_code=$(curl -s -S -L -w "%{http_code}" --output "$dockerfile_path.dockerignore.tmp" "$DOCKERFILE.dockerignore") + if [ $http_code = 200 ]; then + echo "Fetched .dockerignore from $DOCKERFILE.dockerignore" + mv "$dockerfile_path.dockerignore.tmp" $SOURCE_CODE_DIR/$CONTEXT/.dockerignore + fi + else + echo "Cannot find Dockerfile $DOCKERFILE" + exit 1 + fi + + dockerfile_copy=$(mktemp --tmpdir "$(basename "$dockerfile_path").XXXXXX") + cp "$dockerfile_path" "$dockerfile_copy" + + # Fixing group permission on /var/lib/containers + chown root:root /var/lib/containers + + sed -i 's/^\s*short-name-mode\s*=\s*.*/short-name-mode = "disabled"/' /etc/containers/registries.conf + + # Setting new namespace to run buildah - 2^32-2 + echo 'root:1:4294967294' | tee -a /etc/subuid >> /etc/subgid + + build_args=() + if [ -n "${BUILD_ARGS_FILE}" ]; then + # Parse BUILD_ARGS_FILE ourselves because dockerfile-json doesn't support it + echo "Parsing ARGs from $BUILD_ARGS_FILE" + mapfile -t build_args < <( + # https://www.mankier.com/1/buildah-build#--build-arg-file + # delete lines that start with # + # delete blank lines + sed -e '/^#/d' -e '/^\s*$/d' "${SOURCE_CODE_DIR}/${BUILD_ARGS_FILE}" + ) + fi + + LABELS=() + # Split `args` into two sets of arguments. + while [[ $# -gt 0 ]]; do + case $1 in + --build-args) + shift + # Note: this may result in multiple --build-arg=KEY=value flags with the same KEY being + # passed to buildah. In that case, the *last* occurrence takes precedence. This is why + # we append BUILD_ARGS after the content of the BUILD_ARGS_FILE + while [[ $# -gt 0 && $1 != --* ]]; do build_args+=("$1"); shift; done + ;; + --labels) + shift + while [[ $# -gt 0 && $1 != --* ]]; do LABELS+=("--label" "$1"); shift; done + ;; + *) + echo "unexpected argument: $1" >&2 + exit 2 + ;; + esac + done + + BUILD_ARG_FLAGS=() + for build_arg in "${build_args[@]}"; do + BUILD_ARG_FLAGS+=("--build-arg=$build_arg") + done + + dockerfile-json "${BUILD_ARG_FLAGS[@]}" "$dockerfile_copy" > /shared/parsed_dockerfile.json + BASE_IMAGES=$( + jq -r '.Stages[] | select(.From | .Stage or .Scratch | not) | .BaseName | select(test("^oci-archive:") | not)' /shared/parsed_dockerfile.json + ) + + BUILDAH_ARGS=() + UNSHARE_ARGS=() + + if [ "${HERMETIC}" == "true" ]; then + BUILDAH_ARGS+=("--pull=never") + UNSHARE_ARGS+=("--net") + + for image in $BASE_IMAGES; do + unshare -Ufp --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -- buildah pull $image + done + echo "Build will be executed with network isolation" + fi + + if [ -n "${TARGET_STAGE}" ]; then + BUILDAH_ARGS+=("--target=${TARGET_STAGE}") + fi + + BUILDAH_ARGS+=("${BUILD_ARG_FLAGS[@]}") + + if [ "${PRIVILEGED_NESTED}" == "true" ]; then + BUILDAH_ARGS+=("--security-opt=label=disable") + BUILDAH_ARGS+=("--cap-add=all") + BUILDAH_ARGS+=("--device=/dev/fuse") + fi + + if [ -n "${ADD_CAPABILITIES}" ]; then + BUILDAH_ARGS+=("--cap-add=${ADD_CAPABILITIES}") + fi + + if [ "${SQUASH}" == "true" ]; then + BUILDAH_ARGS+=("--squash") + fi + + if [ "${SKIP_UNUSED_STAGES}" != "true" ] ; then + BUILDAH_ARGS+=("--skip-unused-stages=false") + fi + + VOLUME_MOUNTS=() + + if [ -f "$(workspaces.source.path)/cachi2/cachi2.env" ]; then + cp -r "$(workspaces.source.path)/cachi2" /tmp/ + chmod -R go+rwX /tmp/cachi2 + VOLUME_MOUNTS+=(--volume /tmp/cachi2:/cachi2) + # Read in the whole file (https://unix.stackexchange.com/questions/533277), then + # for each RUN ... line insert the cachi2.env command *after* any options like --mount + sed -E -i \ + -e 'H;1h;$!d;x' \ + -e 's@^\s*(run((\s|\\\n)+-\S+)*(\s|\\\n)+)@\1. /cachi2/cachi2.env \&\& \\\n @igM' \ + "$dockerfile_copy" + echo "Prefetched content will be made available" + + prefetched_repo_for_my_arch="/tmp/cachi2/output/deps/rpm/$(uname -m)/repos.d/cachi2.repo" + if [ -f "$prefetched_repo_for_my_arch" ]; then + echo "Adding $prefetched_repo_for_my_arch to $YUM_REPOS_D_FETCHED" + mkdir -p "$YUM_REPOS_D_FETCHED" + cp --no-clobber "$prefetched_repo_for_my_arch" "$YUM_REPOS_D_FETCHED" + fi + fi + + # if yum repofiles stored in git, copy them to mount point outside the source dir + if [ -d "${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}" ]; then + mkdir -p ${YUM_REPOS_D_FETCHED} + cp -r ${SOURCE_CODE_DIR}/${YUM_REPOS_D_SRC}/* ${YUM_REPOS_D_FETCHED} + fi + + # if anything in the repofiles mount point (either fetched or from git), mount it + if [ -d "${YUM_REPOS_D_FETCHED}" ]; then + chmod -R go+rwX ${YUM_REPOS_D_FETCHED} + mount_point=$(realpath ${YUM_REPOS_D_FETCHED}) + VOLUME_MOUNTS+=(--volume "${mount_point}:${YUM_REPOS_D_TARGET}") + fi + + DEFAULT_LABELS=( + "--label" "build-date=$(date -u +'%Y-%m-%dT%H:%M:%S')" + "--label" "architecture=$(uname -m)" + "--label" "vcs-type=git" + ) + [ -n "$COMMIT_SHA" ] && DEFAULT_LABELS+=("--label" "vcs-ref=$COMMIT_SHA") + [ -n "$IMAGE_EXPIRES_AFTER" ] && DEFAULT_LABELS+=("--label" "quay.expires-after=$IMAGE_EXPIRES_AFTER") + + # Concatenate defaults and explicit labels. If a label appears twice, the last one wins. + LABELS=("${DEFAULT_LABELS[@]}" "${LABELS[@]}") + + ACTIVATION_KEY_PATH="/activation-key" + ENTITLEMENT_PATH="/entitlement" + + # 0. if hermetic=true, skip all subscription related stuff + # 1. do not enable activation key and entitlement at same time. If both vars are provided, prefer activation key. + # 2. Activation-keys will be used when the key 'org' exists in the activation key secret. + # 3. try to pre-register and mount files to the correct location so that users do no need to modify Dockerfiles. + # 3. If the Dockerfile contains the string "subcription-manager register", add the activation-keys volume + # to buildah but don't pre-register for backwards compatibility. Mount an empty directory on + # shared emptydir volume to "/etc/pki/entitlement" to prevent certificates from being included + + if [ "${HERMETIC}" != "true" ] && [ -e /activation-key/org ]; then + cp -r --preserve=mode "$ACTIVATION_KEY_PATH" /tmp/activation-key + mkdir -p /shared/rhsm/etc/pki/entitlement + mkdir -p /shared/rhsm/etc/pki/consumer + + VOLUME_MOUNTS+=(-v /tmp/activation-key:/activation-key \ + -v /shared/rhsm/etc/pki/entitlement:/etc/pki/entitlement:Z \ + -v /shared/rhsm/etc/pki/consumer:/etc/pki/consumer:Z) + echo "Adding activation key to the build" + + if ! grep -E "^[^#]*subscription-manager.[^#]*register" "$dockerfile_path"; then + # user is not running registration in the Containerfile: pre-register. + echo "Pre-registering with subscription manager." + subscription-manager register --org "$(cat /tmp/activation-key/org)" --activationkey "$(cat /tmp/activation-key/activationkey)" + trap 'subscription-manager unregister || true' EXIT + + # copy generated certificates to /shared volume + cp /etc/pki/entitlement/*.pem /shared/rhsm/etc/pki/entitlement + cp /etc/pki/consumer/*.pem /shared/rhsm/etc/pki/consumer + + # and then mount get /etc/rhsm/ca/redhat-uep.pem into /run/secrets/rhsm/ca + VOLUME_MOUNTS+=(--volume /etc/rhsm/ca/redhat-uep.pem:/etc/rhsm/ca/redhat-uep.pem:Z) + fi + + elif [ "${HERMETIC}" != "true" ] && find /entitlement -name "*.pem" >> null; then + cp -r --preserve=mode "$ENTITLEMENT_PATH" /tmp/entitlement + VOLUME_MOUNTS+=(--volume /tmp/entitlement:/etc/pki/entitlement) + echo "Adding the entitlement to the build" + fi + + if [ -n "${ADDITIONAL_VOLUME_MOUNTS-}" ]; then + # ADDITIONAL_VOLUME_MOUNTS allows to specify more volumes for the build. + # Instrumented builds (SAST) use this step as their base and add some other tools. + while read -r volume_mount; do + VOLUME_MOUNTS+=("--volume=$volume_mount") + done <<< "$ADDITIONAL_VOLUME_MOUNTS" + fi + + ADDITIONAL_SECRET_PATH="/additional-secret" + ADDITIONAL_SECRET_TMP="/tmp/additional-secret" + if [ -d "$ADDITIONAL_SECRET_PATH" ]; then + cp -r --preserve=mode -L "$ADDITIONAL_SECRET_PATH" $ADDITIONAL_SECRET_TMP + while read -r filename; do + echo "Adding the secret ${ADDITIONAL_SECRET}/${filename} to the build, available at /run/secrets/${ADDITIONAL_SECRET}/${filename}" + BUILDAH_ARGS+=("--secret=id=${ADDITIONAL_SECRET}/${filename},src=$ADDITIONAL_SECRET_TMP/${filename}") + done < <(find $ADDITIONAL_SECRET_TMP -maxdepth 1 -type f -exec basename {} \;) + fi + + # Prevent ShellCheck from giving a warning because 'image' is defined and 'IMAGE' is not. + declare IMAGE + + buildah_cmd_array=( + buildah build + "${VOLUME_MOUNTS[@]}" + "${BUILDAH_ARGS[@]}" + "${LABELS[@]}" + --tls-verify="$TLSVERIFY" --no-cache + --ulimit nofile=4096:4096 + -f "$dockerfile_copy" -t "$IMAGE" . + ) + buildah_cmd=$(printf "%q " "${buildah_cmd_array[@]}") + + if [ "${HERMETIC}" == "true" ]; then + # enabling loopback adapter enables Bazel builds to work in hermetic mode. + command="ip link set lo up && $buildah_cmd" + else + command="$buildah_cmd" + fi + + # disable host subcription manager integration + find /usr/share/rhel/secrets -type l -exec unlink {} \; + + unshare -Uf "${UNSHARE_ARGS[@]}" --keep-caps -r --map-users 1,1,65536 --map-groups 1,1,65536 -w "${SOURCE_CODE_DIR}/$CONTEXT" -- sh -c "$command" + + container=$(buildah from --pull-never "$IMAGE") + + # Save the SBOM produced by Cachi2 so it can be merged into the final SBOM later + if [ -f "/tmp/cachi2/output/bom.json" ]; then + echo "Making copy of sbom-cachi2.json" + cp /tmp/cachi2/output/bom.json ./sbom-cachi2.json + fi + + buildah mount $container | tee /shared/container_path + # delete symlinks - they may point outside the container rootfs, messing with SBOM scanners + find $(cat /shared/container_path) -xtype l -delete + echo $container > /shared/container_name + + touch /shared/base_images_digests + for image in $BASE_IMAGES; do + base_image_digest=$(buildah images --format '{{ .Name }}:{{ .Tag }}@{{ .Digest }}' --filter reference="$image") + # In some cases, there might be BASE_IMAGES, but not any associated digest. This happens + # if buildah did not use that particular image during build because it was skipped + if [ -n "$base_image_digest" ]; then + echo "$image $base_image_digest" >> /shared/base_images_digests + fi + done + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /entitlement + name: etc-pki-entitlement + - mountPath: /activation-key + name: activation-key + - mountPath: /additional-secret + name: additional-secret + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + - args: + - $(params.IMAGE) + image: quay.io/konflux-ci/icm-injection-scripts:latest@sha256:462980e94ba689b5f56c3d5dfb3358cd8c685300daf65a71532f11898935e7f1 + name: icm + securityContext: + capabilities: + add: + - SETFCAP + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + workingDir: $(workspaces.source.path) + - image: quay.io/konflux-ci/buildah-task:latest@sha256:b2d6c32d1e05e91920cd4475b2761d58bb7ee11ad5dff3ecb59831c7572b4d0c + name: push + script: | + #!/bin/bash + set -e + + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + retries=5 + # Push to a unique tag based on the TaskRun name to avoid race conditions + echo "Pushing to ${IMAGE%:*}:${TASKRUN_NAME}" + if ! buildah push \ + --retry "$retries" \ + --tls-verify="$TLSVERIFY" \ + "$IMAGE" \ + "docker://${IMAGE%:*}:$(context.taskRun.name)"; + then + echo "Failed to push sbom image to ${IMAGE%:*}:$(context.taskRun.name) after ${retries} tries" + exit 1 + fi + + # Push to a tag based on the git revision + echo "Pushing to ${IMAGE}" + if ! buildah push \ + --retry "$retries" \ + --tls-verify="$TLSVERIFY" \ + --digestfile "$(workspaces.source.path)/image-digest" "$IMAGE" \ + "docker://$IMAGE"; + then + echo "Failed to push sbom image to $IMAGE after ${retries} tries" + exit 1 + fi + + cat "$(workspaces.source.path)"/image-digest | tee $(results.IMAGE_DIGEST.path) + echo -n "$IMAGE" | tee $(results.IMAGE_URL.path) + { + echo -n "${IMAGE}@" + cat "$(workspaces.source.path)/image-digest" + } > "$(results.IMAGE_REF.path)" + securityContext: + capabilities: + add: + - SETFCAP + runAsUser: 0 + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + - image: registry.access.redhat.com/rh-syft-tech-preview/syft-rhel9:1.4.1@sha256:34d7065427085a31dc4949bd283c001b91794d427e1e4cdf1b21ea4faf9fee3f + name: sbom-syft-generate + script: | + echo "Running syft on the source directory" + syft dir:"$(workspaces.source.path)/$SOURCE_CODE_DIR/$CONTEXT" --output cyclonedx-json="$(workspaces.source.path)/sbom-source.json" + echo "Running syft on the image filesystem" + syft dir:"$(cat /shared/container_path)" --output cyclonedx-json="$(workspaces.source.path)/sbom-image.json" + volumeMounts: + - mountPath: /var/lib/containers + name: varlibcontainers + - mountPath: /shared + name: shared + workingDir: $(workspaces.source.path)/source + - computeResources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + image: quay.io/redhat-appstudio/sbom-utility-scripts-image@sha256:9f1fd11d9c3c517ecc112d192ad361d16ecf6ce00b83b109c93cf3d1c644a357 + name: prepare-sboms + script: | + echo "Merging contents of sbom-source.json and sbom-image.json into sbom-cyclonedx.json" + python3 /scripts/merge_syft_sboms.py + + if [ -f "sbom-cachi2.json" ]; then + echo "Merging contents of sbom-cachi2.json into sbom-cyclonedx.json" + python3 /scripts/merge_cachi2_sboms.py sbom-cachi2.json sbom-cyclonedx.json > sbom-temp.json + mv sbom-temp.json sbom-cyclonedx.json + fi + + echo "Adding base images data to sbom-cyclonedx.json" + python3 /scripts/base_images_sbom_script.py \ + --sbom=sbom-cyclonedx.json \ + --parsed-dockerfile=/shared/parsed_dockerfile.json \ + --base-images-digests=/shared/base_images_digests + + echo "Adding image reference to sbom" + IMAGE_URL="$(cat "$(results.IMAGE_URL.path)")" + IMAGE_DIGEST="$(cat "$(results.IMAGE_DIGEST.path)")" + + python3 /scripts/add_image_reference.py \ + --image-url "$IMAGE_URL" \ + --image-digest "$IMAGE_DIGEST" \ + --input-file sbom-cyclonedx.json \ + --output-file /tmp/sbom-cyclonedx.tmp.json + + mv /tmp/sbom-cyclonedx.tmp.json sbom-cyclonedx.json + securityContext: + runAsUser: 0 + workingDir: $(workspaces.source.path) + - computeResources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + image: quay.io/konflux-ci/appstudio-utils:48c311af02858e2422d6229600e9959e496ddef1@sha256:91ddd999271f65d8ec8487b10f3dd378f81aa894e11b9af4d10639fd52bba7e8 + name: upload-sbom + script: | + #!/bin/bash + + ca_bundle=/mnt/trusted-ca/ca-bundle.crt + if [ -f "$ca_bundle" ]; then + echo "INFO: Using mounted CA bundle: $ca_bundle" + cp -vf $ca_bundle /etc/pki/ca-trust/source/anchors + update-ca-trust + fi + + cosign attach sbom --sbom sbom-cyclonedx.json --type cyclonedx "$(cat "$(results.IMAGE_REF.path)")" + + # Remove tag from IMAGE while allowing registry to contain a port number. + sbom_repo="${IMAGE%:*}" + sbom_digest="$(sha256sum sbom-cyclonedx.json | cut -d' ' -f1)" + # The SBOM_BLOB_URL is created by `cosign attach sbom`. + echo -n "${sbom_repo}@sha256:${sbom_digest}" | tee "$(results.SBOM_BLOB_URL.path)" + volumeMounts: + - mountPath: /mnt/trusted-ca + name: trusted-ca + readOnly: true + workingDir: $(workspaces.source.path) + volumes: + - emptyDir: {} + name: varlibcontainers + - emptyDir: {} + name: shared + - name: etc-pki-entitlement + secret: + optional: true + secretName: $(params.ENTITLEMENT_SECRET) + - name: activation-key + secret: + optional: true + secretName: $(params.ACTIVATION_KEY) + - name: additional-secret + secret: + optional: true + secretName: $(params.ADDITIONAL_SECRET) + - configMap: + items: + - key: $(params.caTrustConfigMapKey) + path: ca-bundle.crt + name: $(params.caTrustConfigMapName) + optional: true + name: trusted-ca + workspaces: + - description: Workspace containing the source code to build. + name: source diff --git a/auto-generated/task/fbc-related-image-check/0.1/tekton.dev_v1_task_fbc-related-image-check.yaml b/auto-generated/task/fbc-related-image-check/0.1/tekton.dev_v1_task_fbc-related-image-check.yaml new file mode 100644 index 0000000000..30cbaff7a5 --- /dev/null +++ b/auto-generated/task/fbc-related-image-check/0.1/tekton.dev_v1_task_fbc-related-image-check.yaml @@ -0,0 +1,72 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + annotations: + build.appstudio.redhat.com/expires-on: "2025-01-31T00:00:00Z" + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: konflux + labels: + app.kubernetes.io/version: "0.1" + name: fbc-related-image-check +spec: + description: Checks the validity of all the images referenced in the file-based + catalog (FBC) to inspect manifest content using Skopeo. + results: + - description: Tekton task test output. + name: TEST_OUTPUT + steps: + - computeResources: + limits: + memory: 4Gi + requests: + cpu: 10m + memory: 512Mi + image: quay.io/konflux-ci/konflux-test:v1.4.8@sha256:2224fabdb0a28a415d4af4c58ae53d7c4c53c83c315f12e07d1d7f48a80bfa70 + name: check-related-images + script: | + #!/usr/bin/env bash + set -euo pipefail + source /utils.sh + trap 'handle_error $(results.TEST_OUTPUT.path)' EXIT + + FAILEDIMAGES="" + catalog="$(opm render $(workspaces.workspace.path)/hacbs/fbc-validation/confdir/)" + + # OPM generates catalog file in a way that yaml file could contain stream of JSON objects + # thats why we need jq in for this situation, because yq can't parse this file + # however there is also posibility that catalog.yaml has yaml data in it + + status=0 + relImgs="$(jq -r '.relatedImages[]?.image' <<< ${catalog})" || status=$? + if [ $status -ne 0 ]; then + echo "Could not get related images. Make sure catalog.yaml exists in FBC fragment image and it is valid .yaml or .json format." + note="Task $(context.task.name) failed: Could not fetch related images. Make sure you have catalog.yaml or catalog.json formatted correctly in your file-based catalog (FBC) fragment image." + TEST_OUTPUT=$(make_result_json -r FAILURE -f 1 -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + + echo -e "These are related images:\n$relImgs." + # cycle through those related images and show outputs + for i in ${relImgs// /} + do + if ! skopeo inspect --no-tags "docker://${i}"; then + echo "Skopeo inspect failed on related image: $i." + FAILEDIMAGES+="$i, " + fi + done + if [ -z "$FAILEDIMAGES" ]; then + note="Task $(context.task.name) succeeded: For details, check Tekton task logs." + TEST_OUTPUT=$(make_result_json -r SUCCESS -s 1 -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + else + echo "These images failed inspection: $FAILEDIMAGES." + note="Task $(context.task.name) failed: Command skopeo inspect could not inspect images. For details, check Tekton task log." + TEST_OUTPUT=$(make_result_json -r FAILURE -f 1 -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + workingDir: $(workspaces.workspace.path)/hacbs/$(context.task.name) + workspaces: + - name: workspace diff --git a/auto-generated/task/fbc-related-image-check/0.2/tekton.dev_v1_task_fbc-related-image-check.yaml b/auto-generated/task/fbc-related-image-check/0.2/tekton.dev_v1_task_fbc-related-image-check.yaml new file mode 100644 index 0000000000..a1230af6cf --- /dev/null +++ b/auto-generated/task/fbc-related-image-check/0.2/tekton.dev_v1_task_fbc-related-image-check.yaml @@ -0,0 +1,72 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + annotations: + build.appstudio.redhat.com/expires-on: "2025-01-31T00:00:00Z" + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: konflux + labels: + app.kubernetes.io/version: "0.2" + name: fbc-related-image-check +spec: + description: Checks the validity of all the images referenced in the file-based + catalog (FBC) to inspect manifest content using Skopeo. + results: + - description: Tekton task test output. + name: TEST_OUTPUT + steps: + - computeResources: + limits: + memory: 4Gi + requests: + cpu: 10m + memory: 512Mi + image: quay.io/konflux-ci/konflux-test:v1.4.8@sha256:2224fabdb0a28a415d4af4c58ae53d7c4c53c83c315f12e07d1d7f48a80bfa70 + name: check-related-images + script: | + #!/usr/bin/env bash + set -euo pipefail + source /utils.sh + trap 'handle_error $(results.TEST_OUTPUT.path)' EXIT + + FAILEDIMAGES="" + catalog="$(opm render $(workspaces.workspace.path)/hacbs/fbc-validation/confdir/)" + + # OPM generates catalog file in a way that yaml file could contain stream of JSON objects + # thats why we need jq in for this situation, because yq can't parse this file + # however there is also posibility that catalog.yaml has yaml data in it + + status=0 + relImgs="$(jq -r '.relatedImages[]?.image' <<< ${catalog})" || status=$? + if [ $status -ne 0 ]; then + echo "Could not get related images. Make sure catalog.yaml exists in FBC fragment image and it is valid .yaml or .json format." + note="Task $(context.task.name) failed: Could not fetch related images. Make sure you have catalog.yaml or catalog.json formatted correctly in your file-based catalog (FBC) fragment image." + TEST_OUTPUT=$(make_result_json -r FAILURE -f 1 -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + + echo -e "These are related images:\n$relImgs." + # cycle through those related images and show outputs + for i in ${relImgs// /} + do + if ! skopeo inspect --no-tags "docker://${i}"; then + echo "Skopeo inspect failed on related image: $i." + FAILEDIMAGES+="$i, " + fi + done + if [ -z "$FAILEDIMAGES" ]; then + note="Task $(context.task.name) succeeded: For details, check Tekton task logs." + TEST_OUTPUT=$(make_result_json -r SUCCESS -s 1 -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + else + echo "These images failed inspection: $FAILEDIMAGES." + note="Task $(context.task.name) failed: Command skopeo inspect could not inspect images. For details, check Tekton task log." + TEST_OUTPUT=$(make_result_json -r FAILURE -f 1 -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + workingDir: $(workspaces.workspace.path)/hacbs/$(context.task.name) + workspaces: + - name: workspace diff --git a/auto-generated/task/fbc-validation/0.1/tekton.dev_v1_task_fbc-validation.yaml b/auto-generated/task/fbc-validation/0.1/tekton.dev_v1_task_fbc-validation.yaml new file mode 100644 index 0000000000..bd4476def7 --- /dev/null +++ b/auto-generated/task/fbc-validation/0.1/tekton.dev_v1_task_fbc-validation.yaml @@ -0,0 +1,278 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + annotations: + build.appstudio.redhat.com/expires-on: "2025-01-31T00:00:00Z" + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: konflux + labels: + app.kubernetes.io/version: "0.1" + name: fbc-validation +spec: + description: Ensures file-based catalog (FBC) components are uniquely linted for + proper construction as part of build pipeline. + params: + - description: Fully qualified image name. + name: IMAGE_URL + - description: Image digest. + name: IMAGE_DIGEST + - description: Fully qualified base image name. + name: BASE_IMAGE + results: + - description: Tekton task test output. + name: TEST_OUTPUT + steps: + - computeResources: + limits: + memory: 4Gi + requests: + cpu: 10m + memory: 512Mi + env: + - name: IMAGE_URL + value: $(params.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(params.IMAGE_DIGEST) + - name: BASE_IMAGE + value: $(params.BASE_IMAGE) + image: quay.io/konflux-ci/konflux-test:v1.4.8@sha256:2224fabdb0a28a415d4af4c58ae53d7c4c53c83c315f12e07d1d7f48a80bfa70 + name: extract-and-check-binaries + script: | + #!/usr/bin/env bash + set -euo pipefail + source /utils.sh + trap 'handle_error $(results.TEST_OUTPUT.path)' EXIT + + declare -a ALLOWED_BASE_IMAGES=( + "registry.redhat.io/openshift4/ose-operator-registry" + "registry.redhat.io/openshift4/ose-operator-registry-rhel9" + "brew.registry.redhat.io/rh-osbs/openshift-ose-operator-registry-rhel9" + ) + + ### FBC base image check + if [ -z "${BASE_IMAGE}" ]; then + echo "Base image is unknown. The file-based catalog must have base image defined. Check inspect-image task log." + note="Task $(context.task.name) failed: The file-based catalog must have base image defined. For details, check Tekton task result TEST_OUTPUT in task inspect-image." + TEST_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + + IMAGE_WITHOUT_TAG=$(echo "${BASE_IMAGE}" | sed "s/:.*$//" | sed "s/@.*$//") + + allowed=false + for value in "${ALLOWED_BASE_IMAGES[@]}" + do + if [[ "${IMAGE_WITHOUT_TAG}" == "${value}" ]]; then + allowed=true + break + fi + done + + if [[ "${allowed}" == false ]]; then + echo "Base image ${BASE_IMAGE} is not allowed for the file based catalog image. Allowed images: ${ALLOWED_BASE_IMAGES}" + note="Task $(context.task.name) failed: Base image ${BASE_IMAGE} is not allowed for the file based catalog image. For details, check Tekton task logs" + TEST_OUTPUT=$(make_result_json -r FAILURE -f 1 -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + + ### Try to extract binaries with configs > check binaries functionality > check opm validate ### + if [ ! -s ../inspect-image/image_inspect.json ]; then + echo "File $(workspaces.workspace.path)/hacbs/inspect-image/image_inspect.json did not generate correctly. Check inspect-image task log." + note="Task $(context.task.name) failed: $(workspaces.workspace.path)/hacbs/inspect-image/image_inspect.json did not generate correctly. For details, check Tekton task result TEST_OUTPUT in task inspect-image." + TEST_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + + if [ ! -s ../inspect-image/raw_image_inspect.json ]; then + echo "File $(workspaces.workspace.path)/hacbs/inspect-image/raw_image_inspect.json did not generate correctly. Check inspect-image task log." + note="Task $(context.task.name) failed: $(workspaces.workspace.path)/hacbs/inspect-image/raw_image_inspect.json did not generate correctly. For details, check Tekton task result TEST_OUTPUT in task inspect-image." + TEST_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + + echo "Getting base image for source image ${IMAGE_URL}." + base_image_name="$(jq -r ".annotations.\"org.opencontainers.image.base.name\"" ../inspect-image/raw_image_inspect.json)" || status=$? + if [ "$base_image_name" == 'null' ]; then + echo "Could not get annotations from inspect-image/raw_image_inspect.json. Make sure file exists and it contains this annotation: org.opencontainers.image.base.name" + echo "Try to get base image from label..." + base_image_name="$(jq -r ".Labels.\"org.opencontainers.image.base.name\"" ../inspect-image/image_inspect.json)" || status=$? + if [ "$base_image_name" == 'null' ]; then + echo "Cannot get base image info from Labels. For details, check source image ../inspect-image/image_inspect.json." + TEST_OUTPUT="$(make_result_json -r ERROR)" + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + fi + if [ -z "$base_image_name" ]; then + echo "Source image ${IMAGE_URL} is built from scratch, so there is no base image." + TEST_OUTPUT="$(make_result_json -r ERROR)" + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + + status=0 + conffolder=$(jq -r '.Labels ."operators.operatorframework.io.index.configs.v1"' ../inspect-image/image_inspect.json) || status=$? + if [ $status -ne 0 ]; then + echo "Could not get labels from inspect-image/image_inspect.json. Make sure file exists and it contains this label: operators.operatorframework.io.index.configs.v1." + TEST_OUTPUT="$(make_result_json -r ERROR)" + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + mkdir -p /tmp/image-content confdir + pushd /tmp/image-content + image_with_digest="${IMAGE_URL}@${IMAGE_DIGEST}" + + if ! oc image extract --registry-config ~/.docker/config.json "${image_with_digest}" ; then + echo "Unable to extract or validate extracted binaries." + note="Task $(context.task.name) failed: Failed to extract image with oc extract command, so it cannot validate extracted binaries. For details, check Tekton task log." + ERROR_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + popd + exit 0 + fi + + if [ -z "$(ls -A .$conffolder)" ]; then + echo "$conffolder is missing catalog file." + TEST_OUTPUT="$(make_result_json -r ERROR)" + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + popd + exit 0 + fi + # copy content of conffolder to confdir - will be used in next task - related image check + cp -r .$conffolder/* $(workspaces.workspace.path)/hacbs/$(context.task.name)/confdir + + EXTRACT_DIR="/extracted_base_img" + mkdir "${EXTRACT_DIR}" + if ! oc image extract ${BASE_IMAGE} --path /:"${EXTRACT_DIR}"; then + echo "Unable to extract opm binary" + note="Task $(context.task.name) failed: Failed to extract base image with oc extract command, so it cannot validate extracted binaries. For details, check Tekton task log." + ERROR_OUTPUT=$(make_result_json -r ERROR -t "$note") + exit 0 + fi + + OPM_BINARIES="$(find "${EXTRACT_DIR}" -type f -name opm)" + BINARIES_COUNT=$(wc -l <<< "${OPM_BINARIES}") + if [[ $BINARIES_COUNT -ne "1" ]]; then + note="Task $(context.task.name) failed: Expected exactly one opm binary in base image. For details, check Tekton task log" + ERROR_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${ERROR_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + echo "found $BINARIES_COUNT opm binaries:" + echo "${OPM_BINARIES}" + exit 0 + fi + OPM_BINARY=$(echo "${OPM_BINARIES}" | head -n 1) + echo "OPM_BINARY: '${OPM_BINARY}'" + chmod 775 "$OPM_BINARY" + + # We have 6 total checks + check_num=6 + failure_num=0 + TESTPASSED=true + + if [[ ! $(find . -name "grpc_health_probe") ]]; then + echo "!FAILURE! - grpc_health_probe binary presence check failed." + failure_num=$((failure_num + 1)) + TESTPASSED=false + fi + + if ! ${OPM_BINARY} validate ."${conffolder}"; then + echo "!FAILURE! - opm validate check failed." + failure_num=$((failure_num + 1)) + TESTPASSED=false + fi + + OPM_RENDERED_CATALOG=/tmp/catalog.json + ${OPM_BINARY} render ."${conffolder}" > ${OPM_RENDERED_CATALOG} + if [ ! -f ${OPM_RENDERED_CATALOG} ]; then + echo "!FAILURE! - unable to render the fragment FBC." + failure_num=$((failure_num + 1)) + TESTPASSED=false + fi + + if jq -en 'reduce (inputs | select(.schema == "olm.package")) as $obj (0; .+1) < 1' ${OPM_RENDERED_CATALOG}; then + echo "!FAILURE! - There are no olm package entries defined in this FBC fragment." + failure_num=$((failure_num + 1)) + TESTPASSED=false + fi + + # examines the base_image_name tag to derive the target OCP version + # assumes this is in the form + # image-path:[v]major-digits.minor-digits[@sha...] + OCP_VER_FROM_BASE=$(echo "${base_image_name}" | sed -e "s/@.*$//" -e "s/^.*://") # strips hash first due to greedy match + # extracts major digits and filters out any leading alphabetic characters, for e.g. 'v4' --> '4' + OCP_VER_MAJOR=$(echo "${OCP_VER_FROM_BASE}" | cut -d '.' -f 1 | sed "s/^[a-zA-Z]*//") + OCP_VER_MINOR=$(echo "${OCP_VER_FROM_BASE}" | cut -d '.' -f 2) + + RUN_OCP_VERSION_VALIDATION="false" + digits_regex='^[0-9]*$' + if [[ ${OCP_VER_MAJOR} =~ $digits_regex ]] && [[ ${OCP_VER_MINOR} =~ $digits_regex ]] ; then + RUN_OCP_VERSION_VALIDATION="true" + fi + + if [ "${RUN_OCP_VERSION_VALIDATION}" == "false" ] ; then + echo "!WARNING! - unable to assess bundle metadata alignment with OCP version because we cannot extract version info from base_image_name: ${base_image_name}" + else + OCP_BUNDLE_METADATA_THRESHOLD_MAJOR=4 + OCP_BUNDLE_METADATA_THRESHOLD_MINOR=17 + OCP_BUNDLE_METADATA_FORMAT="olm.bundle.object" + + if [[ "${OCP_VER_MAJOR}" -ge "${OCP_BUNDLE_METADATA_THRESHOLD_MAJOR}" ]] && [[ "${OCP_VER_MINOR}" -ge "${OCP_BUNDLE_METADATA_THRESHOLD_MINOR}" ]]; then + OCP_BUNDLE_METADATA_FORMAT="olm.csv.metadata" + fi + + # enforce the presence of either olm.csv.metadata or olm.bundle.object based on OCP version + if [[ "${OCP_BUNDLE_METADATA_FORMAT}" = "olm.csv.metadata" ]]; then + if ! jq -en 'reduce( inputs | select(.schema == "olm.bundle" and .properties[].type == "olm.bundle.object")) as $_ (0;.+1) == 0' ${OPM_RENDERED_CATALOG}; then + echo "!FAILURE! - olm.bundle.object bundle properties are not permitted in a FBC fragment for OCP version ${OCP_VER_MAJOR}.${OCP_VER_MINOR}. Fragments must move to olm.csv.metadata bundle metadata." + failure_num=$((failure_num + 1)) + TESTPASSED=false + fi + else + if ! jq -en 'reduce( inputs | select(.schema == "olm.bundle" and .properties[].type == "olm.csv.metadata")) as $_ (0;.+1) == 0' ${OPM_RENDERED_CATALOG}; then + echo "!FAILURE! - olm.csv.metadata bundle properties are not permitted in a FBC fragment for OCP version ${OCP_VER_MAJOR}.${OCP_VER_MINOR}. Fragments must only use olm.bundle.object bundle metadata." + failure_num=$((failure_num + 1)) + TESTPASSED=false + fi + fi + + # enforce that each bundle has the OCP-version-appropriate bundle metadata. + BUNDLE_COUNT=$(jq -en 'def count(stream): reduce stream as $i (0; .+1); count(inputs|select(.schema=="olm.bundle"))' ${OPM_RENDERED_CATALOG}) + BUNDLE_BO_COUNT=$(jq -en 'def count(stream): reduce stream as $i (0; .+1); count(inputs|select(.schema == "olm.bundle" and .properties[].type == "olm.bundle.object"))' ${OPM_RENDERED_CATALOG}) + BUNDLE_CM_COUNT=$(jq -en 'def count(stream): reduce stream as $i (0; .+1); count(inputs|select(.schema == "olm.bundle" and .properties[].type == "olm.csv.metadata"))' ${OPM_RENDERED_CATALOG}) + + if [[ "${OCP_BUNDLE_METADATA_FORMAT}" = "olm.csv.metadata" ]]; then + if [[ "${BUNDLE_COUNT}" -ne "${BUNDLE_CM_COUNT}" ]]; then + echo "!FAILURE! - every olm.bundle object in the fragment must have a corresponding olm.csv.metadata bundle property" + failure_num=$((failure_num + 1)) + TESTPASSED=false + fi + else + if [[ "${BUNDLE_BO_COUNT}" -lt "${BUNDLE_COUNT}" ]]; then + echo "!FAILURE! - every olm.bundle object in the fragment must have at least one olm.bundle.object bundle property" + failure_num=$((failure_num + 1)) + TESTPASSED=false + fi + fi + fi + + note="Task $(context.task.name) completed: Check result for task result." + if [ $TESTPASSED == false ]; then + ERROR_OUTPUT=$(make_result_json -r FAILURE -f $failure_num -s $((check_num - failure_num)) -t "$note") + echo "${ERROR_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + else + TEST_OUTPUT=$(make_result_json -r SUCCESS -s $check_num -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + fi + popd + securityContext: + capabilities: + add: + - SETFCAP + runAsUser: 0 + workingDir: $(workspaces.workspace.path)/hacbs/$(context.task.name) + workspaces: + - name: workspace diff --git a/auto-generated/task/fbc-validation/0.2/tekton.dev_v1_task_fbc-validation.yaml b/auto-generated/task/fbc-validation/0.2/tekton.dev_v1_task_fbc-validation.yaml new file mode 100644 index 0000000000..8d88382556 --- /dev/null +++ b/auto-generated/task/fbc-validation/0.2/tekton.dev_v1_task_fbc-validation.yaml @@ -0,0 +1,278 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + annotations: + build.appstudio.redhat.com/expires-on: "2025-01-31T00:00:00Z" + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: konflux + labels: + app.kubernetes.io/version: "0.2" + name: fbc-validation +spec: + description: Ensures file-based catalog (FBC) components are uniquely linted for + proper construction as part of build pipeline. + params: + - description: Fully qualified image name. + name: IMAGE_URL + - description: Image digest. + name: IMAGE_DIGEST + - description: Fully qualified base image name. + name: BASE_IMAGE + results: + - description: Tekton task test output. + name: TEST_OUTPUT + steps: + - computeResources: + limits: + memory: 4Gi + requests: + cpu: 10m + memory: 512Mi + env: + - name: IMAGE_URL + value: $(params.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(params.IMAGE_DIGEST) + - name: BASE_IMAGE + value: $(params.BASE_IMAGE) + image: quay.io/konflux-ci/konflux-test:v1.4.8@sha256:2224fabdb0a28a415d4af4c58ae53d7c4c53c83c315f12e07d1d7f48a80bfa70 + name: extract-and-check-binaries + script: | + #!/usr/bin/env bash + set -euo pipefail + source /utils.sh + trap 'handle_error $(results.TEST_OUTPUT.path)' EXIT + + declare -a ALLOWED_BASE_IMAGES=( + "registry.redhat.io/openshift4/ose-operator-registry" + "registry.redhat.io/openshift4/ose-operator-registry-rhel9" + "brew.registry.redhat.io/rh-osbs/openshift-ose-operator-registry-rhel9" + ) + + ### FBC base image check + if [ -z "${BASE_IMAGE}" ]; then + echo "Base image is unknown. The file-based catalog must have base image defined. Check inspect-image task log." + note="Task $(context.task.name) failed: The file-based catalog must have base image defined. For details, check Tekton task result TEST_OUTPUT in task inspect-image." + TEST_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + + IMAGE_WITHOUT_TAG=$(echo "${BASE_IMAGE}" | sed "s/:.*$//" | sed "s/@.*$//") + + allowed=false + for value in "${ALLOWED_BASE_IMAGES[@]}" + do + if [[ "${IMAGE_WITHOUT_TAG}" == "${value}" ]]; then + allowed=true + break + fi + done + + if [[ "${allowed}" == false ]]; then + echo "Base image ${BASE_IMAGE} is not allowed for the file based catalog image. Allowed images: ${ALLOWED_BASE_IMAGES}" + note="Task $(context.task.name) failed: Base image ${BASE_IMAGE} is not allowed for the file based catalog image. For details, check Tekton task logs" + TEST_OUTPUT=$(make_result_json -r FAILURE -f 1 -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + + ### Try to extract binaries with configs > check binaries functionality > check opm validate ### + if [ ! -s ../inspect-image/image_inspect.json ]; then + echo "File $(workspaces.workspace.path)/hacbs/inspect-image/image_inspect.json did not generate correctly. Check inspect-image task log." + note="Task $(context.task.name) failed: $(workspaces.workspace.path)/hacbs/inspect-image/image_inspect.json did not generate correctly. For details, check Tekton task result TEST_OUTPUT in task inspect-image." + TEST_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + + if [ ! -s ../inspect-image/raw_image_inspect.json ]; then + echo "File $(workspaces.workspace.path)/hacbs/inspect-image/raw_image_inspect.json did not generate correctly. Check inspect-image task log." + note="Task $(context.task.name) failed: $(workspaces.workspace.path)/hacbs/inspect-image/raw_image_inspect.json did not generate correctly. For details, check Tekton task result TEST_OUTPUT in task inspect-image." + TEST_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + + echo "Getting base image for source image ${IMAGE_URL}." + base_image_name="$(jq -r ".annotations.\"org.opencontainers.image.base.name\"" ../inspect-image/raw_image_inspect.json)" || status=$? + if [ "$base_image_name" == 'null' ]; then + echo "Could not get annotations from inspect-image/raw_image_inspect.json. Make sure file exists and it contains this annotation: org.opencontainers.image.base.name" + echo "Try to get base image from label..." + base_image_name="$(jq -r ".Labels.\"org.opencontainers.image.base.name\"" ../inspect-image/image_inspect.json)" || status=$? + if [ "$base_image_name" == 'null' ]; then + echo "Cannot get base image info from Labels. For details, check source image ../inspect-image/image_inspect.json." + TEST_OUTPUT="$(make_result_json -r ERROR)" + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + fi + if [ -z "$base_image_name" ]; then + echo "Source image ${IMAGE_URL} is built from scratch, so there is no base image." + TEST_OUTPUT="$(make_result_json -r ERROR)" + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + + status=0 + conffolder=$(jq -r '.Labels ."operators.operatorframework.io.index.configs.v1"' ../inspect-image/image_inspect.json) || status=$? + if [ $status -ne 0 ]; then + echo "Could not get labels from inspect-image/image_inspect.json. Make sure file exists and it contains this label: operators.operatorframework.io.index.configs.v1." + TEST_OUTPUT="$(make_result_json -r ERROR)" + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + exit 0 + fi + mkdir -p /tmp/image-content confdir + pushd /tmp/image-content + image_with_digest="${IMAGE_URL}@${IMAGE_DIGEST}" + + if ! oc image extract --registry-config ~/.docker/config.json "${image_with_digest}" ; then + echo "Unable to extract or validate extracted binaries." + note="Task $(context.task.name) failed: Failed to extract image with oc extract command, so it cannot validate extracted binaries. For details, check Tekton task log." + ERROR_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + popd + exit 0 + fi + + if [ -z "$(ls -A .$conffolder)" ]; then + echo "$conffolder is missing catalog file." + TEST_OUTPUT="$(make_result_json -r ERROR)" + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + popd + exit 0 + fi + # copy content of conffolder to confdir - will be used in next task - related image check + cp -r .$conffolder/* $(workspaces.workspace.path)/hacbs/$(context.task.name)/confdir + + EXTRACT_DIR="/extracted_base_img" + mkdir "${EXTRACT_DIR}" + if ! oc image extract ${BASE_IMAGE} --path /:"${EXTRACT_DIR}"; then + echo "Unable to extract opm binary" + note="Task $(context.task.name) failed: Failed to extract base image with oc extract command, so it cannot validate extracted binaries. For details, check Tekton task log." + ERROR_OUTPUT=$(make_result_json -r ERROR -t "$note") + exit 0 + fi + + OPM_BINARIES="$(find "${EXTRACT_DIR}" -type f -name opm)" + BINARIES_COUNT=$(wc -l <<< "${OPM_BINARIES}") + if [[ $BINARIES_COUNT -ne "1" ]]; then + note="Task $(context.task.name) failed: Expected exactly one opm binary in base image. For details, check Tekton task log" + ERROR_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${ERROR_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + echo "found $BINARIES_COUNT opm binaries:" + echo "${OPM_BINARIES}" + exit 0 + fi + OPM_BINARY=$(echo "${OPM_BINARIES}" | head -n 1) + echo "OPM_BINARY: '${OPM_BINARY}'" + chmod 775 "$OPM_BINARY" + + # We have 6 total checks + check_num=6 + failure_num=0 + TESTPASSED=true + + if [[ ! $(find . -name "grpc_health_probe") ]]; then + echo "!FAILURE! - grpc_health_probe binary presence check failed." + failure_num=$((failure_num + 1)) + TESTPASSED=false + fi + + if ! ${OPM_BINARY} validate ."${conffolder}"; then + echo "!FAILURE! - opm validate check failed." + failure_num=$((failure_num + 1)) + TESTPASSED=false + fi + + OPM_RENDERED_CATALOG=/tmp/catalog.json + ${OPM_BINARY} render ."${conffolder}" > ${OPM_RENDERED_CATALOG} + if [ ! -f ${OPM_RENDERED_CATALOG} ]; then + echo "!FAILURE! - unable to render the fragment FBC." + failure_num=$((failure_num + 1)) + TESTPASSED=false + fi + + if jq -en 'reduce (inputs | select(.schema == "olm.package")) as $obj (0; .+1) < 1' ${OPM_RENDERED_CATALOG}; then + echo "!FAILURE! - There are no olm package entries defined in this FBC fragment." + failure_num=$((failure_num + 1)) + TESTPASSED=false + fi + + # examines the base_image_name tag to derive the target OCP version + # assumes this is in the form + # image-path:[v]major-digits.minor-digits[@sha...] + OCP_VER_FROM_BASE=$(echo "${base_image_name}" | sed -e "s/@.*$//" -e "s/^.*://") # strips hash first due to greedy match + # extracts major digits and filters out any leading alphabetic characters, for e.g. 'v4' --> '4' + OCP_VER_MAJOR=$(echo "${OCP_VER_FROM_BASE}" | cut -d '.' -f 1 | sed "s/^[a-zA-Z]*//") + OCP_VER_MINOR=$(echo "${OCP_VER_FROM_BASE}" | cut -d '.' -f 2) + + RUN_OCP_VERSION_VALIDATION="false" + digits_regex='^[0-9]*$' + if [[ ${OCP_VER_MAJOR} =~ $digits_regex ]] && [[ ${OCP_VER_MINOR} =~ $digits_regex ]] ; then + RUN_OCP_VERSION_VALIDATION="true" + fi + + if [ "${RUN_OCP_VERSION_VALIDATION}" == "false" ] ; then + echo "!WARNING! - unable to assess bundle metadata alignment with OCP version because we cannot extract version info from base_image_name: ${base_image_name}" + else + OCP_BUNDLE_METADATA_THRESHOLD_MAJOR=4 + OCP_BUNDLE_METADATA_THRESHOLD_MINOR=17 + OCP_BUNDLE_METADATA_FORMAT="olm.bundle.object" + + if [[ "${OCP_VER_MAJOR}" -ge "${OCP_BUNDLE_METADATA_THRESHOLD_MAJOR}" ]] && [[ "${OCP_VER_MINOR}" -ge "${OCP_BUNDLE_METADATA_THRESHOLD_MINOR}" ]]; then + OCP_BUNDLE_METADATA_FORMAT="olm.csv.metadata" + fi + + # enforce the presence of either olm.csv.metadata or olm.bundle.object based on OCP version + if [[ "${OCP_BUNDLE_METADATA_FORMAT}" = "olm.csv.metadata" ]]; then + if ! jq -en 'reduce( inputs | select(.schema == "olm.bundle" and .properties[].type == "olm.bundle.object")) as $_ (0;.+1) == 0' ${OPM_RENDERED_CATALOG}; then + echo "!FAILURE! - olm.bundle.object bundle properties are not permitted in a FBC fragment for OCP version ${OCP_VER_MAJOR}.${OCP_VER_MINOR}. Fragments must move to olm.csv.metadata bundle metadata." + failure_num=$((failure_num + 1)) + TESTPASSED=false + fi + else + if ! jq -en 'reduce( inputs | select(.schema == "olm.bundle" and .properties[].type == "olm.csv.metadata")) as $_ (0;.+1) == 0' ${OPM_RENDERED_CATALOG}; then + echo "!FAILURE! - olm.csv.metadata bundle properties are not permitted in a FBC fragment for OCP version ${OCP_VER_MAJOR}.${OCP_VER_MINOR}. Fragments must only use olm.bundle.object bundle metadata." + failure_num=$((failure_num + 1)) + TESTPASSED=false + fi + fi + + # enforce that each bundle has the OCP-version-appropriate bundle metadata. + BUNDLE_COUNT=$(jq -en 'def count(stream): reduce stream as $i (0; .+1); count(inputs|select(.schema=="olm.bundle"))' ${OPM_RENDERED_CATALOG}) + BUNDLE_BO_COUNT=$(jq -en 'def count(stream): reduce stream as $i (0; .+1); count(inputs|select(.schema == "olm.bundle" and .properties[].type == "olm.bundle.object"))' ${OPM_RENDERED_CATALOG}) + BUNDLE_CM_COUNT=$(jq -en 'def count(stream): reduce stream as $i (0; .+1); count(inputs|select(.schema == "olm.bundle" and .properties[].type == "olm.csv.metadata"))' ${OPM_RENDERED_CATALOG}) + + if [[ "${OCP_BUNDLE_METADATA_FORMAT}" = "olm.csv.metadata" ]]; then + if [[ "${BUNDLE_COUNT}" -ne "${BUNDLE_CM_COUNT}" ]]; then + echo "!FAILURE! - every olm.bundle object in the fragment must have a corresponding olm.csv.metadata bundle property" + failure_num=$((failure_num + 1)) + TESTPASSED=false + fi + else + if [[ "${BUNDLE_BO_COUNT}" -lt "${BUNDLE_COUNT}" ]]; then + echo "!FAILURE! - every olm.bundle object in the fragment must have at least one olm.bundle.object bundle property" + failure_num=$((failure_num + 1)) + TESTPASSED=false + fi + fi + fi + + note="Task $(context.task.name) completed: Check result for task result." + if [ $TESTPASSED == false ]; then + ERROR_OUTPUT=$(make_result_json -r FAILURE -f $failure_num -s $((check_num - failure_num)) -t "$note") + echo "${ERROR_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + else + TEST_OUTPUT=$(make_result_json -r SUCCESS -s $check_num -t "$note") + echo "${TEST_OUTPUT}" | tee "$(results.TEST_OUTPUT.path)" + fi + popd + securityContext: + capabilities: + add: + - SETFCAP + runAsUser: 0 + workingDir: $(workspaces.workspace.path)/hacbs/$(context.task.name) + workspaces: + - name: workspace diff --git a/auto-generated/task/generate-odcs-compose/0.1/tekton.dev_v1beta1_task_generate-odcs-compose.yaml b/auto-generated/task/generate-odcs-compose/0.1/tekton.dev_v1beta1_task_generate-odcs-compose.yaml new file mode 100644 index 0000000000..62679ae57e --- /dev/null +++ b/auto-generated/task/generate-odcs-compose/0.1/tekton.dev_v1beta1_task_generate-odcs-compose.yaml @@ -0,0 +1,51 @@ +apiVersion: tekton.dev/v1beta1 +kind: Task +metadata: + name: generate-odcs-compose +spec: + params: + - default: compose_inputs.yaml + description: relative path from workdir workspace to the compose inputs file + name: COMPOSE_INPUTS + - default: repos + description: relative path from workdir workspace to store compose output files + name: COMPOSE_OUTPUTS + results: + - description: Directory to write the result .repo files. + name: repodir_path + steps: + - env: + - name: CLIENT_ID + valueFrom: + secretKeyRef: + key: client-id + name: odcs-service-account + - name: CLIENT_SECRET + valueFrom: + secretKeyRef: + key: client-secret + name: odcs-service-account + - name: COMPOSE_INPUTS + value: $(params.COMPOSE_INPUTS) + - name: COMPOSE_OUTPUTS + value: $(params.COMPOSE_OUTPUTS) + image: quay.io/redhat-appstudio/tools@sha256:ca3b24bb2f2935aa31426941687ed0c105bde89e25595c25e5543e87e1b51701 + name: generate-odcs-compose + script: | + #!/bin/bash + set -ex + + repodir_path="$(workspaces.workdir.path)/${COMPOSE_OUTPUTS}" + + cd "$(workspaces.workdir.path)" + + odcs_compose_generator \ + --compose-input-yaml-path "${COMPOSE_INPUTS}" \ + --compose-dir-path "${repodir_path}" + + echo "$repodir_path" > $(results.repodir_path.path) + workspaces: + - description: | + Working directory that will be used for reading configuration files + and writing the output + name: workdir diff --git a/auto-generated/task/generate-odcs-compose/0.2/tekton.dev_v1beta1_task_generate-odcs-compose.yaml b/auto-generated/task/generate-odcs-compose/0.2/tekton.dev_v1beta1_task_generate-odcs-compose.yaml new file mode 100644 index 0000000000..b534a73ef1 --- /dev/null +++ b/auto-generated/task/generate-odcs-compose/0.2/tekton.dev_v1beta1_task_generate-odcs-compose.yaml @@ -0,0 +1,51 @@ +apiVersion: tekton.dev/v1beta1 +kind: Task +metadata: + name: generate-odcs-compose +spec: + params: + - default: source/compose_inputs.yaml + description: relative path from workdir workspace to the compose inputs file + name: COMPOSE_INPUTS + - default: fetched.repos.d + description: relative path from workdir workspace to store compose output files + name: COMPOSE_OUTPUTS + results: + - description: Directory to write the result .repo files. + name: repodir_path + steps: + - env: + - name: CLIENT_ID + valueFrom: + secretKeyRef: + key: client-id + name: odcs-service-account + - name: CLIENT_SECRET + valueFrom: + secretKeyRef: + key: client-secret + name: odcs-service-account + - name: COMPOSE_INPUTS + value: $(params.COMPOSE_INPUTS) + - name: COMPOSE_OUTPUTS + value: $(params.COMPOSE_OUTPUTS) + image: quay.io/redhat-appstudio/tools@sha256:ca3b24bb2f2935aa31426941687ed0c105bde89e25595c25e5543e87e1b51701 + name: generate-odcs-compose + script: | + #!/bin/bash + set -ex + + repodir_path="$(workspaces.workdir.path)/${COMPOSE_OUTPUTS}" + + cd "$(workspaces.workdir.path)" + + odcs_compose_generator \ + --compose-input-yaml-path "${COMPOSE_INPUTS}" \ + --compose-dir-path "${repodir_path}" + + echo "$repodir_path" > $(results.repodir_path.path) + workspaces: + - description: | + Working directory that will be used for reading configuration files + and writing the output + name: workdir diff --git a/auto-generated/task/inspect-image/0.1/tekton.dev_v1beta1_task_inspect-image.yaml b/auto-generated/task/inspect-image/0.1/tekton.dev_v1beta1_task_inspect-image.yaml new file mode 100644 index 0000000000..1b25a128f5 --- /dev/null +++ b/auto-generated/task/inspect-image/0.1/tekton.dev_v1beta1_task_inspect-image.yaml @@ -0,0 +1,168 @@ +apiVersion: tekton.dev/v1beta1 +kind: Task +metadata: + annotations: + build.appstudio.redhat.com/expires-on: "2025-01-31T00:00:00Z" + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: konflux + labels: + app.kubernetes.io/version: "0.1" + name: inspect-image +spec: + description: Inspects and analyzes manifest data of the container's source image, + and its base image (if available) using Skopeo. An image's manifest data contains + information about the layers that make up the image, the platforms for which the + image is intended, and other metadata about the image. + params: + - description: Fully qualified image name. + name: IMAGE_URL + - description: Image digest. + name: IMAGE_DIGEST + type: string + - default: "" + description: unused, should be removed in next task version + name: DOCKER_AUTH + type: string + results: + - description: Base image source image is built from. + name: BASE_IMAGE + - description: Base image repository URL. + name: BASE_IMAGE_REPOSITORY + - description: Tekton task test output. + name: TEST_OUTPUT + steps: + - env: + - name: IMAGE_URL + value: $(params.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(params.IMAGE_DIGEST) + image: quay.io/konflux-ci/konflux-test:v1.4.8@sha256:2224fabdb0a28a415d4af4c58ae53d7c4c53c83c315f12e07d1d7f48a80bfa70 + name: inspect-image + script: | + #!/usr/bin/env bash + set -euo pipefail + source /utils.sh + trap 'handle_error $(results.TEST_OUTPUT.path)' EXIT + + IMAGE_INSPECT=image_inspect.json + BASE_IMAGE_INSPECT=base_image_inspect.json + RAW_IMAGE_INSPECT=raw_image_inspect.json + + IMAGE_URL="${IMAGE_URL}@${IMAGE_DIGEST}" + # Given a tag and a the digest in the IMAGE_URL we opt to use the digest alone + # this is because containers/image currently doesn't support image references + # that contain both. See https://github.com/containers/image/issues/1736 + if [[ "${IMAGE_URL}" == *":"*"@"* ]]; then + IMAGE_URL="${IMAGE_URL/:*@/@}" + fi + + status=-1 + max_run=5 + sleep_sec=10 + for run in $(seq 1 $max_run); do + status=0 + [ "$run" -gt 1 ] && sleep $sleep_sec # skip last sleep + echo "Inspecting manifest for source image ${IMAGE_URL} (try $run/$max_run)." + skopeo inspect --no-tags docker://"${IMAGE_URL}" > $IMAGE_INSPECT && break || status=$? + done + if [ "$status" -ne 0 ]; then + echo "Failed to inspect image ${IMAGE_URL}" + note="Task $(context.task.name) failed: Encountered errors while inspecting image. For details, check Tekton task log." + TEST_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${TEST_OUTPUT}" | tee $(results.TEST_OUTPUT.path) + exit 0 + fi + echo "Image ${IMAGE_URL} metadata:" + cat "$IMAGE_INSPECT" + + run=1 + while [ "$run" -le "$max_run" ]; do + status=0 + [ "$run" -gt 1 ] && sleep $sleep_sec # skip last sleep + echo "Inspecting raw image manifest ${IMAGE_URL} (try $run/$max_run)." + skopeo inspect --no-tags --raw docker://"${IMAGE_URL}" > $RAW_IMAGE_INSPECT || status=$? + + if [ "$status" -eq 0 ] && [ "$(jq 'has("manifests")' ${RAW_IMAGE_INSPECT})" = "true" ]; then + echo "Found an image index, lookup for amd64 manifest" + INDEX_IMAGE_MANIFESTS=$(jq ' .manifests | map ( {(.platform.architecture|tostring|ascii_downcase): .digest} ) | add' "${RAW_IMAGE_INSPECT}" || true) + + AMD64_MANIFEST_DIGEST=$(jq -r '.amd64' <<< "${INDEX_IMAGE_MANIFESTS}" || true ) + if [ -z "$AMD64_MANIFEST_DIGEST" ]; then + # we didn't find amd64 platform, fail horribly as it's the required platform currently for all checks + echo "[ERROR] Could not find amd64 image manifest for image $IMAGE_URL" + note="Task $(context.task.name) failed: Couldn't find amd64 image manifest" + TEST_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${TEST_OUTPUT}" | tee $(results.TEST_OUTPUT.path) + exit 0 + fi + + # Replace image URL with new digest + IMAGE_URL="${IMAGE_URL/[@:]*/@$AMD64_MANIFEST_DIGEST}" + echo "Setting AMD64 specific image: $IMAGE_URL" + run=1 # reset runs, we are looking another image; new image, new life + else + break + fi + done + + if [ "$status" -ne 0 ]; then + echo "Failed to get raw metadata of image ${IMAGE_URL}" + note="Task $(context.task.name) failed: Encountered errors while inspecting image. For details, check Tekton task log." + TEST_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${TEST_OUTPUT}" | tee $(results.TEST_OUTPUT.path) + exit 0 + fi + + echo "Image ${IMAGE_URL} raw metadata:" + cat "$RAW_IMAGE_INSPECT" | jq # jq for readable formatting + + echo "Getting base image manifest for source image ${IMAGE_URL}." + BASE_IMAGE_NAME="$(jq -r ".annotations.\"org.opencontainers.image.base.name\"" $RAW_IMAGE_INSPECT)" + BASE_IMAGE_DIGEST="$(jq -r ".annotations.\"org.opencontainers.image.base.digest\"" $RAW_IMAGE_INSPECT)" + if [ $BASE_IMAGE_NAME == 'null' ]; then + echo "Cannot get base image info from annotations." + BASE_IMAGE_NAME="$(jq -r ".Labels.\"org.opencontainers.image.base.name\"" $IMAGE_INSPECT)" + BASE_IMAGE_DIGEST="$(jq -r ".annotations.\"org.opencontainers.image.base.digest\"" $IMAGE_INSPECT)" + if [ "$BASE_IMAGE_NAME" == 'null' ]; then + echo "Cannot get base image info from Labels. For details, check source image ${IMAGE_URL}." + exit 0 + fi + fi + if [ -z "$BASE_IMAGE_NAME" ]; then + echo "Source image ${IMAGE_URL} is built from scratch, so there is no base image." + exit 0 + fi + + BASE_IMAGE="${BASE_IMAGE_NAME%:*}@$BASE_IMAGE_DIGEST" + echo "Detected base image: $BASE_IMAGE" + echo -n "$BASE_IMAGE" > $(results.BASE_IMAGE.path) + + for run in $(seq 1 $max_run); do + status=0 + [ "$run" -gt 1 ] && sleep $sleep_sec # skip last sleep + echo "Inspecting base image ${BASE_IMAGE} (try $run/$max_run)." + skopeo inspect --no-tags "docker://$BASE_IMAGE" > $BASE_IMAGE_INSPECT && break || status=$? + done + if [ "$status" -ne 0 ]; then + echo "Failed to inspect base image ${BASE_IMAGE}" + note="Task $(context.task.name) failed: Encountered errors while inspecting image. For details, check Tekton task log." + TEST_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${TEST_OUTPUT}" | tee $(results.TEST_OUTPUT.path) + exit 0 + fi + + BASE_IMAGE_REPOSITORY="$(jq -r '.Name | sub("[^/]+/"; "") | sub("[:@].*"; "")' "$BASE_IMAGE_INSPECT")" + echo "Detected base image repository: $BASE_IMAGE_REPOSITORY" + echo -n "$BASE_IMAGE_REPOSITORY" > $(results.BASE_IMAGE_REPOSITORY.path) + + note="Task $(context.task.name) completed: Check inspected JSON files under $(workspaces.source.path)/hacbs/$(context.task.name)." + TEST_OUTPUT=$(make_result_json -r SUCCESS -s 1 -t "$note") + echo "${TEST_OUTPUT}" | tee $(results.TEST_OUTPUT.path) + securityContext: + capabilities: + add: + - SETFCAP + runAsUser: 0 + workingDir: $(workspaces.source.path)/hacbs/$(context.task.name) + workspaces: + - name: source diff --git a/auto-generated/task/inspect-image/0.2/tekton.dev_v1beta1_task_inspect-image.yaml b/auto-generated/task/inspect-image/0.2/tekton.dev_v1beta1_task_inspect-image.yaml new file mode 100644 index 0000000000..8c78172d0d --- /dev/null +++ b/auto-generated/task/inspect-image/0.2/tekton.dev_v1beta1_task_inspect-image.yaml @@ -0,0 +1,168 @@ +apiVersion: tekton.dev/v1beta1 +kind: Task +metadata: + annotations: + build.appstudio.redhat.com/expires-on: "2025-01-31T00:00:00Z" + tekton.dev/pipelines.minVersion: 0.12.1 + tekton.dev/tags: konflux + labels: + app.kubernetes.io/version: "0.2" + name: inspect-image +spec: + description: Inspects and analyzes manifest data of the container's source image, + and its base image (if available) using Skopeo. An image's manifest data contains + information about the layers that make up the image, the platforms for which the + image is intended, and other metadata about the image. + params: + - description: Fully qualified image name. + name: IMAGE_URL + - description: Image digest. + name: IMAGE_DIGEST + type: string + - default: "" + description: unused, should be removed in next task version + name: DOCKER_AUTH + type: string + results: + - description: Base image source image is built from. + name: BASE_IMAGE + - description: Base image repository URL. + name: BASE_IMAGE_REPOSITORY + - description: Tekton task test output. + name: TEST_OUTPUT + steps: + - env: + - name: IMAGE_URL + value: $(params.IMAGE_URL) + - name: IMAGE_DIGEST + value: $(params.IMAGE_DIGEST) + image: quay.io/konflux-ci/konflux-test:v1.4.8@sha256:2224fabdb0a28a415d4af4c58ae53d7c4c53c83c315f12e07d1d7f48a80bfa70 + name: inspect-image + script: | + #!/usr/bin/env bash + set -euo pipefail + source /utils.sh + trap 'handle_error $(results.TEST_OUTPUT.path)' EXIT + + IMAGE_INSPECT=image_inspect.json + BASE_IMAGE_INSPECT=base_image_inspect.json + RAW_IMAGE_INSPECT=raw_image_inspect.json + + IMAGE_URL="${IMAGE_URL}@${IMAGE_DIGEST}" + # Given a tag and a the digest in the IMAGE_URL we opt to use the digest alone + # this is because containers/image currently doesn't support image references + # that contain both. See https://github.com/containers/image/issues/1736 + if [[ "${IMAGE_URL}" == *":"*"@"* ]]; then + IMAGE_URL="${IMAGE_URL/:*@/@}" + fi + + status=-1 + max_run=5 + sleep_sec=10 + for run in $(seq 1 $max_run); do + status=0 + [ "$run" -gt 1 ] && sleep $sleep_sec # skip last sleep + echo "Inspecting manifest for source image ${IMAGE_URL} (try $run/$max_run)." + skopeo inspect --no-tags docker://"${IMAGE_URL}" > $IMAGE_INSPECT && break || status=$? + done + if [ "$status" -ne 0 ]; then + echo "Failed to inspect image ${IMAGE_URL}" + note="Task $(context.task.name) failed: Encountered errors while inspecting image. For details, check Tekton task log." + TEST_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${TEST_OUTPUT}" | tee $(results.TEST_OUTPUT.path) + exit 0 + fi + echo "Image ${IMAGE_URL} metadata:" + cat "$IMAGE_INSPECT" + + run=1 + while [ "$run" -le "$max_run" ]; do + status=0 + [ "$run" -gt 1 ] && sleep $sleep_sec # skip last sleep + echo "Inspecting raw image manifest ${IMAGE_URL} (try $run/$max_run)." + skopeo inspect --no-tags --raw docker://"${IMAGE_URL}" > $RAW_IMAGE_INSPECT || status=$? + + if [ "$status" -eq 0 ] && [ "$(jq 'has("manifests")' ${RAW_IMAGE_INSPECT})" = "true" ]; then + echo "Found an image index, lookup for amd64 manifest" + INDEX_IMAGE_MANIFESTS=$(jq ' .manifests | map ( {(.platform.architecture|tostring|ascii_downcase): .digest} ) | add' "${RAW_IMAGE_INSPECT}" || true) + + AMD64_MANIFEST_DIGEST=$(jq -r '.amd64' <<< "${INDEX_IMAGE_MANIFESTS}" || true ) + if [ -z "$AMD64_MANIFEST_DIGEST" ]; then + # we didn't find amd64 platform, fail horribly as it's the required platform currently for all checks + echo "[ERROR] Could not find amd64 image manifest for image $IMAGE_URL" + note="Task $(context.task.name) failed: Couldn't find amd64 image manifest" + TEST_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${TEST_OUTPUT}" | tee $(results.TEST_OUTPUT.path) + exit 0 + fi + + # Replace image URL with new digest + IMAGE_URL="${IMAGE_URL/[@:]*/@$AMD64_MANIFEST_DIGEST}" + echo "Setting AMD64 specific image: $IMAGE_URL" + run=1 # reset runs, we are looking another image; new image, new life + else + break + fi + done + + if [ "$status" -ne 0 ]; then + echo "Failed to get raw metadata of image ${IMAGE_URL}" + note="Task $(context.task.name) failed: Encountered errors while inspecting image. For details, check Tekton task log." + TEST_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${TEST_OUTPUT}" | tee $(results.TEST_OUTPUT.path) + exit 0 + fi + + echo "Image ${IMAGE_URL} raw metadata:" + cat "$RAW_IMAGE_INSPECT" | jq # jq for readable formatting + + echo "Getting base image manifest for source image ${IMAGE_URL}." + BASE_IMAGE_NAME="$(jq -r ".annotations.\"org.opencontainers.image.base.name\"" $RAW_IMAGE_INSPECT)" + BASE_IMAGE_DIGEST="$(jq -r ".annotations.\"org.opencontainers.image.base.digest\"" $RAW_IMAGE_INSPECT)" + if [ $BASE_IMAGE_NAME == 'null' ]; then + echo "Cannot get base image info from annotations." + BASE_IMAGE_NAME="$(jq -r ".Labels.\"org.opencontainers.image.base.name\"" $IMAGE_INSPECT)" + BASE_IMAGE_DIGEST="$(jq -r ".annotations.\"org.opencontainers.image.base.digest\"" $IMAGE_INSPECT)" + if [ "$BASE_IMAGE_NAME" == 'null' ]; then + echo "Cannot get base image info from Labels. For details, check source image ${IMAGE_URL}." + exit 0 + fi + fi + if [ -z "$BASE_IMAGE_NAME" ]; then + echo "Source image ${IMAGE_URL} is built from scratch, so there is no base image." + exit 0 + fi + + BASE_IMAGE="${BASE_IMAGE_NAME%:*}@$BASE_IMAGE_DIGEST" + echo "Detected base image: $BASE_IMAGE" + echo -n "$BASE_IMAGE" > $(results.BASE_IMAGE.path) + + for run in $(seq 1 $max_run); do + status=0 + [ "$run" -gt 1 ] && sleep $sleep_sec # skip last sleep + echo "Inspecting base image ${BASE_IMAGE} (try $run/$max_run)." + skopeo inspect --no-tags "docker://$BASE_IMAGE" > $BASE_IMAGE_INSPECT && break || status=$? + done + if [ "$status" -ne 0 ]; then + echo "Failed to inspect base image ${BASE_IMAGE}" + note="Task $(context.task.name) failed: Encountered errors while inspecting image. For details, check Tekton task log." + TEST_OUTPUT=$(make_result_json -r ERROR -t "$note") + echo "${TEST_OUTPUT}" | tee $(results.TEST_OUTPUT.path) + exit 0 + fi + + BASE_IMAGE_REPOSITORY="$(jq -r '.Name | sub("[^/]+/"; "") | sub("[:@].*"; "")' "$BASE_IMAGE_INSPECT")" + echo "Detected base image repository: $BASE_IMAGE_REPOSITORY" + echo -n "$BASE_IMAGE_REPOSITORY" > $(results.BASE_IMAGE_REPOSITORY.path) + + note="Task $(context.task.name) completed: Check inspected JSON files under $(workspaces.source.path)/hacbs/$(context.task.name)." + TEST_OUTPUT=$(make_result_json -r SUCCESS -s 1 -t "$note") + echo "${TEST_OUTPUT}" | tee $(results.TEST_OUTPUT.path) + securityContext: + capabilities: + add: + - SETFCAP + runAsUser: 0 + workingDir: $(workspaces.source.path)/hacbs/$(context.task.name) + workspaces: + - name: source diff --git a/auto-generated/task/provision-env-with-ephemeral-namespace/0.1/tekton.dev_v1_task_provision-env-with-ephemeral-namespace.yaml b/auto-generated/task/provision-env-with-ephemeral-namespace/0.1/tekton.dev_v1_task_provision-env-with-ephemeral-namespace.yaml new file mode 100644 index 0000000000..762379aade --- /dev/null +++ b/auto-generated/task/provision-env-with-ephemeral-namespace/0.1/tekton.dev_v1_task_provision-env-with-ephemeral-namespace.yaml @@ -0,0 +1,55 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + name: provision-env-with-ephemeral-namespace +spec: + params: + - name: KONFLUXNAMESPACE + type: string + - name: PIPELINERUN_NAME + type: string + - name: PIPELINERUN_UID + type: string + results: + - description: SecretRef is the name of the secret with a SA token that has admin-like + (or whatever we set in the tier template) permissions in the namespace + name: secretRef + type: string + steps: + - env: + - name: KONFLUXNAMESPACE + value: $(params.KONFLUXNAMESPACE) + - name: PIPELINERUN_NAME + value: $(params.PIPELINERUN_NAME) + - name: PIPELINERUN_UID + value: $(params.PIPELINERUN_UID) + image: registry.redhat.io/openshift4/ose-cli:4.13@sha256:73df37794ffff7de1101016c23dc623e4990810390ebdabcbbfa065214352c7c + name: request-ephemeral-namespace + script: | + #!/bin/bash + set -ex + set -o pipefail + + cat < space_request.yaml + apiVersion: toolchain.dev.openshift.com/v1alpha1 + kind: SpaceRequest + metadata: + generateName: task-spacerequest- + namespace: $KONFLUXNAMESPACE + ownerReferences: + - apiVersion: tekton.dev/v1 + kind: PipelineRun + name: $PIPELINERUN_NAME + uid: $PIPELINERUN_UID + spec: + tierName: appstudio-env + EOF + + SPACEREQUEST_NAME=$(oc create -f space_request.yaml -o=jsonpath='{.metadata.name}') + + if oc wait spacerequests $SPACEREQUEST_NAME --for=condition=Ready --timeout=5m -n $KONFLUXNAMESPACE; then + secretRef=$(oc get spacerequests $SPACEREQUEST_NAME -o=jsonpath='{.status.namespaceAccess[0].secretRef}') + echo -n $secretRef | tee $(results.secretRef.path) + else + exit 1 + fi diff --git a/auto-generated/task/verify-enterprise-contract/0.1/tekton.dev_v1_task_verify-enterprise-contract.yaml b/auto-generated/task/verify-enterprise-contract/0.1/tekton.dev_v1_task_verify-enterprise-contract.yaml new file mode 100644 index 0000000000..220c2196cd --- /dev/null +++ b/auto-generated/task/verify-enterprise-contract/0.1/tekton.dev_v1_task_verify-enterprise-contract.yaml @@ -0,0 +1,181 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + annotations: + tekton.dev/displayName: Verify Enterprise Contract + tekton.dev/pipelines.minVersion: "0.19" + tekton.dev/tags: ec, chains, signature, conftest + labels: + app.kubernetes.io/version: "0.1" + name: verify-enterprise-contract +spec: + description: Verify the enterprise contract is met + params: + - description: | + Spec section of an ApplicationSnapshot resource. Not all fields of the + resource are required. A minimal example: + { + "components": [ + { + "containerImage": "quay.io/example/repo:latest" + } + ] + } + Each "containerImage" in the "components" array is validated. + name: IMAGES + type: string + - default: enterprise-contract-service/default + description: | + Name of the policy configuration (EnterpriseContractPolicy + resource) to use. `namespace/name` or `name` syntax supported. If + namespace is omitted the namespace where the task runs is used. + name: POLICY_CONFIGURATION + type: string + - default: "" + description: Public key used to verify signatures. Must be a valid k8s cosign + reference, e.g. k8s://my-space/my-secret where my-secret contains the expected + cosign.pub attribute. + name: PUBLIC_KEY + type: string + - default: "" + description: Rekor host for transparency log lookups + name: REKOR_HOST + type: string + - default: "false" + description: Skip Rekor transparency log checks during validation. + name: IGNORE_REKOR + type: string + - default: "" + description: TUF mirror URL. Provide a value when NOT using public sigstore deployment. + name: TUF_MIRROR + type: string + - default: "" + description: | + Path to a directory containing SSL certs to be used when communicating + with external services. This is useful when using the integrated registry + and a local instance of Rekor on a development cluster which may use + certificates issued by a not-commonly trusted root CA. In such cases, + "/var/run/secrets/kubernetes.io/serviceaccount" is a good value. Multiple + paths can be provided by using the ":" separator. + name: SSL_CERT_DIR + type: string + - default: "true" + description: Include rule titles and descriptions in the output. Set to "false" + to disable it. + name: INFO + type: string + - default: "true" + description: Fail the task if policy fails. Set to "false" to disable it. + name: STRICT + type: string + - default: /tekton/home + description: Value for the HOME environment variable. + name: HOMEDIR + type: string + - default: now + description: Run policy checks with the provided time. + name: EFFECTIVE_TIME + type: string + results: + - description: Short summary of the policy evaluation for each image + name: TEST_OUTPUT + stepTemplate: + env: + - name: HOME + value: $(params.HOMEDIR) + steps: + - args: + - version + command: + - ec + image: registry.redhat.io/rhtas/ec-rhel9:0.2 + name: version + - env: + - name: TUF_MIRROR + value: $(params.TUF_MIRROR) + image: registry.redhat.io/rhtas/ec-rhel9:0.2 + name: initialize-tuf + script: |- + set -euo pipefail + + if [[ -z "${TUF_MIRROR:-}" ]]; then + echo 'TUF_MIRROR not set. Skipping TUF root initialization.' + exit + fi + + echo 'Initializing TUF root...' + cosign initialize --mirror "${TUF_MIRROR}" --root "${TUF_MIRROR}/root.json" + echo 'Done!' + - args: + - validate + - image + - --verbose + - --images + - $(params.IMAGES) + - --policy + - $(params.POLICY_CONFIGURATION) + - --public-key + - $(params.PUBLIC_KEY) + - --rekor-url + - $(params.REKOR_HOST) + - --ignore-rekor=$(params.IGNORE_REKOR) + - --info=$(params.INFO) + - --strict=false + - --show-successes + - --effective-time=$(params.EFFECTIVE_TIME) + - --output + - yaml=$(params.HOMEDIR)/report.yaml + - --output + - appstudio=$(results.TEST_OUTPUT.path) + - --output + - json=$(params.HOMEDIR)/report-json.json + command: + - ec + computeResources: + limits: + memory: 2Gi + requests: + cpu: 250m + memory: 2Gi + env: + - name: SSL_CERT_DIR + value: /tekton-custom-certs:/etc/ssl/certs:/etc/pki/tls/certs:/system/etc/security/cacerts:$(params.SSL_CERT_DIR) + - name: EC_CACHE + value: "false" + image: registry.redhat.io/rhtas/ec-rhel9:0.2 + name: validate + - args: + - $(params.HOMEDIR)/report.yaml + command: + - cat + image: registry.redhat.io/rhtas/ec-rhel9:0.2 + name: report + - args: + - $(params.HOMEDIR)/report-json.json + command: + - cat + image: registry.redhat.io/rhtas/ec-rhel9:0.2 + name: report-json + - args: + - . + - $(results.TEST_OUTPUT.path) + command: + - jq + image: registry.redhat.io/rhtas/ec-rhel9:0.2 + name: summary + - args: + - --argjson + - strict + - $(params.STRICT) + - -e + - | + .result == "SUCCESS" or .result == "WARNING" or ($strict | not) + - $(results.TEST_OUTPUT.path) + command: + - jq + image: registry.redhat.io/rhtas/ec-rhel9:0.2 + name: assert + workspaces: + - description: The workspace where the snapshot spec json file resides + name: data + optional: true diff --git a/auto-generated/task/verify-signed-rpms/0.1/tekton.dev_v1_task_verify-signed-rpms.yaml b/auto-generated/task/verify-signed-rpms/0.1/tekton.dev_v1_task_verify-signed-rpms.yaml new file mode 100644 index 0000000000..f74a129d64 --- /dev/null +++ b/auto-generated/task/verify-signed-rpms/0.1/tekton.dev_v1_task_verify-signed-rpms.yaml @@ -0,0 +1,70 @@ +apiVersion: tekton.dev/v1 +kind: Task +metadata: + name: verify-signed-rpms +spec: + params: + - description: AppStudio snapshot or a reference to a container image + name: INPUT + type: string + - default: "" + description: '[true | false] If true fail if unsigned RPMs were found' + name: FAIL_UNSIGNED + type: string + - default: /tmp + description: | + Directory that will be used for storing temporary + files produced by this task. + name: WORKDIR + type: string + results: + - description: Tekton task test output. + name: TEST_OUTPUT + steps: + - env: + - name: INPUT + value: $(params.INPUT) + - name: FAIL_UNSIGNED + value: $(params.FAIL_UNSIGNED) + - name: WORKDIR + value: $(params.WORKDIR) + image: quay.io/redhat-appstudio/tools:39497ad4e7761c90fdde580cbb5bce9cb9491427 + name: verify-signed-rpms + script: | + #!/bin/bash + set -ex + set -o pipefail + + rpm_verifier \ + --input "${INPUT}" \ + --fail-unsigned "${FAIL_UNSIGNED}" \ + --workdir "${WORKDIR}" \ + --status-path "${WORKDIR}"/status + volumeMounts: + - mountPath: $(params.WORKDIR) + name: workdir + - env: + - name: WORKDIR + value: $(params.WORKDIR) + image: quay.io/konflux-ci/konflux-test:v1.4.9@sha256:eee855e60b437d9a55a30e63f2eb7f95d9fd6d3b111c32cac8730c9b7a071394 + name: output-results + script: | + #!/bin/bash + set -ex + + source /utils.sh + status=`cat "${WORKDIR}"/status` + if [ "$status" == "ERROR" ]; then + note="Task $(context.task.name) completed: Not all RPMs were confirmed to be signed. Refer to Tekton task output for details" + else + note="Task $(context.task.name) completed: No unsigned RPMs" + fi + + TEST_OUTPUT=$(make_result_json -r "$status" -t "$note") + echo "${TEST_OUTPUT}" | tee $(results.TEST_OUTPUT.path) + volumeMounts: + - mountPath: $(params.WORKDIR) + name: workdir + volumes: + - emptyDir: {} + name: workdir diff --git a/hack/build-manifests.sh b/hack/build-manifests.sh new file mode 100755 index 0000000000..7a88bee0a0 --- /dev/null +++ b/hack/build-manifests.sh @@ -0,0 +1,46 @@ +#!/bin/bash -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" + +main() { + local kustomize=${1:-kustomize} + local dirs + + cd "$SCRIPT_DIR/.." + task_dirs=$(find task -maxdepth 4 \( -name 'kustomization.yaml' -o -name 'kustomization.yml' \) -exec dirname {} \;) + pipeline_dirs=$(find pipelines -maxdepth 3 \( -name 'kustomization.yaml' -o -name 'kustomization.yml' \) -exec dirname {} \;) + local out=auto-generated + local ret=0 + rm -rf "$out" + mkdir -p "$out" + + for d in ${task_dirs}; do + echo "Building task directory: ${d}" + o="${out}/${d}" + mkdir -p "$o" + if ! "$kustomize" build -o "$o" "$d"; then + echo "failed to build task: $d" >&2 + ret=1 + fi + done + + for d in ${pipeline_dirs}; do + echo "Building pipeline directory: ${d}" + o="${out}/${d}" + mkdir -p "$o" + if ! "$kustomize" build -o "$o" "$d"; then + echo "failed to build pipeline: $d" >&2 + ret=1 + fi + done + + exit "$ret" + +} + +if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then + main "$@" +fi + + + diff --git a/hack/get-kustomize.sh b/hack/get-kustomize.sh new file mode 100755 index 0000000000..281165b8ee --- /dev/null +++ b/hack/get-kustomize.sh @@ -0,0 +1,20 @@ +#!/bin/bash -e + +main() { + local target_dir=${1:?target dir for storing kustomize should be specified} + + mkdir -p "$target_dir" + if [[ -f "${target_dir}/kustomize" ]]; then + exit 0 + fi + + curl -L https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv5.3.0/kustomize_v5.3.0_linux_amd64.tar.gz | tar -C "$target_dir" -xvzf - + + ls -l "$target_dir" + echo "PATH -> $PATH" +} + + +if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then + main "$@" +fi diff --git a/hack/verify-manifests.sh b/hack/verify-manifests.sh new file mode 100755 index 0000000000..1562907aea --- /dev/null +++ b/hack/verify-manifests.sh @@ -0,0 +1,22 @@ +#!/bin/bash -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" + +main() { + local kustomize=${1:-kustomize} + + rm -rf "${SCRIPT_DIR}/../auto-generated" + "${SCRIPT_DIR}"/build-manifests.sh "$kustomize" + if [[ $(git status --porcelain) ]]; then + git diff --exit-code >&2 || { + echo "Did you forget to build the manifests locally?" >&2; + echo "Please run ./hack/build-manifests.sh and update your PR" >&2; + exit 1; + } + fi + echo "the auto-generated directory is up to date" >&2 +} + +if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then + main "$@" +fi