Skip to content

Commit

Permalink
feat(cve-scan-patch): improve logging and bugfixing
Browse files Browse the repository at this point in the history
  • Loading branch information
g-iannelli committed Oct 7, 2024
1 parent 7c06b87 commit 857bc14
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 44 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/cve-scan-and-patching.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ permissions:

on:
push:
paths:
- .github/workflows/cve-scan-and-patching.yml
- CVEs/**
#branches:
# - "main"
#schedule:
Expand Down Expand Up @@ -142,6 +145,7 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: patch-report-${{ steps.patching.outputs.IMAGE_TO_PATCH_NORMALIZED }}.md
if-no-files-found: ignore
path: |
CVEs/reports/*.patched.md
scan_post_patch:
Expand Down
8 changes: 4 additions & 4 deletions CVEs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ concat-multiple-kfd-images-list:
rm $(PATCH_FILE_IMAGE_LIST_TO_PATCHING).tmp

patch:
DOCKER_CONFIG="${DOCKER_CONFIG}" DRY_RUN=$(DRY_RUN) ../scripts/patch_images_with_copacetic.sh -i "$(IMAGE_TO_PATCH)" -l "$(PATCH_FILE_IMAGE_LIST_TO_PATCHING)" -o "$(PATCH_REPORT_OUTPUT_FILE)"
DOCKER_CONFIG="${DOCKER_CONFIG}" DRY_RUN=$(DRY_RUN) ./patch_images_with_copacetic.sh -i "$(IMAGE_TO_PATCH)" -l "$(PATCH_FILE_IMAGE_LIST_TO_PATCHING)" -o "$(PATCH_REPORT_OUTPUT_FILE)"

scan-post-patch:
@for version in $(KFD_VERSIONS); do \
Expand Down Expand Up @@ -67,11 +67,11 @@ generate-image-list-from-manifests:
sort -u $(KFD_VERSION)/images.tmp.txt -o $(KFD_VERSION)/images.txt && rm $(KFD_VERSION)/images.tmp.txt

trivy-download-db:
trivy image --download-db-only --db-repository registry.sighup.io/fury-secured/aquasecurity/trivy-db:2
trivy image --download-java-db-only --java-db-repository registry.sighup.io/fury-secured/aquasecurity/trivy-java-db:1
trivy image --download-db-only --db-repository registry.sighup.io/fury-secured/aquasecurity/trivy-db:2 --no-progress
trivy image --download-java-db-only --java-db-repository registry.sighup.io/fury-secured/aquasecurity/trivy-java-db:1 --no-progress

scan-vulns:
../scripts/scan_vuln.sh -v $(KFD_VERSION) -l $(LIST_FILE) -o $(OUTPUT_FILE);
./scan_vuln.sh -v $(KFD_VERSION) -l $(LIST_FILE) -o $(OUTPUT_FILE);



Expand Down
30 changes: 30 additions & 0 deletions CVEs/logging.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/bin/bash

NC='\033[0m' # No Color
BLACK='\033[0;30m'
RED='\033[0;31m'
GREEN='\033[0;32m'
ORANGE='\033[0;33m'
CYAN='\033[0;36m'
YELLOW='\033[1;33m'
WHITE='\033[1;37m'

function info() {
echo -e ">>\t${CYAN}[INFO]${NC} $(date +"%Y-%m-%dT%H:%M:%S.%3NZ"): $*"
}

function warn() {
echo -e ">>\t[${ORANGE}WARN${NC}] $(date +"%Y-%m-%dT%H:%M:%S.%3NZ"): $*"
}

function error() {
echo -e ">>\t[${RED}ERROR${NC}] $(date +"%Y-%m-%dT%H:%M:%S.%3NZ"): $*"
}

function success() {
echo -e ">>\t${GREEN}SUCCESS${NC} $(date +"%Y-%m-%dT%H:%M:%S.%3NZ"): $*"
}

function fail() {
echo -e ">>\t${RED}FAIL${NC} $(date +"%Y-%m-%dT%H:%M:%S.%3NZ"): $*" && exit 1
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#!/bin/bash

source logging.sh

IMAGE_TO_PATCH=
FILE_WITH_IMAGES_LIST_TO_PATCH=
PATCH_REPORT_OUTPUT_FILE=
Expand Down Expand Up @@ -38,7 +40,7 @@ PATCH_ERROR_OUTPUT_FILE="$LOG_OUTPUT_DIR/patch-error.log"

if [ -z "$(docker ps -f name=buildkitd -q)" ]
then
echo ">>>>>>>>>>>>>>>>>>> Start buildkitd instance for COPA <<<<<<<<<<<<<<<<<<<<<"
info "Start buildkitd instance for COPA"
if [ -n "$DOCKER_CONFIG" ]
then
docker_config_extra_args="-v ${DOCKER_CONFIG}:/root/.docker"
Expand All @@ -49,50 +51,49 @@ fi
mkdir -p "$TRIVY_SCAN_OUTPUT_DIR" "$COPA_PATCH_OUTPUT_DIR" "$DOCKERFILE_OUTPUT_DIR" "$LOG_OUTPUT_DIR"
echo -n "" > "${PATCH_ERROR_OUTPUT_FILE}"

{
[[ -n $IMAGE_TO_PATCH ]] && printf "# %s\n\n" $IMAGE_TO_PATCH
printf "Last updated %s\n\n" "$(date +'%Y-%m-%d')";
printf "## CVEs patched\n\n" ;
echo "| Source Image | Source Image Hash |CVE | Severity | Description | Patched Image| Patched Image Hash |"
echo "| --- | --- | --- | --- |--- | --- | --- |"
} > "${PATCH_REPORT_OUTPUT_FILE}"


REGISTRY_BASE_URL='registry.sighup.io/fury'
REGISTRY_SECURED_BASE_URL='registry.sighup.io/fury-secured'
REGISTRY_BASE_URL='registry.sighup.io/fury/'
REGISTRY_SECURED_BASE_URL='registry.sighup.io/fury-secured/'

function patch_image() {
local image="$1"
secured_image=${image//"${REGISTRY_BASE_URL}"/"${REGISTRY_SECURED_BASE_URL}"}
image_to_patch="$image"

DOCKER_PULL_OUTPUT_FILE="$LOG_OUTPUT_DIR/${image_to_patch//[:\/]/_}-image-pull.log"
if ! docker pull "$image_to_patch" >> "${DOCKER_PULL_OUTPUT_FILE}" 2>&1
if ! docker pull "$image_to_patch" > "${DOCKER_PULL_OUTPUT_FILE}" 2>&1
then
echo ">>>>>>>>>>>>>>>>>>> Failed pull $image_to_patch <<<<<<<<<<<<<<<<<<<<<"
error "Failed pull $image_to_patch"
cat "${DOCKER_PULL_OUTPUT_FILE}"
return 1
fi

TRIVY_SCAN_OUTPUT_FILE=$TRIVY_SCAN_OUTPUT_DIR/${image_to_patch//[:\/]/_}.json
COPA_REPORT_OUTPUT_FILE=$COPA_PATCH_OUTPUT_DIR/${image_to_patch//[:\/]/_}.vex.json
COPA_PATCHING_LOG_FILE=$COPA_PATCH_OUTPUT_DIR/${image_to_patch//[:\/]/_}.log
echo ">>>>>>>>>>>>>>>>>>> Scan $image_to_patch for CVEs <<<<<<<<<<<<<<<<<<<<<"
info "Scan $image_to_patch for CVEs"
trivy image --skip-db-update --skip-java-db-update --scanners vuln -q --vuln-type os --ignore-unfixed -f json -o "${TRIVY_SCAN_OUTPUT_FILE}" "$image_to_patch" # --platform=linux/amd64
echo ">>>>>>>>>>>>>>>>>>> Clean trivy scan cache for $image_to_patch <<<<<<<<<<<<<<<<<<<<<"
info "Clean trivy scan cache for $image_to_patch"
trivy clean --scan-cache
echo ">>>>>>>>>>>>>>>>>>> Patching CVEs for $image_to_patch <<<<<<<<<<<<<<<<<<<<<"
info "Patching CVEs for $image_to_patch"
copa patch -r "${TRIVY_SCAN_OUTPUT_FILE}" -i "$image_to_patch" --format="openvex" --output "$COPA_REPORT_OUTPUT_FILE" -a tcp://127.0.0.1:8888 2>&1 | tee "$COPA_PATCHING_LOG_FILE"
copa_exit_code=${PIPESTATUS[0]}

if [ "$copa_exit_code" -eq 0 ]
then
FIXED_CVES=$(jq '.statements[] | select(.status=="fixed") | .vulnerability."@id"' -r < "$COPA_REPORT_OUTPUT_FILE" | sort -r)
echo ">>>>>>>>>>>>>>>>>>> ${FIXED_CVES} patched in $image_to_patch-patched <<<<<<<<<<<<<<<<<<<<<"
{
[[ -n $IMAGE_TO_PATCH ]] && printf "# %s\n\n" $IMAGE_TO_PATCH
printf "Last updated %s\n\n" "$(date +'%Y-%m-%d')";
printf "## CVEs patched\n\n" ;
echo "| Source Image | Source Image Hash |CVE | Severity | Description | Patched Image| Patched Image Hash |"
echo "| --- | --- | --- | --- |--- | --- | --- |"
} > "${PATCH_REPORT_OUTPUT_FILE}"

FIXED_CVES=$(jq '.statements[] | select(.status=="fixed") | .vulnerability."@id"' -r < "$COPA_REPORT_OUTPUT_FILE" | sort -r )
info "CVEs patched in $image_to_patch-patched: ${FIXED_CVES//[$'\r\n']/ }"
DOCKER_LABELS=
image_patched_hash=$(docker inspect "$image_to_patch-patched" --format '{{.Id}}')
echo ">>>>>>>>>>>>>>>>>>> $image_to_patch-patched hash: ${image_patched_hash} <<<<<<<<<<<<<<<<<<<<<"
echo ">>>>>>>>>>>>>>>>>>> Update patching report for $image_to_patch <<<<<<<<<<<<<<<<<<<<<"
info "$image_to_patch-patched hash: ${image_patched_hash}"
info "Update patching report for $image_to_patch"
image_to_patch_hash=$(jq -r '.Metadata.ImageID' < "$TRIVY_SCAN_OUTPUT_FILE")
for FIXED_CVE in ${FIXED_CVES[@]}
do
Expand All @@ -105,7 +106,7 @@ function patch_image() {
--arg image_patched_hash "$image_patched_hash" \
'[try .Results[].Vulnerabilities[] | select(.VulnerabilityID==$cve)][0] | "|" + $image_to_patch + " | " + $image_to_patch_hash + " | " + .VulnerabilityID + " | " + .Severity + " | " + .Title + " | " + $image_patched + "|" + $image_patched_hash + "|"' < "$TRIVY_SCAN_OUTPUT_FILE">> "$PATCH_REPORT_OUTPUT_FILE"
done
echo ">>>>>>>>>>>>>>>>>>> Tag $image_to_patch-patched as secured image: $secured_image <<<<<<<<<<<<<<<<<<<<<"
info "Tag $image_to_patch-patched as secured image: $secured_image"
echo "FROM $image_to_patch-patched" | DOCKER_BUILDKIT=0 docker build \
${DOCKER_LABELS} \
--label io.sighup.secured.image.created="$(date -u +"%Y-%m-%dT%H:%M:%S.%3NZ")" \
Expand All @@ -116,39 +117,45 @@ function patch_image() {
sed -i'.unsecured' s#"$image_to_patch-patched"#"$secured_image"# "$PATCH_REPORT_OUTPUT_FILE"
sed -i'.unsecured' s#"$image_patched_hash"#"$secured_labeled_image_hash"# "$PATCH_REPORT_OUTPUT_FILE"
rm "$PATCH_REPORT_OUTPUT_FILE.unsecured"
echo ">>>>>>>>>>>>>>>>>>> Push secure image: $secured_image <<<<<<<<<<<<<<<<<<<<<"
info "Push secure image: $secured_image"
[[ $DRY_RUN -eq 0 ]] && docker push "$secured_image"
echo ">>>>>>>>>>>>>>>>>>> CLEANUP $image_to_patch-patched <<<<<<<<<<<<<<<<<<<<<"
info "Cleanup $image_to_patch-patched"
buildctl --addr tcp://127.0.0.1:8888 prune
docker rmi -f "$image_to_patch-patched"
echo ">>>>>>>>>>>>>>>>>>> CLEANUP $secured_image <<<<<<<<<<<<<<<<<<<<<"
info "cleanup $secured_image"
docker rmi -f "$secured_image"
success "$secured_image pushed with id: ${secured_labeled_image_hash}"
else
if [ "$image_to_patch" != "$secured_image" ]
then
echo ">>>>>>>>>>>>>>>>>>> No CVEs patched in $image_to_patch <<<<<<<<<<<<<<<<<<<<<"
echo ">>>>>>>>>>>>>>>>>>> Tag $image_to_patch as secured image: $secured_image <<<<<<<<<<<<<<<<<<<<<"
warn "No CVEs patched in $image_to_patch"
warn "Tag $image_to_patch as secured image: $secured_image"
docker tag "$image_to_patch" "$secured_image"
echo ">>>>>>>>>>>>>>>>>>> Push secured image: $secured_image <<<<<<<<<<<<<<<<<<<<<"
[[ $DRY_RUN -eq 0 ]] && docker push "$secured_image"
echo ">>>>>>>>>>>>>>>>>>> CLEANUP $secured_image <<<<<<<<<<<<<<<<<<<<<"
[[ $DRY_RUN -eq 0 ]] && info "Push secured image: $secured_image" && docker push "$secured_image"
info "cleanup $secured_image"
docker rmi -f "$secured_image"
echo ">>>>>>>>>>>>>>>>>>> Update patching error log <<<<<<<<<<<<<<<<<<<<<"
info "Update patching error log"
echo "$secured_image: $(awk -F'Error:' '$0 ~ /Error:/ {print $2}' "$COPA_PATCHING_LOG_FILE")" >> "$PATCH_ERROR_OUTPUT_FILE"
else
echo ">>>>>>>>>>>>>>>>>>> $image_to_patch is the same of $secured_image <<<<<<<<<<<<<<<<<<<<<"
error "$image_to_patch is the same of $secured_image"
fi
fi

echo ">>>>>>>>>>>>>>>>>>> CLEANUP $image_to_patch <<<<<<<<<<<<<<<<<<<<<"
info "Cleanup $image_to_patch"
docker rmi -f "$image_to_patch"
echo ""
echo "================================================================"
echo ""
}

[[ -n $IMAGE_TO_PATCH ]] && patch_image "$IMAGE_TO_PATCH" && exit 0
return 0
}

while IFS= read -r image; do
patch_image "$image"
done < "$FILE_WITH_IMAGES_LIST_TO_PATCH"
if [ -n "$IMAGE_TO_PATCH" ]
then
patch_image "$IMAGE_TO_PATCH"
else
[[ ! -f $FILE_WITH_IMAGES_LIST_TO_PATCH ]] && fail "Missing image list files"
while IFS= read -r image; do
patch_image "$image"
done < "$FILE_WITH_IMAGES_LIST_TO_PATCH"
fi
5 changes: 3 additions & 2 deletions scripts/scan_vuln.sh → CVEs/scan_vuln.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ while getopts ":v:l:o:" o; do
done
shift $((OPTIND-1))

source logging.sh

[[ -z $KFD_VERSION ]] && echo "ERROR: Missing KFD VERSION" && exit 1
[[ -z $KFD_VERSION ]] && fail "Missing KFD VERSION"
[[ -z $IMAGE_LIST_FILE ]] && IMAGE_LIST_FILE="${KFD_VERSION}/images.txt"
[[ -z $SCAN_RESULT_OUTPUT_FILE ]] && SCAN_RESULT_OUTPUT_FILE="${KFD_VERSION}/CVEs.md"

Expand All @@ -53,7 +54,7 @@ mkdir -p "$TRIVY_SCAN_OUTPUT_DIR"
for image in $IMAGE_LIST; do
TRIVY_SCAN_OUTPUT_FILE="$TRIVY_SCAN_OUTPUT_DIR/scan-${image//[:\/]/_}.json"

echo ">>>>>>>>>>>>>>>>>>> Scan $image for CVEs <<<<<<<<<<<<<<<<<<<<<"
info "Scan $image for CVEs"
if ! trivy image --skip-db-update --skip-java-db-update --scanners vuln --no-progress --output "$TRIVY_SCAN_OUTPUT_FILE" --format json --severity CRITICAL "$image"
then
echo "$image | ERROR PROCESSING! " >> "${SCAN_ERROR_OUTPUT_FILE}"
Expand Down

0 comments on commit 857bc14

Please sign in to comment.