全部產品
Search
文件中心

:安全規則DSL文法

更新時間:Jun 30, 2024

DMS定義了一套領域專用語言DSL(Domain Specific Language)用來描述安全規則。DSL文法非常靈活,理論上可以表述任意安全規則,從而協助不同企業定義符合自己的研發規範。

DSL文法概述

DSL文法非常簡單,由分支判斷(IF-ELSE)、條件和動作三部分組成,基本形式如下。

if
    條件1
then
    動作1
end
說明 當滿足條件1,系統就執行動作1。

還有增強形式,即else後面還可以跟著if條件。只有if語句是必須的,elseif可以有0個或多個,else可以有0個或1個。

if
    條件1
then
    動作1
elseif
    條件2
then
    動作2
[else 動作3]
end
說明 如果滿足條件1,就執行動作1,不滿足條件1時如果滿足條件2,就執行動作2,否則就執行動作3,[else 動作3]也可以沒有,不滿足條件2時,不執行任何操作。

DSL文法詳細介紹

  • 條件陳述式

    條件就是判斷語句,用來判定truefalse。條件陳述式由串連符(andor)、操作符、因子(系統變數)組成。如下樣本都是合法的條件陳述式。

    true                    // 最簡單的條件陳述式,結果就是true。
    1 > 0
    1 > 0 and 2 > 1
    1 <= 0 or 1 == 1
    說明 以上結果都是true。
    • 串連符

      和其它語言一樣,andor分別是與和或串連運算,andor優先順序高,但它們都比操作符的優先順序低。

      例如 1 <= 0 or 1 == 1語句:最先執行 1 <= 0判斷,然後執行 1 == 1判斷,最後執行or判斷。

    • 操作符

      操作符用於串連因子(系統變更)、常量進行相關邏輯運算,目前支援的操作符如下。

      操作符說明樣本
      ==等於1 == 1
      !=不等於1 != 2
      >大於1 > 2
      >=大於等於1 >= 2
      <小於1 < 2
      <=小於等於1 <= 2
      in包含於‘a’ in [‘a’, ‘b’, ‘c’]
      not in不包含於‘a’ not in [‘a’, ‘b’, ‘c’]
      matchs(驗證工具)正則匹配'idx_aa' matchs 'idx_\\w+'
      not matchs不匹配'idx_aa' not matchs 'idx_\\w+'
      isBlank為空白‘’ isBlank
      isNotBlank不為空白‘’ isNotBlank

      注意:Regex中(\)需要另外一個(\)轉義,例如:idx_\w+需要寫成:idx_\\w+

      說明 操作符雖然有優先順序,但不建議依賴優先順序。如果條件陳述式較為複雜時,建議將需要先判斷的部分放在括弧內。例如:1 <= 2 == true執行順序不明確,可改為:(1 <= 2) == true,此時一定先執行(1 <= 2)
    • 因子

      因子是系統內建變數,可用來擷取安全規則校正的上下文資訊,如擷取SQL類型、影響行數等。因子全部以@fac.開頭,後接因子名稱。每個模組的不同檢測點均提供不同因子,如下為部分因子及其說明。

      因子名說明
      @fac.env_type環境類型,值為環境標識,如devproduct。詳情請參見執行個體環境說明
      @fac.sql_typeSQL指令碼的類型,如UPDATEINSERT
      @fac.detail_type資料變更的種類:
      • COMMON:普通資料變更
      • CHUNK_DML:無鎖資料變更
      • PROCEDURE:預存程序
      • CRON_CLEAR_DATA:定時清理表
      • BIG_FILE:批量資料匯入
      @fac.is_logic 是否為邏輯庫。
      @fac.extra_info 其他變更資訊(暫無用途)。
      @fac.is_ignore_affect_rows是否跳過校正。
      @fac.insert_rows插入資料的影響行數。
      @fac.update_delete_rows更新資料的影響行數。
      @fac.max_alter_table_size修改表中,最大的資料表空間大小。
      @fac.is_has_security_columnSQL指令碼中是否包含敏感列。
      @fac.security_column_listSQL指令碼中包含的敏感列列表。
      @fac.risk_level識別到的風險層級。
      @fac.risk_reason識別為該風險的原因。

      在條件陳述式中,可直接引用因子,例如:@fac.sql_type == 'DML',判斷SQL類型是不是DML。

  • 動作語句

    動作是滿足if條件之後系統執行的行為,例如:禁止提交工單、選擇工作流程、允許執行、拒絕執行等,這些動作表達了安全規則的主要目的。動作全部以@act.開頭,後接動作名稱。每個模組的不同檢測點均提供不同動作,如下為部分動作及其說明。

    動作名說明
    @act.allow_submit必須提交工單執行。
    @act.allow_execute_direct允許直接在SQL控制台執行。
    @act.forbid_execute禁止執行。
    @act.mark_risk標記風險。用法:@act.mark_risk 'middle' '中風險:線上環境'
    @act.do_not_approve指定審批模板ID。詳情請參見設定審批次程序
    @act.choose_approve_template
    @act.choose_approve_template_with_reason
  • 內建函數

    安全規則內建部分函數,在條件陳述式和動作語句均可以使用。函數全部以 @fun. 開頭,後面是函數名。

    函數名說明樣本
    @fun.concat拼接字串。

    傳回值:字串。

    參數:任意多個字串。
    @fun.concat(‘d’, ‘m’, ‘s’) // ‘dms’

    @fun.concat(‘[研發規範]欄位[‘,@fac.column_name, ‘]必須要填寫備忘資訊’) // 拼接友好的提示資訊返回給使用者。

    @fun.char_length計算字串的長度。

    傳回值:整數。

    參數:一個字串。
    @fun.char_length(‘dms’) // 3

    @fun.char_length(@fac.table_name) // 計算表名長度。

    @fun.is_char_lower判斷字串是否都是小寫。

    傳回值:true或false。

    參數:一個字串。
    @fun.is_char_lower(‘dms’) // true

    @fun.is_char_lower(@fac.table_name) // 返回true的話,表名都是小寫。

    @fun.is_char_upper判斷字串是否都是大寫。

    傳回值:true或false。

    參數:一個字串。
    @fun.is_char_upper(‘dms’) // false

    @fun.is_char_upper(@fac.table_name) // 返回true的話,表名都是大寫。

    @fun.array_size計算集合的大小。

    傳回值:整數。

    參數:一個集合。
    @fun.array_size([1, 2, 3]) // 3

    @fun.array_size(@fac.table_index_array) // 計算表索引的個數。

    @fun.add多個數相加。

    傳回值:數值。

    參數:任意多個數。
    @fun.add(1, 2, 3) // 6
    @fun.sub兩個數相減。

    傳回值:數值。

    參數:2個數值。
    @fun.sub(6, 1) // 5
    @fun.between是否在某區間(支援數值、日期時間比較),判斷時包含邊界值。

    傳回值:true或false。

    參數:3個參數,第一個是目標值,第二個是左區間,第三個是右區間。
    @fun.between(1, 1, 3) // 判斷1是否在1~3區間內,返回true。

    @fun.between(2, 1, 3) // 判斷2是否在1~3區間內,返回true。

    @fun.between(7, 1, 3) // 判斷7是否在1~3區間內,返回false。

    @fun.between(@fac.export_rows, 2001, 100000) // 判斷匯出行數的範圍。

    @fun.between(@fun.current_datetime(), ‘2019-10-31 00:00:00’, ‘2019-11-04 00:00:00’) // 判斷目前時間是否在10.31~11.04號之間。

    @fun.between(@fun.current_date(), ‘2019-10-31’, ‘2019-11-04’) // 判斷目前時間是否在10.31~11.04號之間。

    @fun.current_datetime擷取當前日期時間,格式:yyyy-MM-dd HH:mm:ss。

    傳回值:字串。

    參數:無。
    @fun.current_datetime() // 當前日期時間,例如:2019-10-31 00:00:00。
    @fun.current_date擷取當前日期,格式:yyyy-MM-dd。

    傳回值:字串。

    參數:無。
    @fun.current_date() // 當前日期,例如:2020-01-13。
    @fun.current_time擷取目前時間,格式:HH:mm:ss。

    傳回值:字串。

    參數:無。
    @fun.current_time() // 目前時間,例如:19:43:20。
    @fun.is_contain_str判斷第一個字串是否包含第二個字串。

    傳回值:true或false。

    參數:2個參數,第一個是源字串(Source),第二個是目標字串(Target)。
    @fun.is_contain_str('abcd', 'ab') // 判斷"abcd"是否包含"ab",返回true。
    @fun.listEqualIgnoreOrder判斷兩個字串List是否相同(忽略元素順序和元素的大小寫)。

    傳回值:true或false。

    參數:2個參數,第一個是字串List1,第二個是字串List2。
    @fun.listEqualIgnoreOrder(['ab','cd'], ['Cd','ab']) // 判斷是否相同,返回true。

    @fun.listEqualIgnoreOrder(@fac.perm_type, ['QUERY']) // 判斷是否僅申請了查詢許可權。

    @fun.listEqualIgnoreOrder(@fac.perm_type, ['CORRECT','EXPORT']) // 判斷是否同時申請了變更和匯出許可權。

樣本

  • 控制單次執行SQL個數。
    if
        @fac.sql_count > 1000
    then
        @act.reject_execute '單次執行SQL個數不能超過1000'
    else
        @act.allow_execute
    end
    說明 如果SQL的數量大於1000個時,DMS即拒絕執行,並且返回相應的理由給使用者,否則就允許執行。
  • 允許提交DML語句。
    if
        @fac.sql_type in [ 'UPDATE','DELETE','INSERT','INSERT_SELECT']
    then
        @act.allow_submit
    end
    說明 如果提交的SQL是UPDATEDELETEINSERTINSERT_SELECT類型就允許執行。