SPDL - Speedle 策略定义语言


基本的策略定义语言

基本策略定义语法

保留关键字

grant、deny、user、group、entity、role、from、on、if、in 在各自语法位置有特定含义,策略语句的关键字大小写不敏感;条件成员运算使用 in 或 IN,函数名区分大小写。主体、操作和资源名称也区分大小写。当前解析器在部分名称位置可接受类似关键字的名称,不能把“所有位置都禁止关键字”当作验证规则。为便于审查与客户端互通,建议避免这类名称。

命名规范

推荐使用简明、稳定的标识符;名称包含空格或分隔符时使用解析器支持的单引号或双引号形式,并测试实际输入。不应把历史 Java 正则字符类当作当前 Go 解析器的严格校验。资源前缀 expr: 表示 Go 正则表达式,不是 shell 通配符。条件的属性与函数名称另见下文。

语法

POLICY = EFFECT SUBJECT ACTION RESOURCE [if CONDITION]
EFFECT = grant | deny
SUBJECT = AND_PRINCIPALS (, AND_PRINCIPALS)*
AND_PRINCIPALS = PRINCIPAL | \( PRINCIPAL_LIST \)
PRINCIPAL_LIST = PRINCIPAL (, PRINCIPAL)*
PRINCIPAL = PRINCIPAL_TYPE PRINCIPAL_NAME [PRINCIPAL_IDD]
PRINCIPAL_TYPE = user|group|entity|role
PRINCIPAL_IDD = from IDD_IDENTIFIER
IDD_IDENTIFIER = NAME
ACTION = (ACTION_IDENTIFIER)(, ACTION_IDENTIFIER)*
RESOURCE = RESOURCE_IDENTIFIER
PRINCIPAL_NAME = NAME
ACTION_IDENTIFIER = NAME
RESOURCE_IDENTIFIER = NAME
ROLE_POLICY = EFFECT SUBJECT ROLE (on RESOURCE)? [if CONDITION]
EFFECT = grant | deny
SUBJECT = PRINCIPAL (, PRINCIPAL)*
PRINCIPAL = PRINCIPAL_TYPE PRINCIPAL_NAME [PRINCIPAL_IDD]
PRINCIPAL_TYPE = user|group|entity|role
PRINCIPAL_IDD = from IDD_IDENTIFIER
IDD_IDENTIFIER = NAME
ROLE = (role)? SUBJECT_IDENTIFIER
RESOURCE = RESOURCE_IDENTIFIER
SUBJECT_IDENTIFIER = NAME
RESOURCE_IDENTIFIER = NAME

条件(Condition)

1. 概述

Policy 和 role policy 都支持 Condition。只有 condition 满足了, policy 或 role policy 才会生效。

这一小节主要介绍什么是 condition, 以及如何构建 condition。

2. Condition

Condition 就是一个布尔表达式。由属性(attributes), 函数(functions), 常量(constants), 操作符(operators), 比较运算符(comparators) or 括号(parenthesis)构建的布尔表达式。

2.1 数据类型 (Data Types)

属性和常量的数据类型可以是 string, numeric, bool, datetime,或者由 string, numeric, bool, datetime 构成的数组。
数据类型及其支持的操作符,比较运算符如下表所示:

数据类型
Data Type
操作符
Operators
比较运算符
Comparators
备注
Comment
string + ==
!=
=~
>
>=
<
<=
’+’ 用于字符串连接操作

‘=~’ 用于正则表达式匹配。
左边是匹配的字符串, 右边是正则表达式."=~"返回ture如果匹配成功,或者false如果匹配失败。
numeric +
-
*
/
%
==
!=
>
>=
<
<=
bool &&
||
!
==
!=
datetime ==
!=
>
>=
<
<=
array in membership ‘in’ operator: left side should be a single type(string, numeric, bool, datetime), right side should be an array

2.2 属性(Attributes)

属性(attribute)代表一个变量。属性分为内置属性和用户属性两大类。 内置属性(Built-in attributes)是 Speedle 预定义的,它们的值是在决策运算中由 Authorization Decision Service (ADS)运行时指定的。 用户属性(customer attributes)的值是用户在授权请求(authorization decision request)中传入的。

2.2.1 内置属性(Built-in Attributes)

Speedle 预定义的内置属性如下:

内置属性名
Built-in Attribute Name
数据类型
Data Type
例子
Sample Value
定义
Definition
request_user string "Alice" Authorization请求中(Subject)的user信息
request_groups []string []string{"managers"} Authorization请求中(Subject)的groups信息
request_entity string "/org1/service1" Authorization请求中(Subject)的entity信息
request_resource string "commercialLoans" Authorization请求中的资源
request_action string "issue" Authorization请求中对资源的操作
request_time datetime '2019-01-02T15:04:05-07:00' Authorization请求时的日期和时间
request_year int 2019 Authorization请求时的年份
request_month int 1, 2, ... 12 Authorization请求时的月份
request_day int 1, 2, ... 31 Authorization请求时是一个月中的哪一天
request_hour int 0, 1, ... 23 Authorization请求时是一天中的哪个时辰
request_weekday string "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" Authorization请求时是星期几
2.2.2 用户属性(Customer Attributes)
2.2.2.1 属性名(name)

为便于在条件中直接引用,推荐属性名符合 [A-Za-z][A-Za-z0-9_]*,并避免与内置属性/函数重名。REST 请求层实际接受最长 256 个字符的 ASCII 字母、数字、下划线、连字符与点;包含连字符或点时,应测试表达式中的引用方式,不要把它们误读为运算符。

2.2.2.2 属性值(value)

当用户属性应用于 condition 时, 当用户向 ADS 发送 Authorization Decision 请求时,用户需要将属性值随请求一并传入。

  • 通过 Golang API 传入属性值
    需遵循如下规则:

    • bool 型属性值使用 Golang bool 类型.
    • string 型属性值使用 Golang string 类型.
    • numeric 型属性值使用 Golang float64 类型.
    • datetime 型属性值使用 Golang float64 类型, 也就是 Unix time (using time.Time.Unix()).
    • 数组属性使用 Golang []interface{}.
  • 通过 REST API 传入属性值
    须遵循如下规则:

    • 属性是一个结构体(struct),包含属性名(name), 属性的数据类型(type), 属性值(value). 详细信息参见 REST API.
    • 属性的数据类型(type)只能是 “string”, “numeric”, “bool” or “datetime”.
    • 属性值可以是单个值, 也可以是数组.

2.3 常量(Constants)

支持的数据类型:

  • string: single quotes, ‘foobar’
  • numeric: 10, 3.1415926
  • bool: true or false
  • datetime: single quotes, conform to RFC3339. Datetime of RFC3339 format is YYYY-MM-DDTHH:mm:SS[.sssssssss]Z, Z is [+|-]HH:mm.
  • array: array of type string, numeric, bool, datetime

各种常量的例子如下表所示:

数据类型
Data Type
常量例子
Constant Samples
常量数组例子
Array Constant Samples
string 'a string' ('string1', 'string2')
bool true
false
(true, false, true)
numeric / float 2.1 (1, 2, 3.1)
datetime '2006-01-02T15:04:05-07:00' ('2016-01-02T15:04:05-07:00', '2019-01-02T15:04:05-07:00')

2.4 函数(Functions)

当简单的运算或比较操作符不满足需求时,可以使用函数。函数也分为内置函数和用户自定义函数。

2.4.1 内置函数(Built-in Functions)

Speedle 提供以下内置函数:

Built-in Function Name Functionality Input and Data Type Output and Data Type Sample Usage
Sqrt 求平方根 One numeric parameter numeric Sqrt(x)
Sqrt(64)
Max 取集合中的最大值 1+ numeric parameters numeric Max(1, 4, x)
Min 取集合中的最小值 1+ numeric parameters numeric Min(x, 5, z)
Sum 求和 1+ numeric parameters numeric Sum(1, 3, 5, 7, x)
Avg 求平均值 1+ numeric parameters numeric Avg(x, 8, 10)
IsSubSet 第一个参数是否是第二个参数的子集 2 sets/arrays, elements of the 2 sets/arrays have same data type bool IsSubSet(s1, s2)

数值内置函数会以 BuiltInFuncError 拒绝非有限数值、非有限结果和负数平方根。与其他运行时条件错误一致,函数失败时该条件不匹配。Sum() 和 Avg() 保留历史行为:无参数时返回零。IsSubSet 忽略重复元素,拒绝不支持或混合的元素类型,并保留空集合返回 false 的历史行为。SPDL 名称引号中的反斜杠保持字面含义;名称包含引号时使用另一种引号包围。语句必须完整解析,尾随文本、不完整条件和未闭合的名称引号会被拒绝。

