Skip to content

Commit 272a8c4

Browse files
ericfitzclaude
andcommitted
refactor(security): migrate from Docker Scout to Grype for container scanning
- Replace Docker Scout with Grype (Anchore) for vulnerability scanning - Remove Trivy filesystem scanning target (unused) - Add check-grype make target for tool availability checking - Update build-containers.sh with Grype-based scan_image_vulnerabilities() - Update build-container-oracle.sh run_security_scan() function - Update make-containers-dev-local.sh security scanning - Update CLAUDE.md documentation references Consolidates on Anchore toolchain: Syft for SBOM, Grype for CVE scanning. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 3e7f5fa commit 272a8c4

File tree

5 files changed

+81
-91
lines changed

5 files changed

+81
-91
lines changed

CLAUDE.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,15 @@ The major version remains at 0 during initial development. Version updates are f
7878
- Stop observability: `make observability-stop` (stops monitoring services), `make obs-stop` (alias)
7979
- Clean observability: `make observability-clean` (removes monitoring data), `make obs-clean` (alias)
8080

81-
### Container Management (Docker Scout Integration)
81+
### Container Management (Grype Integration)
8282

8383
- Build individual containers (faster for iterative development):
8484
- `make build-container-db` (PostgreSQL container only)
8585
- `make build-container-redis` (Redis container only)
8686
- `make build-container-tmi` (TMI server container only)
8787
- Build all containers: `make build-containers` (builds db, redis, tmi serially)
88-
- Security scan: `make scan-containers` (scans containers for vulnerabilities using Docker Scout)
88+
- Check scanner: `make check-grype` (verify Grype vulnerability scanner is installed)
89+
- Security scan: `make scan-containers` (scans containers for vulnerabilities using Grype)
8990
- Security report: `make report-containers` (generates comprehensive security report)
9091
- Container development: `make containers-dev` (builds and starts containers, no server)
9192
- Full container workflow: `make containers-all` (builds containers and generates reports)

Makefile

Lines changed: 27 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -945,34 +945,23 @@ analyze-cats-results: parse-cats-results query-cats-results ## Parse and query
945945
# CONTAINER SECURITY AND BUILD MANAGEMENT
946946
# ============================================================================
947947

948-
.PHONY: build-containers build-container-db build-container-redis build-container-tmi build-container-oracle build-container-oracle-push build-container-redis-oracle build-container-redis-oracle-push build-containers-oracle build-containers-oracle-push scan-containers scan-trivy report-containers update-docker-scout
949-
950-
# Update Docker Scout CLI
951-
update-docker-scout:
952-
$(call log_info,Updating Docker Scout CLI...)
953-
@curl -fsSL https://raw.githubusercontent.com/docker/scout-cli/main/install.sh -o install-scout.sh
954-
@sh install-scout.sh
955-
@rm -f install-scout.sh
956-
$(call log_success,Docker Scout CLI updated successfully)
948+
.PHONY: build-containers build-container-db build-container-redis build-container-tmi build-container-oracle build-container-oracle-push build-container-redis-oracle build-container-redis-oracle-push build-containers-oracle build-containers-oracle-push scan-containers report-containers
957949

958950
# Build PostgreSQL container only
959-
build-container-db:
951+
build-container-db: check-grype
960952
$(call log_info,Building PostgreSQL container...)
961-
@$(MAKE) -f $(MAKEFILE_LIST) update-docker-scout
962953
@./scripts/build-containers.sh postgresql
963954
$(call log_success,PostgreSQL container built successfully)
964955

965956
# Build Redis container only
966-
build-container-redis:
957+
build-container-redis: check-grype
967958
$(call log_info,Building Redis container...)
968-
@$(MAKE) -f $(MAKEFILE_LIST) update-docker-scout
969959
@./scripts/build-containers.sh redis
970960
$(call log_success,Redis container built successfully)
971961

972962
# Build TMI server container only
973-
build-container-tmi:
963+
build-container-tmi: check-grype
974964
$(call log_info,Building TMI server container...)
975-
@$(MAKE) -f $(MAKEFILE_LIST) update-docker-scout
976965
@./scripts/build-containers.sh application
977966
$(call log_success,TMI server container built successfully)
978967

@@ -1023,46 +1012,32 @@ build-containers: build-container-db build-container-redis build-container-tmi
10231012
$(call log_success,All containers built successfully)
10241013

