authorize: update opa rego to support additional policy properties

This commit is contained in:
Caleb Doxsey 2020-04-16 12:15:37 -06:00 committed by Caleb Doxsey
parent 5ecfa34361
commit 428dee99c4
2 changed files with 143 additions and 11 deletions

View file

@ -8,7 +8,7 @@ default allow = false
# allow by email
allow {
some route
input.host = route_policies[route].source
allowed_route(input.url, route_policies[route])
token.payload.email = route_policies[route].allowed_users[_]
token.valid
count(deny)==0
@ -17,7 +17,7 @@ allow {
# allow group
allow {
some route
input.host = route_policies[route].source
allowed_route(input.url, route_policies[route])
token.payload.groups[_] = route_policies[route].allowed_groups[_]
token.valid
count(deny)==0
@ -26,7 +26,7 @@ allow {
# allow by impersonate email
allow {
some route
input.host = route_policies[route].source
allowed_route(input.url, route_policies[route])
token.payload.impersonate_email = route_policies[route].allowed_users[_]
token.valid
count(deny)==0
@ -35,7 +35,7 @@ allow {
# allow by impersonate group
allow {
some route
input.host = route_policies[route].source
allowed_route(input.url, route_policies[route])
token.payload.impersonate_groups[_] = route_policies[route].allowed_groups[_]
token.valid
count(deny)==0
@ -44,9 +44,8 @@ allow {
# allow by domain
allow {
some route
input.host = route_policies[route].source
some domain
email_in_domain(token.payload.email, route_policies[route].allowed_domains[domain])
allowed_route(input.url, route_policies[route])
allowed_user_domain(token.payload.email)
token.valid
count(deny)==0
}
@ -54,14 +53,69 @@ allow {
# allow by impersonate domain
allow {
some route
input.host = route_policies[route].source
some domain
email_in_domain(token.payload.impersonate_email, route_policies[route].allowed_domains[domain])
allowed_route(input.url, route_policies[route])
allowed_user_domain(token.payload.impersonate_email)
token.valid
count(deny)==0
}
email_in_domain(email, domain) {
allowed_route(input_url, policy){
input_url_obj := parse_url(input_url)
allowed_route_source(input_url_obj, policy)
allowed_route_prefix(input_url_obj, policy)
allowed_route_path(input_url_obj, policy)
allowed_route_regex(input_url_obj, policy)
}
allowed_route_source(input_url_obj, policy) {
object.get(policy, "source", "") == ""
}
allowed_route_source(input_url_obj, policy) {
object.get(policy, "source", "") != ""
source_url_obj := parse_url(policy.source)
input_url_obj.host == source_url_obj.host
startswith(input_url_obj.path, source_url_obj.path)
}
allowed_route_prefix(input_url_obj, policy) {
object.get(policy, "prefix", "") == ""
}
allowed_route_prefix(input_url_obj, policy) {
object.get(policy, "prefix", "") != ""
startswith(input_url_obj.path, policy.prefix)
}
allowed_route_path(input_url_obj, policy) {
object.get(policy, "path", "") == ""
}
allowed_route_path(input_url_obj, policy) {
object.get(policy, "path", "") != ""
policy.path == input_url_obj.path
}
allowed_route_regex(input_url_obj, policy) {
object.get(policy, "regex", "") == ""
}
allowed_route_regex(input_url_obj, policy) {
object.get(policy, "regex", "") != ""
re_match(policy.regex, input_url_obj.path)
}
parse_url(str) = { "scheme": scheme, "host": host, "path": path } {
[_, scheme, host, rawpath] = regex.find_all_string_submatch_n(
`(?:(http[s]?)://)?([^/]+)([^?#]*)`,
str, 1)[0]
path = normalize_url_path(rawpath)
}
normalize_url_path(str) = "/" {
str == ""
}
normalize_url_path(str) = str {
str != ""
}
allowed_user_domain(email){
x := split(email, "@")
count(x) == 2
x[1] == domain

View file

@ -0,0 +1,78 @@
package pomerium.authz
jwt_header := {
"typ": "JWT",
"alg": "HS256"
}
signing_key := {
"kty": "oct",
"k": "OkFmqMK9U0dmPhMCW0VYy6D_raJKwEJsMdxqdnukThzko3D_XrsihwYE0pxrUSpm0JTrW2QpIz4rT1vdEvZw67WP4xrqjiwyd7PgpPTD5xvQBM7TIKiSW0X2R0pfq_OItszPQRtb7VirrSbGJiLNS-NJMMrYVKWWtUbVSTXEjL7VcFqML5PiSe7XDmyCZjpgEpfE5Q82zIeXM2sLrz6HW2A9IwGk7mWS0c57R_2JGyFO2tCA4zEIYhWvLE62Os2tZ6YrrwdB8n35jlPpgUE6poEvIU20lPLaocozXYMqAku-KJnloJlAzKg2Xa_0iSiSgSAumx44B3n7DQjg3jPhRg"
}
shared_key := base64url.decode(signing_key.k)
test_email_allowed {
user := io.jwt.encode_sign(jwt_header, {
"aud": ["example.com"],
"email": "joe@example.com"
}, signing_key)
allow with data.route_policies as [{
"source": "example.com",
"allowed_users": ["joe@example.com"]
}] with data.signing_key as signing_key with data.shared_key as shared_key with input as {
"url": "http://example.com",
"host": "example.com",
"user": user
}
}
test_email_denied {
user := io.jwt.encode_sign(jwt_header, {
"aud": ["example.com"],
"email": "joe@example.com"
}, signing_key)
not allow with data.route_policies as [{
"source": "example.com",
"allowed_users": ["bob@example.com"]
}] with data.signing_key as signing_key with data.shared_key as shared_key with input as {
"url": "http://example.com",
"host": "example.com",
"user": user
}
}
test_parse_url {
url := parse_url("http://example.com/some/path?qs")
url.scheme == "http"
url.host == "example.com"
url.path == "/some/path"
}
test_allowed_route_source {
allowed_route("http://example.com", {"source": "example.com"})
allowed_route("http://example.com", {"source": "http://example.com"})
allowed_route("http://example.com", {"source": "https://example.com"})
not allowed_route("http://example.org", {"source": "example.com"})
allowed_route("http://example.com/some/path", {"source": "https://example.com/some/path"})
allowed_route("http://example.com/some/path", {"source": "https://example.com/some/path?qs"})
not allowed_route("http://example.com/some/other/path", {"source": "https://example.com/some/path"})
}
test_allowed_route_prefix {
allowed_route("http://example.com", {"prefix": "/"})
allowed_route("http://example.com/admin/somepath", {"prefix": "/admin"})
not allowed_route("http://example.com", {"prefix": "/admin"})
}
test_allowed_route_path {
allowed_route("http://example.com", {"path": "/"})
not allowed_route("http://example.com/admin/somepath", {"path": "/admin"})
not allowed_route("http://example.com", {"path": "/admin"})
}
test_allowed_route_regex {
allowed_route("http://example.com", {"regex": ".*"})
allowed_route("http://example.com/admin/somepath", {"regex": "/admin/.*"})
not allowed_route("http://example.com", {"regex": "[xyz]"})
}