审计制度语法建议

时间:2017-08-16 02:30:10

标签: clips jess

我想知道你是否可以指出我正确的方向。我想编写一个基于规则的系统来审计一组机器 - 例如

  • 检查配置参数以确定它们是否设置正确
  • 检查机器的状态以确定它们是否在可接受的范围内

我正在努力解决的问题是为审计规则提出一个语法,这样我就不需要编码规则。我创建了一些简单的审计规则,但我正在努力想出一个通用的表单。

这是我目前的尝试。

首先,我目前使用单个模板表示配置参数和运行状态(由于缺乏想象力,我称之为audit-fact),因此我的审计语言可以同时适用于配置和状态。我使用域槽来指定配置与状态。

(deftemplate audit-fact 
    (slot domain (allowed-values config state))     ;; config vs. state
    (slot machine)                                  ;; machine to audit 
    (slot name)                                     ;; parameter or state to check/audit
    (slot value)                                    ;; parameter value 
    (slot already-checked (default FALSE))
)   

接下来,我编写了一个程序来读入并断言机器配置和状态为审计事实。以下是示例配置和状态审计事实

(assert (audit-fact 
    (domain config) 
    (machine drl-a-15_0) 
    (name os-version) (value 5.5))
)

(assert (audit-fact 
    (domain state) 
    (machine drl-a-15_0) 
    (name rpm) (value 5023))
)

这是我目前对审计语法/语言的尝试---

(deftemplate rule
    (slot domain) 
    (slot name) 
    (slot constraint (default ?NONE) (allowed-values should-remain-at-default should-equal should-be-between ignore-if-ends-with))
    (multislot values)
    (multislot reasons) 
    (multislot references) 
    (slot criticality (allowed-values critical info suggestion warning))
    (slot already-checked (default FALSE))
)

以下规则用于检查状态或参数是否在特定范围内

(assert (rule 
    (domain state)
    (name rpm) 
    (constraint should-be-between) 
    (values 5000 5500) 
    (criticality critical) 
    (reasons "Low values could cause engine to stall. Prolonged high value could cause engine to heat up") )
)

接下来,我使用以下规则检查状态或参数是否等于特定值

(assert (rule 
    (domain config)
    (name os-version) 
    (constraint should-equal) 
    (values 5.5) 
    (criticality critical) 
    (reasons "OS version must be at 5.5 – no other levels are currently certified.") )
)

以下规则实现了相等和检查之间的

(defrule rule-should-eq
    (rule (domain ?d) (name ?n) (constraint should-equal) (values ?cv) (reasons ?r))
    ?p <- (audit-fact (domain ?d) (name ?n) (value ?v) (already-checked FALSE))
=>
    (if (eq ?v ?cv)
        then 
            (printout t "checking " ?d ": " ?n ". Passed "  crlf)
        else 
            (printout t "checking " ?d “: “ ?n " should be set to " ?cv ". " ?r ". Warning" crlf)
    )       
    (modify ?p (already-checked TRUE))  
)       

(defrule rule-should-be-between
    (rule (domain ?d) (name ?n) (constraint should-be-between) (values ?cv-low ?cv-high) (reasons ?r))
    ?p <- (audit-fact (domain ?d) (name ?n) (value ?v) (already-checked FALSE))
=>
    (if (and (>= ?v ?cv-low) (<= ?v ?cv-high))
        then 
            (printout t "checking " ?n ". Passed "  crlf)
        else 
            (printout t "checking " ?n " should be between " ?cv-low " and " ?cv-high ". " ?r ". Warning" crlf)
    )       
    (modify ?p (already-checked TRUE))  
)       

使用上面的内容,我可以实现简单的检查 - 例如,必须设置,必须在之间,必须不相等,必须保持默认值,必须 - 高于,必须低于等等。

但是我想不出一种简单的方法可以让语法处理多个条件和/或等等。

