Add Trivy security scanning to git hooks
ci/woodpecker/push/woodpecker Pipeline was successful
Details
ci/woodpecker/push/woodpecker Pipeline was successful
Details
- Add mandatory Trivy image scanning to both pre-commit and pre-push hooks - Remove interactive prompts from install script, add --force flag instead - Add automatic cleanup of temporary Docker images after scanning - Check for Docker and Trivy dependencies before running hooks
This commit is contained in:
parent
2907277b52
commit
305a0ece5e
|
|
@ -1,10 +1,33 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Installation script for Git hooks in Hastebin
|
||||
# This script sets up pre-commit hooks (tests) and pre-push hooks (unused code scans)
|
||||
# This script sets up pre-commit hooks (tests + security scan) and pre-push hooks (unused code + security scan)
|
||||
#
|
||||
# Usage:
|
||||
# ./install-git-hooks.sh [--force]
|
||||
#
|
||||
# Options:
|
||||
# --force Overwrite existing hooks without prompting (backs up existing hooks)
|
||||
# Without this flag, fails if hooks already exist
|
||||
|
||||
set -e
|
||||
|
||||
# Parse arguments
|
||||
FORCE_MODE=false
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--force)
|
||||
FORCE_MODE=true
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
echo "Usage: $0 [--force]"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
|
|
@ -16,40 +39,49 @@ NC='\033[0m' # No Color
|
|||
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || echo "$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)")
|
||||
HOOKS_DIR="$REPO_ROOT/.git/hooks"
|
||||
PRE_COMMIT_HOOK="$HOOKS_DIR/pre-commit"
|
||||
PRE_PUSH_HOOK="$HOOKS_DIR/pre-push"
|
||||
SCRIPT_DIR="$REPO_ROOT/scripts"
|
||||
|
||||
echo -e "${BLUE}🔧 Installing Git hooks for Hastebin${NC}"
|
||||
echo -e "${BLUE}Installing Git hooks for Hastebin${NC}"
|
||||
echo ""
|
||||
|
||||
# Check if we're in a git repository
|
||||
if [ ! -d "$REPO_ROOT/.git" ]; then
|
||||
echo -e "${RED}❌ Error: Not a git repository${NC}"
|
||||
echo -e "${RED}Error: Not a git repository${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create hooks directory if it doesn't exist
|
||||
mkdir -p "$HOOKS_DIR"
|
||||
|
||||
# Check if pre-commit hook already exists
|
||||
if [ -f "$PRE_COMMIT_HOOK" ]; then
|
||||
echo -e "${YELLOW}⚠️ Pre-commit hook already exists${NC}"
|
||||
read -p "Do you want to overwrite it? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo -e "${YELLOW}Skipping hook installation${NC}"
|
||||
exit 0
|
||||
# Function to handle existing hook
|
||||
handle_existing_hook() {
|
||||
local hook_path="$1"
|
||||
local hook_name="$2"
|
||||
|
||||
if [ -f "$hook_path" ]; then
|
||||
if [ "$FORCE_MODE" = true ]; then
|
||||
# Backup existing hook with timestamp
|
||||
mv "$hook_path" "$hook_path.backup.$(date +%Y%m%d_%H%M%S)"
|
||||
echo -e "${YELLOW}Backed up existing $hook_name hook${NC}"
|
||||
else
|
||||
echo -e "${RED}Error: $hook_name hook already exists at $hook_path${NC}"
|
||||
echo -e "${YELLOW}Use --force to overwrite (will backup existing hook)${NC}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
# Backup existing hook
|
||||
mv "$PRE_COMMIT_HOOK" "$PRE_COMMIT_HOOK.backup.$(date +%Y%m%d_%H%M%S)"
|
||||
echo -e "${YELLOW}Backed up existing hook${NC}"
|
||||
fi
|
||||
}
|
||||
|
||||
# Create the pre-commit hook
|
||||
# Check for existing hooks
|
||||
handle_existing_hook "$PRE_COMMIT_HOOK" "pre-commit"
|
||||
handle_existing_hook "$PRE_PUSH_HOOK" "pre-push"
|
||||
|
||||
# --- Create the pre-commit hook ---
|
||||
cat > "$PRE_COMMIT_HOOK" << 'HOOK_EOF'
|
||||
#!/bin/bash
|
||||
|
||||
# Git pre-commit hook for Hastebin
|
||||
# Runs tests before allowing commits to prevent pushing broken code
|
||||
# Runs tests and security scans before allowing commits
|
||||
|
||||
set -e
|
||||
|
||||
|
|
@ -60,11 +92,31 @@ YELLOW='\033[0;33m'
|
|||
NC='\033[0m' # No Color
|
||||
|
||||
echo -e "${YELLOW}Running pre-commit checks...${NC}"
|
||||
echo ""
|
||||
|
||||
# Get the repository root
|
||||
REPO_ROOT=$(git rev-parse --show-toplevel)
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
# Check required dependencies
|
||||
MISSING_DEPS=0
|
||||
|
||||
if ! command -v docker &> /dev/null; then
|
||||
echo -e "${RED}Docker not found - required for security scanning${NC}"
|
||||
MISSING_DEPS=1
|
||||
fi
|
||||
|
||||
if ! command -v trivy &> /dev/null; then
|
||||
echo -e "${RED}Trivy not found - required for security scanning${NC}"
|
||||
echo " Install: brew install trivy"
|
||||
MISSING_DEPS=1
|
||||
fi
|
||||
|
||||
if [ $MISSING_DEPS -ne 0 ]; then
|
||||
echo -e "${RED}Missing required dependencies. Commit aborted.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if node_modules exists, if not, install dependencies
|
||||
if [ ! -d "node_modules" ]; then
|
||||
echo -e "${YELLOW}Installing dependencies...${NC}"
|
||||
|
|
@ -72,11 +124,11 @@ if [ ! -d "node_modules" ]; then
|
|||
fi
|
||||
|
||||
# Run the core tests (faster than full test suite)
|
||||
echo -e "${YELLOW}Running core tests...${NC}"
|
||||
echo -e "${YELLOW}[1/2] Running core tests...${NC}"
|
||||
if npm run test:core; then
|
||||
echo -e "${GREEN}✅ Core tests passed${NC}"
|
||||
echo -e "${GREEN}Core tests passed${NC}"
|
||||
else
|
||||
echo -e "${RED}❌ Core tests failed. Commit aborted.${NC}"
|
||||
echo -e "${RED}Core tests failed. Commit aborted.${NC}"
|
||||
echo -e "${YELLOW}To skip this check, use: git commit --no-verify${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -86,37 +138,31 @@ if [ -d "test-data" ]; then
|
|||
rm -rf test-data
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✅ Pre-commit checks passed${NC}"
|
||||
# Run Trivy security scan
|
||||
echo ""
|
||||
echo -e "${YELLOW}[2/2] Running security scan (Trivy image scan)...${NC}"
|
||||
if "$REPO_ROOT/scripts/scan-trivy-image.sh"; then
|
||||
echo -e "${GREEN}Security scan passed${NC}"
|
||||
else
|
||||
echo -e "${RED}Security scan found vulnerabilities. Commit aborted.${NC}"
|
||||
echo -e "${YELLOW}To skip this check, use: git commit --no-verify${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}Pre-commit checks passed${NC}"
|
||||
exit 0
|
||||
HOOK_EOF
|
||||
|
||||
# Make the hook executable
|
||||
chmod +x "$PRE_COMMIT_HOOK"
|
||||
echo -e "${GREEN}Pre-commit hook installed${NC}"
|
||||
|
||||
echo -e "${GREEN}✅ Pre-commit hook installed successfully${NC}"
|
||||
|
||||
# --- Pre-push hook ---
|
||||
PRE_PUSH_HOOK="$HOOKS_DIR/pre-push"
|
||||
|
||||
# Check if pre-push hook already exists
|
||||
if [ -f "$PRE_PUSH_HOOK" ]; then
|
||||
echo -e "${YELLOW}⚠️ Pre-push hook already exists${NC}"
|
||||
read -p "Do you want to overwrite it? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo -e "${YELLOW}Skipping pre-push hook installation${NC}"
|
||||
else
|
||||
mv "$PRE_PUSH_HOOK" "$PRE_PUSH_HOOK.backup.$(date +%Y%m%d_%H%M%S)"
|
||||
echo -e "${YELLOW}Backed up existing pre-push hook${NC}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f "$PRE_PUSH_HOOK" ] || [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
cat > "$PRE_PUSH_HOOK" << 'HOOK_EOF'
|
||||
# --- Create the pre-push hook ---
|
||||
cat > "$PRE_PUSH_HOOK" << 'HOOK_EOF'
|
||||
#!/bin/bash
|
||||
|
||||
# Git pre-push hook for Hastebin
|
||||
# Scans for unused code/dependencies before pushing
|
||||
# Scans for unused code/dependencies and runs security scan before pushing
|
||||
|
||||
set -e
|
||||
|
||||
|
|
@ -127,11 +173,31 @@ YELLOW='\033[0;33m'
|
|||
NC='\033[0m' # No Color
|
||||
|
||||
echo -e "${YELLOW}Running pre-push checks...${NC}"
|
||||
echo ""
|
||||
|
||||
# Get the repository root
|
||||
REPO_ROOT=$(git rev-parse --show-toplevel)
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
# Check required dependencies
|
||||
MISSING_DEPS=0
|
||||
|
||||
if ! command -v docker &> /dev/null; then
|
||||
echo -e "${RED}Docker not found - required for security scanning${NC}"
|
||||
MISSING_DEPS=1
|
||||
fi
|
||||
|
||||
if ! command -v trivy &> /dev/null; then
|
||||
echo -e "${RED}Trivy not found - required for security scanning${NC}"
|
||||
echo " Install: brew install trivy"
|
||||
MISSING_DEPS=1
|
||||
fi
|
||||
|
||||
if [ $MISSING_DEPS -ne 0 ]; then
|
||||
echo -e "${RED}Missing required dependencies. Push aborted.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if node_modules exists, if not, install dependencies
|
||||
if [ ! -d "node_modules" ]; then
|
||||
echo -e "${YELLOW}Installing dependencies...${NC}"
|
||||
|
|
@ -141,48 +207,61 @@ fi
|
|||
# Scan for unused code/dependencies
|
||||
SCAN_FAILED=0
|
||||
|
||||
echo -e "${YELLOW}Scanning for unused files/exports/dependencies (knip)...${NC}"
|
||||
echo -e "${YELLOW}[1/3] Scanning for unused files/exports/dependencies (knip)...${NC}"
|
||||
if npx --yes knip 2>/dev/null; then
|
||||
echo -e "${GREEN}✅ knip passed${NC}"
|
||||
echo -e "${GREEN}knip passed${NC}"
|
||||
else
|
||||
echo -e "${RED}❌ knip found unused code${NC}"
|
||||
echo -e "${RED}knip found unused code${NC}"
|
||||
SCAN_FAILED=1
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}Scanning for unused npm dependencies (depcheck)...${NC}"
|
||||
echo ""
|
||||
echo -e "${YELLOW}[2/3] Scanning for unused npm dependencies (depcheck)...${NC}"
|
||||
if npx --yes depcheck 2>/dev/null; then
|
||||
echo -e "${GREEN}✅ depcheck passed${NC}"
|
||||
echo -e "${GREEN}depcheck passed${NC}"
|
||||
else
|
||||
echo -e "${RED}❌ depcheck found issues${NC}"
|
||||
echo -e "${RED}depcheck found issues${NC}"
|
||||
SCAN_FAILED=1
|
||||
fi
|
||||
|
||||
if [ $SCAN_FAILED -ne 0 ]; then
|
||||
echo -e "${RED}❌ Unused code/dependencies detected. Push aborted.${NC}"
|
||||
echo -e "${RED}Unused code/dependencies detected. Push aborted.${NC}"
|
||||
echo -e "${YELLOW}To skip this check, use: git push --no-verify${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✅ Pre-push checks passed${NC}"
|
||||
# Run Trivy security scan
|
||||
echo ""
|
||||
echo -e "${YELLOW}[3/3] Running security scan (Trivy image scan)...${NC}"
|
||||
if "$REPO_ROOT/scripts/scan-trivy-image.sh"; then
|
||||
echo -e "${GREEN}Security scan passed${NC}"
|
||||
else
|
||||
echo -e "${RED}Security scan found vulnerabilities. Push aborted.${NC}"
|
||||
echo -e "${YELLOW}To skip this check, use: git push --no-verify${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}Pre-push checks passed${NC}"
|
||||
exit 0
|
||||
HOOK_EOF
|
||||
|
||||
chmod +x "$PRE_PUSH_HOOK"
|
||||
echo -e "${GREEN}✅ Pre-push hook installed successfully${NC}"
|
||||
fi
|
||||
chmod +x "$PRE_PUSH_HOOK"
|
||||
echo -e "${GREEN}Pre-push hook installed${NC}"
|
||||
|
||||
echo ""
|
||||
echo -e "${BLUE}Hooks installed:${NC}"
|
||||
echo -e "${BLUE} - pre-commit: runs core tests before each commit${NC}"
|
||||
echo -e "${BLUE} - pre-push: scans for unused code/deps before each push${NC}"
|
||||
echo -e "${BLUE} - pre-commit: core tests + Trivy security scan${NC}"
|
||||
echo -e "${BLUE} - pre-push: knip + depcheck + Trivy security scan${NC}"
|
||||
echo -e "${YELLOW}To skip hooks, use: git commit --no-verify / git push --no-verify${NC}"
|
||||
echo ""
|
||||
|
||||
# Check if dependencies are installed
|
||||
if [ ! -d "$REPO_ROOT/node_modules" ]; then
|
||||
echo -e "${YELLOW}⚠️ Dependencies not found. Installing...${NC}"
|
||||
echo -e "${YELLOW}Dependencies not found. Installing...${NC}"
|
||||
cd "$REPO_ROOT"
|
||||
npm ci
|
||||
echo -e "${GREEN}✅ Dependencies installed${NC}"
|
||||
echo -e "${GREEN}Dependencies installed${NC}"
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}🎉 Git hooks installation complete!${NC}"
|
||||
echo -e "${GREEN}Git hooks installation complete!${NC}"
|
||||
|
|
|
|||
|
|
@ -1,33 +1,65 @@
|
|||
#!/bin/bash
|
||||
# Run Trivy image security scan
|
||||
# Builds the Docker image and scans it for vulnerabilities
|
||||
# Builds the Docker image locally and scans it for vulnerabilities
|
||||
#
|
||||
# Usage:
|
||||
# ./scan-trivy-image.sh [image-name]
|
||||
#
|
||||
# Exit codes:
|
||||
# 0 - No HIGH/CRITICAL vulnerabilities found
|
||||
# 1 - Vulnerabilities found or error occurred
|
||||
|
||||
set -e
|
||||
|
||||
IMAGE_NAME="${1:-hastebin:test}"
|
||||
IMAGE_NAME="${1:-hastebin:local-scan}"
|
||||
|
||||
echo "🐳 Building Docker image: $IMAGE_NAME"
|
||||
docker build -t "$IMAGE_NAME" --no-cache .
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[0;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
echo ""
|
||||
echo "🔒 Running Trivy image security scan..."
|
||||
# Cleanup function to remove temporary image
|
||||
cleanup() {
|
||||
if docker image inspect "$IMAGE_NAME" &> /dev/null; then
|
||||
echo -e "${YELLOW}Cleaning up temporary image: $IMAGE_NAME${NC}"
|
||||
docker rmi "$IMAGE_NAME" --force &> /dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
# Set trap to cleanup on exit (success or failure)
|
||||
trap cleanup EXIT
|
||||
|
||||
# Check dependencies BEFORE building
|
||||
if ! command -v docker &> /dev/null; then
|
||||
echo -e "${RED}Docker not found. Please install Docker.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if trivy is installed
|
||||
if ! command -v trivy &> /dev/null; then
|
||||
echo "Trivy not found. Please install it:"
|
||||
echo -e "${RED}Trivy not found. Please install it:${NC}"
|
||||
echo " brew install trivy"
|
||||
echo " or visit: https://aquasecurity.github.io/trivy/latest/getting-started/installation/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Build the Docker image (always clean build, no cache)
|
||||
echo -e "${YELLOW}Building Docker image: $IMAGE_NAME${NC}"
|
||||
docker build -t "$IMAGE_NAME" --no-cache .
|
||||
|
||||
echo ""
|
||||
echo -e "${YELLOW}Running Trivy image security scan...${NC}"
|
||||
|
||||
# Show version
|
||||
trivy --version
|
||||
|
||||
echo ""
|
||||
echo "📦 Scanning Docker image for vulnerabilities..."
|
||||
echo -e "${YELLOW}Scanning Docker image for vulnerabilities...${NC}"
|
||||
echo ""
|
||||
|
||||
# Scan image with exit code 1 (fail on HIGH/CRITICAL vulnerabilities)
|
||||
# Store result to allow cleanup even on failure
|
||||
SCAN_RESULT=0
|
||||
trivy image \
|
||||
--timeout 10m \
|
||||
--scanners vuln \
|
||||
|
|
@ -35,7 +67,13 @@ trivy image \
|
|||
--ignore-unfixed \
|
||||
--exit-code 1 \
|
||||
--format table \
|
||||
"$IMAGE_NAME"
|
||||
"$IMAGE_NAME" || SCAN_RESULT=$?
|
||||
|
||||
echo ""
|
||||
echo "✅ Trivy image scan completed!"
|
||||
|
||||
if [ $SCAN_RESULT -eq 0 ]; then
|
||||
echo -e "${GREEN}Trivy image scan completed - no HIGH/CRITICAL vulnerabilities found!${NC}"
|
||||
else
|
||||
echo -e "${RED}Trivy image scan found HIGH/CRITICAL vulnerabilities!${NC}"
|
||||
exit $SCAN_RESULT
|
||||
fi
|
||||
|
|
|
|||
Loading…
Reference in New Issue