diff --git a/policies/ubi-versions.json b/policies/ubi-versions.json new file mode 100755 index 0000000..b23e100 --- /dev/null +++ b/policies/ubi-versions.json @@ -0,0 +1,84 @@ +{ + "policies": [ + { + "id": "53e1d1fb-bc1e-4ef3-98c3-8df0dd5679b8", + "name": "UBI version compliance", + "description": "All images on the cluster using the Red Hat Universal Base Image (UBI) must use at least versions 8.5 or 9.3", + "rationale": "Using an older UBI image potentially exposes the workload to additional vulnerabilities", + "remediation": "Update the base image to at least UBI 8.5 or 9.3", + "disabled": true, + "categories": [ + "Package Management" + ], + "lifecycleStages": [ + "BUILD", + "DEPLOY" + ], + "eventSource": "NOT_APPLICABLE", + "exclusions": [ + { + "name": "", + "deployment": { + "name": "", + "scope": { + "cluster": "", + "namespace": "openshift-*", + "label": null + } + }, + "image": null, + "expiration": null + }, + { + "name": "", + "deployment": { + "name": "", + "scope": { + "cluster": "", + "namespace": "stackrox", + "label": null + } + }, + "image": null, + "expiration": null + } + ], + "scope": [], + "severity": "MEDIUM_SEVERITY", + "enforcementActions": [], + "notifiers": [], + "SORTName": "", + "SORTLifecycleStage": "", + "SORTEnforcement": false, + "policyVersion": "1.1", + "policySections": [ + { + "sectionName": "Rule 1", + "policyGroups": [ + { + "fieldName": "Image Component", + "booleanOperator": "OR", + "negate": false, + "values": [ + { + "value": "redhat-release=8\\.[0-4]-[0-9]+(?:\\.[0-9]+)?\\.el8" + }, + { + "value": "redhat-release=9\\.[0-2]-[0-9]+(?:\\.[0-9]+)?\\.el9" + }, + { + "value": "redhat-release-server=7.*" + } + ] + } + ] + } + ], + "mitreAttackVectors": [], + "criteriaLocked": false, + "mitreVectorsLocked": false, + "isDefault": false, + "source": "IMPERATIVE" + } + ] +} \ No newline at end of file diff --git a/util-scripts/ubi-versions/README.md b/util-scripts/ubi-versions/README.md new file mode 100644 index 0000000..33617e3 --- /dev/null +++ b/util-scripts/ubi-versions/README.md @@ -0,0 +1,21 @@ +# ubi-versions.sh +## Description +This script exports deployments that are using older Red Hat Universal Base Image (UBI) versions into a CSV file. + +Exported values for deployments include: +- Cluster name +- Namespace +- Deployment name +- Image +- Universal Base Image (UBI) version + +## Required environment vars +ROX_ENDPOINT - Host for StackRox central (central.example.com) + +ROX_API_TOKEN - Token data from StackRox API token [How to generate an API Token](https://docs.openshift.com/acs/4.6/configuration/configure-api-token.html) + +## Required policies +This policy relies on the 'UBI version compliance' policy having been imported to the cluster (also available in this repository) + +## Usage +Run the script ./ubi-versions results.csv to generate a file with all deployment information. diff --git a/util-scripts/ubi-versions/ubi-versions.sh b/util-scripts/ubi-versions/ubi-versions.sh new file mode 100755 index 0000000..8b5d873 --- /dev/null +++ b/util-scripts/ubi-versions/ubi-versions.sh @@ -0,0 +1,70 @@ +#! /bin/bash +# This script is designed to report on container images that use a specific UBI version. It is designed to be used +# with a policy that creates violations for specific versions of the `redhat-release` package. + +# To use this image, set ROX_ENDPOINT to the ACS central instance and set ROX_API_TOKEN +# to an ACS 'admin' token created. + +# e.g. export ROX_ENDPOINT=central-acs-central.apps.cluster1.example.com:443 +# export ROX_API_TOKEN=eyJhbGciOiJSUzI1NiIsImtpZCI6Imp3dGsw... +# ./ubi-versions.sh images.csv + +set -e + +if [[ -z "${ROX_ENDPOINT}" ]]; then + echo >&2 "ROX_ENDPOINT must be set" + exit 1 +fi + +if [[ -z "${ROX_API_TOKEN}" ]]; then + echo >&2 "ROX_API_TOKEN must be set" + exit 1 +fi + +if [[ -z "$1" ]]; then + echo >&2 "usage: ubi-versions.sh " + exit 1 +fi + +output_file="$1" +echo '"Cluster Name", "Namespace", "Deployment", "Image", "UBI version"' > "${output_file}" + +function curl_central() { + curl -sk -H "Authorization: Bearer ${ROX_API_TOKEN}" "https://${ROX_ENDPOINT}/$1" +} + +# Collect all alerts +res="$(curl_central "v1/alerts?query=Policy%3AUBI%20version%20compliance")" + +# Iterate over all deployments and get the full deployment +for deployment_id in $(echo "${res}" | jq -r .alerts[].deployment.id); do + deployment_res="$(curl_central "v1/deployments/${deployment_id}")" + if [[ "$(echo "${deployment_res}" | jq -rc .name)" == null ]]; then + continue; + fi + + if [[ "$(echo "${deployment_res}" | jq '.containers | length')" == "0" ]]; then + continue; + fi + + export deployment_name="$(echo "${deployment_res}" | jq -rc .name)" + export namespace="$(echo "${deployment_res}" | jq -rc .namespace)" + export clusterName="$(echo "${deployment_res}" | jq -rc .clusterName)" + + # Iterate over all images within the deployment and render the CSV Lines + for image_id in $(echo "${deployment_res}" | jq -r 'select(.containers != null) | .containers[].image.id'); do + if [[ "${image_id}" != "" ]]; then + image_res="$(curl_central "v1/images/${image_id}" | jq -rc)" + if [[ "$(echo "${image_res}" | jq -rc .name)" == null ]]; then + continue; + fi + + image_name="$(echo "${image_res}" | jq -rc '.name.fullName')" + export image_name + + # find the redhat-release (UBI 8/9) or redhat-release-server (UBI 7) version and format lines + export ubi_version="$(echo "${image_res}" | jq '.scan.components[] | select(.name=="redhat-release" or .name=="redhat-release-server") | .version'| grep -o '[0-9]\.[0-9]\+' | head -1 )" + echo "${clusterName},${namespace},${deployment_name},${image_name},${ubi_version}" >> "${output_file}" + fi + done + done