Skip to content

Instantly share code, notes, and snippets.

@dmc5179
Last active February 3, 2023 14:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dmc5179/b9430c5555bcdfe731a1d6c80615223e to your computer and use it in GitHub Desktop.
Save dmc5179/b9430c5555bcdfe731a1d6c80615223e to your computer and use it in GitHub Desktop.
Script to generate an ACS CVE report on all images required for a specific operator and version of that operator. Requires oc-mirror and access to an ACS cluster
#!/bin/bash
# Tool to generate an ACS scan of container images needed for any particular operator/version
# Requires a running ACS system.
OC_MIRROR="${OC_MIRROR:-oc-mirror}"
OCP_VERSION="${OCP_VERSION:-4.11}"
OPERATOR_CATALOG="${OPERATOR_CATALOG:-registry.redhat.io/redhat/redhat-operator-index}"
OPERATOR="${OPERATOR:-compliance-operator}"
#OPERATOR_CHANNEL=""
#OPERATOR_VERSION=""
# Example endpoint
#ROX_ENDPOINT="https://central-rhacs-operator.apps.cluster_name.basedomain.io:443"
#ROX_PASSWD=""
if [ -z ${OPERATOR} ];
then
echo "Operator name is required, set OPERATOR env variable"
exit 1
fi
if [ -z ${ROX_ENDPOINT} ];
then
echo "ROX_ENDPOINT is required, set ROX_ENDPOINT env variable"
exit 1
fi
if [ -z ${ROX_PASSWD} ];
then
echo "ROX_PASSWD is required, set ROX_PASSWD env variable"
exit 1
fi
# Lookup main operator channel if not specified by user
if [ -z ${OPERATOR_CHANNEL} ];
then
echo "Operator channel not specified, selecting primary channel"
${OC_MIRROR} list operators --catalog=${OPERATOR_CATALOG}:v${OCP_VERSION} --package=${OPERATOR}
OPERATOR_CHANNEL=$(${OC_MIRROR} list operators --catalog=${OPERATOR_CATALOG}:v${OCP_VERSION} \
--package=${OPERATOR} 2>/dev/null | grep -A 1 'DEFAULT CHANNEL' | tail -1 | awk -F\ '{print $NF}')
fi
# Lookup latest operator version in channel if not specified by user
if [ -z ${OPERATOR_VERSION} ];
then
echo "Operator version not specified, selecting head for channel: ${OPERATOR_CHANNEL}"
OPERATOR_VERSION=$(${OC_MIRROR} list operators --catalog=${OPERATOR_CATALOG}:v${OCP_VERSION} \
--package=${OPERATOR} --channel=${OPERATOR_CHANNEL} 2>/dev/null | grep -A 1 'VERSIONS' | tail -1)
fi
# Create oc mirror config file to get manifests for operator version
rm -f imageset-config.yaml
sed "s|TMP_DIR|${TMP_DIR}|g" imageset-config.yaml.template | sed "s|OCP_VERSION|${OCP_VERSION}|g" | \
sed "s|operator-name|${OPERATOR}|g" | sed "s|channel-name|${OPERATOR_CHANNEL}|g" | \
sed "s|operator-version|${OPERATOR_VERSION}|g" > imageset-config.yaml
# Get manifests for operator version
rm -rf archives
oc-mirror --config ./imageset-config.yaml --dry-run file://archives
# Request ACS to generate a scan of each image that is part of the operator bundle
for image in $(cat archives/oc-mirror-workspace/mapping.txt | awk -F\= '{print $1}')
do
echo "Scanning image: ${image}"
FILENAME=$(echo "${image}" | sed 's|/|_|g')
FILENAME="${FILENAME}_scan.json"
roxctl image scan --insecure --insecure-skip-tls-verify \
--endpoint "${ROX_ENDPOINT}" --password "${ROX_PASSWD}" \
--image "${image}" | tee "${FILENAME}"
done
# Extract CVE information from ACS scan results for each image and combine into CSV format
output_file="${OPERATOR}-${OPERATOR_VERSION}-scan.csv"
# Column Names
echo '"Image", "CVE", "CVSS Score", "Summary", "Severity", "Component", "Version", "Fixed By"' > "${output_file}"
for f in *.json
do
image_name="$(jq -rc '.name.fullName' ${f})"
export image_name
jq -r --argjson cvss "$cvss" 'try (.metadata.v1.layers as $layers | .scan.components | sort_by(.layerIndex, .name) | .[]? | . as $component | select(.vulns != null) | .vulns[] | select(.cvss >= $cvss) | select(.fixedBy != null) | [ env.image_name, .cve, .cvss, .summary, .severity, $component.name, $component.version, .fixedBy]) | @csv' ${f} >> "${output_file}"
done
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment