├── .github └── workflows │ └── opa.yml ├── .gitignore ├── LICENSE ├── README.md ├── data.json ├── images └── flow.png ├── input.json ├── main.go ├── rbac.authz.rego └── rbac.authz_test.rego /.github/workflows/opa.yml: -------------------------------------------------------------------------------- 1 | name: Open Policy Agent Testing 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - main 10 | 11 | jobs: 12 | test: 13 | strategy: 14 | matrix: 15 | os: [ubuntu-latest, macos-latest] 16 | name: ${{ matrix.os }} 17 | runs-on: ${{ matrix.os }} 18 | steps: 19 | - name: Checkout Code 20 | uses: actions/checkout@v2 21 | with: 22 | ref: ${{ github.ref }} 23 | 24 | - name: Download OPA Binary 25 | if: startsWith(matrix.os, 'macOS') 26 | run: | 27 | curl -L -o opa https://openpolicyagent.org/downloads/latest/opa_darwin_amd64 28 | chmod +x opa 29 | ./opa -h 30 | 31 | - name: Download OPA Binary 32 | if: startsWith(matrix.os, 'ubuntu') 33 | run: | 34 | curl -L -o opa https://openpolicyagent.org/downloads/latest/opa_linux_amd64 35 | chmod +x opa 36 | ./opa -h 37 | 38 | - name: Run Testing 39 | run: | 40 | ./opa test -v *.rego 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | _build 2 | _tracks 3 | 4 | opa-debug-js 5 | 6 | *.opp 7 | *.opx 8 | *.opx.broken 9 | *.dump 10 | *.api 11 | *.api-txt 12 | *.exe 13 | *.log 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 golang workshop 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # opa-resful 2 | 3 | [![Open Policy Agent Testing](https://github.com/go-training/opa-restful/actions/workflows/opa.yml/badge.svg)](https://github.com/go-training/opa-restful/actions/workflows/opa.yml) 4 | 5 | ## System Flow 6 | 7 | ![flow](./images/flow.png) 8 | 9 | ## Integrating with the REST API 10 | 11 | This document is the authoritative specification of the [OPA REST API](https://www.openpolicyagent.org/docs/latest/rest-api/). 12 | 13 | ### Run Open Policy Server 14 | 15 | Run OPA server using the following command: 16 | 17 | ```sh 18 | $ opa run --server 19 | {"addrs":[":8181"],"diagnostic-addrs":[],"level":"info","msg":"Initializing server.","time":"2021-04-27T15:54:57+08:00"} 20 | ``` 21 | 22 | ### Upload custom data 23 | 24 | Uploading the role permission and group data: 25 | 26 | ```sh 27 | curl -X PUT http://localhost:8181/v1/data/rbac/authz/acl --data-binary @data.json 28 | ``` 29 | 30 | See the data with `JSON` format: 31 | 32 | ```json 33 | { 34 | "group_roles": { 35 | "admin": ["admin"], 36 | "quality_head_design": ["quality_head_design"], 37 | "quality_head_system": ["quality_head_system"], 38 | "quality_head_manufacture": ["quality_head_manufacture"], 39 | "kpi_editor_design": ["kpi_editor_design"], 40 | "kpi_editor_system": ["kpi_editor_system"], 41 | "kpi_editor_manufacture": ["kpi_editor_manufacture"], 42 | "viewer": ["viewer"], 43 | "viewer_limit_ds": ["viewer_limit_ds"], 44 | "viewer_limit_m": ["viewer_limit_m"], 45 | "design_group_kpi_editor": ["kpi_editor_design", "viewer_limit_ds"], 46 | "system_group_kpi_editor": ["kpi_editor_system", "viewer_limit_ds"], 47 | "manufacture_group_kpi_editor": ["kpi_editor_manufacture", "viewer"], 48 | "project_leader": ["viewer_limit_ds", "viewer_limit_m"] 49 | }, 50 | "role_permissions": { 51 | "admin": [ 52 | {"action": "view_all", "object": "design"}, 53 | {"action": "edit", "object": "design"}, 54 | {"action": "view_all", "object": "system"}, 55 | {"action": "edit", "object": "system"}, 56 | {"action": "view_all", "object": "manufacture"}, 57 | {"action": "edit", "object": "manufacture"} 58 | ], 59 | "quality_head_design": [ 60 | {"action": "view_all", "object": "design"}, 61 | {"action": "edit", "object": "design"}, 62 | {"action": "view_all", "object": "system"}, 63 | {"action": "view_all", "object": "manufacture"} 64 | ], 65 | "quality_head_system": [ 66 | {"action": "view_all", "object": "design"}, 67 | {"action": "view_all", "object": "system"}, 68 | {"action": "edit", "object": "system"}, 69 | {"action": "view_all", "object": "manufacture"} 70 | ], 71 | "quality_head_manufacture": [ 72 | {"action": "view_all", "object": "design"}, 73 | {"action": "view_all", "object": "system"}, 74 | {"action": "view_all", "object": "manufacture"}, 75 | {"action": "edit", "object": "manufacture"} 76 | ], 77 | "kpi_editor_design": [ 78 | {"action": "view_all", "object": "design"}, 79 | {"action": "edit", "object": "design"} 80 | ], 81 | "kpi_editor_system": [ 82 | {"action": "view_all", "object": "system"}, 83 | {"action": "edit", "object": "system"} 84 | ], 85 | "kpi_editor_manufacture": [ 86 | {"action": "view_all", "object": "manufacture"}, 87 | {"action": "edit", "object": "manufacture"} 88 | ], 89 | "viewer": [ 90 | {"action": "view_all", "object": "design"}, 91 | {"action": "view_all", "object": "system"}, 92 | {"action": "view_all", "object": "manufacture"} 93 | ], 94 | "viewer_limit_ds": [ 95 | {"action": "view_all", "object": "design"}, 96 | {"action": "view_all", "object": "system"} 97 | ], 98 | "viewer_limit_m": [{"action": "view_l3_project", "object": "manufacture"}] 99 | } 100 | } 101 | ``` 102 | 103 | Try to fetch group roles data: 104 | 105 | ```sh 106 | # curl tool 107 | $ curl http://localhost:8181/v1/data/rbac/authz/acl/group_roles | jq 108 | # or bat tool 109 | $ bat GET http://localhost:8181/v1/data/rbac/authz/acl/group_roles 110 | ``` 111 | 112 | See the result: 113 | 114 | ```sh 115 | $ curl http://localhost:8181/v1/data/rbac/authz/acl/group_roles | jq 116 | % Total % Received % Xferd Average Speed Time Time Time Current 117 | Dload Upload Total Spent Left Speed 118 | 100 661 100 661 0 0 107k 0 --:--:-- --:--:-- --:--:-- 107k 119 | { 120 | "result": { 121 | "admin": [ 122 | "admin" 123 | ], 124 | "design_group_kpi_editor": [ 125 | "kpi_editor_design", 126 | "viewer_limit_ds" 127 | ], 128 | "kpi_editor_design": [ 129 | "kpi_editor_design" 130 | ], 131 | "kpi_editor_manufacture": [ 132 | "kpi_editor_manufacture" 133 | ], 134 | "kpi_editor_system": [ 135 | "kpi_editor_system" 136 | ], 137 | "manufacture_group_kpi_editor": [ 138 | "kpi_editor_manufacture", 139 | "viewer" 140 | ], 141 | "project_leader": [ 142 | "viewer_limit_ds", 143 | "viewer_limit_m" 144 | ], 145 | "quality_head_design": [ 146 | "quality_head_design" 147 | ], 148 | "quality_head_manufacture": [ 149 | "quality_head_manufacture" 150 | ], 151 | "quality_head_system": [ 152 | "quality_head_system" 153 | ], 154 | "system_group_kpi_editor": [ 155 | "kpi_editor_system", 156 | "viewer_limit_ds" 157 | ], 158 | "viewer": [ 159 | "viewer" 160 | ], 161 | "viewer_limit_ds": [ 162 | "viewer_limit_ds" 163 | ], 164 | "viewer_limit_m": [ 165 | "viewer_limit_m" 166 | ] 167 | } 168 | } 169 | ``` 170 | 171 | ### Upload policy data 172 | 173 | ```sh 174 | curl -X PUT http://localhost:8181/v1/policies/rbac.authz --data-binary @rbac.authz.rego 175 | ``` 176 | 177 | See the rego data 178 | 179 | ```rego 180 | package rbac.authz 181 | 182 | import data.rbac.authz.acl 183 | import input 184 | 185 | # logic that implements RBAC. 186 | default allow = false 187 | 188 | allow { 189 | # lookup the list of roles for the user 190 | roles := acl.group_roles[input.user[_]] 191 | 192 | # for each role in that list 193 | r := roles[_] 194 | 195 | # lookup the permissions list for role r 196 | permissions := acl.role_permissions[r] 197 | 198 | # for each permission 199 | p := permissions[_] 200 | 201 | # check if the permission granted to r matches the user's request 202 | p == {"action": input.action, "object": input.object} 203 | } 204 | ``` 205 | 206 | ### Testing your input 207 | 208 | Using [curl](https://curl.se/) tool. 209 | 210 | ```sh 211 | curl -X POST http://localhost:8181/v1/data/rbac/authz/allow --data-binary @input.json 212 | ``` 213 | 214 | Using [bat](https://github.com/astaxie/bat) tool. 215 | 216 | ```sh 217 | $ bat POST http://localhost:8181/v1/data/rbac/authz/allow < input.json 218 | POST /v1/data/rbac/authz/allow HTTP/1.1 219 | Host: localhost:8181 220 | Accept: application/json 221 | Accept-Encoding: gzip, deflate 222 | Content-Type: application/json 223 | User-Agent: bat/0.1.0 224 | 225 | 226 | {"input":{"action":"edit","object":"design","user":["design_group_kpi_editor","system_group_kpi_editor"]}} 227 | 228 | 229 | HTTP/1.1 200 OK 230 | Content-Type: application/json 231 | Date: Sat, 01 May 2021 08:43:30 GMT 232 | Content-Length: 15 233 | 234 | 235 | { 236 | "result": true 237 | } 238 | ``` 239 | 240 | See the input data with `JSON` format. 241 | 242 | ```json 243 | { 244 | "input": { 245 | "user": ["design_group_kpi_editor", "system_group_kpi_editor"], 246 | "action": "edit", 247 | "object": "design" 248 | } 249 | } 250 | ``` 251 | 252 | or testing in golang: 253 | 254 | ```go 255 | package main 256 | 257 | import ( 258 | "bytes" 259 | _ "embed" 260 | "fmt" 261 | "io/ioutil" 262 | "net/http" 263 | "time" 264 | ) 265 | 266 | //go:embed input.json 267 | var input []byte 268 | 269 | func main() { 270 | url := "http://localhost:8181/v1/data/rbac/authz/allow" 271 | method := "POST" 272 | 273 | payload := bytes.NewReader(input) 274 | 275 | client := &http.Client{ 276 | Timeout: 5 * time.Second, 277 | } 278 | req, err := http.NewRequest(method, url, payload) 279 | 280 | if err != nil { 281 | fmt.Println(err) 282 | return 283 | } 284 | req.Header.Add("Content-Type", "application/json") 285 | 286 | res, err := client.Do(req) 287 | if err != nil { 288 | fmt.Println(err) 289 | return 290 | } 291 | defer res.Body.Close() 292 | 293 | body, err := ioutil.ReadAll(res.Body) 294 | if err != nil { 295 | fmt.Println(err) 296 | return 297 | } 298 | fmt.Println(string(body)) 299 | } 300 | ``` 301 | -------------------------------------------------------------------------------- /data.json: -------------------------------------------------------------------------------- 1 | { 2 | "group_roles": { 3 | "admin": ["admin"], 4 | "quality_head_design": ["quality_head_design"], 5 | "quality_head_system": ["quality_head_system"], 6 | "quality_head_manufacture": ["quality_head_manufacture"], 7 | "kpi_editor_design": ["kpi_editor_design"], 8 | "kpi_editor_system": ["kpi_editor_system"], 9 | "kpi_editor_manufacture": ["kpi_editor_manufacture"], 10 | "viewer": ["viewer"], 11 | "viewer_limit_ds": ["viewer_limit_ds"], 12 | "viewer_limit_m": ["viewer_limit_m"], 13 | "design_group_kpi_editor": ["kpi_editor_design", "viewer_limit_ds"], 14 | "system_group_kpi_editor": ["kpi_editor_system", "viewer_limit_ds"], 15 | "manufacture_group_kpi_editor": ["kpi_editor_manufacture", "viewer"], 16 | "project_leader": ["viewer_limit_ds", "viewer_limit_m"] 17 | }, 18 | "role_permissions": { 19 | "admin": [ 20 | {"action": "view_all", "object": "design"}, 21 | {"action": "edit", "object": "design"}, 22 | {"action": "view_all", "object": "system"}, 23 | {"action": "edit", "object": "system"}, 24 | {"action": "view_all", "object": "manufacture"}, 25 | {"action": "edit", "object": "manufacture"} 26 | ], 27 | "quality_head_design": [ 28 | {"action": "view_all", "object": "design"}, 29 | {"action": "edit", "object": "design"}, 30 | {"action": "view_all", "object": "system"}, 31 | {"action": "view_all", "object": "manufacture"} 32 | ], 33 | "quality_head_system": [ 34 | {"action": "view_all", "object": "design"}, 35 | {"action": "view_all", "object": "system"}, 36 | {"action": "edit", "object": "system"}, 37 | {"action": "view_all", "object": "manufacture"} 38 | ], 39 | "quality_head_manufacture": [ 40 | {"action": "view_all", "object": "design"}, 41 | {"action": "view_all", "object": "system"}, 42 | {"action": "view_all", "object": "manufacture"}, 43 | {"action": "edit", "object": "manufacture"} 44 | ], 45 | "kpi_editor_design": [ 46 | {"action": "view_all", "object": "design"}, 47 | {"action": "edit", "object": "design"} 48 | ], 49 | "kpi_editor_system": [ 50 | {"action": "view_all", "object": "system"}, 51 | {"action": "edit", "object": "system"} 52 | ], 53 | "kpi_editor_manufacture": [ 54 | {"action": "view_all", "object": "manufacture"}, 55 | {"action": "edit", "object": "manufacture"} 56 | ], 57 | "viewer": [ 58 | {"action": "view_all", "object": "design"}, 59 | {"action": "view_all", "object": "system"}, 60 | {"action": "view_all", "object": "manufacture"} 61 | ], 62 | "viewer_limit_ds": [ 63 | {"action": "view_all", "object": "design"}, 64 | {"action": "view_all", "object": "system"} 65 | ], 66 | "viewer_limit_m": [{"action": "view_l3_project", "object": "manufacture"}] 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /images/flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-training/opa-restful/3086e5876173e88c917cc7b4c06c2227c7677a77/images/flow.png -------------------------------------------------------------------------------- /input.json: -------------------------------------------------------------------------------- 1 | { 2 | "input": { 3 | "user": ["design_group_kpi_editor", "system_group_kpi_editor"], 4 | "action": "edit", 5 | "object": "design" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | _ "embed" 6 | "fmt" 7 | "io/ioutil" 8 | "net/http" 9 | "time" 10 | ) 11 | 12 | //go:embed input.json 13 | var input []byte 14 | 15 | func main() { 16 | url := "http://localhost:8181/v1/data/rbac/authz/allow" 17 | method := "POST" 18 | 19 | payload := bytes.NewReader(input) 20 | 21 | client := &http.Client{ 22 | Timeout: 5 * time.Second, 23 | } 24 | req, err := http.NewRequest(method, url, payload) 25 | 26 | if err != nil { 27 | fmt.Println(err) 28 | return 29 | } 30 | req.Header.Add("Content-Type", "application/json") 31 | 32 | res, err := client.Do(req) 33 | if err != nil { 34 | fmt.Println(err) 35 | return 36 | } 37 | defer res.Body.Close() 38 | 39 | body, err := ioutil.ReadAll(res.Body) 40 | if err != nil { 41 | fmt.Println(err) 42 | return 43 | } 44 | fmt.Println(string(body)) 45 | } 46 | -------------------------------------------------------------------------------- /rbac.authz.rego: -------------------------------------------------------------------------------- 1 | package rbac.authz 2 | 3 | import data.rbac.authz.acl 4 | import input 5 | 6 | # logic that implements RBAC. 7 | default allow = false 8 | 9 | allow { 10 | # lookup the list of roles for the user 11 | roles := acl.group_roles[input.user[_]] 12 | 13 | # for each role in that list 14 | r := roles[_] 15 | 16 | # lookup the permissions list for role r 17 | permissions := acl.role_permissions[r] 18 | 19 | # for each permission 20 | p := permissions[_] 21 | 22 | # check if the permission granted to r matches the user's request 23 | p == {"action": input.action, "object": input.object} 24 | } 25 | -------------------------------------------------------------------------------- /rbac.authz_test.rego: -------------------------------------------------------------------------------- 1 | package rbac.authz 2 | 3 | acl = { 4 | "group_roles": { 5 | "admin": ["admin"], 6 | "quality_head_design": ["quality_head_design"], 7 | "quality_head_system": ["quality_head_system"], 8 | "quality_head_manufacture": ["quality_head_manufacture"], 9 | "kpi_editor_design": ["kpi_editor_design"], 10 | "kpi_editor_system": ["kpi_editor_system"], 11 | "kpi_editor_manufacture": ["kpi_editor_manufacture"], 12 | "viewer": ["viewer"], 13 | "viewer_limit_ds": ["viewer_limit_ds"], 14 | "viewer_limit_m": ["viewer_limit_m"], 15 | "design_group_kpi_editor": ["kpi_editor_design", "viewer_limit_ds"], 16 | "system_group_kpi_editor": ["kpi_editor_system", "viewer_limit_ds"], 17 | "manufacture_group_kpi_editor": ["kpi_editor_manufacture", "viewer"], 18 | "project_leader": ["viewer_limit_ds", "viewer_limit_m"], 19 | }, 20 | "role_permissions": { 21 | "admin": [ 22 | {"action": "view_all", "object": "design"}, 23 | {"action": "edit", "object": "design"}, 24 | {"action": "view_all", "object": "system"}, 25 | {"action": "edit", "object": "system"}, 26 | {"action": "view_all", "object": "manufacture"}, 27 | {"action": "edit", "object": "manufacture"}, 28 | ], 29 | "quality_head_design": [ 30 | {"action": "view_all", "object": "design"}, 31 | {"action": "edit", "object": "design"}, 32 | {"action": "view_all", "object": "system"}, 33 | {"action": "view_all", "object": "manufacture"}, 34 | ], 35 | "quality_head_system": [ 36 | {"action": "view_all", "object": "design"}, 37 | {"action": "view_all", "object": "system"}, 38 | {"action": "edit", "object": "system"}, 39 | {"action": "view_all", "object": "manufacture"}, 40 | ], 41 | "quality_head_manufacture": [ 42 | {"action": "view_all", "object": "design"}, 43 | {"action": "view_all", "object": "system"}, 44 | {"action": "view_all", "object": "manufacture"}, 45 | {"action": "edit", "object": "manufacture"}, 46 | ], 47 | "kpi_editor_design": [ 48 | {"action": "view_all", "object": "design"}, 49 | {"action": "edit", "object": "design"}, 50 | ], 51 | "kpi_editor_system": [ 52 | {"action": "view_all", "object": "system"}, 53 | {"action": "edit", "object": "system"}, 54 | ], 55 | "kpi_editor_manufacture": [ 56 | {"action": "view_all", "object": "manufacture"}, 57 | {"action": "edit", "object": "manufacture"}, 58 | ], 59 | "viewer": [ 60 | {"action": "view_all", "object": "design"}, 61 | {"action": "view_all", "object": "system"}, 62 | {"action": "view_all", "object": "manufacture"}, 63 | ], 64 | "viewer_limit_ds": [ 65 | {"action": "view_all", "object": "design"}, 66 | {"action": "view_all", "object": "system"}, 67 | ], 68 | "viewer_limit_m": [{"action": "view_l3_project", "object": "manufacture"}], 69 | }, 70 | } 71 | 72 | test_design_group_kpi_editor { 73 | allow with input as {"user": ["design_group_kpi_editor"], "action": "view_all", "object": "design"} with data.rbac.authz.acl as acl 74 | allow with input as {"user": ["design_group_kpi_editor"], "action": "edit", "object": "design"} with data.rbac.authz.acl as acl 75 | allow with input as {"user": ["design_group_kpi_editor"], "action": "view_all", "object": "system"} with data.rbac.authz.acl as acl 76 | not allow with input as {"user": ["design_group_kpi_editor"], "action": "edit", "object": "system"} with data.rbac.authz.acl as acl 77 | not allow with input as {"user": ["design_group_kpi_editor"], "action": "view_all", "object": "manufacture"} with data.rbac.authz.acl as acl 78 | not allow with input as {"user": ["design_group_kpi_editor"], "action": "edit", "object": "manufacture"} with data.rbac.authz.acl as acl 79 | } 80 | 81 | test_system_group_kpi_editor { 82 | allow with input as {"user": ["system_group_kpi_editor"], "action": "view_all", "object": "design"} with data.rbac.authz.acl as acl 83 | not allow with input as {"user": ["system_group_kpi_editor"], "action": "edit", "object": "design"} with data.rbac.authz.acl as acl 84 | allow with input as {"user": ["system_group_kpi_editor"], "action": "view_all", "object": "system"} with data.rbac.authz.acl as acl 85 | allow with input as {"user": ["system_group_kpi_editor"], "action": "edit", "object": "system"} with data.rbac.authz.acl as acl 86 | not allow with input as {"user": ["system_group_kpi_editor"], "action": "view_all", "object": "manufacture"} with data.rbac.authz.acl as acl 87 | not allow with input as {"user": ["system_group_kpi_editor"], "action": "edit", "object": "manufacture"} with data.rbac.authz.acl as acl 88 | } 89 | 90 | test_manufacture_group_kpi_editor { 91 | allow with input as {"user": ["manufacture_group_kpi_editor"], "action": "view_all", "object": "design"} with data.rbac.authz.acl as acl 92 | not allow with input as {"user": ["manufacture_group_kpi_editor"], "action": "edit", "object": "design"} with data.rbac.authz.acl as acl 93 | allow with input as {"user": ["manufacture_group_kpi_editor"], "action": "view_all", "object": "system"} with data.rbac.authz.acl as acl 94 | not allow with input as {"user": ["manufacture_group_kpi_editor"], "action": "edit", "object": "system"} with data.rbac.authz.acl as acl 95 | allow with input as {"user": ["manufacture_group_kpi_editor"], "action": "view_all", "object": "manufacture"} with data.rbac.authz.acl as acl 96 | allow with input as {"user": ["manufacture_group_kpi_editor"], "action": "edit", "object": "manufacture"} with data.rbac.authz.acl as acl 97 | } 98 | 99 | test_project_leader { 100 | allow with input as {"user": ["project_leader"], "action": "view_all", "object": "design"} with data.rbac.authz.acl as acl 101 | not allow with input as {"user": ["project_leader"], "action": "edit", "object": "design"} with data.rbac.authz.acl as acl 102 | allow with input as {"user": ["project_leader"], "action": "view_all", "object": "system"} with data.rbac.authz.acl as acl 103 | not allow with input as {"user": ["project_leader"], "action": "edit", "object": "system"} with data.rbac.authz.acl as acl 104 | not allow with input as {"user": ["project_leader"], "action": "view_all", "object": "manufacture"} with data.rbac.authz.acl as acl 105 | not allow with input as {"user": ["project_leader"], "action": "edit", "object": "manufacture"} with data.rbac.authz.acl as acl 106 | allow with input as {"user": ["project_leader"], "action": "view_l3_project", "object": "manufacture"} with data.rbac.authz.acl as acl 107 | } 108 | 109 | test_design_group_kpi_editor_and_system_group_kpi_editor { 110 | allow with input as {"user": ["design_group_kpi_editor", "system_group_kpi_editor"], "action": "edit", "object": "design"} with data.rbac.authz.acl as acl 111 | allow with input as {"user": ["design_group_kpi_editor", "system_group_kpi_editor"], "action": "edit", "object": "system"} with data.rbac.authz.acl as acl 112 | } 113 | --------------------------------------------------------------------------------