关于sql:SQL审核-如何快速使用-SQLE-审核各种类型的数据库

39次阅读

共计 4356 个字符,预计需要花费 11 分钟才能阅读完成。

作者:孙健

孙健,爱可生研发工程师,负责 SQLE 相干开发;

本文起源:原创投稿

* 爱可生开源社区出品,原创内容未经受权不得随便应用,转载请分割小编并注明起源。


前言

近些年来,数据库产业倒退迅猛,各种新兴数据库如雨后春笋般呈现,各个公司的技术栈也不再局限于某一种数据库。对于 SQL 品质治理平台来说仅反对某一个类型的数据库(例如 MySQL),那么是会有肯定的局限性,SQLE 在设计之初思考反对多种数据库,因而产品设计时,将审核流程(业务)的代码和具体 SQL 审核上线的代码进行拆散,SQL 审核上线通过插件的模式实现。SQLE 对外提供插件开发所需的接口和库,能够疾速创立开启一个审核插件,无需降级软件,导入审核插件即可获对应数据库类型的审核上线能力,应用平台所有性能。

插件的开发参考文档:https://actiontech.github.io/…,

插件的应用参考文档:https://actiontech.github.io/…。

本文将演示如何从零开始创立一个简略可用的审核插件,作为案例。

指标

首先将创立一个 Postgres 数据库审核插件,并增加两条规定,“禁止应用 SELECT *”和“创立的表字段过多”,并在开发过程中联合 SQLE 对 Postgres 数据库进行 SQL 审核上线工单的测试演示。以下过程中的演示代码可从此处 https://github.com/actiontech… 下载。

实操

提醒:SQLE 和插件为 GO 语言开发,如果要进行插件开发,须要对 GO 有一丢丢理解即可。

1. 创立插件我的项目

首先应用 go mod 初始化一个 go 我的项目,而后

mkdir sqle-pg-plugin
cd sqle-pg-plugin
touch main.go
go mod init sqle-pg-plugin # 初始化 go mod 
export GOPROXY=goproxy.cn,goproxy.io,direct # 设置 GoProxy,解决 SQLE 库下载问题,通过 IDEA 开发的能够在 IDEA 软件上设置;go get github.com/actiontech/sqle@v1.2204.0 # 此版本为该文章编辑时的最新版本。

2. 编写最小化插件代码

在我的项目 main.go 文件内编写如下代码,即可最快的增加一个 Postgres 数据库审核插件,此时插件没有审核规定。

package main
 
import (adaptor "github.com/actiontech/sqle/sqle/pkg/driver")
 
func main() {plugin := adaptor.NewAdaptor(&adaptor.PostgresDialector{})
   plugin.Serve()}

应用‘go build‘编译后失去二进制文件 sqle-pg-plugin,按前言中的插件的应用参考文档,咱们部署到 SQLE 服务里。能够失常增加数据源,如下图所示:

此时失常进行 SQL 审核上线工单创立并上线,如下图所示:

3. 给插件增加一条规定

在刚刚代码的根底上,咱们在 main 函数内增加如下代码来新增一条规定“禁止应用 SELECT *”,残缺代码如下所示。

package main
 
import (
   "context"
   "strings"
 
   "github.com/actiontech/sqle/sqle/driver"
   adaptor "github.com/actiontech/sqle/sqle/pkg/driver"
 
)
 
func main() {plugin := adaptor.NewAdaptor(&adaptor.PostgresDialector{})
   rule1 := &driver.Rule{
      Name:     "pg_rule_1", // 规定 ID,该值会与插件类型一起作为这条规定在 SQLE 的惟一标识
      Desc:     "禁止应用 SELECT *",      // 规定形容
      Category: "DQL 标准",           // 规定分类,用于分组,雷同类型的规定会在 SQLE 的页面上展现在一起
      Level:    driver.RuleLevelError,    // 规定等级,示意该规定的重大水平
   }
    //
   rule1Handler := func(ctx context.Context, rule *driver.Rule, sql string) (string, error) {if strings.Contains(sql, "select *") {return rule.Desc, nil}
      return "", nil
   }
   plugin.AddRule(rule1, rule1Handler)
   plugin.Serve()}

咱们按之前的形式编译插件二进制文件,并部署到 SQLE server 内,能够看到新增了一条规定,如下图所示:

此时咱们提交一个工单验证一下,能够看到触发了咱们刚增加的规定

4. 给插件增加一条可配置的简单规定

