From d975442a4878fa14502029b934451a0cef68170a Mon Sep 17 00:00:00 2001 From: Yashvardhan Nanavati Date: Tue, 10 Dec 2024 02:17:59 -0800 Subject: [PATCH] feat: add fbc-fips-check task Refers to CVP-4334. This task is used to verify FIPS compliance of unreleased bundles in an FBC fragment. FBC fragment provides the target OCP version of the bundle, which enables the task to run check-payload with version specific embedded config. Signed-off-by: Yashvardhan Nanavati --- CODEOWNERS | 1 + renovate.json | 1 + task/fbc-fips-check/0.1/README.md | 25 ++++ task/fbc-fips-check/0.1/fbc-fips-check.yaml | 157 ++++++++++++++++++++ 4 files changed, 184 insertions(+) create mode 100644 task/fbc-fips-check/0.1/README.md create mode 100644 task/fbc-fips-check/0.1/fbc-fips-check.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 3997eb7e29..7a8c81c453 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -53,6 +53,7 @@ /task/clair-scan @konflux-ci/integration-service-maintainers /task/clamav-scan @konflux-ci/integration-service-maintainers /task/deprecated-image-check @konflux-ci/integration-service-maintainers +/task/fbc-fips-check @konflux-ci/integration-service-maintainers /task/fbc-related-image-check @konflux-ci/integration-service-maintainers /task/fbc-validation @konflux-ci/integration-service-maintainers /task/inspect-image @konflux-ci/integration-service-maintainers diff --git a/renovate.json b/renovate.json index ec4332c7d7..485221ba0f 100644 --- a/renovate.json +++ b/renovate.json @@ -106,6 +106,7 @@ "task/coverity-availability-check-oci-ta/**", "task/coverity-availability-check/**", "task/deprecated-image-check/**", + "task/fbc-fips-check/**", "task/fbc-related-image-check/**", "task/fbc-validation/**", "task/inspect-image/**", diff --git a/task/fbc-fips-check/0.1/README.md b/task/fbc-fips-check/0.1/README.md new file mode 100644 index 0000000000..e807d5ee94 --- /dev/null +++ b/task/fbc-fips-check/0.1/README.md @@ -0,0 +1,25 @@ +# fips-operator-bundle-check task + +## Description: +The fbc-fips-check task uses the check-payload tool to verify if an unreleased operator bundle in an FBC fragment image is FIPS compliant. +It only scans operator bundle images which either claim to be FIPS compliant by setting the `features.operators.openshift.io/fips-compliant` +label to `"true"` on the bundle image or require one of `OpenShift Kubernetes Engine, OpenShift Platform Plus or OpenShift Container Platform` +subscriptions to run the operator on an Openshift cluster. + +## Params: + +| name | description | default | +|--------------------------|------------------------------------------------------------------------|---------------| +| image-digest | Image digest to scan. | None | +| image-url | Image URL. | None | + +## Results: + +| name | description | +|--------------------|------------------------------| +| TEST_OUTPUT | Tekton task test output. | +| IMAGES_PROCESSED | Images processed in the task.| + + +## Additional links: +https://github.com/openshift/check-payload \ No newline at end of file diff --git a/task/fbc-fips-check/0.1/fbc-fips-check.yaml b/task/fbc-fips-check/0.1/fbc-fips-check.yaml new file mode 100644 index 0000000000..ceb5d25984 --- /dev/null +++ b/task/fbc-fips-check/0.1/fbc-fips-check.yaml @@ -0,0 +1,157 @@ +--- +apiVersion: tekton.dev/v1 +kind: Task +metadata: + labels: + app.kubernetes.io/version: "0.1" + annotations: + tekton.dev/pipelines.minVersion: "0.12.1" + tekton.dev/tags: "konflux" + name: fbc-fips-check +spec: + description: >- + Checks operator bundle image builds for FIPS compliance using the check-payload tool. + params: + - name: image-digest + description: Image digest to scan. + - name: image-url + description: Image URL. + results: + - name: TEST_OUTPUT + description: Tekton task test output. + value: $(steps.fips-operator-check-step-action.results.TEST_OUTPUT) + - name: IMAGES_PROCESSED + description: Images processed in the task. + steps: + - name: get-unique-related-images + image: quay.io/redhat-appstudio/konflux-test:v1.4.9@sha256:eee855e60b437d9a55a30e63f2eb7f95d9fd6d3b111c32cac8730c9b7a071394 + computeResources: + limits: + memory: 8Gi + cpu: '2' + requests: + memory: 8Gi + cpu: '1' + env: + - name: IMAGE_URL + value: $(params.image-url) + - name: IMAGE_DIGEST + value: $(params.image-digest) + - name: SOURCE_CODE_DIR + value: $(workspaces.workspace.path) + securityContext: + capabilities: + add: + - SETFCAP + script: | + #!/usr/bin/env bash + set -euo pipefail + # shellcheck source=/dev/null + . /utils.sh + + mirror_set="$(workspaces.output.path)/source/.tekton/related-images-mirror-set.yaml" + if [[ -f "${mirror_set}" ]]; then + mirror_set_yaml=$(cat "${mirror_set}") + process_image_digest_mirror_set "${mirror_set_yaml}" > "/tekton/home/related-images-map.txt" + else + echo "Could not find Related Images mirror set at ${mirror_set}. Unreleased relatedImages will fail the scan." + fi + + unique_related_images=() + digests_processed=() + images_processed_template='{"image": {"pullspec": "'"$IMAGE_URL"'", "digests": [%s]}}' + + image_without_tag=$(echo -n "${IMAGE_URL}" | sed "s/\(.*\):.*/\1/") + # strip new-line escape symbol from parameter and save it to variable + image_and_digest="${image_without_tag}@${IMAGE_DIGEST}" + + echo "Inspecting raw image manifest $image_and_digest." + # Get the arch and image manifests by inspecting the image. This is mainly for identifying image indexes + image_manifests=$(get_image_manifests -i "${image_and_digest}") + echo "Image manifests are $image_manifests" + + echo "Getting Target ocp version for the FBC fragment" + image_manifest_sha=$(echo "${image_manifests}" | jq -r 'to_entries[0].value') + target_ocp_version=$(get_ocp_version_from_fbc_fragment "$image_without_tag@$image_manifest_sha") + echo "${target_ocp_version#v}" > "/tekton/home/target_ocp_version.txt" + echo "Target OCP version is ${target_ocp_version}" + + declare -A seen_related_images + while read -r _ arch_sha; do + digests_processed+=("\"$arch_sha\"") + + unreleased_bundles=$(get_unreleased_bundle -i "$image_without_tag@$arch_sha") + echo "Unreleased bundle images are $unreleased_bundles" + + for bundle in ${unreleased_bundles}; do + echo "Processing bundle image : ${bundle}" + # Run the FIPS check only if the bundle is part of the Openshift Subscription or has the fips label set + bundle_out=$(opm render "$bundle") + subscription_label=$(echo "${bundle_out}" | jq -r '.properties[] | select(.value.annotations["operators.openshift.io/valid-subscription"] != null) | (.value.annotations["operators.openshift.io/valid-subscription"] | fromjson)[]') + + bundle_labels=$(get_image_labels "${bundle}") + fips_label=$(echo "${bundle_labels}" | grep 'features.operators.openshift.io/fips-compliant=' | cut -d= -f2 || true) + + if ! echo "${subscription_label}" | grep -e "OpenShift Kubernetes Engine" -e "OpenShift Container Platform" -e "OpenShift Platform Plus"; then + echo "OpenShift Kubernetes Engine, OpenShift Platform Plus or OpenShift Container Platform are not present in operators.openshift.io/valid-subscription." + echo "Subscription labels are : $subscription_label" + if [ -z "${fips_label}" ] || [ "${fips_label}" != "true" ]; then + echo "The label features.operators.openshift.io/fips-compliant is also not set to true. Skipping the FIPS static check for ${bundle}" + continue + else + echo "The label features.operators.openshift.io/fips-compliant is set to true. Running the FIPS static check..." + fi + else + echo "OpenShift Kubernetes Engine, OpenShift Platform Plus or OpenShift Container Platform are present in operators.openshift.io/valid-subscription. Running the FIPS static check..." + fi + + manifest_related_images=$(extract_related_images_from_bundle "$bundle") + if [ -n "$manifest_related_images" ]; then + for img in $manifest_related_images; do + if [ -z "${seen_related_images["$img"]:-}" ]; then + unique_related_images+=("$img") + seen_related_images["$img"]=1 + fi + done + fi + echo "Current unique images list is ${unique_related_images[*]}" + + done + done < <(echo "$image_manifests" | jq -r 'to_entries[] | "\(.key) \(.value)"') + + echo "Unique related images: ${unique_related_images[*]}" + echo "${unique_related_images[*]}" > "/tekton/home/unique_related_images.txt" + + # If the image is an Image Index, also add the Image Index digest to the list. + if [[ "${digests_processed[*]}" != *"$IMAGE_DIGEST"* ]]; then + digests_processed+=("\"$IMAGE_DIGEST\"") + fi + digests_processed_string=$(IFS=,; echo "${digests_processed[*]}") + + echo "${images_processed_template/\[%s]/[$digests_processed_string]}" > "/tekton/home/images_processed.txt" + + - name: fips-operator-check-step-action + computeResources: + limits: + memory: 512Mi + cpu: 200m + requests: + memory: 256Mi + cpu: 100m + ref: + name: fips-operator-check-step-action + + - name: parse-images-processed-result + image: quay.io/redhat-appstudio/konflux-test:v1.4.9@sha256:eee855e60b437d9a55a30e63f2eb7f95d9fd6d3b111c32cac8730c9b7a071394 + script: | + #!/usr/bin/env bash + set -euo pipefail + + if [ -e "/tekton/home/images_processed.txt" ]; then + tee "$(results.IMAGES_PROCESSED.path)" < /tekton/home/images_processed.txt + else + echo "Task was skipped. Exiting" + exit 0 + fi + workspaces: + - name: workspace \ No newline at end of file