feat: Phase 4 - SQL AST analyzer, audit rules CRUD, Alembic, Docker (128 tests)
This commit is contained in:
1 parent
e45fbf3586
commit
ff0a330e8a
23 files changed
+1404
-159
No files matched your search
@@ -5,13 +5,14 @@ from typing import Optional
|
||||
|
||||
from app.models.instance import Instance
|
||||
from app.schemas.query import QueryResult
|
||||
from app.services.sql_analyzer import SQLAnalyzer
|
||||
|
||||
|
||||
FORBIDDEN_KEYWORDS = ["DROP", "TRUNCATE", "DELETE", "UPDATE", "INSERT", "CREATE", "ALTER", "GRANT", "REVOKE"]
|
||||
MAX_ROWS = 10000
|
||||
|
||||
|
||||
class QueryService:
|
||||
_analyzer = SQLAnalyzer()
|
||||
|
||||
@staticmethod
|
||||
async def execute_query(
|
||||
instance: Instance, database: Optional[str], sql: str, user_id: int
|
||||
@@ -19,11 +20,13 @@ class QueryService:
|
||||
if instance.db_type != "mysql":
|
||||
raise ValueError(f"暂不支持 {instance.db_type} 查询")
|
||||
|
||||
upper_sql = sql.strip().upper()
|
||||
for kw in FORBIDDEN_KEYWORDS:
|
||||
if upper_sql.startswith(kw) or f" {kw} " in upper_sql:
|
||||
raise ValueError(f"查询模式禁止执行 {kw} 操作")
|
||||
# AST-based SQL validation (replaces keyword matching)
|
||||
is_safe, error_msg = QueryService._analyzer.validate_readonly(sql)
|
||||
if not is_safe:
|
||||
raise ValueError(error_msg)
|
||||
|
||||
# Auto-add LIMIT if missing
|
||||
upper_sql = sql.strip().upper()
|
||||
if not re.search(r"LIMIT\s+\d+", upper_sql, re.IGNORECASE):
|
||||
sql = sql.rstrip(";") + f" LIMIT {MAX_ROWS};"
|
||||
|
||||
|
||||
Reference in new issue
Block a user