问题---

  • 是否有一篇论文描述了上述审计规则的设计模式。我目前正在研究示例中的wine.clp(CLIPS)。
  • 我应该放弃并只使用简单的语法来处理简单的审计规则,只使用defrules来处理任何复杂的事情 - 例如,如果config-A设置为X,那么检查其他五个配置以确保它们也设置正确,然后断言检查状态。一旦声明,然后检查状态是否在一定范围内。

提前致谢。

伯尼

2 个答案:

答案 0 :(得分:1)

1)如果RHS上的陈述是代码气味:不要! 2)由于您没有修改这些事实,因此您不需要已经检查过的标记。

针对一个机器属性重写检查:

?p <- (Configuration (machine ?m)(param ?p)(value ?v))
(ConfigCheckRange (param ?p){?v < loBound || $v > hiBound})

(您可能需要其他变体,例如,ConfigCheckEnum在一个时间间隔内不允许使用值。)

检查参数值组合更加困难,因为您已选择通过单独的事实表示每个参数值。你必须

 ?p1 <- (Configuration (machine ?m)(param ?p1)(value ?v1))
 ?p2 <- (Configuration (machine ?m)(param ?p2)(value ?v2)
         {?p2 != ?p1))
(ConfigCheckCombi (param1 ?p1)(param2 ?p2)
      {lowBound1 <= ?v1 && ?v2 <= lowBound2}
      {?v2 < loBound2 || $v2 > hiBound2})

右手边应该只是在(新的)事实中记录违规行为,让我们称之为调查结果。 One Findings包含机器的id和(违反的)ConfigCheck事实列表。

最后(使用低显着性规则),您可以找到Findings事实并在其上调用报告方法。 (使用一些合适的Java bean作为事实可能更方便。)

答案 1 :(得分:1)

这是一种从通用规则评估任意表达式的方法:

CLIPS> 
(deffunction str-replace (?str ?rpl ?fnd)
   (if (eq ?fnd "") then (return ?str))
   (bind ?rv "")
   (bind ?i (str-index ?fnd ?str))
   (while ?i
      (bind ?rv (str-cat ?rv (sub-string 1 (- ?i 1) ?str) ?rpl))
      (bind ?str (sub-string (+ ?i (str-length ?fnd)) (str-length ?str) ?str))
      (bind ?i (str-index ?fnd ?str)))
   (bind ?rv (str-cat ?rv ?str)))
CLIPS>    
(deftemplate audit-fact 
    (slot domain)   
    (slot machine)                                   
    (slot name)                                   
    (slot value))
CLIPS>   
(deftemplate rule
    (slot domain) 
    (slot name) 
    (slot constraint)
    (multislot reasons) 
    (multislot references) 
    (slot criticality))
CLIPS> 
(deffacts initial
   (audit-fact 
      (domain config) 
      (machine drl-a-15_0) 
      (name os-version) 
      (value 5.4))
   (audit-fact 
      (domain state) 
      (machine drl-a-15_0) 
      (name rpm) 
      (value 5023))
   (rule 
      (domain state)
      (name rpm) 
      (constraint "(and (>= ?v 5000) (<= ?v 5500))")
      (criticality critical) 
      (reasons "Low values could cause engine to stall. Prolonged high value could cause engine to heat up."))
   (rule 
      (domain config)
      (name os-version) 
      (constraint "(eq ?v 5.5)")
      (criticality critical) 
      (reasons "OS version must be at 5.5 – no other levels are currently certified.")))
CLIPS> 
(defrule rule-check
   (rule (domain ?d) (name ?n) (constraint ?constraint) (reasons ?r))
   ?p <- (audit-fact (domain ?d) (name ?n) (value ?v))
   =>
   (bind ?constraint (str-replace ?constraint ?v "?v"))
   (if (eval ?constraint)
      then 
      (printout t "checking " ?d ": " ?n " Passed"  crlf)
      else 
      (printout t "checking " ?d ": " ?n " Warning : " ?r crlf)))
CLIPS> (reset)
CLIPS> (run)
checking config: os-version Warning : OS version must be at 5.5 – no other levels are currently certified.
checking state: rpm Passed
CLIPS>