Skip to content

Commit e1724d1

Browse files
committed
wip: basic trivy scan script
Tool: gitpod/catfood.gitpod.cloud
1 parent 91ad3e7 commit e1724d1

File tree

3 files changed

+194
-0
lines changed

3 files changed

+194
-0
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
apiVersion: v1
2+
domain: example.com
3+
authProviders: []
4+
blockNewUsers:
5+
enabled: false
6+
passlist: []
7+
certificate:
8+
kind: secret
9+
name: https-certificates
10+
containerRegistry:
11+
enableAdditionalECRAuth: false
12+
inCluster: false
13+
privateBaseImageAllowList: []
14+
subassemblyBucket: ""
15+
external:
16+
url: "registry.example.com"
17+
certificate:
18+
kind: secret
19+
name: registry-certificate
20+
database:
21+
inCluster: false
22+
external:
23+
certificate:
24+
kind: secret
25+
name: database-certificate
26+
disableDefinitelyGp: true
27+
kind: Full
28+
metadata:
29+
region: local
30+
shortname: default
31+
objectStorage:
32+
inCluster: false
33+
resources:
34+
requests:
35+
memory: 2Gi
36+
s3:
37+
endpoint: "s3.example.com"
38+
bucket: "gitpod-storage"
39+
credentials:
40+
kind: secret
41+
name: object-storage-credentials
42+
observability:
43+
logLevel: info
44+
openVSX:
45+
url: https://open-vsx.org
46+
repository: eu.gcr.io/gitpod-dev-artifact/build
47+
workspace:
48+
maxLifetime: 36h0m0s
49+
resources:
50+
requests:
51+
cpu: "1"
52+
memory: 2Gi
53+
runtime:
54+
containerdRuntimeDir: /var/lib/containerd/io.containerd.runtime.v2.task/k8s.io
55+
containerdSocketDir: /run/containerd
56+
fsShiftMethod: shiftfs
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
#!/bin/bash
2+
# Copyright (c) 2025 Gitpod GmbH. All rights reserved.
3+
# Licensed under the GNU Affero General Public License (AGPL).
4+
# See License.AGPL.txt in the project root for license information.
5+
6+
set -uox pipefail
7+
8+
# Check if VERSION is provided
9+
if [[ $# -lt 1 ]]; then
10+
echo "Usage: $0 VERSION [TRIVY_ARGS...]"
11+
echo "Example: $0 main-gha.32006 --severity HIGH,CRITICAL"
12+
exit 1
13+
fi
14+
15+
# Extract VERSION from first argument and remove it from args list
16+
VERSION="$1"
17+
shift
18+
19+
# Set up working directory
20+
SCAN_DIR=$(mktemp -d -t trivy-scan-XXXXXX)
21+
echo "Working directory: $SCAN_DIR"
22+
23+
# Directory where this script is located
24+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
25+
CONFIG_DIR="$SCRIPT_DIR"
26+
INSTALLER_CONFIG_FILE="scan-installer-config.yaml"
27+
TRIVYIGNORE_PATH="$SCRIPT_DIR/trivyignore.yaml"
28+
29+
# Ensure Trivy is installed
30+
TRIVY_CMD="trivy"
31+
if ! command -v "$TRIVY_CMD" &> /dev/null; then
32+
echo "Trivy not found. Installing..."
33+
mkdir -p "$SCAN_DIR/bin"
34+
TRIVY_CMD="$SCAN_DIR/bin/trivy"
35+
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b "$SCAN_DIR/bin"
36+
fi
37+
38+
echo "=== Gathering list of all images for $VERSION"
39+
# Run the installer docker image to get the list of images
40+
docker run --rm -v "$CONFIG_DIR:/config" eu.gcr.io/gitpod-core-dev/build/installer:"${VERSION}" mirror list \
41+
-c "/config/$INSTALLER_CONFIG_FILE" > "$SCAN_DIR/mirror.json"
42+
43+
# Extract original image references
44+
jq -r '.[].original' "$SCAN_DIR/mirror.json" > "$SCAN_DIR/images.txt"
45+
46+
# Remove empty lines
47+
sed -i '/^\s*$/d' "$SCAN_DIR/images.txt"
48+
49+
# Filter out specific image patterns
50+
echo "=== Filtered out images:"
51+
TOTAL_BEFORE=$(wc -l < "$SCAN_DIR/images.txt")
52+
53+
# Apply all filters at once using extended regex
54+
grep -v -E "/build/ide/|/gitpod/workspace-|/library/mysql|/library/redis|/cloudsql-docker/gce-proxy" "$SCAN_DIR/images.txt" > "$SCAN_DIR/filtered_images.txt"
55+
56+
TOTAL_AFTER=$(wc -l < "$SCAN_DIR/filtered_images.txt")
57+
FILTERED=$((TOTAL_BEFORE - TOTAL_AFTER))
58+
59+
echo " Total filtered: $FILTERED"
60+
61+
# Use filtered list for scanning
62+
mv "$SCAN_DIR/filtered_images.txt" "$SCAN_DIR/images.txt"
63+
64+
# Count total images
65+
TOTAL_IMAGES=$(wc -l < "$SCAN_DIR/images.txt")
66+
echo "=== Found $TOTAL_IMAGES images to scan"
67+
68+
# Create results directory
69+
RESULT_FILE="$SCAN_DIR/result.jsonl"
70+
71+
# Scan all images with Trivy
72+
COUNTER=0
73+
FAILED=0
74+
while IFS= read -r IMAGE_REF; do
75+
((COUNTER=COUNTER+1))
76+
77+
echo "= Scanning $IMAGE_REF [$COUNTER / $TOTAL_IMAGES]"
78+
79+
# Run Trivy on the image
80+
scan_time=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
81+
trivy_output=$("$TRIVY_CMD" image "$IMAGE_REF" --ignorefile "$TRIVYIGNORE_PATH" --scanners vuln --format json "$@" | jq -c)
82+
scan_status=$?
83+
84+
echo "Trivy scan status: $scan_status"
85+
echo "Trivy output: $trivy_output"
86+
87+
# Create a JSON object for the current scan
88+
if [ $scan_status -eq 0 ]; then
89+
# Check if trivy_output is valid JSON
90+
if echo "$trivy_output" | jq empty > /dev/null 2>&1; then
91+
# Direct approach - create the combined JSON object using jq directly
92+
jq -c --arg image "$IMAGE_REF" --arg scan_time "$scan_time" \
93+
'. + {image: $image, scan_time: $scan_time}' <<< "$trivy_output" | jq >> "$RESULT_FILE"
94+
else
95+
# If trivy output is not valid JSON, treat as error
96+
echo "Warning: Trivy returned invalid JSON for $IMAGE_REF"
97+
jq -n --arg image "$IMAGE_REF" \
98+
--arg scan_time "$scan_time" \
99+
--arg error "Invalid JSON output from Trivy" \
100+
--arg details "$trivy_output" \
101+
'{image: $image, scan_time: $scan_time, error: $error, error_details: $details}' | jq >> "$RESULT_FILE"
102+
((FAILED=FAILED+1))
103+
fi
104+
105+
else
106+
# For error cases, create a simple JSON object
107+
jq -n --arg image "$IMAGE_REF" \
108+
--arg scan_time "$scan_time" \
109+
--arg error "Trivy scan failed" \
110+
--arg details "$trivy_output" \
111+
'{image: $image, scan_time: $scan_time, error: $error, error_details: $details}' >> "$RESULT_FILE"
112+
((FAILED=FAILED+1))
113+
fi
114+
115+
echo ""
116+
done < "$SCAN_DIR/images.txt"
117+
118+
# Generate summary report
119+
echo "=== Scan Summary ==="
120+
echo "Scan directory: $SCAN_DIR"
121+
echo "Total ignored images: $FILTERED"
122+
echo "Total scanned images: $TOTAL_IMAGES"
123+
echo "Failed scans: $FAILED"
124+
125+
# Count vulnerabilities by severity
126+
if command -v jq &> /dev/null; then
127+
echo "=== Vulnerability Summary ==="
128+
echo "CRITICAL: $(jq -r 'if .Results != null then [.Results[].Vulnerabilities // [] | .[] | select(.Severity == "CRITICAL")] | length else 0 end' "$RESULT_FILE" 2>/dev/null | awk '{sum+=$1} END {print sum}')"
129+
echo "HIGH: $(jq -r 'if .Results != null then [.Results[].Vulnerabilities // [] | .[] | select(.Severity == "HIGH")] | length else 0 end' "$RESULT_FILE" 2>/dev/null | awk '{sum+=$1} END {print sum}')"
130+
fi
131+
132+
echo "=== Scan completed ==="
133+
if [[ $FAILED -gt 0 ]]; then
134+
echo "ERROR: $FAILED scans failed"
135+
exit 1
136+
fi
137+
138+
exit 0

install/installer/trivy/trivyignore.yaml

Whitespace-only changes.

0 commit comments

Comments
 (0)