Soar项目中添加一条新的SQL审核规则示例

news2024/11/17 17:31:07

    soar是一个开源的SQL规则审核工具,是一个go语言项目,可以直接编译构建成一个可执行程序,而且是一个命令行工具,我们可以利用archey来调用soar进行sql规则审核以及sql的分析,包括执行计划的查看及sql建议等。

soar中已经有很多规则了,现在来添加一条soar中没有的新的sql审核规则,例如一条新的审核规则:多表关联必须有关联条件,禁止出现笛卡尔积

我的思路是校验联表查询不允许没有on和useing关键词,同时不允许混用逗号和 ANSI 模式

首先在advisor包下的rule.go文件中添加规则说明

	//多表关联必须有关联条件,禁止出现笛卡尔积
		"JOI.009": {
			Item:     "JOI.009",
			Severity: "L4",
			Summary:  "多表关联必须有关联条件,禁止出现笛卡尔积",
			Content:  `多表关联必须有关联条件,禁止出现笛卡尔积`,
			Case:     "SELECT s,p,d FROM tb1,tb2 ",
			Func:     (*Query4Audit).RuleJoinQueryNoCondition,
		},

同时会利用到本来用的联表的规则1

	"JOI.001": {
			Item:     "JOI.001",
			Severity: "L2",
			Summary:  "JOIN 语句混用逗号和 ANSI 模式",
			Content:  `表连接的时候混用逗号和 ANSI JOIN 不便于人类理解,并且MySQL不同版本的表连接行为和优先级均有所不同,当 MySQL 版本变化后可能会引入错误。`,
			Case:     "select c1,c2,c3 from t1,t2 join t3 on t1.c1=t2.c1,t1.c3=t3,c1 where id>1000",
			Func:     (*Query4Audit).RuleCommaAnsiJoin,
		},

 

 然后来添加新的约束规则方法:

在advisor包下的heuristic.go文件中加上新的方法:

//判断联表查询中是否有关联条件 on 或者using 对应需求表中规则编号70
func (q *Query4Audit) RuleJoinQueryNoCondition() Rule {
	var rule = q.RuleOK()
	var tables []string

	switch q.Stmt.(type) {
	case *sqlparser.Union:
		return rule
	default:
		err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) {
			switch n := node.(type) {
			case *sqlparser.AliasedTableExpr:
				switch table := n.Expr.(type) {
				case sqlparser.TableName:
					for _, t := range tables {
						if t == table.Name.String() {
							rule = HeuristicRules["JOI.002"]
							return false, nil
						}
					}
					tables = append(tables, table.Name.String())

				}
			case *sqlparser.JoinTableExpr: // 处理 JOIN 表达式
				if n.Condition.On == nil || len(n.Condition.Using) == 0 { // 检查是否有 ON 或 USING 条件
					rule = HeuristicRules["JOI.009"] // 更新规则
					return false, nil
				}

			}

			return true, nil
		}, q.Stmt)
		common.LogIfError(err, "")
	}
	return rule
}

今天还加了几个其他的规则判断如下:rule.go文件中

			//为每个字段应添加注释,对应需求表中的开发规则编号15
		"CLA.011": {
			Item:     "CLA.011",
			Severity: "L1",
			Summary:  "表中的每个字段都应该添加注释",
			Content:  `为表添加注释能够使得表的意义更明确,从而为日后的维护带来极大的便利。`,
			Case:     "CREATE TABLE `test1` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`c1` varchar(128) DEFAULT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8",
			Func:     (*Query4Audit).RuleTblCommentCheck,
		},

//禁止查询时 select * 对应开发需求中的规则编号49
		"COL.001": {
			Item:     "COL.001",
			Severity: "L1",
			Summary:  "SELECT语句必须指定具体字段名称,禁止写成 select*",
			Content:  `当表结构变更时,使用 * 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。`,
			Case:     "select * from tbl where id=1",
			Func:     (*Query4Audit).RuleForbiddenSelectStar,
		},	


