CodeReview/scripts/setup_security_tools.sh

942 lines
28 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
#
# DeepAudit 安全工具一键安装脚本 (增强版)
# 自动安装沙盒和外部安全扫描工具
#
# 特性:
# - 多种安装方式自动回退
# - 网络问题自动重试
# - 详细的错误诊断
# - 支持代理设置
# - 虚拟环境兼容
#
set -e
# ============================================================
# 配置
# ============================================================
# 版本配置
GITLEAKS_VERSION="8.18.4"
OSV_SCANNER_VERSION="1.8.3"
TRUFFLEHOG_VERSION="3.80.0"
# 重试配置
MAX_RETRIES=3
RETRY_DELAY=2
# 超时配置
DOWNLOAD_TIMEOUT=60
INSTALL_TIMEOUT=120
# 获取脚本目录
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
# 工具安装目录
TOOLS_DIR="$HOME/.local/bin"
mkdir -p "$TOOLS_DIR"
# ============================================================
# 颜色和日志
# ============================================================
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'
log_info() { echo -e "${BLUE}${NC} $1"; }
log_success() { echo -e "${GREEN}${NC} $1"; }
log_warning() { echo -e "${YELLOW}!${NC} $1"; }
log_error() { echo -e "${RED}${NC} $1"; }
log_debug() { [[ "$VERBOSE" == "1" ]] && echo -e "${CYAN} $1${NC}"; }
log_header() {
echo ""
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
echo -e "${BLUE} $1${NC}"
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
echo ""
}
# ============================================================
# 工具函数
# ============================================================
# 检查命令是否存在且可执行
command_exists() {
command -v "$1" &> /dev/null || return 1
# 额外检查:确保命令真的能运行(排除 pyenv shim 等假阳性)
case "$1" in
semgrep) "$1" --version &> /dev/null ;;
bandit) "$1" --version &> /dev/null ;;
safety) "$1" --version &> /dev/null ;;
gitleaks) "$1" version &> /dev/null ;;
osv-scanner) "$1" --version &> /dev/null ;;
trufflehog) "$1" --version &> /dev/null ;;
*) return 0 ;;
esac
}
# 检测操作系统
detect_os() {
if [[ "$OSTYPE" == "darwin"* ]]; then
OS="macos"
ARCH=$(uname -m)
if [[ "$ARCH" == "arm64" ]]; then
ARCH_TYPE="arm64"
else
ARCH_TYPE="x64"
fi
elif [[ -f /etc/debian_version ]]; then
OS="debian"
ARCH_TYPE=$(dpkg --print-architecture 2>/dev/null || echo "amd64")
elif [[ -f /etc/redhat-release ]]; then
OS="redhat"
ARCH_TYPE=$(uname -m)
else
OS="linux"
ARCH_TYPE=$(uname -m)
fi
# 标准化架构名称
case "$ARCH_TYPE" in
x86_64|amd64) ARCH_TYPE="x64" ;;
aarch64|arm64) ARCH_TYPE="arm64" ;;
esac
log_info "检测到系统: $OS ($ARCH_TYPE)"
}
# 检测 Python 环境
detect_python() {
PYTHON_CMD=""
PIP_CMD=""
# 优先使用虚拟环境
if [[ -n "$VIRTUAL_ENV" ]]; then
log_info "检测到虚拟环境: $VIRTUAL_ENV"
PYTHON_CMD="python"
PIP_CMD="pip"
# 检查 python3
elif command_exists python3; then
PYTHON_CMD="python3"
if command_exists pip3; then
PIP_CMD="pip3"
else
PIP_CMD="python3 -m pip"
fi
# 检查 python
elif command_exists python; then
PYTHON_CMD="python"
if command_exists pip; then
PIP_CMD="pip"
else
PIP_CMD="python -m pip"
fi
else
log_error "未找到 Python请先安装 Python 3.8+"
return 1
fi
# 验证 Python 版本
PYTHON_VERSION=$($PYTHON_CMD --version 2>&1 | grep -oE '[0-9]+\.[0-9]+')
log_info "Python 版本: $PYTHON_VERSION (命令: $PYTHON_CMD)"
log_debug "pip 命令: $PIP_CMD"
# 确保 pip 可用
if ! $PIP_CMD --version &>/dev/null; then
log_warning "pip 不可用,尝试安装..."
$PYTHON_CMD -m ensurepip --upgrade 2>/dev/null || true
fi
return 0
}
# 带重试的下载函数
download_with_retry() {
local url="$1"
local output="$2"
local description="$3"
for attempt in $(seq 1 $MAX_RETRIES); do
log_info "下载 $description (尝试 $attempt/$MAX_RETRIES)..."
if command_exists curl; then
if curl -fsSL --connect-timeout 10 --max-time $DOWNLOAD_TIMEOUT -o "$output" "$url" 2>/dev/null; then
log_success "$description 下载成功"
return 0
fi
elif command_exists wget; then
if wget -q --timeout=$DOWNLOAD_TIMEOUT -O "$output" "$url" 2>/dev/null; then
log_success "$description 下载成功"
return 0
fi
else
log_error "未找到 curl 或 wget"
return 1
fi
log_warning "下载失败,${RETRY_DELAY}秒后重试..."
sleep $RETRY_DELAY
done
log_error "$description 下载失败 (已重试 $MAX_RETRIES 次)"
return 1
}
# 带重试的 pip 安装
pip_install_with_retry() {
local package="$1"
for attempt in $(seq 1 $MAX_RETRIES); do
log_info "安装 $package (尝试 $attempt/$MAX_RETRIES)..."
# 尝试方式 1: 普通安装
if $PIP_CMD install "$package" --timeout 60 2>&1; then
log_success "$package 安装成功"
return 0
fi
# 尝试方式 2: --user 标志
log_debug "尝试 --user 安装..."
if $PIP_CMD install "$package" --user --timeout 60 2>&1; then
log_success "$package 安装成功 (--user)"
return 0
fi
# 尝试方式 3: --break-system-packages (Python 3.11+ PEP 668)
log_debug "尝试 --break-system-packages..."
if $PIP_CMD install "$package" --break-system-packages --timeout 60 2>&1; then
log_success "$package 安装成功 (--break-system-packages)"
return 0
fi
# 尝试升级 pip 后重试
if [[ $attempt -eq 1 ]]; then
log_debug "升级 pip 后重试..."
$PIP_CMD install --upgrade pip --quiet 2>/dev/null || true
fi
sleep $RETRY_DELAY
done
# 尝试方式 4: 使用 pipx (推荐的 CLI 工具安装方式)
if command -v pipx &> /dev/null; then
log_info "尝试使用 pipx 安装 $package..."
if pipx install "$package" 2>&1; then
log_success "$package 安装成功 (pipx)"
return 0
fi
fi
log_error "$package 安装失败"
return 1
}
# 添加到 PATH
add_to_path() {
local dir="$1"
# 当前会话
if [[ ":$PATH:" != *":$dir:"* ]]; then
export PATH="$dir:$PATH"
fi
# 持久化到 shell 配置
local shell_rc=""
if [[ -f "$HOME/.zshrc" ]]; then
shell_rc="$HOME/.zshrc"
elif [[ -f "$HOME/.bashrc" ]]; then
shell_rc="$HOME/.bashrc"
elif [[ -f "$HOME/.bash_profile" ]]; then
shell_rc="$HOME/.bash_profile"
fi
if [[ -n "$shell_rc" ]]; then
if ! grep -q "$dir" "$shell_rc" 2>/dev/null; then
echo "export PATH=\"$dir:\$PATH\"" >> "$shell_rc"
log_debug "已添加 $dir$shell_rc"
fi
fi
}
# ============================================================
# Python 工具安装
# ============================================================
install_python_tools() {
log_header "安装 Python 安全工具"
detect_python || return 1
local tools=("bandit" "safety")
local failed=()
local installed=()
# Semgrep 单独处理(较大)
log_info "检查 semgrep..."
if command_exists semgrep; then
log_success "semgrep 已安装: $(semgrep --version 2>&1 | head -1)"
else
# 尝试 pip 安装
if pip_install_with_retry "semgrep"; then
installed+=("semgrep")
# macOS: 尝试 brew 安装
elif [[ "$OS" == "macos" ]] && command -v brew &> /dev/null; then
log_info "pip 安装失败,尝试 brew install semgrep..."
if brew install semgrep 2>&1; then
installed+=("semgrep")
log_success "semgrep 安装成功 (brew)"
else
failed+=("semgrep")
fi
else
failed+=("semgrep")
log_warning "semgrep 安装失败,可尝试: brew install semgrep (macOS)"
fi
fi
# 安装其他工具
for tool in "${tools[@]}"; do
log_info "检查 $tool..."
if command_exists "$tool"; then
log_success "$tool 已安装"
else
if pip_install_with_retry "$tool"; then
installed+=("$tool")
else
failed+=("$tool")
fi
fi
done
# 可选: TruffleHog
if [[ "$INSTALL_OPTIONAL" == "1" ]] || [[ "$INTERACTIVE" == "1" ]]; then
if [[ "$INTERACTIVE" == "1" ]]; then
read -p "是否安装 TruffleHog (高级密钥扫描约100MB)? [y/N] " -n 1 -r
echo
fi
if [[ "$INSTALL_OPTIONAL" == "1" ]] || [[ $REPLY =~ ^[Yy]$ ]]; then
if command_exists trufflehog; then
log_success "trufflehog 已安装"
else
pip_install_with_retry "trufflehog" || failed+=("trufflehog")
fi
fi
fi
# 报告结果
echo ""
if [[ ${#installed[@]} -gt 0 ]]; then
log_success "已安装: ${installed[*]}"
fi
if [[ ${#failed[@]} -gt 0 ]]; then
log_warning "安装失败: ${failed[*]}"
log_info "💡 提示: 可尝试使用 pipx 安装: pipx install <package>"
log_info " 或使用虚拟环境: python3 -m venv venv && source venv/bin/activate && pip install <package>"
return 1
fi
return 0
}
# ============================================================
# 系统工具安装 (macOS)
# ============================================================
install_macos_tools() {
log_header "安装 macOS 系统工具"
local failed=()
local installed=()
# 检查/安装 Homebrew
if ! command_exists brew; then
log_warning "Homebrew 未安装"
if [[ "$INTERACTIVE" == "1" ]]; then
read -p "是否安装 Homebrew? [Y/n] " -n 1 -r
echo
[[ $REPLY =~ ^[Nn]$ ]] && return 1
fi
log_info "安装 Homebrew..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" || {
log_error "Homebrew 安装失败"
log_info "尝试使用二进制方式安装工具..."
install_binary_tools
return $?
}
# 配置 Homebrew PATH (Apple Silicon)
if [[ -f "/opt/homebrew/bin/brew" ]]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
fi
fi
log_success "Homebrew 可用: $(brew --version | head -1)"
# Gitleaks
log_info "检查 gitleaks..."
if command_exists gitleaks; then
log_success "gitleaks 已安装: $(gitleaks version 2>&1 | head -1)"
else
log_info "安装 gitleaks..."
if brew install gitleaks 2>/dev/null; then
installed+=("gitleaks")
log_success "gitleaks 安装成功"
else
log_warning "brew 安装失败,尝试二进制安装..."
install_gitleaks_binary || failed+=("gitleaks")
fi
fi
# OSV-Scanner
log_info "检查 osv-scanner..."
if command_exists osv-scanner; then
log_success "osv-scanner 已安装"
else
log_info "安装 osv-scanner..."
if brew install osv-scanner 2>/dev/null; then
installed+=("osv-scanner")
log_success "osv-scanner 安装成功"
else
log_warning "brew 安装失败,尝试二进制安装..."
install_osv_scanner_binary || failed+=("osv-scanner")
fi
fi
# 可选: TruffleHog (brew)
if [[ "$INSTALL_OPTIONAL" == "1" ]]; then
if ! command_exists trufflehog; then
log_info "安装 trufflehog (brew)..."
brew install trufflehog 2>/dev/null || log_warning "trufflehog brew 安装失败"
fi
fi
# 报告结果
echo ""
if [[ ${#installed[@]} -gt 0 ]]; then
log_success "已安装: ${installed[*]}"
fi
if [[ ${#failed[@]} -gt 0 ]]; then
log_warning "安装失败: ${failed[*]}"
return 1
fi
return 0
}
# ============================================================
# 二进制工具安装 (回退方案)
# ============================================================
install_binary_tools() {
log_info "使用二进制方式安装工具..."
install_gitleaks_binary
install_osv_scanner_binary
}
install_gitleaks_binary() {
log_info "下载 Gitleaks 二进制..."
local arch_suffix=""
case "$OS-$ARCH_TYPE" in
macos-x64) arch_suffix="darwin_x64" ;;
macos-arm64) arch_suffix="darwin_arm64" ;;
*-x64) arch_suffix="linux_x64" ;;
*-arm64) arch_suffix="linux_arm64" ;;
*) arch_suffix="linux_x64" ;;
esac
local url="https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_${arch_suffix}.tar.gz"
local tmp_file="/tmp/gitleaks.tar.gz"
if download_with_retry "$url" "$tmp_file" "Gitleaks"; then
tar -xzf "$tmp_file" -C "$TOOLS_DIR" gitleaks 2>/dev/null || {
# 某些版本可能没有子目录
tar -xzf "$tmp_file" -C "/tmp" 2>/dev/null
mv /tmp/gitleaks "$TOOLS_DIR/" 2>/dev/null || true
}
chmod +x "$TOOLS_DIR/gitleaks"
rm -f "$tmp_file"
add_to_path "$TOOLS_DIR"
log_success "Gitleaks 二进制安装成功"
return 0
fi
return 1
}
install_osv_scanner_binary() {
log_info "下载 OSV-Scanner 二进制..."
local arch_suffix=""
case "$OS-$ARCH_TYPE" in
macos-x64) arch_suffix="darwin_amd64" ;;
macos-arm64) arch_suffix="darwin_arm64" ;;
*-x64) arch_suffix="linux_amd64" ;;
*-arm64) arch_suffix="linux_arm64" ;;
*) arch_suffix="linux_amd64" ;;
esac
local url="https://github.com/google/osv-scanner/releases/download/v${OSV_SCANNER_VERSION}/osv-scanner_${arch_suffix}"
local target="$TOOLS_DIR/osv-scanner"
if download_with_retry "$url" "$target" "OSV-Scanner"; then
chmod +x "$target"
add_to_path "$TOOLS_DIR"
log_success "OSV-Scanner 二进制安装成功"
return 0
fi
return 1
}
install_trufflehog_binary() {
log_info "下载 TruffleHog 二进制..."
local arch_suffix=""
case "$OS-$ARCH_TYPE" in
macos-x64) arch_suffix="darwin_amd64" ;;
macos-arm64) arch_suffix="darwin_arm64" ;;
*-x64) arch_suffix="linux_amd64" ;;
*-arm64) arch_suffix="linux_arm64" ;;
*) arch_suffix="linux_amd64" ;;
esac
local url="https://github.com/trufflesecurity/trufflehog/releases/download/v${TRUFFLEHOG_VERSION}/trufflehog_${TRUFFLEHOG_VERSION}_${arch_suffix}.tar.gz"
local tmp_file="/tmp/trufflehog.tar.gz"
if download_with_retry "$url" "$tmp_file" "TruffleHog"; then
tar -xzf "$tmp_file" -C "$TOOLS_DIR" trufflehog 2>/dev/null || {
tar -xzf "$tmp_file" -C "/tmp" 2>/dev/null
mv /tmp/trufflehog "$TOOLS_DIR/" 2>/dev/null || true
}
chmod +x "$TOOLS_DIR/trufflehog"
rm -f "$tmp_file"
add_to_path "$TOOLS_DIR"
log_success "TruffleHog 二进制安装成功"
return 0
fi
return 1
}
# ============================================================
# Linux 工具安装
# ============================================================
install_linux_tools() {
log_header "安装 Linux 系统工具"
# 直接使用二进制安装(最可靠)
install_binary_tools
}
# ============================================================
# Docker 沙盒安装
# ============================================================
install_docker_sandbox() {
log_header "配置 Docker 沙盒"
# 检查 Docker
if ! command_exists docker; then
log_error "Docker 未安装!"
log_info "macOS: brew install --cask docker"
log_info "Linux: https://docs.docker.com/engine/install/"
return 1
fi
# 检查 Docker 是否运行
if ! docker info &> /dev/null; then
log_error "Docker 未运行!请启动 Docker。"
# macOS: 尝试启动 Docker Desktop
if [[ "$OS" == "macos" ]]; then
log_info "尝试启动 Docker Desktop..."
open -a Docker 2>/dev/null || true
log_info "等待 Docker 启动 (最多 60 秒)..."
for i in {1..12}; do
sleep 5
if docker info &> /dev/null; then
log_success "Docker 已启动"
break
fi
echo -n "."
done
echo ""
if ! docker info &> /dev/null; then
log_error "Docker 启动超时,请手动启动 Docker Desktop"
return 1
fi
else
return 1
fi
fi
log_success "Docker 已运行"
# 构建沙盒镜像
local sandbox_dir="$PROJECT_ROOT/docker/sandbox"
local dockerfile="$sandbox_dir/Dockerfile"
if [[ ! -f "$dockerfile" ]]; then
log_warning "沙盒 Dockerfile 不存在,创建默认配置..."
mkdir -p "$sandbox_dir"
create_sandbox_dockerfile "$sandbox_dir"
fi
log_info "构建 DeepAudit 沙盒镜像..."
cd "$sandbox_dir"
# 带重试的构建
for attempt in $(seq 1 $MAX_RETRIES); do
log_info "构建镜像 (尝试 $attempt/$MAX_RETRIES)..."
if docker build -t deepaudit-sandbox:latest -f Dockerfile . 2>&1; then
log_success "沙盒镜像构建成功: deepaudit-sandbox:latest"
# 验证
log_info "验证沙盒镜像..."
if docker run --rm deepaudit-sandbox:latest python3 --version; then
log_success "Python 环境正常"
fi
if docker run --rm deepaudit-sandbox:latest node --version 2>/dev/null; then
log_success "Node.js 环境正常"
fi
return 0
fi
log_warning "构建失败,重试..."
sleep $RETRY_DELAY
done
log_error "沙盒镜像构建失败"
return 1
}
create_sandbox_dockerfile() {
local dir="$1"
cat > "$dir/Dockerfile" << 'EOF'
# DeepAudit 安全沙盒
FROM python:3.11-slim-bookworm
# 安装基础工具
RUN apt-get update && apt-get install -y --no-install-recommends \
curl wget netcat-openbsd dnsutils iputils-ping ca-certificates git \
&& rm -rf /var/lib/apt/lists/*
# 安装 Node.js 20
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
&& apt-get install -y nodejs \
&& rm -rf /var/lib/apt/lists/*
# 创建非特权用户
RUN groupadd -g 1000 sandbox \
&& useradd -u 1000 -g sandbox -m -s /bin/bash sandbox
# 安装 Python 安全测试库
RUN pip install --no-cache-dir \
requests httpx aiohttp beautifulsoup4 lxml \
pycryptodome paramiko pyjwt python-jose sqlparse
# 设置工作目录
WORKDIR /workspace
RUN mkdir -p /workspace /tmp/sandbox \
&& chown -R sandbox:sandbox /workspace /tmp/sandbox
USER sandbox
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1 HOME=/home/sandbox
CMD ["/bin/bash"]
EOF
log_success "已创建沙盒 Dockerfile"
}
# ============================================================
# 验证安装
# ============================================================
verify_installation() {
log_header "验证安装结果"
local tools=(
"semgrep:Semgrep 静态分析"
"bandit:Bandit Python安全"
"safety:Safety 依赖漏洞"
"gitleaks:Gitleaks 密钥检测"
"osv-scanner:OSV-Scanner 漏洞"
"trufflehog:TruffleHog 密钥"
"npm:NPM Audit"
"docker:Docker"
)
local installed=0
local total=${#tools[@]}
echo ""
printf "%-18s %-12s %-30s\n" "工具" "状态" "版本/路径"
echo "────────────────────────────────────────────────────────────"
for tool_info in "${tools[@]}"; do
IFS=':' read -r tool desc <<< "$tool_info"
if command_exists "$tool"; then
local version=""
case "$tool" in
semgrep) version=$(semgrep --version 2>&1 | head -1) ;;
bandit) version=$(bandit --version 2>&1 | head -1) ;;
safety) version=$(safety --version 2>&1 | head -1) ;;
gitleaks) version=$(gitleaks version 2>&1 | head -1) ;;
osv-scanner) version=$(osv-scanner --version 2>&1 | head -1) ;;
trufflehog) version=$(trufflehog --version 2>&1 | head -1) ;;
npm) version=$(npm --version 2>&1) ;;
docker) version=$(docker --version 2>&1 | cut -d' ' -f3) ;;
esac
version="${version:0:28}"
printf "%-18s ${GREEN}%-12s${NC} %-30s\n" "$tool" "已安装" "$version"
((installed++))
else
printf "%-18s ${YELLOW}%-12s${NC} %-30s\n" "$tool" "未安装" "-"
fi
done
echo "────────────────────────────────────────────────────────────"
# Docker 沙盒检查
if command_exists docker && docker info &>/dev/null; then
if docker image inspect deepaudit-sandbox:latest &>/dev/null; then
echo ""
log_success "Docker 沙盒镜像: deepaudit-sandbox:latest ✓"
else
echo ""
log_warning "Docker 沙盒镜像未构建"
fi
fi
echo ""
log_info "安装统计: $installed/$total 个工具可用"
# 检查 PATH
if [[ ":$PATH:" != *":$TOOLS_DIR:"* ]]; then
log_warning "请重启终端或运行: source ~/.zshrc (或 ~/.bashrc)"
fi
if [[ $installed -ge 5 ]]; then
log_success "核心安全工具已就绪!"
return 0
else
log_warning "部分工具未安装,某些功能可能受限"
return 1
fi
}
# ============================================================
# 更新环境配置
# ============================================================
update_env_config() {
log_header "更新环境配置"
local env_file="$PROJECT_ROOT/backend/.env"
if [[ ! -f "$env_file" ]]; then
log_warning ".env 文件不存在,跳过配置更新"
return 0
fi
if grep -q "SANDBOX_IMAGE" "$env_file"; then
log_info "沙盒配置已存在于 .env 文件中"
else
log_info "添加沙盒配置到 .env 文件..."
cat >> "$env_file" << 'EOF'
# =============================================
# 沙盒配置 (自动添加)
# =============================================
SANDBOX_IMAGE=deepaudit-sandbox:latest
SANDBOX_MEMORY_LIMIT=512m
SANDBOX_CPU_LIMIT=1.0
SANDBOX_TIMEOUT=60
SANDBOX_NETWORK_MODE=none
EOF
log_success "沙盒配置已添加到 .env"
fi
}
# ============================================================
# 显示帮助
# ============================================================
show_help() {
cat << 'EOF'
DeepAudit 安全工具一键安装脚本
用法:
./setup_security_tools.sh [选项]
选项:
-a, --all 全部安装 (默认交互式)
-p, --python 仅安装 Python 工具
-s, --system 仅安装系统工具
-d, --docker 仅构建 Docker 沙盒
-v, --verify 仅验证安装状态
-o, --optional 包含可选工具 (TruffleHog)
--verbose 显示详细输出
-h, --help 显示帮助
示例:
./setup_security_tools.sh # 交互式安装
./setup_security_tools.sh -a # 自动全部安装
./setup_security_tools.sh -a -o # 全部安装 + 可选工具
./setup_security_tools.sh -v # 仅检查状态
EOF
}
# ============================================================
# 主函数
# ============================================================
main() {
# 解析参数
INTERACTIVE="1"
INSTALL_ALL=""
INSTALL_PYTHON=""
INSTALL_SYSTEM=""
INSTALL_DOCKER=""
VERIFY_ONLY=""
INSTALL_OPTIONAL=""
VERBOSE=""
while [[ $# -gt 0 ]]; do
case $1 in
-a|--all) INSTALL_ALL="1"; INTERACTIVE="" ;;
-p|--python) INSTALL_PYTHON="1"; INTERACTIVE="" ;;
-s|--system) INSTALL_SYSTEM="1"; INTERACTIVE="" ;;
-d|--docker) INSTALL_DOCKER="1"; INTERACTIVE="" ;;
-v|--verify) VERIFY_ONLY="1"; INTERACTIVE="" ;;
-o|--optional) INSTALL_OPTIONAL="1" ;;
--verbose) VERBOSE="1" ;;
-h|--help) show_help; exit 0 ;;
*) log_error "未知选项: $1"; show_help; exit 1 ;;
esac
shift
done
# 显示标题
echo ""
echo -e "${BLUE}╔═══════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ ║${NC}"
echo -e "${BLUE}║ 🔐 DeepAudit 安全工具一键安装脚本 (增强版) ║${NC}"
echo -e "${BLUE}║ ║${NC}"
echo -e "${BLUE}╚═══════════════════════════════════════════════════════════════╝${NC}"
echo ""
# 检测系统
detect_os
# 仅验证模式
if [[ "$VERIFY_ONLY" == "1" ]]; then
verify_installation
exit $?
fi
# 自动安装模式
if [[ "$INSTALL_ALL" == "1" ]]; then
install_python_tools
if [[ "$OS" == "macos" ]]; then
install_macos_tools
else
install_linux_tools
fi
install_docker_sandbox
update_env_config
verify_installation
exit $?
fi
# 单独安装模式
if [[ "$INSTALL_PYTHON" == "1" ]]; then
install_python_tools
verify_installation
exit $?
fi
if [[ "$INSTALL_SYSTEM" == "1" ]]; then
if [[ "$OS" == "macos" ]]; then
install_macos_tools
else
install_linux_tools
fi
verify_installation
exit $?
fi
if [[ "$INSTALL_DOCKER" == "1" ]]; then
install_docker_sandbox
update_env_config
verify_installation
exit $?
fi
# 交互式模式
echo "请选择要安装的组件:"
echo " 1) 全部安装 (推荐)"
echo " 2) 仅 Python 工具 (pip)"
echo " 3) 仅系统工具 (brew/binary)"
echo " 4) 仅 Docker 沙盒"
echo " 5) 仅验证安装状态"
echo " 6) 退出"
echo ""
read -p "请输入选项 [1-6]: " choice
case $choice in
1)
install_python_tools
if [[ "$OS" == "macos" ]]; then
install_macos_tools
else
install_linux_tools
fi
install_docker_sandbox
update_env_config
verify_installation
;;
2) install_python_tools; verify_installation ;;
3)
if [[ "$OS" == "macos" ]]; then
install_macos_tools
else
install_linux_tools
fi
verify_installation
;;
4) install_docker_sandbox; update_env_config; verify_installation ;;
5) verify_installation ;;
6) echo "退出"; exit 0 ;;
*) log_error "无效选项"; exit 1 ;;
esac
log_header "安装完成"
echo ""
echo "下一步操作:"
echo " 1. 重启终端使 PATH 生效"
echo " 2. 启动后端: cd backend && uvicorn app.main:app --reload"
echo " 3. 在 Agent 审计中测试工具"
echo ""
}
main "$@"