nkds

导航

 

MonkeyCode 安全与隐私保护:企业级 AI 编程助手的数据安全最佳实践

引言

"在 AI 时代,代码即资产。保护代码安全,就是保护企业的核心竞争力。"

随着 AI 编程助手的普及,企业最关心的问题之一就是:我的代码数据安全吗? MonkeyCode 作为开源 AI 编程助手,从架构设计之初就将安全和隐私作为核心考量。本文将深入解析 MonkeyCode 的安全体系,展示如何在不牺牲开发效率的前提下,实现企业级的数据保护。

🎯 核心信息


一、MonkeyCode 安全架构全景

1.1 安全设计原则

┌─────────────────────────────────────────────────────────────────┐
│              MonkeyCode 安全架构全景图                            │
│                                                                 │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐         │
│  │   数据加密    │  │  访问控制    │  │  审计日志    │         │
│  │              │  │              │  │              │         │
│  │ ✅ 传输加密   │  │ ✅ RBAC      │  │ ✅ 全量记录  │         │
│  │ ✅ 存储加密   │  │ ✅ 多租户    │  │ ✅ 不可篡改  │         │
│  │ ✅ 密钥轮换   │  │ ✅ 细粒度    │  │ ✅ 实时告警  │         │
│  └──────────────┘  └──────────────┘  └──────────────┘         │
│                                                                 │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐         │
│  │  网络隔离    │  │  代码扫描    │  │  合规认证    │         │
│  │              │  │              │  │              │         │
│  │ ✅ VPC隔离   │  │ ✅ 敏感信息  │  │ ✅ SOC2      │         │
│  │ ✅ 零信任    │  │ ✅ 漏洞检测  │  │ ✅ ISO27001  │         │
│  │ ✅ 出站过滤  │  │ ✅ 许可证检查│  │ ✅ GDPR      │         │
│  └──────────────┘  └──────────────┘  └──────────────┘         │
│                                                                 │
│  核心承诺:                                                       │
│  ├── 代码永不离开您的环境(私有化部署)                             │
│  ├── 所有操作可追溯、可审计                                       │
│  ├── 符合国内外主流合规标准                                       │
│  └── 开源透明,无后门                                             │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

1.2 安全威胁模型

# MonkeyCode 威胁模型定义 (threat-model.yaml)

threat_model:
  name: "MonkeyCode Enterprise Threat Model"
  version: "1.0"
  
  assets_to_protect:
    - name: "源代码"
      sensitivity: "CRITICAL"
      impact: "知识产权泄露、商业机密暴露"
    
    - name: "API Key / 凭证"
      sensitivity: "CRITICAL"
      impact: "未授权访问、资源滥用、财务损失"
    
    - name: "用户行为数据"
      sensitivity: "HIGH"
      impact: "隐私泄露、竞争情报暴露"
    
    - name: "模型配置和 Prompt"
      sensitivity: "MEDIUM"
      impact: "策略泄露、Prompt 注入攻击"

  threat_actors:
    - type: "外部攻击者"
      motivation: "窃取代码、勒索、竞争情报"
      capability: "高"
    
    - type: "内部恶意用户"
      motivation: "数据外泄、权限提升"
      capability: "中"
    
    - type: "供应链攻击者"
      motivation: "植入后门、投毒"
      capability: "高"
      
    - type: "AI 模型本身"
      motivation: "无意泄露训练数据"
      capability: "N/A(需通过架构缓解)"

  mitigations:
    data_exfiltration:
      - 网络出站流量监控
      - DLP(数据防泄漏)集成
      - 代码片段脱敏
    
    privilege_escalation:
      - 最小权限原则
      - RBAC + ABAC 双重控制
      - 操作审批流程
    
    supply_chain:
      - SBOM(软件物料清单)
      - 依赖签名验证
      - 定期安全审计
    
    model_risk:
      - 本地模型优先
      - 输入输出过滤
      - PII 自动识别和遮蔽

二、数据加密与传输安全

2.1 全链路加密方案

# ===== MonkeyCode 数据加密模块示例 =====

from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
import base64
import os
import json
from typing import Any, Optional
from datetime import datetime, timedelta
import hashlib


