Skip to content

Commit

Permalink
fix hhyo#20
Browse files Browse the repository at this point in the history
  • Loading branch information
hhyo authored and kjiLupin committed Apr 28, 2019
1 parent fedba6c commit 57f2c7b
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 28 deletions.
13 changes: 7 additions & 6 deletions sql/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import traceback

import simplejson as json
import sqlparse
from django.contrib.auth.decorators import permission_required
from django.core import serializers
from django.db import connection
Expand Down Expand Up @@ -67,10 +68,10 @@ def query_priv_check(user, instance_name, db_name, sql_content, limit_num):

# 检查用户是否有该数据库/表的查询权限
if user.is_superuser:
if SysConfig().sys_config.get('admin_query_limit'):
if SysConfig().sys_config.get('admin_query_limit', 5000):
user_limit_num = int(SysConfig().sys_config.get('admin_query_limit'))
else:
user_limit_num = 0
user_limit_num = 5000
limit_num = int(user_limit_num) if int(limit_num) == 0 else min(int(limit_num), int(user_limit_num))

# 查看表结构和执行计划,inception会报错,故单独处理,explain直接跳过不做校验
Expand Down Expand Up @@ -484,8 +485,8 @@ def query(request):
result['msg'] = '仅支持^select|^show|^explain语法,请联系管理员!'
return HttpResponse(json.dumps(result), content_type='application/json')

# 按照分号截取第一条有效sql执行
sql_content = sql_content.strip().split(';')[0]
# 执行第一条有效sql
sql_content = sqlparse.split(sql_content)[0].rstrip(';')

try:
# 查询权限校验
Expand Down Expand Up @@ -641,8 +642,8 @@ def explain(request):
result['msg'] = '仅支持explain开头的语句,请检查'
return HttpResponse(json.dumps(result), content_type='application/json')

# 按照分号截取第一条有效sql执行
sql_content = sql_content.strip().split(';')[0]
# 执行第一条有效sql
sql_content = sqlparse.split(sql_content)[0].rstrip(';')

# 执行获取执行计划语句
sql_result = Dao(instance_name=instance_name).mysql_query(str(db_name), sql_content)
Expand Down
7 changes: 5 additions & 2 deletions sql/sql_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from threading import Thread

import simplejson as json
import sqlparse
from django.contrib.auth.decorators import permission_required
from django.core.exceptions import PermissionDenied
from django.db import transaction, connection
Expand Down Expand Up @@ -263,8 +264,10 @@ def autoreview(request):

# 判断SQL是否包含DDL语句,SQL语法 1、DDL,2、DML
sql_syntax = 2
for row in sql_content.strip(';').split(';'):
if re.match(r"^alter|^create|^drop|^truncate|^rename", row.strip().lower()):
for stmt in sqlparse.split(sql_content):
statement = sqlparse.parse(stmt)[0]
syntax_type = statement.token_first().ttype.__str__()
if syntax_type == 'Token.Keyword.DDL':
sql_syntax = 1
break

Expand Down
6 changes: 3 additions & 3 deletions sql/utils/dao.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import MySQLdb
import traceback
import sqlparse

from common.utils.aes_decryptor import Prpcrypt
from sql.models import Instance
Expand Down Expand Up @@ -135,14 +136,13 @@ def mysql_execute(self, db_name, sql):
conn = MySQLdb.connect(host=self.host, port=self.port, user=self.user, passwd=self.password, db=db_name,
charset='utf8')
cursor = conn.cursor()
for row in sql.strip(';').split(';'):
cursor.execute(row)
for statement in sqlparse.split(sql):
cursor.execute(statement)
conn.commit()
except Exception as e:
logger.error(traceback.format_exc())
result['Error'] = str(e)
else:

cursor.close()
conn.close()
return result
14 changes: 7 additions & 7 deletions sql/utils/execute_sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import time
from threading import Thread

import sqlparse
from django.db import connection
from django.utils import timezone

Expand Down Expand Up @@ -197,26 +197,26 @@ def send_msg(workflow_detail, url):

