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