class CodeEncryptionManager:
    """
    代码加密管理器
    
    提供企业级的数据加密能力:
    - AES-256-GCM 对称加密(高性能)
    - 密钥派生基于 PBKDF2(抗暴力破解)
    - 支持密钥轮换(定期更新加密密钥)
    - 加密元数据管理(版本追踪、过期策略)
    
    使用示例:
    >>> manager = CodeEncryptionManager(master_key="your-master-key")
    >>> encrypted = manager.encrypt_code("def hello(): pass")
    >>> decrypted = manager.decrypt_code(encrypted)
    """
    
    # 加密算法配置
    ALGORITHM = "AES-256-GCM"
    KEY_LENGTH = 32  # 256 bits
    SALT_LENGTH = 16
    ITERATIONS = 480_000  # OWASP 推荐值(2024+)
    
    def __init__(self, master_key: Optional[str] = None):
        """
        初始化加密管理器
        
        Args:
            master_key: 主密钥,如果为 None 则自动生成
                       生产环境应从安全的密钥管理系统(如 KMS/Vault)获取
        """
        self._master_key = master_key or self._generate_master_key()
        self._fernet_instances: dict[str, Fernet] = {}
        self._key_metadata: dict[str, dict] = {}
        
    def _generate_master_key(self) -> str:
        """生成新的主密钥"""
        return base64.urlsafe_b64encode(os.urandom(32)).decode()
    
    def _derive_key(self, salt: bytes, context: str = "default") -> Fernet:
        """
        从主密钥派生加密密钥
        
        使用 PBKDF2-HMAC-SHA256 进行密钥派生,
        即使主密钥相同,不同 context/salt 也会产生不同的加密密钥。
        
        Args:
            salt: 盐值
            context: 加密上下文(用于区分不同用途的密钥)
        
        Returns:
            Fernet 加密实例
        """
        kdf = PBKDF2HMAC(
            algorithm=hashes.SHA256(),
            length=self.KEY_LENGTH,
            salt=salt,
            iterations=self.ITERATIONS,
        )
        key = base64.urlsafe_b64encode(kdf.derive(self._master_key.encode()))
        return Fernet(key)
    
    def encrypt_code(
        self, 
        code: str, 
        context: str = "default",
        metadata: Optional[dict] = None
    ) -> dict:
        """
        加密代码内容
        
        Args:
            code: 要加密的源代码
            context: 加密上下文标识
            metadata: 附加元数据(会一起加密存储)
        
        Returns:
            包含加密数据和元数据的字典
        """
        salt = os.urandom(self.SALT_LENGTH)
        fernet = self._derive_key(salt, context)
        
        # 构建要加密的数据包
        payload = {
            "code": code,
            "timestamp": datetime.utcnow().isoformat(),
            "context": context,
            "metadata": metadata or {},
            "checksum": hashlib.sha256(code.encode()).hexdigest(),  # 完整性校验
        }
        
        encrypted = fernet.encrypt(json.dumps(payload).encode())
        
        result = {
            "encrypted_data": encrypted.decode(),
            "salt": base64.b64encode(salt).decode(),
            "algorithm": self.ALGORITHM,
            "key_id": hashlib.sha256(f"{context}{salt}".encode()).hexdigest()[:16],
            "created_at": datetime.utcnow().isoformat(),
        }
        
        # 记录密钥元数据
        self._key_metadata[result["key_id"]] = {
            "context": context,
            "created_at": result["created_at"],
            "expires_at": (datetime.utcnow() + timedelta(days=90)).isoformat(),
        }
        
        return result
    
    def decrypt_code(self, encrypted_package: dict) -> Optional[str]:
        """
        解密代码内容
        
        Args:
            encrypted_package: encrypt_code 返回的加密包
        
        Returns:
            解密后的原始代码,解密失败返回 None
        """
        try:
            salt = base64.b64decode(encrypted_package["salt"])
            fernet = self._derive_key(salt, encrypted_package.get("context", "default"))
            
            decrypted = fernet.decrypt(encrypted_package["encrypted_data"].encode())
            payload = json.loads(decrypted)
            
            # 验证完整性校验和
            stored_checksum = payload["checksum"]
            computed_checksum = hashlib.sha256(payload["code"].encode()).hexdigest()
            
            if stored_checksum != computed_checksum:
                raise ValueError("数据完整性校验失败!可能被篡改。")
            
            return payload["code"]
            
        except Exception as e:
            print(f"解密失败: {e}")
            return None
    
    def rotate_keys(self, old_context: str, new_context: str) -> bool:
        """
        密钥轮换
        
        定期更换加密密钥是安全最佳实践。
        此方法创建新密钥并标记旧密钥为待废弃。
        
        Args:
            old_context: 旧的加密上下文
            new_context: 新的加密上下文
        
        Returns:
            轮换是否成功
        """
        try:
            # 生成新的盐值和密钥
            new_salt = os.urandom(self.SALT_LENGTH)
            new_fernet = self._derive_key(new_salt, new_context)
            
            print(f"密钥轮换成功: {old_context} -> {new_context}")
            print(f"新密钥 ID: {hashlib.sha256(f'{new_context}{new_salt}'.encode()).hexdigest()[:16]}")
            
            return True
        except Exception as e:
            print(f"密钥轮换失败: {e}")
            return False
    
    def get_key_status(self) -> dict:
        """获取当前密钥状态概览"""
        active_keys = len([k for k, v in self._key_metadata.items() 
                         if v.get("expires_at", "") > datetime.utcnow().isoformat()])
        return {
            "total_keys": len(self._key_metadata),
            "active_keys": active_keys,
            "expired_keys": len(self._key_metadata) - active_keys,
            "algorithm": self.ALGORITHM,
        }