# 匹配DDL语句CREATE、ALTER(排除索引变更)、DROP、TRUNCATE、RENAME
send = 0
for row in sql_content.strip(';').split(';'):
for statement in sqlparse.split(sql_content):
# alter语法
if re.match(r"^alter\s+table\s+\S+\s+(add|alter|change|drop|rename|modify)\s+(?!.*(index|key|unique))",
row.strip().lower()):
statement.strip().lower()):
send = 1
break
# create语法
elif re.match(r"^create\s+(temporary\s+)?(database|schema|table)", row.strip().lower()):
elif re.match(r"^create\s+(temporary\s+)?(database|schema|table)", statement.strip().lower()):
send = 1
break
# drop语法
elif re.match(r"^drop", row.strip().lower()):
elif re.match(r"^drop|^rename|^truncate", statement.strip().lower()):
send = 1
break
# rename语法
elif re.match(r"^rename", row.strip().lower()):
elif re.match(r"", statement.strip().lower()):
send = 1
break
# truncate语法
elif re.match(r"^truncate", row.strip().lower()):
elif re.match(r"", statement.strip().lower()):
send = 1
break

Expand Down
22 changes: 14 additions & 8 deletions sql/utils/inception.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import simplejson as json
import MySQLdb
import traceback
import sqlparse
from django.db import connection

from sql.models import Instance, SqlWorkflow
Expand Down Expand Up @@ -51,15 +52,15 @@ def critical_ddl(self, sql_content):
map(lambda x: re.compile(r'(^--\s+.*|^/\*.*\*/;\s*$)').sub('', x, count=1),
sql_content.splitlines(1))).strip()

for row in sql_content.rstrip(';').split(';'):
if p.match(row.strip().lower()):
for statement in sqlparse.split(sql_content):
if p.match(statement.strip().lower()):
result = (
'', '', 2, '驳回高危SQL', '禁止提交匹配' + critical_ddl_regex + '条件的语句!',
row,
statement,
'', '', '', '')
critical_sql_found = 1
else:
result = ('', '', 0, '', 'None', row, '', '', '', '')
result = ('', '', 0, '', 'None', statement, '', '', '', '')
result_list.append(result)
if critical_sql_found == 1:
return result_list
Expand All @@ -70,15 +71,20 @@ def pre_check(self, sql_content):
"""
在提交给inception之前,预先识别一些Inception不能正确审核的SQL,比如"alter table t1;"或"alter table test.t1;" 以免导致inception core dump
"""
# 删除注释语句
sql_content = ''.join(
map(lambda x: re.compile(r'(^--\s+.*|^/\*.*\*/;\s*$)').sub('', x, count=1),
sql_content.splitlines(1))).strip()
result_list = []
syntax_error_sql_found = 0
for row in sql_content.rstrip(';').split(';'):
for statement in sqlparse.split(sql_content):
# 注释不检测
if re.match(r"(\s*)alter(\s+)table(\s+)(\S+)(\s*);|(\s*)alter(\s+)table(\s+)(\S+)\.(\S+)(\s*);",
row.lower() + ";"):
result = ('', '', 2, 'SQL语法错误', 'ALTER TABLE 必须带有选项', row, '', '', '', '')
statement.lower() + ";"):
result = ('', '', 2, 'SQL语法错误', 'ALTER TABLE 必须带有选项', statement, '', '', '', '')
syntax_error_sql_found = 1
else:
result = ('', '', 0, '', 'None', row, '', '', '', '')
result = ('', '', 0, '', 'None', statement, '', '', '', '')
result_list.append(result)
if syntax_error_sql_found == 1:
return result_list
Expand Down
5 changes: 3 additions & 2 deletions sql/utils/sql_review.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import re
import sqlparse

from common.utils.const import Const
from sql.models import SqlWorkflow
Expand Down Expand Up @@ -36,8 +37,8 @@ def is_auto_review(workflow_id):

# 判断是否匹配到需要手动审核的语句
is_autoreview = True
for row in sql_content.strip(';').split(';'):
if p.match(row.strip().lower()):
for statement in sqlparse.split(sql_content):
if p.match(statement.strip().lower()):
is_autoreview = False
break
if is_autoreview:
Expand Down

0 comments on commit 57f2c7b

Please sign in to comment.