275 lines
12 KiB
Bash
Executable File
275 lines
12 KiB
Bash
Executable File
#!/bin/bash
|
|
# =============================================================================
|
|
# GO BACKEND AUDIT SCRIPT
|
|
# Comprehensive analysis of Go microservices
|
|
# =============================================================================
|
|
|
|
set -e
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
BACKEND_DIR="$PROJECT_ROOT/backend/functions"
|
|
OUTPUT_DIR="$PROJECT_ROOT/audit-reports/go-audit"
|
|
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
echo -e "${BLUE}========================================${NC}"
|
|
echo -e "${BLUE} GO BACKEND COMPREHENSIVE AUDIT${NC}"
|
|
echo -e "${BLUE}========================================${NC}"
|
|
echo ""
|
|
|
|
mkdir -p "$OUTPUT_DIR"
|
|
|
|
# =============================================================================
|
|
# 1. STATIC ANALYSIS WITH go vet
|
|
# =============================================================================
|
|
echo -e "${YELLOW}[1/10] Running go vet (static analysis)...${NC}"
|
|
GO_VET_OUTPUT="$OUTPUT_DIR/go-vet-$TIMESTAMP.txt"
|
|
echo "# Go Vet Results - $TIMESTAMP" > "$GO_VET_OUTPUT"
|
|
echo "" >> "$GO_VET_OUTPUT"
|
|
|
|
for service_dir in "$BACKEND_DIR"/*/; do
|
|
service_name=$(basename "$service_dir")
|
|
if [ -f "$service_dir/go.mod" ]; then
|
|
echo "Analyzing: $service_name" >> "$GO_VET_OUTPUT"
|
|
echo "---" >> "$GO_VET_OUTPUT"
|
|
(cd "$service_dir" && go vet ./... 2>&1) >> "$GO_VET_OUTPUT" || true
|
|
echo "" >> "$GO_VET_OUTPUT"
|
|
fi
|
|
done
|
|
echo -e "${GREEN} Output: $GO_VET_OUTPUT${NC}"
|
|
|
|
# =============================================================================
|
|
# 2. STATICCHECK (if available)
|
|
# =============================================================================
|
|
echo -e "${YELLOW}[2/10] Running staticcheck (advanced static analysis)...${NC}"
|
|
STATICCHECK_OUTPUT="$OUTPUT_DIR/staticcheck-$TIMESTAMP.txt"
|
|
echo "# Staticcheck Results - $TIMESTAMP" > "$STATICCHECK_OUTPUT"
|
|
|
|
if command -v staticcheck &> /dev/null; then
|
|
for service_dir in "$BACKEND_DIR"/*/; do
|
|
service_name=$(basename "$service_dir")
|
|
if [ -f "$service_dir/go.mod" ]; then
|
|
echo "Analyzing: $service_name" >> "$STATICCHECK_OUTPUT"
|
|
echo "---" >> "$STATICCHECK_OUTPUT"
|
|
(cd "$service_dir" && staticcheck ./... 2>&1) >> "$STATICCHECK_OUTPUT" || true
|
|
echo "" >> "$STATICCHECK_OUTPUT"
|
|
fi
|
|
done
|
|
echo -e "${GREEN} Output: $STATICCHECK_OUTPUT${NC}"
|
|
else
|
|
echo "staticcheck not installed. Install with: go install honnef.co/go/tools/cmd/staticcheck@latest" >> "$STATICCHECK_OUTPUT"
|
|
echo -e "${RED} staticcheck not installed${NC}"
|
|
fi
|
|
|
|
# =============================================================================
|
|
# 3. GOLANGCI-LINT (if available)
|
|
# =============================================================================
|
|
echo -e "${YELLOW}[3/10] Running golangci-lint (comprehensive linting)...${NC}"
|
|
GOLINT_OUTPUT="$OUTPUT_DIR/golangci-lint-$TIMESTAMP.txt"
|
|
echo "# GolangCI-Lint Results - $TIMESTAMP" > "$GOLINT_OUTPUT"
|
|
|
|
if command -v golangci-lint &> /dev/null; then
|
|
for service_dir in "$BACKEND_DIR"/*/; do
|
|
service_name=$(basename "$service_dir")
|
|
if [ -f "$service_dir/go.mod" ]; then
|
|
echo "Analyzing: $service_name" >> "$GOLINT_OUTPUT"
|
|
echo "---" >> "$GOLINT_OUTPUT"
|
|
(cd "$service_dir" && golangci-lint run --enable-all --disable=gci,wrapcheck,exhaustruct,depguard 2>&1) >> "$GOLINT_OUTPUT" || true
|
|
echo "" >> "$GOLINT_OUTPUT"
|
|
fi
|
|
done
|
|
echo -e "${GREEN} Output: $GOLINT_OUTPUT${NC}"
|
|
else
|
|
echo "golangci-lint not installed. Install from: https://golangci-lint.run/usage/install/" >> "$GOLINT_OUTPUT"
|
|
echo -e "${RED} golangci-lint not installed${NC}"
|
|
fi
|
|
|
|
# =============================================================================
|
|
# 4. GOSEC (Security Scanner)
|
|
# =============================================================================
|
|
echo -e "${YELLOW}[4/10] Running gosec (security scanner)...${NC}"
|
|
GOSEC_OUTPUT="$OUTPUT_DIR/gosec-$TIMESTAMP.txt"
|
|
GOSEC_JSON="$OUTPUT_DIR/gosec-$TIMESTAMP.json"
|
|
echo "# GoSec Security Scan Results - $TIMESTAMP" > "$GOSEC_OUTPUT"
|
|
|
|
if command -v gosec &> /dev/null; then
|
|
for service_dir in "$BACKEND_DIR"/*/; do
|
|
service_name=$(basename "$service_dir")
|
|
if [ -f "$service_dir/go.mod" ]; then
|
|
echo "Analyzing: $service_name" >> "$GOSEC_OUTPUT"
|
|
echo "---" >> "$GOSEC_OUTPUT"
|
|
(cd "$service_dir" && gosec -fmt=text ./... 2>&1) >> "$GOSEC_OUTPUT" || true
|
|
echo "" >> "$GOSEC_OUTPUT"
|
|
fi
|
|
done
|
|
echo -e "${GREEN} Output: $GOSEC_OUTPUT${NC}"
|
|
else
|
|
echo "gosec not installed. Install with: go install github.com/securego/gosec/v2/cmd/gosec@latest" >> "$GOSEC_OUTPUT"
|
|
echo -e "${RED} gosec not installed${NC}"
|
|
fi
|
|
|
|
# =============================================================================
|
|
# 5. DEPENDENCY AUDIT
|
|
# =============================================================================
|
|
echo -e "${YELLOW}[5/10] Auditing dependencies...${NC}"
|
|
DEP_OUTPUT="$OUTPUT_DIR/dependencies-$TIMESTAMP.txt"
|
|
echo "# Dependency Audit Results - $TIMESTAMP" > "$DEP_OUTPUT"
|
|
|
|
for service_dir in "$BACKEND_DIR"/*/; do
|
|
service_name=$(basename "$service_dir")
|
|
if [ -f "$service_dir/go.mod" ]; then
|
|
echo "=== $service_name ===" >> "$DEP_OUTPUT"
|
|
echo "" >> "$DEP_OUTPUT"
|
|
|
|
echo "Direct Dependencies:" >> "$DEP_OUTPUT"
|
|
(cd "$service_dir" && go list -m all 2>&1) >> "$DEP_OUTPUT" || true
|
|
echo "" >> "$DEP_OUTPUT"
|
|
|
|
echo "Outdated Dependencies:" >> "$DEP_OUTPUT"
|
|
(cd "$service_dir" && go list -u -m all 2>&1 | grep '\[' ) >> "$DEP_OUTPUT" || echo "None found" >> "$DEP_OUTPUT"
|
|
echo "" >> "$DEP_OUTPUT"
|
|
|
|
# Check for known vulnerabilities
|
|
echo "Vulnerability Check (govulncheck):" >> "$DEP_OUTPUT"
|
|
if command -v govulncheck &> /dev/null; then
|
|
(cd "$service_dir" && govulncheck ./... 2>&1) >> "$DEP_OUTPUT" || true
|
|
else
|
|
echo "govulncheck not installed. Install with: go install golang.org/x/vuln/cmd/govulncheck@latest" >> "$DEP_OUTPUT"
|
|
fi
|
|
echo "" >> "$DEP_OUTPUT"
|
|
fi
|
|
done
|
|
echo -e "${GREEN} Output: $DEP_OUTPUT${NC}"
|
|
|
|
# =============================================================================
|
|
# 6. CODE COMPLEXITY ANALYSIS
|
|
# =============================================================================
|
|
echo -e "${YELLOW}[6/10] Analyzing code complexity...${NC}"
|
|
COMPLEXITY_OUTPUT="$OUTPUT_DIR/complexity-$TIMESTAMP.txt"
|
|
echo "# Code Complexity Analysis - $TIMESTAMP" > "$COMPLEXITY_OUTPUT"
|
|
|
|
if command -v gocyclo &> /dev/null; then
|
|
echo "Cyclomatic Complexity (threshold > 10):" >> "$COMPLEXITY_OUTPUT"
|
|
echo "---" >> "$COMPLEXITY_OUTPUT"
|
|
gocyclo -over 10 "$BACKEND_DIR" 2>&1 >> "$COMPLEXITY_OUTPUT" || true
|
|
echo "" >> "$COMPLEXITY_OUTPUT"
|
|
|
|
echo "All Functions by Complexity:" >> "$COMPLEXITY_OUTPUT"
|
|
echo "---" >> "$COMPLEXITY_OUTPUT"
|
|
gocyclo -top 50 "$BACKEND_DIR" 2>&1 >> "$COMPLEXITY_OUTPUT" || true
|
|
echo -e "${GREEN} Output: $COMPLEXITY_OUTPUT${NC}"
|
|
else
|
|
echo "gocyclo not installed. Install with: go install github.com/fzipp/gocyclo/cmd/gocyclo@latest" >> "$COMPLEXITY_OUTPUT"
|
|
echo -e "${RED} gocyclo not installed${NC}"
|
|
fi
|
|
|
|
# =============================================================================
|
|
# 7. DEAD CODE DETECTION
|
|
# =============================================================================
|
|
echo -e "${YELLOW}[7/10] Detecting dead code...${NC}"
|
|
DEADCODE_OUTPUT="$OUTPUT_DIR/deadcode-$TIMESTAMP.txt"
|
|
echo "# Dead Code Detection - $TIMESTAMP" > "$DEADCODE_OUTPUT"
|
|
|
|
if command -v deadcode &> /dev/null; then
|
|
for service_dir in "$BACKEND_DIR"/*/; do
|
|
service_name=$(basename "$service_dir")
|
|
if [ -f "$service_dir/go.mod" ]; then
|
|
echo "=== $service_name ===" >> "$DEADCODE_OUTPUT"
|
|
(cd "$service_dir" && deadcode ./... 2>&1) >> "$DEADCODE_OUTPUT" || true
|
|
echo "" >> "$DEADCODE_OUTPUT"
|
|
fi
|
|
done
|
|
echo -e "${GREEN} Output: $DEADCODE_OUTPUT${NC}"
|
|
else
|
|
echo "deadcode not installed. Install with: go install golang.org/x/tools/cmd/deadcode@latest" >> "$DEADCODE_OUTPUT"
|
|
echo -e "${RED} deadcode not installed${NC}"
|
|
fi
|
|
|
|
# =============================================================================
|
|
# 8. ERROR HANDLING AUDIT
|
|
# =============================================================================
|
|
echo -e "${YELLOW}[8/10] Auditing error handling patterns...${NC}"
|
|
ERROR_OUTPUT="$OUTPUT_DIR/error-handling-$TIMESTAMP.txt"
|
|
echo "# Error Handling Audit - $TIMESTAMP" > "$ERROR_OUTPUT"
|
|
|
|
echo "== Potentially Ignored Errors ==" >> "$ERROR_OUTPUT"
|
|
grep -rn "_ = " "$BACKEND_DIR" --include="*.go" 2>/dev/null >> "$ERROR_OUTPUT" || echo "None found" >> "$ERROR_OUTPUT"
|
|
echo "" >> "$ERROR_OUTPUT"
|
|
|
|
echo "== Bare error returns (missing context) ==" >> "$ERROR_OUTPUT"
|
|
grep -rn "return err$" "$BACKEND_DIR" --include="*.go" 2>/dev/null >> "$ERROR_OUTPUT" || echo "None found" >> "$ERROR_OUTPUT"
|
|
echo "" >> "$ERROR_OUTPUT"
|
|
|
|
echo "== Panic usage ==" >> "$ERROR_OUTPUT"
|
|
grep -rn "panic(" "$BACKEND_DIR" --include="*.go" 2>/dev/null >> "$ERROR_OUTPUT" || echo "None found" >> "$ERROR_OUTPUT"
|
|
echo "" >> "$ERROR_OUTPUT"
|
|
|
|
echo "== log.Fatal usage (prevents defer) ==" >> "$ERROR_OUTPUT"
|
|
grep -rn "log.Fatal" "$BACKEND_DIR" --include="*.go" 2>/dev/null >> "$ERROR_OUTPUT" || echo "None found" >> "$ERROR_OUTPUT"
|
|
echo -e "${GREEN} Output: $ERROR_OUTPUT${NC}"
|
|
|
|
# =============================================================================
|
|
# 9. HARDCODED SECRETS SCAN
|
|
# =============================================================================
|
|
echo -e "${YELLOW}[9/10] Scanning for hardcoded secrets...${NC}"
|
|
SECRETS_OUTPUT="$OUTPUT_DIR/secrets-scan-$TIMESTAMP.txt"
|
|
echo "# Hardcoded Secrets Scan - $TIMESTAMP" > "$SECRETS_OUTPUT"
|
|
|
|
echo "== Potential Hardcoded Passwords ==" >> "$SECRETS_OUTPUT"
|
|
grep -rniE "(password|passwd|pwd)\s*[:=]\s*['\"][^'\"]+['\"]" "$BACKEND_DIR" --include="*.go" 2>/dev/null >> "$SECRETS_OUTPUT" || echo "None found" >> "$SECRETS_OUTPUT"
|
|
echo "" >> "$SECRETS_OUTPUT"
|
|
|
|
echo "== Potential API Keys ==" >> "$SECRETS_OUTPUT"
|
|
grep -rniE "(api[_-]?key|apikey|secret[_-]?key)\s*[:=]\s*['\"][^'\"]+['\"]" "$BACKEND_DIR" --include="*.go" 2>/dev/null >> "$SECRETS_OUTPUT" || echo "None found" >> "$SECRETS_OUTPUT"
|
|
echo "" >> "$SECRETS_OUTPUT"
|
|
|
|
echo "== Potential Tokens ==" >> "$SECRETS_OUTPUT"
|
|
grep -rniE "(token|bearer|jwt)\s*[:=]\s*['\"][^'\"]+['\"]" "$BACKEND_DIR" --include="*.go" 2>/dev/null >> "$SECRETS_OUTPUT" || echo "None found" >> "$SECRETS_OUTPUT"
|
|
echo "" >> "$SECRETS_OUTPUT"
|
|
|
|
echo "== Base64 Encoded Strings (potential secrets) ==" >> "$SECRETS_OUTPUT"
|
|
grep -rnoE "['\"][A-Za-z0-9+/]{40,}={0,2}['\"]" "$BACKEND_DIR" --include="*.go" 2>/dev/null >> "$SECRETS_OUTPUT" || echo "None found" >> "$SECRETS_OUTPUT"
|
|
echo -e "${GREEN} Output: $SECRETS_OUTPUT${NC}"
|
|
|
|
# =============================================================================
|
|
# 10. TEST COVERAGE
|
|
# =============================================================================
|
|
echo -e "${YELLOW}[10/10] Generating test coverage report...${NC}"
|
|
COVERAGE_OUTPUT="$OUTPUT_DIR/coverage-$TIMESTAMP.txt"
|
|
COVERAGE_HTML="$OUTPUT_DIR/coverage-$TIMESTAMP.html"
|
|
echo "# Test Coverage Report - $TIMESTAMP" > "$COVERAGE_OUTPUT"
|
|
|
|
for service_dir in "$BACKEND_DIR"/*/; do
|
|
service_name=$(basename "$service_dir")
|
|
if [ -f "$service_dir/go.mod" ]; then
|
|
echo "=== $service_name ===" >> "$COVERAGE_OUTPUT"
|
|
(cd "$service_dir" && go test -coverprofile=coverage.out ./... 2>&1) >> "$COVERAGE_OUTPUT" || true
|
|
if [ -f "$service_dir/coverage.out" ]; then
|
|
(cd "$service_dir" && go tool cover -func=coverage.out 2>&1) >> "$COVERAGE_OUTPUT" || true
|
|
rm "$service_dir/coverage.out"
|
|
fi
|
|
echo "" >> "$COVERAGE_OUTPUT"
|
|
fi
|
|
done
|
|
echo -e "${GREEN} Output: $COVERAGE_OUTPUT${NC}"
|
|
|
|
# =============================================================================
|
|
# SUMMARY
|
|
# =============================================================================
|
|
echo ""
|
|
echo -e "${BLUE}========================================${NC}"
|
|
echo -e "${BLUE} GO AUDIT COMPLETE${NC}"
|
|
echo -e "${BLUE}========================================${NC}"
|
|
echo ""
|
|
echo -e "Reports generated in: ${GREEN}$OUTPUT_DIR${NC}"
|
|
echo ""
|
|
echo "Files generated:"
|
|
ls -la "$OUTPUT_DIR"/*$TIMESTAMP* 2>/dev/null || echo "No files generated"
|