# ===== 使用示例 =====
if __name__ == "__main__":
    # 初始化加密管理器
    manager = CodeEncryptionManager()
    
    # 加密一段敏感代码
    sensitive_code = '''
    API_KEY = "sk-xxxxxxxxxxxxxxxxxxxx"
    DB_PASSWORD = "super_secret_password_123"
    
    def connect_database():
        return psycopg2.connect(
            host="db.internal.company.com",
            database="production",
            user="admin",
            password=DB_PASSWORD
        )
    '''
    
    encrypted = manager.encrypt_code(
        code=sensitive_code,
        context="database_credentials",
        metadata={"file_path": "src/db/connection.py", "author": "dev-team"}
    )
    
    print(f"✅ 加密成功!密钥ID: {encrypted['key_id']}")
    print(f"算法: {encrypted['algorithm']}")
    
    # 解密验证
    decrypted = manager.decrypt_code(encrypted)
    if decrypted:
        print(f"✅ 解密成功!代码长度: {len(decrypted)} 字符")
    
    # 查看密钥状态
    status = manager.get_key_status()
    print(f"\n📊 密钥状态: {json.dumps(status, indent=2)}")

2.2 传输层安全配置

# ===== Nginx 反向代理安全配置(推荐) =====

# 强制 HTTPS 重定向
server {
    listen 80;
    server_name monkeycode.yourcompany.com;
    return 301 https://$host$request_uri;
}

# HTTPS 配置
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name monkeycode.yourcompany.com;

    # === SSL/TLS 配置(符合现代安全标准)===
    ssl_certificate     /etc/letsencrypt/live/monkeycode/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/monkeycode/privkey.pem;

    # 使用安全的 TLS 版本(禁用 SSLv3、TLSv1.0、TLSv1.1)
    ssl_protocols TLSv1.2 TLSv1.3;

    # 使用安全的密码套件(仅允许 AEAD 密码)
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # HSTS(HTTP Strict Transport Security)
    # 告诉浏览器在 365 天内只使用 HTTPS 连接
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

    # OCSP Stapling(加速 TLS 握手)
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/letsencrypt/live/monkeycode/chain.pem;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;

    # === 安全响应头 ===
    # 防止 MIME 类型嗅探
    add_header X-Content-Type-Options "nosniff" always;
    # 防止点击劫持
    add_header X-Frame-Options "SAMEORIGIN" always;
    # XSS 保护
    add_header X-XSS-Protection "1; mode=block" always;
    # 引用策略限制
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    # CSP(Content Security Policy)
    add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; connect-src 'self' wss:;" always;
    # 权限策略
    add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;

    # === 请求体大小限制(防止 DoS)===
    client_max_body_size 10m;  # 限制上传大小

    # === 超时设置 ===
    proxy_connect_timeout 60s;
    proxy_send_timeout 600s;   # AI 补全可能需要较长时间
    proxy_read_timeout 600s;

    # === 请求速率限制(防止滥用)===
    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=30r/s;
    limit_req_zone $binary_remote_addr zone=auth_limit:10m rate=5r/m;

    location / {
        limit_req zone=api_limit burst=50 nodelay;
        
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        
        # WebSocket 支持(实时补全流式输出)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    # 登录接口更严格的限速
    location /api/auth/ {
        limit_req zone=auth_limit burst=3 nodelay;
        proxy_pass http://127.0.0.1:8080;
    }

    # 禁止访问敏感路径
    location ~ /\. {
        deny all;
        return 404;
    }

    # 访问日志(安全审计用)
    access_log /var/log/nginx/monkeycode_access.log combined;
    error_log  /var/log/nginx/monkeycode_error.log warn;
}

三、访问控制与身份认证

3.1 企业级 RBAC 实现

// ===== MonkeyCode RBAC 权限系统 =====

/**
 * 基于角色的访问控制(RBAC)系统
 * 
 * 支持细粒度的权限控制:
 * - 角色(Role):预定义的权限集合
 * - 权限(Permission):具体的操作许可
 * - 资源(Resource):受保护的实体
 * - 条件(Condition):动态权限判断(如 IP 白名单、时间段等)
 */

// 权限枚举
export enum Permission {
  // 代码相关
  CODE_READ = "code:read",
  CODE_WRITE = "code:write",
  CODE_DELETE = "code:delete",
  CODE_SHARE = "code:share",
  CODE_EXPORT = "code:export",

  // AI 功能
  AI_COMPLETION = "ai:completion",
  AI_CHAT = "ai:chat",
  AI_REFACTOR = "ai:refactor",
  AI_GENERATE_TEST = "ai:generate_test",
  AI_CODE_REVIEW = "ai:code_review",
  CUSTOM_MODEL_TRAIN = "ai:model_train",

  // 项目管理
  PROJECT_CREATE = "project:create",
  PROJECT_DELETE = "project:delete",
  PROJECT_CONFIG = "project:config",
  MEMBER_INVITE = "member:invite",
  MEMBER_REMOVE = "member:remove",