基于下面的代码,咱们再增加一条规定“创立的表字段过多”,具备如下个性:

  • 下面增加的规定基于字符串匹配进行的,准确性不高,无奈匹配到不同的书写格局,比方大小写,换行等。因而咱们在这里会基于 SQL 解析器开发一条规定,测试应用的解析库 https://github.com/pganalyze/…;
  • 为了减少规定的适用性,咱们筹备给规定加一个动静配置给用户提供可选项。

代码如下:

package main
 
import (
   "context"
   "fmt"
   "strings"
 
   "github.com/actiontech/sqle/sqle/driver"
   adaptor "github.com/actiontech/sqle/sqle/pkg/driver"
   "github.com/actiontech/sqle/sqle/pkg/params"
   parser "github.com/pganalyze/pg_query_go/v2"
)
 
func main() {plugin := adaptor.NewAdaptor(&adaptor.PostgresDialector{})
 
   rule1 := &driver.Rule{
      Name:     "pg_rule_1",           // 规定 ID,该值会与插件类型一起作为这条规定在 SQLE 的惟一标识
      Desc:     "防止查问所有的列",            // 规定形容
      Category: "DQL 标准",               // 规定分类,用于分组,雷同类型的规定会在 SQLE 的页面上展现在一起
      Level:    driver.RuleLevelError, // 规定等级,示意该规定的重大水平
   }
   rule1Handler := func(ctx context.Context, rule *driver.Rule, sql string) (string, error) {if strings.Contains(sql, "select *") {return rule.Desc, nil}
      return "", nil
   }
 
   // 定义第二条规定
   rule2 := &driver.Rule{
      Name:     "pg_rule_2",
      Desc:     "表字段不倡议过多",
      Level:    driver.RuleLevelWarn,
      Category: "DDL 标准",
      Params: []*params.Param{ // 自定义参数列表
         &params.Param{
            Key:   "max_column_count",  // 自定义参数的 ID
            Value: "50",                // 自定义参数的默认值
            Desc:  "最大字段个数",            // 自定义参数在页面上的形容
            Type:  params.ParamTypeInt, // 自定义参数的值类型
         },
      },
   }
 
   // 这时处理函数的参数是 interface{} 类型,须要将其断言成 AST 语法树。rule2Handler := func(ctx context.Context, rule *driver.Rule, ast interface{}) (string, error) {node, ok := ast.(*parser.RawStmt)
      if !ok {return "", nil}
      switch stmt := node.GetStmt().GetNode().(type) {
      case *parser.Node_CreateStmt:
         columnCounter := 0
         for _, elt := range stmt.CreateStmt.TableElts {switch elt.GetNode().(type) {
            case *parser.Node_ColumnDef:
               columnCounter++
            }
         }
         // 读取 SQLE 传递过去的该参数配置的值
         count := rule.Params.GetParam("max_column_count").Int()
         if count > 0 && columnCounter > count {return fmt.Sprintf("表字段不倡议超过 %d 个,目前有 %d 个", count, columnCounter), nil
         }
      }
      return "", nil
   }
 
   plugin.AddRule(rule1, rule1Handler)
   plugin.AddRuleWithSQLParser(rule2, rule2Handler)
 
   // 须要将 SQL 解析的办法注册到插件中。plugin.Serve(adaptor.WithSQLParser(func(sql string) (ast interface{}, err error) {
      // parser.Parse 应用 PostgreSQL 的解析器,将 sql 解析成 AST 语法树。result, err := parser.Parse(sql)
      if err != nil {return nil, fmt.Errorf("parse sql error")
      }
      if len(result.Stmts) != 1 {return nil, fmt.Errorf("unexpected statement count: %d", len(result.Stmts))
      }
      // 将 SQL 的语法树返回。return result.Stmts[0], nil
   }))
 
   plugin.Serve()}

关上 SQLE 规定界面,能够看到该规定曾经增加到 SQLE 了,如图:

咱们将规定模板内该规定的值调小点而后进行测试一下

首先咱们提交一条超过 5 个字段的建表语句,此时 SQLE 会触发该规定并给出预期的提示信息,如下图所示:

而后咱们提交一条不超过 5 个字段的建表语句,此时 SQLE 不会触发该规定,如下图所示:

总结

通过下面的演示,大略介绍了 SQLE 数据库审核插件的简略开发测试过程。大家可依据相似步骤开发出一套合乎本人公司需要的规定集,联合 SQLE 平台来满足日常应用。咱们也提供了一些常见数据库的审核插件,大家也能够在此基础上进行开发,参考文档:https://actiontech.github.io/…

正文完
 0