$ cosign verify registry.k8s.io/kube-apiserver-amd64:v1.25.2
Get and Verify All Kubernetes Images
$ version=v1.25.0
curl -Ls https://sbom.k8s.io/v1.25.0/release \
| grep 'PackageName: registry.k8s.io/' \
| awk '{print $2}' > images.txt \
&& input=images.txt \
&& while IFS= read -r image; \
fullimageurl=$image
fullimageurl+=version
echo image
do cosign verify --certificate-identity-regexp=.* --certificate-oidc-issuer-regexp=.* asia.gcr.io/k8s-artifacts-prod/kubernetes/kube-apiserver-amd64:v1.25.0 2> /dev/null | jq -r '.[0].optional | "Issuer: \(.Issuer)\nSubject: \(.Subject)"'
done < "$input"
$ crane config cgr.dev/chainguard/node | jq .config
Print all the repos you can access on cgr.dev
$ crane catalog cgr.dev
$ crane manifest <image> | jq .
$ crane export --platform=linux/amd64 cgr.dev/chainguard/glibc-dynamic:latest - 2>/dev/null | tar --ignore-command-error -xvf - --wildcards 'var/lib/db/sbom/*.json' -C . 2>/dev/null
$ sudo docker cp $(docker ps -a | grep cgr.dev/c3.ai/glibc-dynamic:13 | head -n1 | awk '{print $1;}'):/var/lib/db/sbom -
List SBOM Directory Contents with Crane
$ crane export cgr.dev/chainguard-private/dotnet-sdk:6 - | tar -tvf - | grep -i 'var/lib/db/sbom'
Extract a Package SBOM with Crane
$ crane export cgr.dev/chainguard-private/dotnet-sdk:6 - | tar -Oxf - var/lib/db/sbom/aspnet-6-runtime-6.0.126-r1.spdx.json > /tmp/aspnet-6-runtime-sbom.json
Print the Operating System Identifier with Crane
$ IMAGE="cgr.dev/chainguard-private/dotnet-sdk:7"; echo $(crane export $IMAGE - | tar -Oxf - etc/os-release | head -n 1)
Verify SBOMs and SBOM integrity using cosign
$ cosign verify-attestation \
--type https://spdx.dev/Document \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com \
--certificate-identity=https://github.com/chainguard-images/images/.github/workflows/release.yaml@refs/heads/main \
cgr.dev/chainguard/glibc-dynamic:latest 2>/dev/null \
| jq -r .payload | base64 -d | jq
Print all the APKs for a given image
$ IMAGE="cgr.dev/chainguard-private/jdk:openjdk-17"; crane manifest $IMAGE | jq -r '.manifests[] | select (.platform.architecture=="amd64") | .digest' | xargs -I {} cosign verify-attestation --type=spdx --certificate-identity-regexp=.* --certificate-oidc-issuer-regexp=.* $IMAGE@{} 2> /dev/null | jq -r .payload | base64 -d | jq '.predicate' | jq '.packages[] | select(.externalRefs[]?.referenceCategory == "PACKAGE_MANAGER") | .externalRefs[] | select(.referenceCategory == "PACKAGE_MANAGER") | .referenceLocator'
Print images in a helm chart
#! /bin/bash
if [ " $# " -ne 3 ]; then
echo " Usage: $0 <helm-rep-url> <name> <repo-url> <path-chart>"
echo " Example: ./print-helm-chart-images.sh argo https://argoproj.github.io/argo-helm argo-cd"
exit 1
fi
name=$1
helmrepo=$2
chartpath=$3
renderedhelmfile=$( mktemp --suffix=.yaml)
helm repo add $name $helmrepo
helm template $name /$chartpath > " $renderedhelmfile "
mapfile -t deployment_array < <( cat " $renderedhelmfile " | yq ' . | select(.kind == "Deployment") | .metadata.name' | sort -u | grep -E ' ^[a-zA-Z]' )
for helmdeployment in " ${deployment_array[@]} " ; do
echo " Deployment: $helmdeployment "
echo -n " image: "
cat " $renderedhelmfile " | yq eval ' . | select(.kind == "Deployment" and .metadata.name == "' $helmdeployment ' ") | .spec.template.spec.containers[].image' | sort -u
echo " "
done
Print the timestamp and installed APK list from a multi-arch digest
#! /bin/bash
IMAGE_NAME=" chainguard/wolfi-base" # Change as needed
DIGEST=" sha256:909ed72dc072188cce611c98f556b3a4e9a62ad4078d766e78c180eb8b02fa23" # Change as needed
ARCHITECTURE=" amd64" # Change as needed
tok=$( curl -H " Authorization: Bearer $( echo ' cgr.dev' | docker-credential-cgr get) " \
-v " https://cgr.dev/token?scope=repository:${IMAGE_NAME} :pull" 2> /dev/null \
| jq -r .token)
timestamp=$( curl -H " Authorization: Bearer $tok " \
" https://cgr.dev/v2/${IMAGE_NAME} /_chainguard/history/latest" 2> /dev/null \
| jq -r " .history[] | select(.digest == \" ${DIGEST} \" ) | .updateTimestamp" )
apks=$( crane manifest cgr.dev/${IMAGE_NAME} 2> /dev/null | jq -r " .manifests[] | select (.platform.architecture==\" ${ARCHITECTURE} \" ) | .digest" \
| xargs -I {} cosign verify-attestation --type=spdx --certificate-identity-regexp=.* --certificate-oidc-issuer-regexp=.* cgr.dev/${IMAGE_NAME} @{} 2> /dev/null \
| jq -r .payload | base64 -d | jq ' .predicate' 2> /dev/null \
| jq -r ' [.packages[] | select(.externalRefs[]?.referenceCategory == "PACKAGE_MANAGER") | .externalRefs[] | select(.referenceCategory == "PACKAGE_MANAGER") | .referenceLocator]' )
echo " {\" updateTimestamp\" : \" $timestamp \" , \" apks\" : $apks }" | jq
done
Identify CVEs from a JAR perspective for an array of images
#! /bin/bash
# Define an array of image names
images=(
" spark:latest"
" tomcat:latest"
" paketobuildpacks/spring-boot:latest"
" zookeeper:latest"
" cassandra:latest"
" flink:latest"
" cockroachdb/cockroach:latest"
" bitnami/kafka:latest"
" keycloak/keycloak:latest"
" jenkins/jenkins:latest"
" elasticsearch:8.11.0"
" apachepinot/pinot-presto:latest"
" selenium/standalone-chrome:latest"
" trinodb/trino:latest"
" apache/druid:28.0.0"
" apache/hive:4.0.0-beta-2-SNAPSHOT"
" logstash:8.11.1"
)
# File to store full inventory of .jars
jarlistfile=$( mktemp --suffix=.csv)
echo " Container Image,Jar Name,Full Path" > " $jarlistfile "
# File to store Image CVE Results
tempcsvfile1=$( mktemp --suffix=.csv)
echo " Image,Total CVEs,Critical CVEs,High CVEs,Medium CVEs" > " $tempcsvfile1 "
# File to store Image CVE Results by JAR
tempcsvfile2=$( mktemp --suffix=.csv)
echo " Image,Artifact,Jar CVEs,Jar CVEs with Fixes,Critical Jar CVEs,Critical Jar CVEs with Fixes,High Jar CVEs,High Jar CVEs with Fixes" > " $tempcsvfile2 "
echo " Pulling the latest image for..."
for IMAGE in " ${images[@]} " ; do
echo " $IMAGE "
DOCKER_CLI_HINTS=false docker pull " $IMAGE " 2>&1 1> /dev/null
done
echo " ---------------------------------------------"
crane export " $IMAGE " 2> /dev/null - | tar -tvf - 2> /dev/null | grep " \.jar$" | while read -r line; do
jar_name_full_path=$( echo " $line " | awk ' {print $NF}' )
jar_name=$( basename " $jar_name_full_path " )
echo " $IMAGE ,$jar_name ,$jar_name_full_path " >> " $jarlistfile "
done
echo " Running grype scan for..."
for IMAGE in " ${images[@]} " ; do
echo " $IMAGE "
GRYPE_OUTPUT=$( grype $IMAGE -o json 2> /dev/null)
echo " $GRYPE_OUTPUT " | jq -r --arg img " $IMAGE " '
[$img, ([.matches[].vulnerability] | length), ([.matches[] | select(.vulnerability.severity == "Critical")] | length), ([.matches[] | select(.vulnerability.severity == "High")] | length), ([.matches[] | select(.vulnerability.severity == "Medium")] | length)] |
@csv' >> " $tempcsvfile1 "
echo " $GRYPE_OUTPUT " | jq -r --arg img " $IMAGE " '
[ .matches[]
| select(.artifact.type == "java-archive")
| {artifact: .artifact.name, vulnerability: {id: .vulnerability.id, severity: (.vulnerability.severity) | ascii_upcase, fix_state: (.vulnerability.fix.state)}}
] | group_by(.artifact)
| map({
artifact: .[0].artifact,
jar_cves: length,
jar_cves_with_fixes: (map(select(.vulnerability.fix_state == "fixed")) | length),
critical_jar_cves: (map(select(.vulnerability.severity | ascii_upcase == "CRITICAL")) | length),
critical_jar_cves_with_fixes: (map(select(.vulnerability.fix_state == "fixed" and (.vulnerability.severity | ascii_upcase == "CRITICAL"))) | length),
high_jar_cves: (map(select(.vulnerability.severity | ascii_upcase == "HIGH")) | length),
high_jar_cves_with_fixes: (map(select(.vulnerability.fix_state == "fixed" and (.vulnerability.severity | ascii_upcase == "HIGH"))) | length)
})
| .[]
| [$img, .artifact, (.jar_cves|tostring), (.jar_cves_with_fixes|tostring), (.critical_jar_cves|tostring), (.critical_jar_cves_with_fixes|tostring), (.high_jar_cves|tostring), (.high_jar_cves_with_fixes|tostring)]
| @csv' >> " $tempcsvfile2 "
done
# Output the file paths
echo " Inventory List of Jars is saved to: $jarlistfile "
echo " Image Vulnerability Results (CSV) saved to: $tempcsvfile1 "
echo " Image Vulnerability results by JAR (CSV) saved to: $tempcsvfile2 "
echo " ---------------------------------------------"
List all images in a Chainguard IAM Group
$ chainctl img repo list --group=private-images -o table | cut -d'|' -f2 | sort
Find what apk has a given command with curl
$ curl -s https://packages.wolfi.dev/os/x86_64/APKINDEX.tar.gz | tar -xzO APKINDEX | grep -B 10 "p:.*cmd:setcap" | grep "P:" | uniq
Find what apk provided a file
$ apk info -W
Find what apk provided a shared library
$ apk search so:libstdc*
Run a locally built Wolfi APK without building an image
$ docker run -it --rm -v /path/to/fooapk/:/ --entrypoint sh cgr.dev/chainguard/wolfi-base:latest
$ apk update
$ apk add --allow-untrusted /foo.apk
# Note: You can also copy your local signing key such as local-melange.rsa.pub to /etc/apk/keys/
Latest Chainguard Image Build Date (of its constituent packages:
$ crane config cgr.dev/chainguard/static | jq -r .created
$ chainctl clusters print-config
Scan an array of images with grype
#!/bin/bash
# Define an array of image names
images=(
"python"
"redis"
"bitnami/kubectl:1.29"
)
# Loop through each item and append ":latest" if no tag is present
for i in "${!images[@]}"; do
if [[ "${images[i]}" != *:* ]]; then
images[i]="${images[i]}:latest"
fi
echo "Pulling ${images[i]}"
if docker pull ${images[i]} 2>&1 | grep -iq "error"; then
echo "Error encountered while pulling $image. Exiting..."
exit 1
fi
done
echo "---------------------------------------------"
json='{"items":[]}'
totalCritical=0
totalHigh=0
totalMedium=0
totalLow=0
totalWontFix=0
totalCount=0
echo "Scanning images..."
for IMAGE in "${images[@]}"; do
# echo "$IMAGE"
# Capture the JSON output in a variable
output=$(grype $IMAGE -o json 2>/dev/null | jq -c '{Total: [.matches[].vulnerability] | length, Critical: [.matches[] | select(.vulnerability.severity == "Critical")] | length, High: [.matches[] | select(.vulnerability.severity == "High")] | length, Medium: [.matches[] | select(.vulnerability.severity == "Medium")] | length, Low: [.matches[] | select(.vulnerability.severity == "Low")] | length, WontFix: [.matches[] | select(.vulnerability.fix.state == "wont-fix")] | length }')
echo "$output"
critical=$(jq '.Critical' <<< "$output")
high=$(jq '.High' <<< "$output")
medium=$(jq '.Medium' <<< "$output")
low=$(jq '.Low' <<< "$output")
wontfix=$(jq '.WontFix' <<< "$output")
total=$(jq '.Total' <<< "$output")
json=$(jq --arg image "$IMAGE" \
--arg critical "$critical" \
--arg high "$high" \
--arg medium "$medium" \
--arg low "$low" \
--arg wontfix "$wontfix" \
--arg total "$total" \
'.items += [{
image: $image,
scan: {
type: "grype",
critical: ($critical | tonumber),
high: ($high | tonumber),
medium: ($medium | tonumber),
low: ($low | tonumber),
wontfix: ($wontfix | tonumber),
total: ($total | tonumber)
}
}]' <<< "$json")
totalCritical=$((totalCritical + critical))
totalHigh=$((totalHigh + high))
totalMedium=$((totalMedium + medium))
totalLow=$((totalLow + low))
totalWontFix=$((totalWontFix + wontfix))
totalCount=$((totalCount + total))
done
echo "---------------------------------------------"
# Calculate averages
averageCritical=$((totalCritical / ${#images[@]}))
averageHigh=$((totalHigh / ${#images[@]}))
averageMedium=$((totalMedium / ${#images[@]}))
averageLow=$((totalLow / ${#images[@]}))
averageWontFix=$((totalWontFix / ${#images[@]}))
# Display totals and averages
echo "Total Vulnerabilities: $totalCount"
echo "Total Critcal CVEs: $totalCritical"
echo "Total High CVEs: $totalHigh"
echo "Total Medium CVEs: $totalMedium"
echo "Total Low CVEs: $totalLow"
echo -n "Average Vulnerabilities: "; echo "scale=2; $totalCount / ${#images[@]}" | bc
echo -n "Average Critcal CVEs: "; echo "scale=2; $totalCritical / ${#images[@]}" | bc
echo -n "Average High CVEs: "; echo "scale=2; $totalHigh / ${#images[@]}" | bc
echo -n "Average Medium CVEs: "; echo "scale=2; $totalMedium / ${#images[@]}" | bc
echo -n "Average Low CVEs: "; echo "scale=2; $totalLow / ${#images[@]}" | bc
echo "JSON Output:"
echo "$json"
echo "CSV Output:"
echo "$json" | jq -r '.items[] | [.scan.total, .scan.critical, .scan.high, .scan.medium, .scan.low, .scan.wontfix] | @csv'
Scan an array of images for a specific CVE
#!/bin/bash
vulnid="CVE-2023-6246"
images=(
"cgr.dev/chainguard/cosign"
"cgr.dev/chainguard/curl"
)
# Loop through each item and append ":latest" if no tag is present
for i in "${!images[@]}"; do
if [[ "${images[i]}" != *:* ]]; then
images[i]="${images[i]}:latest"
fi
echo "Pulling ${images[i]}"
docker pull "${images[i]}" -o json 2>/dev/null
done
echo "---------------------------------------------"
echo "Scanning images for CVE"
for IMAGE in "${images[@]}"; do
echo "$IMAGE"
output=$(grype $IMAGE -o json 2>/dev/null | jq --arg vulnid "$vulnid" '.matches[] | .matchDetails[] | select(.found.vulnerabilityID == $vulnid) | "Vulnerability \($vulnid) found!" // null')
if [ -z "$output" ]; then
echo "Not Affected"
else
echo "Vulnerability $vulnid FOUND"
fi
done
echo "---------------------------------------------"
Verify attestation signatures and save attestations for an array of multi-arch images
#! /bin/bash
images=(" cgr.dev/chainguard/glibc-dynamic:latest" )
arch=" amd64"
types=(" https://slsa.dev/provenance/v1" " https://apko.dev/image-configuration" " https://spdx.dev/Document" )
# Outer loop for images
for image in " ${images[@]} " ; do
digest=$( crane manifest " $image " 2> /dev/null | jq -r " .manifests[] | select (.platform.architecture==\" ${arch} \" ) | .digest" )
imgdigestref=$( echo " $image " | awk -F' :' ' {print $(NF-1)}' ) @$digest
img_short_name=$( echo " $image " | awk -F' [:/]' ' {print $(NF-1)"-"$NF}' )
echo " Checking image $imgdigestref "
for type in " ${types[@]} " ; do
short_type=" "
case $type in
" https://slsa.dev/provenance/v1" )
short_type=" slsa-prov-v1"
;;
" https://apko.dev/image-configuration" )
short_type=" apko-img-cfg"
;;
" https://spdx.dev/Document" )
short_type=" spdx-sbom-doc"
;;
esac
file=" $img_short_name -$short_type .json"
echo " *Verifying signature of attestation $type and saving to file $file "
cosign verify-attestation \
--type " $type " \
--certificate-oidc-issuer=" https://token.actions.githubusercontent.com" \
--certificate-identity=" https://github.com/chainguard-images/images/.github/workflows/release.yaml@refs/heads/main" \
" $imgdigestref " 2> /dev/null \
| jq -r .payload | base64 -d | jq > " $file "
done
done
Reverse engineer the image tag from a digest for a multi-arch image
#! /bin/bash
if [ " $# " -ne 3 ]; then
echo " Usage: $0 <full-image-name> <arch> <sha256-hash>"
echo " Example: ./get-tag.sh cgr.dev/chainguard/glibc-dynamic amd64 sha256:00821ae6d724e1ac736aa3aabf3107a0c24583d53caaf5e99364257e2766b336"
exit 1
fi
image=$1
arch=$2
sha256digest=$3
tags=$( crane ls " $image " --omit-digest-tags)
tagcount=0
matchcount=0
echo " "
echo " Found the following tags..."
for tag in $tags ; do
echo -n " $tag "
let tagcount++
done
echo " "
echo " "
echo " Total number of tags found: $tagcount "
for tag in $tags ; do
digest=$( crane manifest " $image " 2> /dev/null | jq -r " .manifests[] | select (.platform.architecture==\" ${arch} \" ) | .digest" )
imgdigestref=$( echo " $image " | awk -F' :' ' {print $(NF-1)}' ) @$digest
# Check if the digest matches the provided SHA256 hash
if [[ $imgdigestref =~ $sha256digest ]]; then
echo " Match found for tag $tag "
let matchcount++
fi
done
echo " Total number of matches found: $matchcount "
$ chainctl images diff --platform=linux/amd64 \
cgr.dev/chainguard-private/argocd:latest \
cgr.dev/chainguard/argocd:latest 2>/dev/null | \
( output=$(cat); \
echo -e "Packages added:\n$(echo "$output" | jq -r '.packages.added[] | select(.reference | startswith("pkg:apk")) | .name')"; \
echo -e "Packages removed:\n$(echo "$output" | jq -r '.packages.removed[] | select(.reference | startswith("pkg:apk")) | .name')"
)
Print history for specific Chainguard Image Stream
#! /bin/bash
show_help () {
echo " "
echo " Usage: $0 image-stream-base-uri image-stream-version"
echo " $0 cgr.dev/chainguard-private/python 3.9"
echo " "
echo " Options:"
echo " --platform Specifies the platform in the form os/arch[/variant][:osversion] (default: linux/amd64)"
echo " --image-ref-type tags | digests (default: tags)"
echo " -h, --help Display this help message and exit"
echo " "
}
if [ $# -ne 2 ]; then
show_help
exit 1
fi
repository=" $1 "
version=" $2 "
# Removing cgr.dev/
repository=${1# cgr.dev/ }
# Fetch history using the provided parameters
history=$( curl -s -H " $( crane auth token -H cgr.dev/$repository ) " " https://cgr.dev/v2/$repository /_chainguard/history/$version " | jq .)
IFS=$' \n ' read -r -d ' ' -a historyapidigestarray <<< $( echo $history | jq -r ' .history[].digest' )
echo " "
echo " History API digests found: ${# historyapidigestarray[@]} "
echo " "
echo " oldest:"
echo -n " - digest: "
echo " $history " | jq -r ' .history[0].digest'
echo -n " - timestamp: "
echo " $history " | jq -r ' .history[0].updateTimestamp'
echo " newest:"
echo -n " - digest: "
echo " $history " | jq -r ' .history[-1].digest'
echo -n " - timestamp: "
echo " $history " | jq -r ' .history[-1].updateTimestamp'
echo " "
# Extract the substring after the last '/' in the first parameter
repository_name=${1##*/ }
temp_file=$( mktemp /tmp/${repository_name} -${version// ./ } -history-XXXXXX.json)
echo $history | jq > $temp_file
echo " Full history written to $temp_file "
Check CVEs and release for an ImageStream history
#! /bin/bash
show_help () {
echo " Warning: If you are on Mac run: "
echo " brew install bash coreutils"
echo " Then modify all instances of date to gdate and run with " bash $0 image-stream-base-uri image-stream-version"
echo " "
echo " Usage: $0 image-stream-base-uri image-stream-version"
echo " $0 cgr.dev/chainguard-private/python 3.9"
echo " "
echo " Options:"
echo " --platform Specifies the platform in the form os/arch[/variant][:osversion] (default: linux/amd64)"
echo " --image-ref-type tags | digests (default: tags)"
echo " -h, --help Display this help message and exit"
echo " "
}
if [ $# -ne 2 ]; then
show_help
exit 1
fi
repository=" $1 "
version=" $2 "
# Removing cgr.dev/
repository=${1# cgr.dev/ }
# Fetch history using the provided parameters
history=$( curl -s -H " $( crane auth token -H cgr.dev/$repository ) " " https://cgr.dev/v2/$repository /_chainguard/history/$version " | jq .)
IFS=$'\n' read -r -d '' -a historyapidigestarray <<< $( echo $history | jq -r ' .history[].digest' )
oldest_digest=$( echo " $history " | jq -r ' .history[0].digest' )
oldtimestamp=$( echo " $history " | jq -r ' .history[0].updateTimestamp' )
newest_digest=$( echo " $history " | jq -r ' .history[-1].digest' )
newtimestamp=$( echo " $history " | jq -r ' .history[-1].updateTimestamp' )
oldimage=" cgr.dev/$repository @$oldest_digest "
newimage=" cgr.dev/$repository @$newest_digest "
oldcvejson=$( grype $oldimage -o json 2> /dev/null | jq ' {Total: [.matches[].vulnerability] | length, Critical: [.matches[] | select(.vulnerability.severity == "Critical")] | length, High: [.matches[] | select(.vulnerability.severity == "High")] | length, WontFix: [.matches[] | select(.vulnerability.fix.state == "wont-fix")] | length }' )
newcvejson=$( grype $newimage -o json 2> /dev/null | jq ' {Total: [.matches[].vulnerability] | length, Critical: [.matches[] | select(.vulnerability.severity == "Critical")] | length, High: [.matches[] | select(.vulnerability.severity == "High")] | length, WontFix: [.matches[] | select(.vulnerability.fix.state == "wont-fix")] | length }' )
cveresults=$( echo " $oldcvejson " | jq --argjson new " $newcvejson " ' {
Total: (.Total - $new.Total),
Critical: (.Critical - $new.Critical),
High: (.High - $new.High),
WontFix: (.WontFix - $new.WontFix)
}' )
epoch1=$( date -u -d " $oldtimestamp " +" %s" )
epoch2=$( date -u -d " $newtimestamp " +" %s" )
diff_seconds=$(( epoch2 - epoch1 ))
diff_days=$(( diff_seconds / 86400 ))
total_cves=$( echo " $cveresults " | jq -r ' .Total | tostring' )
critical_cves=$( echo " $cveresults " | jq -r ' .Critical | tostring' )
high_cves=$( echo " $cveresults " | jq -r ' .High | tostring' )
echo " "
echo " Summary:"
echo " ${# historyapidigestarray[@]} releases over the course of $diff_days days"
echo " These releases remediated $total_cves CVEs ($critical_cves Critical and $high_cves High)"
Generate Image CHANGELOG between 2 images using the chainctl diff API
#! /bin/bash
print_dots () {
while true ; do
echo -n " ."
sleep 1
done
}
show_help () {
echo " "
echo " Usage: $0 [options] <image_name> <previous_version> <new_version>"
echo " "
echo " Options:"
echo " --platform Specifies the platform in the form os/arch[/variant][:osversion] (default: linux/amd64)"
echo " --image-ref-type tags | digests (default: tags)"
echo " -h, --help Display this help message and exit"
echo " "
}
# Formatting variables
header=" \e[1m" # Bold text
normal=" \e[0m" # Normal text
green=" \e[32m" # Green
red=" \e[31m" # Red
yellow=" \e[33m" # Yellow
blue=" \e[34m" # Blue
purple=" \e[35m" # Purple
cyan=" \e[36m"
lightgrey=" \e[37m"
# Defaults
platform=" linux/amd64"
reftype=" tags"
# Check if they specified the platform
if [[ " $1 " == " --platform" ]]; then
platform=" $2 "
shift 2
fi
# Prepend '@' to versions if digests is true
if [ " $1 " = " --image-ref-type=digests" ] || [ " $1 " = " --image-ref-type" -a " $2 " = " digests" ]; then
reftype=" digests"
shift
if [[ " $1 " == " digests" ]]; then
shift
fi
fi
# Assigning arguments to variables
image_name=" $1 "
previous_version=" $2 "
new_version=" $3 "
if [ " $reftype " = " digests" ]; then
new_version=" @$new_version "
previous_version=" @$previous_version "
fi
echo " "
echo -ne " Platform: ${purple} $platform ${normal} \n"
echo -ne " Image Reference Type: ${purple} $reftype ${normal} \n"
echo -ne " Image Name: ${purple} $image_name ${normal} \n"
echo -ne " Previous Version: ${purple} $previous_version ${normal} \n"
echo -ne " New Version: ${purple} $new_version ${normal} \n"
echo " "
# Check if all required arguments are provided
if [[ -z " $image_name " || -z " $previous_version " || -z " $new_version " ]]; then
show_help
exit 1
fi
echo -ne " ${header} Generating CHANGELOG${normal} "
print_dots &
dots_pid=$!
diff_api_json_output=$( chainctl images diff --platform=" $platform " " $image_name " :" $previous_version " " $image_name " :" $new_version " 2> /dev/null)
kill $dots_pid > /dev/null 2>&1
echo " "
echo " "
echo -ne " Packages Added:${normal} "
packages_added=$( echo " $diff_api_json_output " | jq -r ' .packages.added[] | select(.reference | startswith("pkg:apk")) | .name' )
if [ -z " $packages_added " ]; then
echo -n " "
else
for pkg_added in $packages_added ; do
echo -ne " \n - ${green} $pkg_added ${normal} "
done
fi
echo -ne " \nPackages Removed:${normal} "
packages_removed=$( echo " $diff_api_json_output " | jq -r ' .packages.removed[] | select(.reference | startswith("pkg:apk")) | .name' )
if [ -z " $packages_removed " ]; then
echo -n " "
else
for pkg_rm in $packages_removed ; do
echo -ne " \n - ${red} $pkg_rm ${normal} "
done
fi
echo -ne " \nPackages Changed:${normal} "
packages_changed=$( echo " $diff_api_json_output " | jq -r ' .packages.changed[] | "\(.name) \(.previous.version) \(.current.version)"' )
if [ -z " $packages_changed " ]; then
echo -n " "
else
echo " $packages_changed " | while read -r name prev_version curr_version; do
prev_version=${prev_version// _/ .}
curr_version=${curr_version// _/ .}
IFS=' .' read -ra PREV <<< " $prev_version"
IFS=' .' read -ra CURR <<< " $curr_version"
upgraded=false
downgraded=false
for i in {0..2}; do
if [[ ${CURR[i]} -gt ${PREV[i]} ]]; then
upgraded=true
break
elif [[ ${CURR[i]} -lt ${PREV[i]} ]]; then
downgraded=true
break
fi
done
if $upgraded ; then
echo -ne " \n - ${blue} $name : Upgraded from $prev_version to $curr_version ${normal} "
elif $downgraded ; then
echo -ne " \n - ${red} $name : Downgraded from $prev_version to $curr_version ${normal} "
fi
done
fi
# Extracting and printing vulnerabilities removed
echo -e " \nVulnerabilities Removed:${normal} "
# Define an array of severities for organization
declare -a severities=(" Critical" " High" " Medium" " Low" " Unknown" )
# Loop through each severity and print vulnerabilities
for severity in " ${severities[@]} " ; do
# Extract vulnerabilities of this severity
vulnerabilities=$( echo " $diff_api_json_output " | jq -r --arg sev " $severity " ' .vulnerabilities.removed[] | select(.severity == $sev) | .id' )
# Check if there are vulnerabilities of this severity
if [ -z " $vulnerabilities " ]; then
echo -e " ${purple}${severity} :${normal} "
else
echo -e " ${purple}${severity} :${normal} "
for vuln in $vulnerabilities ; do
echo -ne " - $vuln ${normal} \n"
done
fi
done
echo -e " \n${header} Finished!\n${normal} "
$ curl https://api.securityscorecards.dev/projects/github.com/kubernetes/kubernetes \
| jq | grep -i -B 1 -A 1 \"score\"
$ step oauth --provider=https://oauth2.sigstore.dev/auth --client-id=sigstore --listen \
localhost:0 --oidc --bare 2>/dev/null > id_token
$ cat id_token | step crypto jwt inspect --insecure
$ rekor-cli search --sha <digest> | uniq
$ rekor-cli get --uuid <UUID> --format=json | jq -r .Attestation | base64 -D | jq -r .
$ rekor-cli search --artifact <(echo -n CHAINS_GIT_COMMIT)
rekor-cli get --uuid <UUID> --format=json | jq -r .Body.RekordObj.signature.publicKey.content | base64 -D | openssl x509 -text- noout