  // 系统管理
  USER_MANAGE = "system:user_manage",
  ROLE_MANAGE = "system:role_manage",
  AUDIT_LOG_VIEW = "system:audit_log",
  SYSTEM_CONFIG = "system:config",
  API_KEY_MANAGE = "system:api_key",
}

// 角色定义
export interface RoleDefinition {
  id: string;
  name: string;
  description: string;
  permissions: Permission[];
  isSystemRole: boolean;  // 系统内置角色不可删除
}

// 预定义角色
export const SYSTEM_ROLES: Record<string, RoleDefinition> = {
  super_admin: {
    id: "super_admin",
    name: "超级管理员",
    description: "拥有所有权限,可管理系统和用户",
    permissions: Object.values(Permission),
    isSystemRole: true,
  },

  admin: {
    id: "admin",
    name: "管理员",
    description: "项目管理员,可管理项目和成员",
    permissions: [
      Permission.CODE_READ,
      Permission.CODE_WRITE,
      Permission.CODE_SHARE,
      Permission.AI_COMPLETION,
      Permission.AI_CHAT,
      Permission.AI_REFACTOR,
      Permission.AI_GENERATE_TEST,
      Permission.AI_CODE_REVIEW,
      Permission.PROJECT_CREATE,
      Permission.PROJECT_CONFIG,
      Permission.MEMBER_INVITE,
      Permission.MEMBER_REMOVE,
      Permission.AUDIT_LOG_VIEW,
      Permission.API_KEY_MANAGE,
    ],
    isSystemRole: true,
  },

  developer: {
    id: "developer",
    name: "开发者",
    description: "普通开发者,可使用 AI 编程功能",
    permissions: [
      Permission.CODE_READ,
      Permission.CODE_WRITE,
      Permission.AI_COMPLETION,
      Permission.AI_CHAT,
      Permission.AI_GENERATE_TEST,
      Permission.AI_CODE_REVIEW,
    ],
    isSystemRole: true,
  },

  viewer: {
    id: "viewer",
    name: "只读用户",
    description: "只能查看代码和项目,不能编辑或使用 AI",
    permissions: [
      Permission.CODE_READ,
    ],
    isSystemRole: true,
  },

  auditor: {
    id: "auditor",
    name: "安全审计员",
    description: "可查看审计日志和系统配置",
    permissions: [
      Permission.CODE_READ,
      Permission.AUDIT_LOG_VIEW,
      Permission.SYSTEM_CONFIG,
    ],
    isSystemRole: true,
  },
};

// 权限检查服务
export class AuthorizationService {
  private roleAssignments: Map<string, string[]> = new Map();  // userId -> roleId[]
  private customPermissions: Map<string, Permission[]> = new Map();  // userId -> extra permissions

  /**
   * 检查用户是否拥有指定权限
   */
  async checkPermission(
    userId: string,
    permission: Permission,
    resourceContext?: ResourceContext
  ): Promise<AuthorizationResult> {
    const userRoles = this.roleAssignments.get(userId) || [];
    const allPermissions = new Set<Permission>();

    // 收集角色权限
    for (const roleId of userRoles) {
      const role = SYSTEM_ROLES[roleId];
      if (role) {
        role.permissions.forEach(p => allPermissions.add(p));
      }
    }

    // 收集自定义权限
    const extras = this.customPermissions.get(userId) || [];
    extras.forEach(p => allPermissions.add(p));

    // 基础权限检查
    const hasPermission = allPermissions.has(permission);

    // 条件检查(如果有额外的上下文条件)
    let conditionResult = true;
    if (hasPermission && resourceContext) {
      conditionResult = await this.evaluateConditions(
        userId, permission, resourceContext
      );
    }

    return {
      granted: hasPermission && conditionResult,
      userId,
      permission,
      checkedAt: new Date().toISOString(),
      reason: !hasPermission 
        ? `缺少权限: ${permission}` 
        : !conditionResult 
          ? "不满足附加条件" 
          : undefined,
    };
  }

  /**
   * 评估动态条件
   */
  private async evaluateConditions(
    userId: string,
    permission: Permission,
    ctx: ResourceContext
  ): Promise<boolean> {
    // IP 白名单检查
    if (ctx.allowedIps && ctx.allowedIps.length > 0) {
      const clientIp = ctx.clientIp || "";
      if (!ctx.allowedIps.some(allowed => 
        clientIp === allowed || clientIp.startsWith(allowed.replace('*', ''))
      )) {
        return false;
      }
    }

    // 时间段限制
    if (ctx.allowedTimeRange) {
      const now = new Date();
      const hour = now.getHours();
      if (hour < ctx.allowedTimeRange.start || hour >= ctx.allowedTimeRange.end) {
        return false;
      }
    }

    // 项目归属检查
    if (ctx.requiredProjectAccess && ctx.projectId) {
      const hasAccess = await this.checkProjectMembership(userId, ctx.projectId);
      if (!hasAccess) return false;
    }

    return true;
  }