10251014
# Run security scan on existing containers
1026-
scan-containers:
1015+
scan-containers: check-grype
10271016
$(call log_info,Running security scans on container images...)
1028-
@$(MAKE) -f $(MAKEFILE_LIST) update-docker-scout
1029-
@if ! command -v docker scout >/dev/null 2>&1; then \
1030-
$(call log_error,Docker Scout not available after update. Installation may have failed); \
1031-
exit 1; \
1032-
fi
10331017
@mkdir -p security-reports
10341018
@echo "Scanning cgr.dev/chainguard/postgres:latest..."
1035-
@docker scout cves cgr.dev/chainguard/postgres:latest --only-severity critical,high > security-reports/postgresql-scan.txt 2>&1 || true
1019+
@grype cgr.dev/chainguard/postgres:latest -o sarif > security-reports/postgresql-scan.sarif 2>/dev/null || true
1020+
@grype cgr.dev/chainguard/postgres:latest -o table > security-reports/postgresql-scan.txt 2>&1 || true
10361021
@echo "Scanning tmi/tmi-redis:latest..."
1037-
@docker scout cves tmi/tmi-redis:latest --only-severity critical,high > security-reports/redis-scan.txt 2>&1 || true
1022+
@grype tmi/tmi-redis:latest -o sarif > security-reports/redis-scan.sarif 2>/dev/null || true
1023+
@grype tmi/tmi-redis:latest -o table > security-reports/redis-scan.txt 2>&1 || true
10381024
@if [ -f "Dockerfile.dev" ]; then \
10391025
echo "Building and scanning application image..."; \
10401026
docker build -f Dockerfile.dev -t tmi-temp-scan:latest . >/dev/null 2>&1 || true; \
1041-
docker scout cves tmi-temp-scan:latest --only-severity critical,high > security-reports/application-scan.txt 2>&1 || true; \
1027+
grype tmi-temp-scan:latest -o sarif > security-reports/application-scan.sarif 2>/dev/null || true; \
1028+
grype tmi-temp-scan:latest -o table > security-reports/application-scan.txt 2>&1 || true; \
10421029
docker rmi tmi-temp-scan:latest >/dev/null 2>&1 || true; \
10431030
fi
10441031
$(call log_success,Security scans completed. Reports in security-reports/)
10451032

