install script improved, minor rules.go fixes

This commit is contained in:
fabriziosalmi
2025-01-22 14:28:14 +01:00
parent f4bd92c5a0
commit 1bac5200b2
2 changed files with 156 additions and 82 deletions

View File

@@ -1,55 +1,168 @@
#!/bin/bash
set -e
# --- Configuration ---
GREEN="\033[1;32m"
RED="\033[1;31m"
YELLOW="\033[1;33m"
NC="\033[0m" # No Color
REPO_URL="https://github.com/fabriziosalmi/caddy-waf.git"
REPO_DIR="caddy-waf"
GO_VERSION_REQUIRED="1.22.3"
GO_VERSION_TARGET="1.23.4"
XCADDY_VERSION="latest" # or specify a version like "v0.3.7"
GEOLITE2_DB_URL="https://git.io/GeoLite2-Country.mmdb"
GEOLITE2_DB_FILE="GeoLite2-Country.mmdb"
# Helper functions
# --- Helper Functions ---
print_success() {
echo -e "${GREEN}$1${NC}"
echo -e "${GREEN} Success: $1${NC}"
}
print_warning() {
echo -e "${YELLOW}⚠️ Warning: $1${NC}"
}
print_info() {
echo -e " Info: $1${NC}"
}
print_error() {
echo -e "${RED}$1${NC}"
echo -e "${RED} Error: $1${NC}"
echo -e "${RED} $1${NC}" >&2 # Print error to stderr as well
exit 1
}
# Detect OS
OS=$(uname -s)
GO_VERSION_REQUIRED="1.22.3"
GO_VERSION_TARGET="1.23.4"
check_command_exists() {
if ! command -v "$1" &> /dev/null; then
return 1 # Command not found
else
return 0 # Command found
fi
}
ensure_go_installed() {
if ! check_command_exists go; then
print_info "Go not found. Installing Go $GO_VERSION_TARGET..."
install_go
else
check_go_version
fi
}
ensure_xcaddy_installed() {
if ! check_command_exists xcaddy; then
print_info "xcaddy not found. Installing xcaddy..."
install_xcaddy
else
print_info "xcaddy is already installed."
fi
}
clone_or_update_repo() {
if [ -d "$REPO_DIR" ]; then
print_info "$REPO_DIR directory already exists. Pulling latest changes..."
cd "$REPO_DIR" || print_error "Could not change directory to $REPO_DIR"
git pull origin main || print_error "Failed to pull $REPO_DIR updates." # Specify origin and branch
cd .. # Go back to the script's directory
else
print_info "Cloning $REPO_DIR repository..."
git clone "$REPO_URL" "$REPO_DIR" || print_error "Failed to clone repository from $REPO_URL."
fi
cd "$REPO_DIR" || print_error "Could not change directory to $REPO_DIR after clone/pull"
}
update_dependencies() {
print_info "Running go mod tidy..."
go mod tidy || print_error "Failed to run go mod tidy."
print_success "Dependencies updated (go mod tidy)."
print_info "Fetching Go modules..."
go get -v github.com/caddyserver/caddy/v2 github.com/caddyserver/caddy/v2/caddyconfig/caddyfile github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile github.com/caddyserver/caddy/v2/modules/caddyhttp github.com/oschwald/maxminddb-golang github.com/fsnotify/fsnotify github.com/fabriziosalmi/caddy-waf || print_error "Failed to fetch Go modules." # Combined go get
print_success "Go modules fetched successfully."
}
download_geolite2_db() {
if [ ! -f "$GEOLITE2_DB_FILE" ]; then
print_info "Downloading GeoLite2 Country database..."
wget -q "$GEOLITE2_DB_URL" -O "$GEOLITE2_DB_FILE" || print_error "Failed to download GeoLite2 database from $GEOLITE2_DB_URL." # Specify output file
print_success "GeoLite2 database downloaded."
else
print_info "GeoLite2 database already exists."
fi
}
build_caddy() {
print_info "Building Caddy with caddy-waf module..."
xcaddy build --with github.com/fabriziosalmi/caddy-waf=./ || print_error "Failed to build Caddy."
print_success "Caddy built successfully."
}
format_caddyfile() {
print_info "Formatting Caddyfile..."
./caddy fmt --overwrite || print_warning "Failed to format Caddyfile (This is a warning, Caddy might still run)." # Warning instead of error
print_success "Caddyfile formatted."
}
run_caddy() {
print_info "Starting Caddy server..."
./caddy run || print_error "Failed to start Caddy." # Keep as error, Caddy run failure is critical
print_success "Caddy is running." # This line will likely not be reached in a typical run
}
# --- OS Specific Functions ---
install_go_linux() {
echo -e "⚙️ Installing Go $GO_VERSION_TARGET for Linux..."
wget https://go.dev/dl/go${GO_VERSION_TARGET}.linux-amd64.tar.gz && \
sudo rm -rf /usr/local/go && \
sudo tar -C /usr/local -xzf go${GO_VERSION_TARGET}.linux-amd64.tar.gz && \
rm go${GO_VERSION_TARGET}.linux-amd64.tar.gz && \
export PATH=$PATH:/usr/local/go/bin && \
print_success "Go $GO_VERSION_TARGET installed successfully." || print_error "Failed to install Go."
print_info "Installing Go $GO_VERSION_TARGET for Linux..."
GOBIN="/usr/local/go/bin" # Define GOBIN for clarity
wget "https://go.dev/dl/go${GO_VERSION_TARGET}.linux-amd64.tar.gz" || print_error "Failed to download Go for Linux."
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf "go${GO_VERSION_TARGET}.linux-amd64.tar.gz" || print_error "Failed to extract Go for Linux."
rm "go${GO_VERSION_TARGET}.linux-amd64.tar.gz"
export PATH="$PATH:$GOBIN" # Ensure PATH is updated in current shell
print_success "Go $GO_VERSION_TARGET installed successfully on Linux."
}
install_go_macos() {
echo -e "⚙️ Installing Go $GO_VERSION_TARGET for macOS..."
curl -LO https://go.dev/dl/go${GO_VERSION_TARGET}.darwin-amd64.pkg && \
sudo installer -pkg go${GO_VERSION_TARGET}.darwin-amd64.pkg -target / && \
rm go${GO_VERSION_TARGET}.darwin-amd64.pkg && \
export PATH=$PATH:/usr/local/go/bin && \
print_success "Go $GO_VERSION_TARGET installed successfully." || print_error "Failed to install Go."
print_info "Installing Go $GO_VERSION_TARGET for macOS..."
curl -LO "https://go.dev/dl/go${GO_VERSION_TARGET}.darwin-amd64.pkg" || print_error "Failed to download Go for macOS."
sudo installer -pkg "go${GO_VERSION_TARGET}.darwin-amd64.pkg" -target / || print_error "Failed to install Go package on macOS."
rm "go${GO_VERSION_TARGET}.darwin-amd64.pkg"
export PATH="$PATH:/usr/local/go/bin" # Ensure PATH is updated in current shell
print_success "Go $GO_VERSION_TARGET installed successfully on macOS."
}
install_xcaddy() {
print_info "Installing xcaddy $XCADDY_VERSION..."
GOBIN="$(go env GOBIN)"
if [ -z "$GOBIN" ]; then
GOBIN="$HOME/go/bin" # Default GOBIN if not set
fi
go install "github.com/caddyserver/xcaddy/cmd/xcaddy@$XCADDY_VERSION" || print_error "Failed to install xcaddy."
export PATH="$PATH:$GOBIN" # Ensure PATH is updated in current shell
print_success "xcaddy $XCADDY_VERSION installed successfully."
}
check_go_version() {
local version
version=$(go version | awk '{print $3}' | sed 's/go//')
version=$(go version 2>&1 | awk '{print $3}' | sed 's/go//') # Redirect stderr to stdout for error handling
if [[ "$version" == *"error"* ]]; then # Check for "error" string in output
print_warning "Failed to get Go version. Assuming Go is outdated or not properly installed. Attempting to install Go $GO_VERSION_TARGET."
install_go # Attempt reinstall if version check fails
return
fi
if [[ $(printf '%s\n' "$GO_VERSION_REQUIRED" "$version" | sort -V | head -n1) != "$GO_VERSION_REQUIRED" ]]; then
print_error "Go version must be $GO_VERSION_REQUIRED or newer. Current version: $version"
print_warning "Go version $version is older than required $GO_VERSION_REQUIRED. Attempting to install Go $GO_VERSION_TARGET."
install_go # Attempt reinstall if version is too old
else
print_success "Go version $version meets requirements."
print_info "Go version $version meets requirements ($GO_VERSION_REQUIRED or newer)."
fi
}
install_go() {
OS=$(uname -s)
if [ "$OS" == "Linux" ]; then
install_go_linux
elif [ "$OS" == "Darwin" ]; then
@@ -57,67 +170,21 @@ install_go() {
else
print_error "Unsupported OS: $OS"
fi
check_go_version # Re-check version after install to confirm success
}
# Install Go if not present or outdated
if ! command -v go &> /dev/null; then
echo -e "⚙️ Go not found. Installing Go $GO_VERSION_TARGET..."
install_go
else
echo -e "🔍 Checking Go version..."
check_go_version
fi
# Install xcaddy if not present
if ! command -v xcaddy &> /dev/null; then
echo -e "⚙️ xcaddy not found. Installing xcaddy..."
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest && \
export PATH=$PATH:$(go env GOPATH)/bin && \
print_success "xcaddy installed successfully." || print_error "Failed to install xcaddy."
else
print_success "xcaddy is already installed."
fi
# --- Main Script Execution ---
# Clone the repository
if [ -d "caddy-waf" ]; then
echo -e "🔄 caddy-waf directory already exists. Pulling latest changes..."
cd caddy-waf && git pull || print_error "Failed to pull caddy-waf updates."
else
echo -e "📥 Cloning caddy-waf repository..."
git clone https://github.com/fabriziosalmi/caddy-waf.git && \
cd caddy-waf && \
print_success "caddy-waf repository cloned successfully." || print_error "Failed to clone repository."
fi
print_info "Starting setup for caddy-waf..."
# Clean and update dependencies
echo -e "📦 Running go mod tidy..."
go mod tidy && print_success "Dependencies updated (go mod tidy)." || print_error "Failed to run go mod tidy."
echo -e "🔍 Fetching Go modules..."
go get -v github.com/caddyserver/caddy/v2 github.com/caddyserver/caddy/v2/caddyconfig/caddyfile github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile github.com/caddyserver/caddy/v2 github.com/caddyserver/caddy/v2/modules/caddyhttp github.com/oschwald/maxminddb-golang github.com/fsnotify/fsnotify github.com/fabriziosalmi/caddy-waf && \
print_success "Go modules fetched successfully." || print_error "Failed to fetch Go modules."
# Download GeoLite2 Country database
if [ ! -f "GeoLite2-Country.mmdb" ]; then
echo -e "🌍 Downloading GeoLite2 Country database..."
wget -q https://git.io/GeoLite2-Country.mmdb && \
print_success "GeoLite2 database downloaded." || print_error "Failed to download GeoLite2 database."
else
print_success "GeoLite2 database already exists."
fi
# Build with xcaddy
echo -e "⚙️ Building Caddy with caddy-waf module..."
xcaddy build --with github.com/fabriziosalmi/caddy-waf=./ && \
print_success "Caddy built successfully." || print_error "Failed to build Caddy."
# Format Caddyfile
echo -e "🧹 Formatting Caddyfile..."
./caddy fmt --overwrite && \
print_success "Caddyfile formatted." || print_error "Failed to format Caddyfile."
# Run Caddy
echo -e "🚀 Starting Caddy server..."
./caddy run && \
print_success "Caddy is running." || print_error "Failed to start Caddy."
ensure_go_installed
ensure_xcaddy_installed
clone_or_update_repo
update_dependencies
download_geolite2_db
build_caddy
format_caddyfile
run_caddy
print_success "caddy-waf setup completed!"

View File

@@ -23,6 +23,8 @@ func (m *Middleware) processRuleMatch(w http.ResponseWriter, r *http.Request, ru
zap.String("value", value),
zap.String("description", rule.Description),
zap.Int("score", rule.Score),
zap.Int("anomaly_threshold_config", m.AnomalyThreshold), // ADDED: Log configured anomaly threshold
zap.Int("current_anomaly_score", state.TotalScore), // ADDED: Log current anomaly score before increment
)
// Rule Hit Counter - Refactored for clarity
@@ -52,16 +54,19 @@ func (m *Middleware) processRuleMatch(w http.ResponseWriter, r *http.Request, ru
}
}
m.logRequest(zapcore.DebugLevel, "Anomaly score increased", r, // 'r' is now the 3rd argument
m.logRequest(zapcore.DebugLevel, "Determining Block Action", r, // More descriptive log message
zap.String("action", rule.Action),
zap.Bool("should_block", shouldBlock),
zap.String("block_reason", blockReason),
zap.Int("total_score", state.TotalScore), // ADDED: Log total score in block decision log
zap.Int("anomaly_threshold", m.AnomalyThreshold), // ADDED: Log anomaly threshold in block decision log
)
if shouldBlock {
m.blockRequest(w, r, state, http.StatusForbidden, blockReason, string(rule.ID), value,
zap.Int("total_score", state.TotalScore),
zap.Int("anomaly_threshold", m.AnomalyThreshold),
zap.String("final_block_reason", blockReason), // ADDED: Clarify block reason in blockRequest log
)
return false
}
@@ -70,6 +75,8 @@ func (m *Middleware) processRuleMatch(w http.ResponseWriter, r *http.Request, ru
m.logRequest(zapcore.InfoLevel, "Rule action: Log", r,
zap.String("log_id", logID),
zap.String("rule_id", string(rule.ID)),
zap.Int("total_score", state.TotalScore), // ADDED: Log total score for log action
zap.Int("anomaly_threshold", m.AnomalyThreshold), // ADDED: Log anomaly threshold for log action
)
} else if !shouldBlock && !state.ResponseWritten {
m.logRequest(zapcore.DebugLevel, "Rule action: No Block", r,