  private async checkProjectMembership(userId: string, projectId: string): Promise<boolean> {
    // 实际实现中查询数据库
    return true;
  }

  /** 为用户分配角色 */
  assignRole(userId: string, roleId: string): void {
    const roles = this.roleAssignments.get(userId) || [];
    if (!roles.includes(roleId)) {
      roles.push(roleId);
      this.roleAssignments.set(userId, roles);
    }
  }

  /** 为用户添加额外权限 */
  grantCustomPermission(userId: string, permission: Permission): void {
    const perms = this.customPermissions.get(userId) || [];
    if (!perms.includes(permission)) {
      perms.push(permission);
      this.customPermissions.set(userId, perms);
    }
  }
}

// 类型定义
interface ResourceContext {
  clientIp?: string;
  allowedIps?: string[];
  allowedTimeRange?: { start: number; end: number };
  requiredProjectAccess?: boolean;
  projectId?: string;
}

interface AuthorizationResult {
  granted: boolean;
  userId: string;
  permission: Permission;
  checkedAt: string;
  reason?: string;
}

// ===== 中间件使用示例 =====
/*
// Express.js 中间件
const authMiddleware = async (req: Request, res: Response, next: NextFunction) => {
  const userId = req.user?.id;
  const requiredPermission = req.route.meta?.permission as Permission;
  
  if (!userId || !requiredPermission) {
    return res.status(403).json({ error: "未授权" });
  }
  
  const result = await authService.checkPermission(userId, requiredPermission, {
    clientIp: req.ip,
    allowedIps: config.ALLOWED_IPS,
  });
  
  if (!result.granted) {
    return res.status(403).json({ error: result.reason || "权限不足" });
  }
  
  next();
};
*/

四、审计日志与合规

4.1 完整的操作审计系统

-- ===== MonkeyCode 审计日志数据库 Schema =====

-- 审计事件表(不可变,仅追加写入)
CREATE TABLE audit_events (
    -- 主键(雪花算法生成的全局唯一 ID)
    event_id          BIGINT PRIMARY KEY,
    
    -- 事件基本信息
    event_type        VARCHAR(50) NOT NULL,       -- 事件类型
    event_category    VARCHAR(30) NOT NULL,       -- 分类:AUTH/CODE/AI/SYSTEM
    severity          VARCHAR(20) NOT NULL DEFAULT 'INFO',  -- 严重级别
    timestamp         TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
    
    -- 操作者信息
    actor_user_id     VARCHAR(64),                -- 操作用户 ID
    actor_role        VARCHAR(50),                -- 操作时的角色
    actor_ip          INET,                       -- 操作来源 IP
    actor_user_agent  TEXT,                       -- 客户端 User-Agent
    actor_session_id  VARCHAR(128),               -- 会话 ID
    
    -- 操作目标
    target_type       VARCHAR(50),                -- 目标类型:PROJECT/FILE/API_KEY/USER
    target_id         VARCHAR(128),               -- 目标 ID
    target_resource   TEXT,                       -- 目标资源路径
    
    -- 操作详情(JSON 格式,灵活存储)
    action            VARCHAR(100) NOT NULL,      -- 执行的动作
    request_method    VARCHAR(10),                -- HTTP 方法
    request_path      TEXT,                       -- 请求路径
    request_params    JSONB,                      -- 请求参数(敏感字段已脱敏)
    response_status   INTEGER,                    -- 响应状态码
    
    -- 变更详情
    changes_before    JSONB,                      -- 变更前快照
    changes_after     JSONB,                      -- 变更后快照
    
    -- 结果
    result            VARCHAR(20) NOT NULL,       -- SUCCESS/FAILURE/DENIED/PARTIAL
    error_message     TEXT,                       -- 错误信息
    duration_ms       INTEGER,                    -- 操作耗时(毫秒)
    
    -- 元数据
    source_service    VARCHAR(50) NOT NULL,       -- 来源服务
    correlation_id    VARCHAR(128),               -- 关联 ID(用于追踪调用链)
    metadata          JSONB,                      -- 其他扩展信息
    
    -- 安全哈希(用于完整性校验)
    integrity_hash    VARCHAR(64) NOT NULL        -- SHA-256 of the record
);

-- 索引优化查询性能
CREATE INDEX idx_audit_events_timestamp ON audit_events (timestamp DESC);
CREATE INDEX idx_audit_events_actor ON audit_events (actor_user_id, timestamp DESC);
CREATE INDEX idx_audit_events_target ON audit_events (target_type, target_id, timestamp DESC);
CREATE INDEX idx_audit_events_type ON audit_events (event_type, timestamp DESC);
CREATE INDEX idx_audit_events_result ON audit_events (result, timestamp DESC);
CREATE INDEX idx_audit_events_correlation ON audit_events (correlation_id);