//建表语句以及alter语句修改表结构时候自增列字段使用bigint,.禁止使用int类型 对应需求表中的规则编号19
		"COL.020": {

			Item:     "COL.020",
			Severity: "L2",
			Summary:  "自增列字段使用bigint,.禁止使用int类型,防止存储溢出",
			Content:  `自增列字段使用bigint,.禁止使用int类型,防止存储溢出`,
			Case:     "create table test(`id` int(11) NOT NULL AUTO_INCREMENT)",
			Func:     (*Query4Audit).RuleAutoIncShouldBigint,
		},

//建表语句以及修改表结构时中禁止使用float、double类型,小数类型使用decimal类型 对应需求表中的规则编号8
		"COL.021": {
			Item:     "COL.021",
			Severity: "L2",
			Summary:  "建表语句以及修改表结构时中禁止使用float、double类型,小数类型使用decimal类型 ",
			Content:  `建表语句以及修改表结构时中禁止使用float、double类型,小数类型使用decimal类型`,
			Case:     "create table test(`id` int(11) NOT NULL AUTO_INCREMENT)",
			Func:     (*Query4Audit).RuleFloatDoubleCheck,
		},



对应的方法:heuristic.go文件中:

// RuleTblCommentCheck CLA.011 检查表中每个字段是否都添加注释,对应需求表中的开发规则编号15
func (q *Query4Audit) RuleTblCommentCheck() Rule {
	var rule = q.RuleOK()
	switch node := q.Stmt.(type) {
	case *sqlparser.DDL:
		if strings.ToLower(node.Action) != "create" {
			return rule
		}
		if node.TableSpec == nil {
			return rule
		}
		if options := node.TableSpec.Options; options == "" {
			rule = HeuristicRules["CLA.011"]
		} else {
			//正则表达式匹配comment,不区分大小写
			reg := regexp.MustCompile("(?i)comment")
			if !reg.MatchString(options) {
				rule = HeuristicRules["CLA.011"]
			}
		}
	}
	return rule
}

// RuleForbiddenSelectStar COL.001 禁止使用select *  对应需求表中的开发规则编号49
func (q *Query4Audit) RuleForbiddenSelectStar() Rule {
	var rule = q.RuleOK()
	// 先把count(*)替换为count(1)
	re := regexp.MustCompile(`(?i)count\s*\(\s*\*\s*\)`)
	sql := re.ReplaceAllString(q.Query, "count(1)")
	stmt, err := sqlparser.Parse(sql)
	if err != nil {
		common.Log.Debug("RuleSelectStar sqlparser.Parse Error: %v", err)
		return rule
	}
	err = sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) {
		switch node.(type) {
		case *sqlparser.StarExpr:
			rule = HeuristicRules["COL.001"]
			return false, nil
		}
		return true, nil
	}, stmt)
	common.LogIfError(err, "")
	return rule
}

// 建表以及修改表字段时候自增列字段使用bigint,.禁止使用int类型 对应需求表中的规则编号19
func (q *Query4Audit) RuleAutoIncShouldBigint() Rule {
	var rule = q.RuleOK()
	switch q.Stmt.(type) {
	case *sqlparser.DDL:
		for _, tiStmt := range q.TiStmt {
			switch node := tiStmt.(type) {
			case *tidb.CreateTableStmt:
				for _, col := range node.Cols {
					if col.Tp == nil {
						continue
					}
					for _, opt := range col.Options {
						if opt.Tp == tidb.ColumnOptionAutoIncrement {
							if col.Tp.Tp != mysql.TypeLong { // 检查是否为 bigint 类型
								rule = HeuristicRules["COL.020"]
								break
							}
						}
						if rule.Item == "COL.020" {
							break
						}
					}
				}
			case *tidb.AlterTableStmt:
				for _, spec := range node.Specs {
					switch spec.Tp {
					case tidb.AlterTableChangeColumn, tidb.AlterTableAlterColumn,
						tidb.AlterTableModifyColumn, tidb.AlterTableAddColumns:
						for _, col := range spec.NewColumns {
							if col.Tp == nil {
								continue
							}
							for _, opt := range col.Options {
								if opt.Tp == tidb.ColumnOptionAutoIncrement {
									if col.Tp.Tp != mysql.TypeLong { // 检查是否为 bigint 类型
										rule = HeuristicRules["COL.020"]
										break
									}
								}
								if rule.Item == "COL.020" {
									break
								}
							}
						}
					}
				}
			}
		}
	}
	return rule
}

