diff --git a/api_authz/docker/docker-compose-token.yaml b/api_authz/docker/docker-compose-token.yaml index 95cb3bb6..7c491102 100644 --- a/api_authz/docker/docker-compose-token.yaml +++ b/api_authz/docker/docker-compose-token.yaml @@ -1,9 +1,14 @@ version: '2' services: opa: - image: openpolicyagent/opa:0.10.5 + image: openpolicyagent/opa:0.13.2 ports: - 8181:8181 + # WARNING: OPA is NOT running with an authorization policy configured. This + # means that clients can read and write policies in OPA. If you are + # deploying OPA in an insecure environment, be sure to configure + # authentication and authorization on the daemon. See the Security page for + # details: https://www.openpolicyagent.org/docs/security.html. command: - "run" - "--server" diff --git a/api_authz/docker/docker-compose.yaml b/api_authz/docker/docker-compose.yaml index ea1cb5bf..b0d5cd1d 100644 --- a/api_authz/docker/docker-compose.yaml +++ b/api_authz/docker/docker-compose.yaml @@ -1,9 +1,14 @@ version: '2' services: opa: - image: openpolicyagent/opa:0.10.5 + image: openpolicyagent/opa:0.13.2 ports: - 8181:8181 + # WARNING: OPA is NOT running with an authorization policy configured. This + # means that clients can read and write policies in OPA. If you are + # deploying OPA in an insecure environment, be sure to configure + # authentication and authorization on the daemon. See the Security page for + # details: https://www.openpolicyagent.org/docs/security.html. command: - "run" - "--server" diff --git a/api_authz/docker/policy/api_authz.rego b/api_authz/docker/policy/api_authz.rego index fee775e7..03460f3b 100644 --- a/api_authz/docker/policy/api_authz.rego +++ b/api_authz/docker/policy/api_authz.rego @@ -3,8 +3,8 @@ package httpapi.authz subordinates = {"alice": [], "charlie": [], "bob": ["alice"], "betty": ["charlie"]} # HTTP API request -import input as http_api -# http_api = { +import input +# input = { # "path": ["finance", "salary", "alice"], # "user": "alice", # "method": "GET" @@ -14,14 +14,14 @@ default allow = false # Allow users to get their own salaries. allow { - http_api.method = "GET" - http_api.path = ["finance", "salary", username] - username = http_api.user + input.method = "GET" + input.path = ["finance", "salary", username] + input.user == username } # Allow managers to get their subordinates' salaries. allow { - http_api.method = "GET" - http_api.path = ["finance", "salary", username] - subordinates[http_api.user][_] = username + input.method = "GET" + input.path = ["finance", "salary", username] + subordinates[input.user][_] == username } diff --git a/api_authz/docker/policy/api_authz_token.rego b/api_authz/docker/policy/api_authz_token.rego index 57facb33..70e7f830 100644 --- a/api_authz/docker/policy/api_authz_token.rego +++ b/api_authz/docker/policy/api_authz_token.rego @@ -1,35 +1,39 @@ package httpapi.authz -import input as http_api -# http_api = { -# "path": ["finance", "salary", "alice"], -# "user": "alice", -# "method": "GET", -# "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiYWxpY2UiLCJhenAiOiJhbGljZSIsInN1Ym9yZGluYXRlcyI6W10sImhyIjpmYWxzZX0.rz3jTY033z-NrKfwrK89_dcLF7TN4gwCMj-fVBDyLoM" -# } +import input # io.jwt.decode takes one argument (the encoded token) and has three outputs: # the decoded header, payload and signature, in that order. Our policy only # cares about the payload, so we ignore the others. -token = {"payload": payload} { io.jwt.decode(http_api.token, _, payload, _) } +token = {"payload": payload} { io.jwt.decode(input.token, [_, payload, _]) } # Ensure that the token was issued to the user supplying it. -user_owns_token { http_api.user = token.payload.azp } +user_owns_token { input.user == token.payload.azp } default allow = false # Allow users to get their own salaries. allow { - http_api.method = "GET" - http_api.path = ["finance", "salary", username] - username = token.payload.user + some username + input.method == "GET" + input.path = ["finance", "salary", username] + token.payload.user == username user_owns_token } # Allow managers to get their subordinate' salaries. allow { - http_api.method = "GET" - http_api.path = ["finance", "salary", username] - token.payload.subordinates[_] = username + some username + input.method == "GET" + input.path = ["finance", "salary", username] + token.payload.subordinates[_] == username + user_owns_token +} + +# Allow HR members to get anyone's salary. +allow { + input.method == "GET" + input.path = ["finance", "salary", _] + token.payload.hr == true user_owns_token }