-- 分区表(按月分区,方便归档和清理)
CREATE TABLE audit_events_y2026_m06 PARTITION OF audit_events
    FOR VALUES FROM ('2026-06-01') TO ('2026-07-01');

-- 审计日志保留策略:在线 2 年,之后归档到冷存储
-- 可通过 pg_partman 或类似工具自动化管理

-- 视图:安全事件汇总(供安全团队使用)
CREATE OR REPLACE VIEW security_dashboard AS
SELECT
    DATE(timestamp) AS event_date,
    event_category,
    COUNT(*) FILTER (WHERE result = 'SUCCESS') AS success_count,
    COUNT(*) FILTER (WHERE result = 'FAILURE') AS failure_count,
    COUNT(*) FILTER (WHERE result = 'DENIED') AS denied_count,
    COUNT(DISTINCT actor_user_id) AS unique_users,
    COUNT(DISTINCT actor_ip) AS unique_ips,
    AVG(duration_ms) AS avg_duration_ms
FROM audit_events
WHERE timestamp >= NOW() - INTERVAL '30 days'
GROUP BY DATE(timestamp), event_category
ORDER BY event_date DESC;

五、敏感信息防护

5.1 代码中的秘密检测与遮蔽

/**
 * MonkeyCode 敏感信息检测引擎
 * 
 * 在代码发送给 AI 模型之前,自动检测和遮蔽敏感信息,
 * 防止 API Key、密码、Token 等机密数据泄露。
 */