//建表语句以及修改表结构时中禁止使用float、double类型,小数类型使用decimal类型 对应需求表中的规则编号8
func (q *Query4Audit) RuleFloatDoubleCheck() Rule {
	var rule = q.RuleOK()
	switch q.Stmt.(type) {
	case *sqlparser.DDL:
		for _, tiStmt := range q.TiStmt {
			switch node := tiStmt.(type) {
			case *tidb.CreateTableStmt:
				for _, col := range node.Cols {
					if col.Tp == nil {
						continue
					}
					if col.Tp.Tp == mysql.TypeFloat || col.Tp.Tp == mysql.TypeDouble {
						rule = HeuristicRules["COL.021"]
						break
					}
				}
			case *tidb.AlterTableStmt:
				// 对 ALTER TABLE 语句的类似检查
				for _, spec := range node.Specs {
					switch spec.Tp {
					case tidb.AlterTableChangeColumn, tidb.AlterTableAlterColumn,
						tidb.AlterTableModifyColumn, tidb.AlterTableAddColumns:
						for _, col := range spec.NewColumns {
							if col.Tp == nil {
								continue
							}
							if col.Tp.Tp == mysql.TypeFloat || col.Tp.Tp == mysql.TypeDouble {
								rule = HeuristicRules["COL.021"]
								break
							}
						}
					}
				}
			}
		}
	}
	return rule
}

通过代码可以看出一些规则实际上是调用了tidb的审核分析工具包进行处理的。sql语句的解析拆分各个部分当然还是用的sqlparser,sqlparser又在vitess模块依赖包下

 

拆分sql语句靠sqlparser,分析sql则依赖tidb(pingcap公司产品)的相关模块工具依赖包

比如判断mysql的字段的各种数据类型 ,再比如判断sql语句属于类名类型

而且tidb主要用于分析mysql语句 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2175709.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

django开发流程3(轮播图)