2.4.2 用户自定义函数(Custom Functions)

用户可以向 Speedle 暴露自己定义的函数, 并将自定义函数用于 condition.
更多细节, 参见 custom function.

2.5 运算比较操作符的优先级(operator/Comparator Precedence)

2.5.1 优先顺序(Precedence order)

当两个运算符共享一个操作数时,优先级较高的运算符优先。例如, 1 + 2 * 3 被处理成 1 + (2 * 3), 但是 1 * 2 + 3 被处理成 (1 * 2) + 3。 因为乘法比加法的优先级高。

2.5.2 关联(Associativity)

当表达式具有两个具有相同优先级的运算符时,将根据其关联性来计算表达式。 72/2/3被视为(72/2)/ 3,因为/运算符具有从左到右的关联性。 有些运算符不是关联的:例如,表达式(x <= y <= z)和x ++ -无效。

2.5.3 Precedence and Associativity of Supported Operators and Comparators

下表列出本文公开语法的优先级。比较运算先于逻辑与/或;组合复杂条件时建议使用括号。

优先级(由高到低)运算符/比较符结合性
1( )N/A
2function callN/A
3! and unary -Right to left
4* / %Left to right
5+ -Left to right
6== != =~ > >= < <= inN/A
7&&Left to right
8||Left to right

2.6 Condition 示例

Condition Comment
a=='abc' Value of attribute 'a' equals 'abc'
a!='abc'
a>='abc'
a+b=='ab'
a=~'^get.*'Value of attribute 'a' matches regular expression '^get.*'
a==123
a-b>123
a in (1, 2, 3) Value of attribute 'a' is one of 1, 2, 3
'manager' in a 'a' is an attribute of string array, 'manager' is one of the array element
IsSubSet(e, ('s1', 's2', 's3'))'e' is an attribute of string array/set, and e is subset of array/set ('s1', 's2', 's3')
a in (1, 2, 3) && (b==c || d==3) && IsSubSet(e, ('s1', 's2', 's3'))
request_year==2019 && request_month==12 request_year and request_month are built-in attributes. The year when a resource is accessed equals 2019, and the month when the resource is accessed is 12

Condition 定义

Condition 必须是一个合法的布尔表达式。 下面是常用表达式的语法摘要,具体输入应以当前解析器和实际测试为准:

BoolExpr: ('!')BoolExpr
          | BoolExpr ('&&'|'||') BoolExpr
		  | BoolConstant
		  | Attribute
		  | Function
		  | RelationalExpr
		  | '(' BoolExpr ')'


RelationalExpr: NumericExpr ('=='|'!='|'>'|'>='|'<'|'<=') NumericExpr
              | StringExpr ('=='|'!='|'=~'|'>'|'>='|'<'|'<=') StringExpr
			  | BoolExpr ('=='|'!=') BoolExpr
			  | DateTimeExpr ('=='|'!='|'>'|'>='|'<'|'<=') DateTimeExpr
			  | (NumericExpr|StringExpr|BoolExpr|DateTimeExpr) ('in') ArrayExpr


NumericExpr: NumericExpr('+'|'-'|'*'|'/'|'%')NumericExpr
           | NumericConstant
		   | Attribute
		   | Function
		   | '(' NumericExpr ')'

StringExpr: StringExpr('+') StringExpr
           | StringConstant
		   | Attribute
		   | Function
           | '(' StringExpr ')'

DateTimeExpr: DateTimeConstant
           | Attribute
           | Function

ArrayExpr: ArrayConstant
         | Attribute
         | Function

ArrayConstant: '('Constant [, Constant]* ')'

Constant: NumericConstant
         |StringConstant
         |BoolConstant
         |DateTimeConstant

NumericConstant: any numeric float64 data
StringConstant: single quoted string, for example, 'string1'
BoolConstant: true|false
DateTimeConstant: single quoted datetime, datetime should conform to the format defined by RFC3339: YYYY-MM-DDTHH:mm:SS[.sssssssss]Z, Z is [+|-]HH:mm. For example, '2016-01-02T15:04:05-07:00'

Attribute: attribute name should conform to  [a-zA-Z]+[a-zA-Z0-9_]*, prefer simple portable identifiers; REST attribute names are limited to 256 ASCII characters
Function: FunctionName '(' Argument [,Argument]* ')'

附录

完整策略定义语法

完整策略定义语法