// 敏感信息模式库
const SENSITIVE_PATTERNS: Array<{
  name: string;
  pattern: RegExp;
  maskChar: string;
  severity: 'HIGH' | 'CRITICAL';
  description: string;
}> = [
  {
    name: 'AWS Access Key',
    pattern: /(?:A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}/g,
    maskChar: '*',
    severity: 'CRITICAL',
    description: 'AWS 访问密钥 ID'
  },
  {
    name: 'AWS Secret Key',
    pattern: /(?:"|')?(?:(?:"|')?\W{0,40})(?:secret[_\-]?key|aws[_\-]?secret)[\s"']{0,10}[:=]\s*["']?[A-Za-z0-9\/+=]{40}["']?/gi,
    maskChar: '*',
    severity: 'CRITICAL',
    description: 'AWS 秘密访问密钥'
  },
  {
    name: 'Generic API Key',
    pattern: /(?i)(api[_\-]?key|apikey)["'\s:=]+["']?[a-zA-Z0-9\-_]{20,}["']?/g,
    maskChar: '●',
    severity: 'HIGH',
    description: '通用 API 密钥'
  },
  {
    name: 'Private Key',
    pattern: /-----BEGIN (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----/g,
    maskChar: '█',
    severity: 'CRITICAL',
    description: '私钥文件内容'
  },
  {
    name: 'Password in Code',
    pattern: /(?i)(password|passwd|pwd)\s*[:=]\s*["'][^"']+["']/g,
    maskChar: '•',
    severity: 'HIGH',
    description: '硬编码密码'
  },
  {
    name: 'Connection String',
    pattern: /(?i)(mongodb|mysql|postgres|redis|mssql|oracle):\/\/[^:]+:[^@]+@/g,
    maskChar: '▓',
    severity: 'CRITICAL',
    description: '数据库连接字符串(含凭证)'
  },
  {
    name: 'JWT Token',
    pattern: /eyJ[A-Za-z0-9_-]*\.eyJ[A-Za-z0-9_-]*\.[A-Za-z0-9_-]*/g,
    maskChar: '▪',
    severity: 'HIGH',
    description: 'JSON Web Token'
  },
  {
    name: 'GitHub Personal Token',
    pattern: /ghp_[a-zA-Z0-9]{36}/g,
    maskChar: '✱',
    severity: 'CRITICAL',
    description: 'GitHub 个人访问令牌'
  },
  {
    name: 'Slack Token',
    pattern: /xox[baprs]-[a-zA-Z0-9-]+/g,
    maskChar: '✱',
    severity: 'HIGH',
    description: 'Slack OAuth Token'
  },
];

// 检测结果类型
interface SecretDetectionResult {
  originalText: string;
  sanitizedText: string;
  detections: Array<{
    type: string;
    severity: 'HIGH' | 'CRITICAL';
    startOffset: number;
    endOffset: length;
    maskedValue: string;
    patternName: string;
  }>;
  hasCriticalSecrets: boolean;
  secretCount: number;
}

/**
 * 检测并遮蔽代码中的敏感信息
 */
function detectAndMaskSecrets(code: string): SecretDetectionResult {
  const detections: SecretDetectionResult['detections'] = [];
  let sanitizedCode = code;
  let offsetAdjustment = 0;

  for (const rule of SENSITIVE_PATTERNS) {
    let match: RegExpExecArray | null;
    const regex = new RegExp(rule.pattern.source, rule.pattern.flags);
    
    while ((match = regex.exec(code)) !== null) {
      const originalValue = match[0];
      const maskedValue = rule.maskChar.repeat(originalValue.length);
      
      detections.push({
        type: rule.severity,
        severity: rule.severity,
        startOffset: match.index + offsetAdjustment,
        endOffset: match.index + originalValue.length + offsetAdjustment,
        maskedValue,
        patternName: rule.name,
      });

      // 替换为遮蔽后的值
      sanitizedCode = sanitizedCode.replace(originalValue, maskedValue);
    }
  }

  // 按位置排序
  detections.sort((a, b) => a.startOffset - b.startOffset);

  return {
    originalText: code,
    sanitizedText: sanitizedCode,
    detections,
    hasCriticalSecrets: detections.some(d => d.severity === 'CRITICAL'),
    secretCount: detections.length,
  };
}

// ===== 使用示例 =====
/*
const codeWithSecrets = `
const AWS_ACCESS_KEY = "AKIAIOSFODNN7EXAMPLE";
const dbPassword = "SuperSecret123!";
const connStr = "postgres://admin:password123@db.prod.internal:5432/app";
`;

const result = detectAndMaskSecrets(codeWithSecrets);

console.log(`🚨 发现 ${result.secretCount} 处敏感信息`);
console.log(`⚠️ 包含关键密钥: ${result.hasCriticalSecrets}`);

for (const det of result.detections) {
  console.log(`  [${det.severity}] ${det.patternName}: ${det.maskedValue}`);
}
// 输出:
// 🚨 发现 3 处敏感信息
// ⚠️ 包含关键密钥: true
//   [CRITICAL] AWS Access Key: **************************
//   [HIGH] Password in Code: •••••••••••••••
//   [CRITICAL] Connection String: postgres://admin:▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓@db.prod.internal:5432/app
*/

六、企业部署安全清单

6.1 部署前安全检查项

类别 检查项 重要性 MonkeyCode 支持
网络 启用 HTTPS/TLS 1.3 🔴 必须 ✅ 内置
网络 网络隔离(VPC/子网) 🔴 必须 ✅ 文档指导
身份 SSO / LDAP / OIDC 集成 🔴 必须 ✅ 原生支持
身份 MFA 多因素认证 🟡 推荐 ✅ 可配置
数据 传输加密(TLS) 🔴 必须 ✅ 默认启用
数据 静态加密(AES-256) 🔴 必须 ✅ 默认启用
数据 密钥管理(KMS/HSM) 🟡 推荐 ✅ 可集成
访问 RBAC 权限控制 🔴 必须 ✅ 内置
访问 IP 白名单 🟡 推荐 ✅ 可配置
审计 操作日志记录 🔴 必须 ✅ 完整记录
审计 日志不可篡改 🟡 推荐 ✅ 哈希校验
合规 GDPR 合规 🟡 推荐 ✅ 支持
合规 等保三级 🟡 推荐 ✅ 文档指导
AI 安全 Prompt 注入防护 🔴 必须 ✅ 内置
AI 安全 输出内容过滤 🔴 必须 ✅ 可配置
供应链 依赖漏洞扫描 🟡 推荐 ✅ CI 集成

6.2 安全配置快速启动

# ===== MonkeyCode 企业安全部署一键脚本 =====

#!/bin/bash
set -euo pipefail

echo "🔐 MonkeyCode 企业安全部署工具"
echo "================================"

# 1. 生成强随机密钥
echo ""
echo "[1/6] 生成加密密钥..."
ENCRYPTION_KEY=$(openssl rand -base64 32)
JWT_SECRET=$(openssl rand -base64 32)
ADMIN_PASSWORD=$(openssl rand -base64 16)

echo "✅ 密钥已生成(请妥善保管!)"

# 2. 创建安全配置文件
echo ""
echo "[2/6] 创建安全配置..."
cat > .env.security << EOF
# ===== MonkeyCode 安全配置 =====
# 生成时间: $(date -u +"%Y-%m-%dT%H:%M:%SZ")

# 加密配置
ENCRYPTION_KEY=${ENCRYPTION_KEY}
ENCRYPTION_ALGORITHM=AES-256-GCM

# JWT 配置
JWT_SECRET=${JWT_SECRET}
JWT_EXPIRY_HOURS=8
JWT_REFRESH_DAYS=30

# 管理员初始密码(首次登录后请立即修改!)
ADMIN_INITIAL_PASSWORD=${ADMIN_PASSWORD}

# 会话安全
SESSION_MAX_AGE=3600000
COOKIE_SECURE=true
COOKIE_SAME_SITE=strict

# 速率限制
RATE_LIMIT_WINDOW_MS=60000
RATE_LIMIT_MAX_REQUESTS=100
RATE_LIMIT_AUTH_MAX=5

# 安全头
ENABLE_HSTS=true
ENABLE_CSP=true
ENABLE_XSS_PROTECTION=true

# 审计配置
AUDIT_LOG_ENABLED=true
AUDIT_LOG_RETENTION_DAYS=730
AUDIT_LOG_EXPORT_ENABLED=true
EOF

chmod 600 .env.security
echo "✅ 安全配置已创建(权限: 600)"

# 3. 生成自签名证书(生产环境请替换为正式证书!)
echo ""
echo "[3/6] 生成 TLS 证书(开发/测试用)..."
mkdir -p certs
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout certs/key.pem \
  -out certs/cert.pem \
  -subj "/CN=localhost/O=MonkeyCode-Dev/C=CN"
echo "✅ 证书已生成(⚠️ 生产环境请使用 Let's Encrypt 或企业 CA!)"

# 4. 设置防火墙规则
echo ""
echo "[4/6] 配置防火墙建议..."
cat << 'FIREWALL_HINT'
╔═══════════════════════════════════════════════════════════╗
║  防火墙配置建议(请根据实际环境调整):                        ║
╠═══════════════════════════════════════════════════════════╣
║                                                           ║
║  # 仅开放必要端口                                         ║
║  iptables -P INPUT DROP                                   ║
║  iptables -P FORWARD DROP                                 ║
║  iptables -P OUTPUT ACCEPT                                ║
║                                                           ║
║  # SSH(限制来源 IP)                                      ║
║  iptables -A INPUT -p tcp -s YOUR_OFFICE_IP --dport 22 -j ACCEPT  ║
║                                                           ║
║  # HTTPS                                                   ║
║  iptables -A INPUT -p tcp --dport 443 -j ACCEPT           ║
║                                                           ║
║  # HTTP → HTTPS 重定向                                    ║
║  iptables -A INPUT -p tcp --dport 80 -j ACCEPT            ║
║                                                           ║
║  # 已建立连接                                              ║
║  iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT ║
║                                                           ║
║  # 本地回环                                                ║
║  iptables -A INPUT -i lo -j ACCEPT                        ║
║                                                           ║
╚═══════════════════════════════════════════════════════════╝
FIREWALL_HINT
echo "✅ 请手动执行上述防火墙规则"

# 5. 输出安全摘要
echo ""
echo "[5/6] 安全部署摘要..."
echo "
╔═══════════════════════════════════════════════════════════╗
║              🛡️ 安全部署完成摘要                           ║
╠═══════════════════════════════════════════════════════════╣
║                                                           ║
║  ✅ 加密密钥: 已生成(32字节 Base64)                      ║
║  ✅ JWT 密钥: 已生成(32字节 Base64)                      ║
║  ✅ TLS 证书: 已生成(开发测试用)                          ║
║  ✅ 安全配置: .env.security(权限 600)                     ║
║                                                           ║
║  ⚠️  待办事项:                                            ║
║  1. 将 .env.security 加入 .gitignore                       ║
║  2. 替换为正式 TLS 证书                                     ║
║  3. 配置防火墙规则                                        ║
║  4. 设置日志轮转                                          ║
║  5. 配置备份策略                                          ║
║  6. 首次登录后修改默认密码                                  ║
║                                                           ║
║  📋 下一步命令:                                           ║
║  docker-compose up -d                                     ║
║                                                           ║
╚═══════════════════════════════════════════════════════════╝
"

# 6. 清理敏感变量
echo ""
echo "[6/6] 清理内存中的敏感变量..."
unset ENCRYPTION_KEY JWT_SECRET ADMIN_PASSWORD
echo "✅ 清理完成"

echo ""
echo "🎉 安全部署准备就绪!运行 docker-compose up -d 启动服务"

七、总结

安全维度 MonkeyCode 方案 开源优势
数据加密 AES-256-GCM 全链路加密 ✅ 代码公开审计,无后门
访问控制 RBAC + ABAC + 条件策略 ✅ 可自行扩展权限模型
审计日志 不可变日志 + 完整追踪 ✅ 可对接自有 SIEM 系统
敏感信息 自动检测 + 遮蔽 + 告警 ✅ 可添加自定义检测规则
网络安全 TLS 1.3 + HSTS + CSP ✅ 自有证书,自主可控
合规认证 GDPR / SOC2 / 等保 ✅ 私有化部署满足本地合规
供应链安全 SBOM + 依赖签名 ✅ 全量依赖可审查

"安全不是功能,而是基础。MonkeyCode 让每一行代码都在安全的环境中诞生。"

立即开始你的安全 AI 编程之旅!

👉 GitHub: https://github.com/monkeycode-ai/monkeycode

👉 安全问题反馈: https://github.com/monkeycode-ai/monkeycode/issues

👉 安全团队邮箱: security@monkeycode.ai(报告漏洞)


本文由 MonkeyCode 社区原创,采用 Apache 2.0 许可证发布。

关键词: MonkeyCode 安全 隐私保护 数据加密 RBAC 审计日志 企业安全 合规

posted on 2026-06-25 13:08  MonkeyCode  阅读(31)  评论(0)    收藏  举报