1.在models中创建一个模板 class Ads(models.Model):title models.CharField(verbose_name"标题", max_length30)image models.ImageField(verbose_name"广告图", upload_to"ads")url models.URLField(verbose_name"链接网址", de…

Stable Diffusion绘画 | Checkpoint Merger 模型融合

在我们的模型库中,经常会发现下载的模型,生成的图片颜色发灰,暗沉: 主要原因就是,我们下载的模型,作者训练时并没有加入VAE色调文件。 为了解决这个问题,我们可以使用 SD 自带额模型融合页面&am…

召回08 双塔模型——线上服务、模型更新

线上召回 离线存储: 模型训练好之后,部署到线上做召回,快速找到用户感兴趣的物品。 对训练好的两个塔,线上服务前,先用右边的物品塔提取物品的特征做离线存储,记作特征向量b,把(b…

redux的基础知识

1. 概念 是集中状态管理工具 2. 使用步骤 3. 总结 参考:黑马程序员react教程

Linux Reverse(1)-LD_PRELOAD

LD_PRELOAD 是 Linux 系统中的一个环境变量,它允许用户在程序运行时动态地加载共享库。通过设置该环境变量,用户可以指定一个或多个共享库,这些库中的函数将在其他库或程序调用相同函数时优先使用。这在调试、注入、替换函数实现或修改程序行…

大数据Hologres(二):Hologres 快速入门

文章目录 Hologres 快速入门 一、资源领取 二、入门体验 1、创建数据库 2、创建表 3、导入示例数据 4、查询表中数据 Hologres 快速入门 一、资源领取 领取链接: 阿里云免费试用 - 阿里云 (aliyun.com) 二、入门体验 1、创建数据库 进入Hologres管理控制…

递归,搜索与回溯40道算法题

目录 一递归 1汉诺塔问题 2合并两个有序链表 3反转链表 4两两交换链表的节点 5Pow(x,n) 二二叉树的深搜 1计算布尔二叉树的值 2求根节点到叶节点数字之和 3二叉树剪枝 4验证二叉搜索树 5二叉搜索树中第K小的元素 6二叉树的所有路径 三穷举vs暴搜vs深搜vs回溯vs…

AI 大模型浪潮下,大龄程序员怎样转型求变,攀登技术高峰?

前言 在信息技术迅猛发展的今天,程序员作为技术的创造者和实践者,正面临前所未有的挑战。技术的迭代速度日益加快,传统项目的生命周期不断缩短。同时,人工智能(AI)尤其是大模型技术的兴起,使得…

如何使用ssm实现基于web的学生就业管理系统的设计与实现+vue

TOC ssm726基于web的学生就业管理系统的设计与实现vue 第1章 绪论 1.1 课题背景 二十一世纪互联网的出现,改变了几千年以来人们的生活,不仅仅是生活物资的丰富,还有精神层次的丰富。在互联网诞生之前,地域位置往往是人们思想上…

算法题题解:两个链表的交点

在这篇博客中,请允许我分享一下力扣上的算法题目:“两个链表的交点”,记录一下上面的一个有效的解法。该问题的目标是找到两个单链表的交点节点,若无交点则返回NULL。 题目描述 给你两个单链表的头节点 headA 和 headB &#xf…

【蚂蚁HR-注册/登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 暴力破解密码,造成用户信息泄露短信盗刷的安全问题,影响业务及导致用户投诉带来经济损失,尤其是后付费客户,风险巨大,造成亏损无底洞…

每日一练:从前序遍历与中序遍历序列构造二叉树

105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode) 题目要求: 给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节…

在 Delphi BSD11中安装 DCU 格式的第三方组件库

在 Delphi BSD 11 中安装 DCU 格式的第三方组件库可以按照以下步骤进行: 打开 Delphi:启动 Delphi 开发环境。 选择安装组件: 在菜单栏中,选择 Component -> Install Component。 选择 DCU 文件: 在弹出的对话框中…

【重学 MySQL】四十一、子查询举例与分类

【重学 MySQL】四十一、子查询举例与分类 引入子查询在SELECT子句中引入子查询在FROM子句中引入子查询在WHERE子句中引入子查询注意事项 子查询分类标量子查询列子查询行子查询表子查询 子查询注意事项子查询的位置子查询的返回类型别名的使用性能考虑相关性错误处理逻辑清晰 总…

Vue 学习

vue 核心语法 <!DOCTYPE html> <html> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Vue 核心语法测试</title> </head><body&…

GGHead:基于3D高斯的快速可泛化3D数字人生成技术

随着虚拟现实(VR)、增强现实(AR)和数字人技术的发展,对高质量、实时生成的3D头部模型的需求日益增长。传统的3D生成方法往往依赖于复杂的2D超分辨率网络或大量的3D数据,这不仅增加了计算成本,还限制了生成速度和灵活性。为了解决这些问题,研究人员开发了一种名为GGHead…

14.安卓逆向-frida基础-编写hook脚本2

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a;图灵Python学院 本人写的内容纯属胡编乱造&#xff0c;全都是合成造假&#xff0c;仅仅只是为了娱乐&#xff0c;请不要盲目相信。 工…

图技术与大语言模型 LLM 结合,打造下一代知识图谱应用

随着 AI 人工智能技术的迅猛发展和自然语言处理领域的研究日益深入&#xff0c;如何构建强大的大语言模型对于企业来说愈发重要&#xff0c;而图数据库作为处理复杂数据结构的有力工具&#xff0c;为企业构建行业大语言模型提供了强大的支持。 近日&#xff0c;国产企业级分布…

UE学习篇ContentExample解读------Blueprints Advanced-下

文章目录 总览描述批次阅览2.1 Timeline animation2.2 Actor tracking2.3 Button Trigger using a blueprint interface2.4 Opening door with trigger2.5 Child Blueprints 概念总结致谢&#xff1a; 总览描述 打开关卡后&#xff0c;引入眼帘的就是针对关卡的总体性文字描述&…

netdata(Linux 性能实时监测工具)一键安装 for armbian

下载地址netdata/netdata: Architected for speed. Automated for easy. Monitoring and troubleshooting, transformed! (github.com) sh netdata-armv7l-latest.gz.run^|.-. .-. .-. .-. . netdata| - - - - real-time performance monitoring, done righ…