1046-
# Run Trivy filesystem security scan
1047-
scan-trivy:
1048-
$(call log_info,Running Trivy filesystem security scan...)
1049-
@if ! command -v trivy >/dev/null 2>&1; then \
1050-
$(call log_error,Trivy not found. Please install it first.); \
1051-
$(call log_info,See: https://aquasecurity.github.io/trivy/); \
1052-
$(call log_info,On MacOS with Homebrew: brew install trivy); \
1053-
exit 1; \
1054-
fi
1055-
@trivy fs --ignorefile ./.trivyignore.yaml .
1056-
$(call log_success,Trivy filesystem scan completed)
1057-
10581033
# Generate comprehensive security report
10591034
report-containers: scan-containers
10601035
$(call log_info,Generating container security report...)
10611036
@mkdir -p security-reports
10621037
@echo "# TMI Container Security Report" > security-reports/security-summary.md
10631038
@echo "" >> security-reports/security-summary.md
10641039
@echo "**Generated:** $$(date)" >> security-reports/security-summary.md
1065-
@echo "**Scanner:** Docker Scout" >> security-reports/security-summary.md
1040+
@echo "**Scanner:** Grype (Anchore)" >> security-reports/security-summary.md
10661041
@echo "" >> security-reports/security-summary.md
10671042
@echo "## Vulnerability Summary" >> security-reports/security-summary.md
10681043
@echo "" >> security-reports/security-summary.md
@@ -1375,7 +1350,7 @@ clean-wstest:
13751350
# SBOM GENERATION - Software Bill of Materials
13761351
# ============================================================================
13771352

1378-
.PHONY: check-cyclonedx check-syft generate-sbom generate-sbom-all build-with-sbom build-server-sbom
1353+
.PHONY: check-cyclonedx check-syft check-grype generate-sbom generate-sbom-all build-with-sbom build-server-sbom
13791354

13801355
# Check for cyclonedx-gomod (Go components)
13811356
check-cyclonedx:
@@ -1401,6 +1376,18 @@ check-syft:
14011376
fi
14021377
@$(call log_success,Syft is available)
14031378

1379+
# Check for Grype (container vulnerability scanning)
1380+
check-grype:
1381+
@if ! command -v grype >/dev/null 2>&1; then \
1382+
$(call log_error,Grype not found); \
1383+
echo ""; \
1384+
$(call log_info,Install using:); \
1385+
echo " Homebrew: brew install grype"; \
1386+
echo " Script: curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin"; \
1387+
exit 1; \
1388+
fi
1389+
@$(call log_success,Grype is available)
1390+
14041391
# Generate SBOM for Go application only
14051392
generate-sbom: check-cyclonedx
14061393
$(call log_info,Generating SBOM for Go application...)
@@ -1618,8 +1605,8 @@ help:
16181605
@echo " reset-db-oci - Drop all tables in OCI ADB (destructive)"
16191606
@echo " clean-dev - Clean development environment"
16201607
@echo ""
1621-
@echo "Container Management (Docker Scout Integration):"
1622-
@echo " update-docker-scout - Update Docker Scout CLI to latest version"
1608+
@echo "Container Management (Grype Integration):"
1609+
@echo " check-grype - Verify Grype vulnerability scanner is installed"
16231610
@echo " build-container-db - Build PostgreSQL container only"
16241611
@echo " build-container-redis - Build Redis container only"
16251612
@echo " build-container-tmi - Build TMI server container only"
@@ -1631,7 +1618,6 @@ help:
16311618
@echo " build-containers-oracle-push - Build and push all Oracle containers"
16321619
@echo " build-containers - Build all containers (db, redis, tmi serially)"
16331620
@echo " scan-containers - Scan existing containers for vulnerabilities"
1634-
@echo " scan-trivy - Run Trivy filesystem security scan"
16351621
@echo " report-containers - Generate comprehensive security report"
16361622
@echo " start-containers-environment - Start development with containers"
16371623
@echo " build-containers-all - Run full container build and report"

scripts/build-container-oracle.sh

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -368,26 +368,24 @@ run_security_scan() {
368368

369369
log_info "Running security scan on ${component} container image..."
370370

371-
# Check for Docker Scout
372-
if docker scout version &> /dev/null 2>&1; then
373-
log_info "Using Docker Scout for security scanning..."
371+
# Check for Grype
372+
if command -v grype &> /dev/null; then
373+
log_info "Using Grype for security scanning..."
374374

375375
# Create reports directory
376376
local reports_dir="${PROJECT_ROOT}/security-reports/oracle-container"
377377
mkdir -p "$reports_dir"
378378

379-
# Run CVE scan
380-
docker scout cves "${image_name}:${TAG}" \
381-
--format sarif \
382-
--output "${reports_dir}/${component}-cve-report.sarif.json" 2>/dev/null || true
379+
# Run CVE scan with SARIF output
380+
grype "${image_name}:${TAG}" -o sarif > "${reports_dir}/${component}-cve-report.sarif.json" 2>/dev/null || true
383381

384-
# Show summary
385-
docker scout cves "${image_name}:${TAG}" --format summary 2>/dev/null || true
382+
# Show summary table
383+
grype "${image_name}:${TAG}" -o table 2>/dev/null || true
386384

387385
log_success "Security scan complete. Report: ${reports_dir}/${component}-cve-report.sarif.json"
388386
else
389-
log_warn "Docker Scout not available. Skipping security scan."
390-
log_info "Install Docker Scout: curl -fsSL https://raw.githubusercontent.com/docker/scout-cli/main/install.sh | sh"
387+
log_warn "Grype not available. Skipping security scan."
388+
log_info "Install Grype: brew install grype"
391389
fi
392390

393391
# Generate SBOM if syft is available

scripts/build-containers.sh

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/bin/bash
22

3-
# Container Build Script with Docker Scout Security Scanning and Patching
4-
# This script builds container images with automated vulnerability patching
3+
# Container Build Script with Grype Security Scanning
4+
# This script builds container images with automated vulnerability scanning using Grype (Anchore)
55

66
set -e # Exit immediately if a command exits with a non-zero status
77
set -o pipefail # Exit if any command in a pipeline fails
@@ -48,17 +48,19 @@ log_error() {
4848
echo -e "${RED}[ERROR]${NC} $1"
4949
}
5050

51-
# Function to check if Docker Scout is available
52-
check_docker_scout() {
53-
if ! docker scout version >/dev/null 2>&1; then
54-
log_error "Docker Scout is not available. Please install Docker Scout CLI."
55-
log_info "Installation: https://docs.docker.com/scout/install/"
56-
exit 1
51+
# Function to check if Grype is available
52+
check_grype() {
53+
if ! command -v grype >/dev/null 2>&1; then
54+
log_warning "Grype is not available. Vulnerability scanning will be skipped."
55+
log_info "Install: brew install grype"
56+
log_info "Or: curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin"
57+
return 1
5758
fi
58-
log_success "Docker Scout is available"
59+
log_success "Grype is available"
60+
return 0
5961
}
6062

61-
# Function to scan image for vulnerabilities
63+
# Function to scan image for vulnerabilities using Grype
6264
scan_image_vulnerabilities() {
6365
local image_name="$1"
6466
local report_file="$2"
@@ -68,19 +70,21 @@ scan_image_vulnerabilities() {
6870
# Create security reports directory
6971
mkdir -p "${SECURITY_SCAN_OUTPUT_DIR}"
7072

71-
# Scan for critical and high vulnerabilities
72-
docker scout cves "${image_name}" \
73-
--only-severity critical,high \
74-
--format sarif \
75-
--output "${report_file}.sarif" || true
73+
# Check if Grype is available
74+
if ! command -v grype >/dev/null 2>&1; then
75+
log_warning "Grype not available, skipping vulnerability scan"
76+
return 0
77+
fi
78+
79+
# Generate SARIF report
80+
grype "${image_name}" -o sarif > "${report_file}.sarif" 2>/dev/null || true
7681

77-
# Get human-readable summary
78-
docker scout cves "${image_name}" \
79-
--only-severity critical,high > "${report_file}.txt" || true
82+
# Generate human-readable table report
83+
grype "${image_name}" -o table > "${report_file}.txt" 2>/dev/null || true
8084

81-
# Count vulnerabilities
82-
local critical_count=$(docker scout cves "${image_name}" --only-severity critical --format sarif 2>/dev/null | jq -r '.runs[0].results | length' 2>/dev/null || echo "0")
83-
local high_count=$(docker scout cves "${image_name}" --only-severity high --format sarif 2>/dev/null | jq -r '.runs[0].results | length' 2>/dev/null || echo "0")
85+
# Count vulnerabilities using JSON output
86+
local critical_count=$(grype "${image_name}" -o json 2>/dev/null | jq '[.matches[] | select(.vulnerability.severity == "Critical")] | length' 2>/dev/null || echo "0")
87+
local high_count=$(grype "${image_name}" -o json 2>/dev/null | jq '[.matches[] | select(.vulnerability.severity == "High")] | length' 2>/dev/null || echo "0")
8488

8589
# Default to 0 if jq fails
8690
critical_count=${critical_count:-0}
@@ -262,7 +266,7 @@ generate_security_summary() {
262266
263267
**Scan Date:** ${BUILD_DATE}
264268
**Git Commit:** ${GIT_COMMIT}
265-
**Scanner:** Docker Scout
269+
**Scanner:** Grype (Anchore)
266270
267271
## Images Scanned
268272
@@ -363,7 +367,7 @@ main() {
363367
echo ""
364368

365369
# Pre-checks
366-
check_docker_scout
370+
check_grype
367371

368372
# Clean up old images first
369373
cleanup_old_images
@@ -400,22 +404,22 @@ main() {
400404
# Handle script arguments
401405
case "${1:-all}" in
402406
postgresql|pg)
403-
check_docker_scout
407+
check_grype
404408
build_postgresql_secure
405409
;;
406410
redis)
407-
check_docker_scout
411+
check_grype
408412
build_redis_secure
409413
;;
410414
application|app)
411-
check_docker_scout
415+
check_grype
412416
build_application_secure
413417
;;
414418
all)
415419
main
416420
;;
417421
scan-only)
418-
check_docker_scout
422+
check_grype
419423
generate_security_summary
420424
;;
421425
*)

scripts/make-containers-dev-local.sh

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,14 @@ fi
6161

6262
log_success "Docker found. Proceeding with setup."
6363

64-
# Check if Docker Scout is available
64+
# Check if Grype is available for security scanning
6565
if [ "$SECURITY_SCAN_ENABLED" = true ]; then
66-
if ! docker scout version >/dev/null 2>&1; then
67-
log_warning "Docker Scout is not available. Security scanning will be disabled."
66+
if ! command -v grype >/dev/null 2>&1; then
67+
log_warning "Grype is not available. Security scanning will be disabled."
68+
log_info "Install: brew install grype"
6869
SECURITY_SCAN_ENABLED=false
6970
else
70-
log_success "Docker Scout is available for security scanning"
71+
log_success "Grype is available for security scanning"
7172
mkdir -p "$SECURITY_REPORTS_DIR"
7273
fi
7374
fi
@@ -92,15 +93,15 @@ fi
9293
# --- Security Scanning (if enabled) ---
9394
if [ "$SECURITY_SCAN_ENABLED" = true ]; then
9495
log_info "Performing security scans on images..."
95-
96+
9697
# Scan PostgreSQL image
9798
log_info "Scanning PostgreSQL image for vulnerabilities..."
98-
docker scout cves "$PG_IMAGE" --only-severity critical,high > "$SECURITY_REPORTS_DIR/postgresql-prescan.txt" 2>&1 || true
99-
100-
# Scan Redis image
99+
grype "$PG_IMAGE" -o table > "$SECURITY_REPORTS_DIR/postgresql-prescan.txt" 2>&1 || true
100+
101+
# Scan Redis image
101102
log_info "Scanning Redis image for vulnerabilities..."
102-
docker scout cves "$REDIS_IMAGE" --only-severity critical,high > "$SECURITY_REPORTS_DIR/redis-prescan.txt" 2>&1 || true
103-
103+
grype "$REDIS_IMAGE" -o table > "$SECURITY_REPORTS_DIR/redis-prescan.txt" 2>&1 || true
104+
104105
log_success "Security scans completed. Reports saved to $SECURITY_REPORTS_DIR"
105106
fi
106107

0 commit comments

Comments
 (0)