- Add container-scanning.yml task file for vulnerability scans - Add systemd timer and service for scheduled scans - Add container-security-scan.sh script for manual scans - Integrate Trivy for Docker image vulnerability detection Implements: Automated container security monitoring
125 lines
3.6 KiB
Bash
125 lines
3.6 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# Container Image Security Scanner
|
|
# Uses Trivy to scan images for CVEs
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
VAULT_PASSWORD_FILE="${VAULT_PASSWORD_FILE:-secrets/.vault_pass}"
|
|
REPORT_DIR="${REPORT_DIR:-/var/log/trivy-scans}"
|
|
SEVERITY="${SEVERITY:-HIGH,CRITICAL}"
|
|
|
|
usage() {
|
|
echo "Usage: $0 [options]"
|
|
echo "Options:"
|
|
echo " --scan-all Scan all running containers (default)"
|
|
echo " --scan-image IMAGE Scan specific image"
|
|
echo " --severity LEVEL Severity filter (default: HIGH,CRITICAL)"
|
|
echo " --report-only Exit 0 even if CVEs found (for CI reporting)"
|
|
echo " --help Show this help"
|
|
exit 1
|
|
}
|
|
|
|
SCAN_MODE="all"
|
|
TARGET_IMAGE=""
|
|
REPORT_ONLY=false
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
--scan-all) SCAN_MODE="all"; shift ;;
|
|
--scan-image)
|
|
SCAN_MODE="single"
|
|
TARGET_IMAGE="$2"
|
|
shift 2
|
|
;;
|
|
--severity) SEVERITY="$2"; shift 2 ;;
|
|
--report-only) REPORT_ONLY=true; shift ;;
|
|
--help) usage ;;
|
|
*) echo "Unknown option: $1"; usage ;;
|
|
esac
|
|
done
|
|
|
|
# Check if Trivy is installed
|
|
if ! command -v trivy &> /dev/null; then
|
|
echo "Installing Trivy..."
|
|
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
|
|
fi
|
|
|
|
# Create report directory
|
|
mkdir -p "$REPORT_DIR"
|
|
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
|
REPORT_FILE="$REPORT_DIR/trivy-scan-$TIMESTAMP.json"
|
|
SUMMARY_FILE="$REPORT_DIR/trivy-scan-$TIMESTAMP.summary"
|
|
|
|
scan_image() {
|
|
local image="$1"
|
|
echo "Scanning: $image"
|
|
|
|
# Scan with Trivy
|
|
if trivy image \
|
|
--severity "$SEVERITY" \
|
|
--format json \
|
|
--output "$REPORT_FILE.tmp" \
|
|
--scanners vuln,config \
|
|
"$image" 2>/dev/null; then
|
|
|
|
# Check for vulnerabilities
|
|
if command -v jq &> /dev/null; then
|
|
CRITICAL=$(jq '[.Results[]?.Vulnerabilities? // empty | .[] | select(.Severity == "CRITICAL")] | length' "$REPORT_FILE.tmp" 2>/dev/null || echo "0")
|
|
HIGH=$(jq '[.Results[]?.Vulnerabilities? // empty | .[] | select(.Severity == "HIGH")] | length' "$REPORT_FILE.tmp" 2>/dev/null || echo "0")
|
|
|
|
echo " CRITICAL: $CRITICAL, HIGH: $HIGH"
|
|
|
|
if [[ "$CRITICAL" -gt 0 ]] && [[ "$REPORT_ONLY" == "false" ]]; then
|
|
echo "ERROR: CRITICAL vulnerabilities found in $image" >&2
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
cat "$REPORT_FILE.tmp" >> "$REPORT_FILE"
|
|
rm -f "$REPORT_FILE.tmp"
|
|
return 0
|
|
else
|
|
echo "WARNING: Failed to scan $image" >&2
|
|
return 0 # Continue scanning other images
|
|
fi
|
|
}
|
|
|
|
# Main scanning logic
|
|
echo "Starting Trivy container scan at $(date)"
|
|
echo "Severity filter: $SEVERITY"
|
|
echo ""
|
|
|
|
if [[ "$SCAN_MODE" == "single" ]]; then
|
|
scan_image "$TARGET_IMAGE"
|
|
else
|
|
# Get all unique images from running containers
|
|
IMAGES=$(docker ps --format '{{.Image}}' | sort -u)
|
|
|
|
TOTAL=0
|
|
FAILED=0
|
|
|
|
for image in $IMAGES; do
|
|
TOTAL=$((TOTAL + 1))
|
|
if ! scan_image "$image"; then
|
|
FAILED=$((FAILED + 1))
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
echo "Scan complete: $TOTAL images scanned, $FAILED failed"
|
|
fi
|
|
|
|
# Generate summary
|
|
echo ""
|
|
echo "Report saved to: $REPORT_FILE"
|
|
echo "To view: trivy convert --format table $REPORT_FILE"
|
|
|
|
# Cleanup old reports (keep last 30 days)
|
|
find "$REPORT_DIR" -name "trivy-scan-*.json" -mtime +30 -delete 2>/dev/null || true
|
|
|
|
if [[ "$FAILED" -gt 0 ]] && [[ "$REPORT_ONLY" == "false" ]]; then
|
|
exit 1
|
|
fi
|
|
|
|
exit 0
|