Syntax
Keywords
The reserved keywords in SPDL are as follows. You cannot use any of these keywords as user name, group name, action, resource, attribute name, and so on.
- role
- user
- group
- entity
- grant
- deny
- if
- in
- on
- from
The keywords are all case-insensitive, which means that you cannot use one of “role”, “ROLE”, “Role”, “rOLe”, etc as user name, group name, action, resource, attribute name, and so on.
Naming Convention
User Name: a user name consists of letters, decimal digits, punctuation marks except for comma i.e. [\p{L}\p{Nd}[\p{Punct}&&[^,]]]+ Group Name: a group name consists of letters, decimal digits, punctuation marks except for comma i.e. [\p{L}\p{Nd}[\p{Punct}&&[^,]]]+ Role Name: a role name consists of letters, decimal digits, punctuation marks except for comma i.e. [\p{L}\p{Nd}[\p{Punct}&&[^,]]]+ Action: an action consists of letters, decimal digits, punctuation marks except for comma i.e. [\p{L}\p{Nd}[\p{Punct}&&[^,]]]+ Resource: a resource consists of letters, decimal digits, punctuation marks i.e. [\p{L}\p{Nd}\p{Punct}]+
Please see Unicode Standard and Javadoc for the definition of letter, decimal digit, and punctuation mark.
Syntax
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 = [\p{L}\p{Nd}\p{Punct}]+ ACTION = (ACTION_IDENTIFIER)(, ACTION_IDENTIFIER)* RESOURCE = RESOURCE_IDENTIFIER PRINCIPAL_NAME = [\p{L}\p{Nd}[\p{Punct}&&[^,]]]+ ACTION_IDENTIFIER = [\p{L}\p{Nd}[\p{Punct}&&[^,]]]+ RESOURCE_IDENTIFIER = [\p{L}\p{Nd}\p{Punct}]+
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 = [\p{L}\p{Nd}\p{Punct}]+ ROLE = (role)? SUBJECT_IDENTIFIER RESOURCE = RESOURCE_IDENTIFIER SUBJECT_IDENTIFIER = [\p{L}\p{Nd}[\p{Punct}&&[^,]]]+ RESOURCE_IDENTIFIER = [\p{L}\p{Nd}\p{Punct}]+
Condition
1. Overview
Condition is supported in both policy and role policy definitions. The policy or role policy can take effect only when the condition is met.
This document focuses on what a condition is, and how to write a condition.
2. Condition
A condition is a bool expression that is constructed using attributes, functions, constants, operators, comparators or parenthesis and produces a bool value.
2.1 Data Types
The data type of an attribute value and constant can be a string, numeric, bool, datetime or an array of string, numeric, bool, datetime.
The data types and the corresponding supported operators and comparators are listed in following table.
Data Type | Operators | Comparators | Comment |
---|---|---|---|
string | + | == != =~ > >= < <= |
’+’ is for string concatenation ‘=~’ is for regular expr matching, see the annotation below the table. |
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 |
Most comparators are self explanatory, here is the annotation for "=~"
:
"=~"
is the regex comparator. It uses Go’s standard regexp flavor of regex. The left side is expected to be the candidate string; the right side is the pattern.
"=~"
returns whether or not the candidate string matches the regex pattern given on the right.
- Left side: string
- Right side: string
- Returns: bool
2.2 Attributes
An attribute in a condition represents a variable. The attribute value is determined at runtime, obtained from either the Authorization Decision Service (ADS) runtime or the customer. Built-in attributes are those values that are populated by the ADS runtime. Customer attributes are those values that are provided by the customer when asking the ADS for authorization decisions.
2.2.1 Built-in Attributes
Built-in attributes are as follows:
Built-in Attribute Name | Data Type | Sample Value | Definition |
---|---|---|---|
request_user | string | "Alice" | The user information in the subject who is requesting to act on a resource |
request_groups | []string | []string{"managers"} | The groups information in the subject who is requesting to act on a resource |
request_entity | string | "/org1/service1" | The service name or other entity info in the subject which the service or program is requesting to act on a resource |
request_resource | string | "commercialLoans" | The resource on which the subject is to act |
request_action | string | "issue" | The action that the subject is to carry out on a resource |
request_time | datetime | '2019-01-02T15:04:05-07:00' | The date and time when the request happens |
request_year | int | 2019 | The year when the request happens |
request_month | int | 1, 2, ... 12 | The month when the request happens |
request_day | int | 1, 2, ... 31 | The day in a month when the request happens |
request_hour | int | 0, 1, ... 23 | The hour in a day when the request happens |
request_weekday | string | "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" | The day of the week when the request happens |
2.2.2 Customer Attributes
2.2.2.1 name
A valid customer attribute name is a sequence of letters, digits or the underscore character " _ "
. It must begin with a letter, and is limited to 255 characters. Customer attribute names must adhere to this rule, and should not use any reserved words (built-in attribute, built-in function name, operators, comparators) as attribute names.
2.2.2.2 value
When customer attributes are used in a condition, the customer needs to pass the customer attribute values when requesting an isAllowed result.
Passing attribute values in Golang API
Adhere to these rules when passing customer attribute values to a Golang API:- Use Golang bool type for bool attribute value.
- Use Golang string type for string attribute value.
- Use Golang float64 type for any numeric attribute value.
- For datetime attribute value, use a Golang float64 representation of that datetime’s Unix time (using
time.Time.Unix()
). - Use Golang []interface{} for array attribute value.
Passing attribute values in REST API
Adhere to these rules when passing customer attribute values to a REST API:- Attribute is a struct, which contains name, type, value of the attribute. See the REST API for details.
- Attribute type can be only “string”, “numeric”, “bool” or “datetime”.
- Attribute value can be a single value or a slice.
2.3 Constants
Supported data types:
- 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
The following table shows sample constants.
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
Use functions when existing operators or comparators do not meet customer requirements.
2.4.1 Built-in Functions
Speedle provides the following built-in functions.
Built-in Function Name | Functionality | Input and Data Type | Output and Data Type | Sample Usage |
---|---|---|---|---|
Sqrt | Square root of a numeric | One numeric parameter | numeric | Sqrt(x) Sqrt(64) |
Max | Get the max numeric in a set | 1+ numeric parameters | numeric | Max(1, 4, x) |
Min | Get the min numeric in a set | 1+ numeric parameters | numeric | Min(x, 5, z) |
Sum | Get the sum of a set of numeric | 1+ numeric parameters | numeric | Sum(1, 3, 5, 7, x) |
Avg | Get the average value for a set of numeric | 1+ numeric parameters | numeric | Avg(x, 8, 10) |
IsSubSet | Check if the first set/array is a subset of the second set/array | 2 sets/arrays, elements of the 2 sets/arrays have same data type | bool | IsSubset(s1, s2)) |
2.4.2 Custom Functions
Customers can also expose their own functions through a REST API, and use custom functions in a condition expression.
For details, see custom function.
2.5 Operator/Comparator Precedence
2.5.1 Precedence order
When two operators share an operand, the operator with the higher precedence goes first. For example, 1 + 2 * 3
is treated as 1 + (2 * 3)
, whereas 1 * 2 + 3
is treated as (1 * 2) + 3
because multiplication has a higher precedence than addition.
2.5.2 Associativity
When an expression has two operators with the same precedence, the expression is evaluated according to its associativity. 72 / 2 / 3
is treated as (72 / 2) / 3
because the /
operator has left-to-right associativity. Some operators are not associative: for example, the expressions (x <= y <= z)
and x++--
are invalid.
2.5.3 Precedence and Associativity of Supported Operators and Comparators
The following table lists all supported operators/comparators from highest to lowest precedence, along with their associativity.
Precedence | Operator/Comparator | Description | Associativity |
---|---|---|---|
7 | ( ) | parentheses | N/A |
6 | function call | N/A | |
5 | * / % |
Left to right | |
4 | + - |
1+ numeric parameters | Left to right |
3 | ! | N/A | |
2 | && | Left to right | |
1 | || | Left to right | |
0 | == != =~ > >= < <= in |
N/A |
2.6 Sample Conditions
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 Definition
Condition should be a valid bool expression. The bool expression Speedle supports is strictly defined as follows:
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_]*, length should be <=255
Function: FuntionName '(' Argument [,Argument]* ')'
Appendix
Full Syntax of SPDL