1# @Language: Markdown
2# @Software: VS Code/MacDown/Typora/Vim
3# @Author  : Di Wang
4# @Email   : [email protected]

关键词

  • ASL: Access Security Level.
  • ASG: Access Security Group
  • UAG: User Access Group
  • HAG: Host Access Group

每个record field都有ASL, 在dbd文件中定义, 可以是ASL0或者ASL1. 通常VAL field为ASL0, 其它为ASL1. ASL1的优先级高于ASL0

每个record都有一个ASG field, 默认为default.

as file语法

  • as file中定义一些用户组, 主机组, 然后一些规则组.
  • record在它自己的ASG field中指定要使用的规则组.
  • 规则组内包含了若干RULE.
  • 每个RULE中可以设置用户组和主机组是否可读/可写.
  • 每个RULE可以设置ASL
  • 规则组可以依据某个pv的值来生效. 通过INP来指定pv, CALC来判断pv值.
 1UAG(<name>) { <user> [, <user> ...] }
 2...
 3HAG(<name>) { <host> [, <host> ...] }
 4...
 5ASG(<name>) {
 6  [INP<index>(<pvname>) ...]
 7  RULE(<level>,NONE |READ|WRITE [,NOTRAPWRITE | TRAPWRITE] ) {
 8    [UAG(<name> [,<name> ...])]
 9    [HAG(<name> [,<name> ...])]
10    CALC(<calculation>)
11  }
12...
13}
14...

启用

as file 中可以使用macro.

1asSetFilename("/full/path/to/accessSecurityFile")
2asSetSubstitutions("var1=sub1,var2=sub2,...")
3ascheck -S "xxx=yyy,..." < "filename"

可以在运行中重载as, 但不推荐. 具体方法为使用subroutine record, 指定asSubInitasSubProcess函数.

示例

使用softIoc st.cmd运行ioc, 无法通过caput修改demo:limit.

1$ caput demo:limit 5
2Old : demo:limit                     10
3Error from put operation: Write access denied

st.cmd

1asSetFilename("$(PWD)/secure.acf")
2asSetSubstitutions("S=demo")
3dbLoadRecords("solution.db", "S=demo")
4
5# var("asCheckClientIP",1)
6iocInit

slotion.db

 1record(calc, "$(S):ramp")
 2{
 3  field(CALC, "(A<B)?(A+C):0")
 4  field(INPA, "$(S):ramp")
 5  field(SCAN, "1 second")
 6  field(INPB, "$(S):limit")
 7  field(INPC, "$(S):step")
 8}
 9
10record(ai, "$(S):limit")
11{
12  field(INP, "10")
13  # ACC SECURITY
14  field(ASG, "EXPERT")
15}
16
17record(ai, "$(S):step")
18{
19  field(INP, "1")
20}
21
22# ACC SECURITY
23record(bo, "$(S):accessState") {
24  field(DESC, "Used by ASG to open access")
25  field(ZNAM, "Expert-Only")
26  field(ONAM, "Anybody")
27}

secure.acf

 1# list of users
 2UAG(normUsers) {training}
 3UAG(expertUsers) {expert}
 4
 5HAG(normHosts) {training, training.epics, training-VirtualBox}
 6
 7ASG(DEFAULT) {
 8    RULE(1,READ)
 9    RULE(1,WRITE) {
10        UAG(normUsers)
11        HAG(normHosts)
12    }
13}
14
15ASG(EXPERT) {
16    INPA($(S):accessState)
17
18    RULE(1,READ)
19
20    RULE(1,WRITE) {
21        UAG(expertUsers)
22        HAG(normHosts)
23    }
24
25    RULE(1,WRITE) {
26        UAG(normUsers)
27        HAG(normHosts)
28        CALC("A=1")
29    }
30}

IP

R7.0.3.1开始, 可以使用asCheckClientIP variable来检查HAG中指定的host的真实IP. 这样可以防止有人伪装自己的hostname来绕开AS. 如下所示, HAG中的host变为HAG(normHosts) {unresolved:training,unresolved:training.epics,127.0.1.1}. 无法解析的hostname会带有unresolved字样.

 1epics> asdbdump
 2UAG(expertUsers) {expert}
 3UAG(normUsers) {training}
 4HAG(normHosts) {unresolved:training,unresolved:training.epics,127.0.1.1}
 5ASG(DEFAULT) {
 6	RULE(1,READ,NOTRAPWRITE)
 7	RULE(1,WRITE,NOTRAPWRITE) {
 8		UAG(normUsers)
 9		HAG(normHosts)
10	}
11	MEMBERLIST
12		<null> Record:demo:accessState
13		<null> Record:demo:step
14		<null> Record:demo:ramp
15}
16ASG(EXPERT) {
17	INPA(demo:accessState) INVALID value=0.000000
18	RULE(1,READ,NOTRAPWRITE)
19	RULE(1,WRITE,NOTRAPWRITE) {
20		UAG(expertUsers)
21		HAG(normHosts)
22	}
23	RULE(1,WRITE,NOTRAPWRITE) {
24		UAG(normUsers)
25		HAG(normHosts)
26		CALC("A=1") result=FALSE
27	}
28	MEMBERLIST
29		EXPERT Record:demo:limit
30}
31epics>

tips

1ASG(private) {
2    RULE(1, NONE)
3}
4ASG(DEFAULT) {
5   RULE(1,READ)
6   RULE(1,WRITE,TRAPWRITE)
7}