Last active
February 3, 2023 14:47
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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