feature/databroker: user data and session refactor project (#926)

* databroker: add databroker, identity manager, update cache (#864)

* databroker: add databroker, identity manager, update cache

* fix cache tests

* directory service (#885)

* directory: add google and okta

* add onelogin

* add directory provider

* initialize before sync, upate google provider, remove dead code

* add azure provider

* fix azure provider

* fix gitlab

* add gitlab test, fix azure test

* hook up okta

* remove dead code

* fix tests

* fix flaky test

* authorize: use databroker data for rego policy (#904)

* wip

* add directory provider

* initialize before sync, upate google provider, remove dead code

* fix flaky test

* update authorize to use databroker data

* implement signed jwt

* wait for session and user to appear

* fix test

* directory service (#885)

* directory: add google and okta

* add onelogin

* add directory provider

* initialize before sync, upate google provider, remove dead code

* add azure provider

* fix azure provider

* fix gitlab

* add gitlab test, fix azure test

* hook up okta

* remove dead code

* fix tests

* fix flaky test

* remove log line

* only redirect when no session id exists

* prepare rego query as part of create

* return on ctx done

* retry on disconnect for sync

* move jwt signing

* use !=

* use parent ctx for wait

* remove session state, remove logs

* rename function

* add log message

* pre-allocate slice

* use errgroup

* return nil on eof for sync

* move check

* disable timeout on gRPC requests in envoy

* fix gitlab test

* use v4 backoff

* authenticate: databroker changes (#914)

* wip

* add directory provider

* initialize before sync, upate google provider, remove dead code

* fix flaky test

* update authorize to use databroker data

* implement signed jwt

* wait for session and user to appear

* fix test

* directory service (#885)

* directory: add google and okta

* add onelogin

* add directory provider

* initialize before sync, upate google provider, remove dead code

* add azure provider

* fix azure provider

* fix gitlab

* add gitlab test, fix azure test

* hook up okta

* remove dead code

* fix tests

* fix flaky test

* remove log line

* only redirect when no session id exists

* prepare rego query as part of create

* return on ctx done

* retry on disconnect for sync

* move jwt signing

* use !=

* use parent ctx for wait

* remove session state, remove logs

* rename function

* add log message

* pre-allocate slice

* use errgroup

* return nil on eof for sync

* move check

* disable timeout on gRPC requests in envoy

* fix dashboard

* delete session on logout

* permanently delete sessions once they are marked as deleted

* remove permanent delete

* fix tests

* remove groups and refresh test

* databroker: remove dead code, rename cache url, move dashboard (#925)

* wip

* add directory provider

* initialize before sync, upate google provider, remove dead code

* fix flaky test

* update authorize to use databroker data

* implement signed jwt

* wait for session and user to appear

* fix test

* directory service (#885)

* directory: add google and okta

* add onelogin

* add directory provider

* initialize before sync, upate google provider, remove dead code

* add azure provider

* fix azure provider

* fix gitlab

* add gitlab test, fix azure test

* hook up okta

* remove dead code

* fix tests

* fix flaky test

* remove log line

* only redirect when no session id exists

* prepare rego query as part of create

* return on ctx done

* retry on disconnect for sync

* move jwt signing

* use !=

* use parent ctx for wait

* remove session state, remove logs

* rename function

* add log message

* pre-allocate slice

* use errgroup

* return nil on eof for sync

* move check

* disable timeout on gRPC requests in envoy

* fix dashboard

* delete session on logout

* permanently delete sessions once they are marked as deleted

* remove permanent delete

* fix tests

* remove cache service

* remove kv

* remove refresh docs

* remove obsolete cache docs

* add databroker url option

* cache: use memberlist to detect multiple instances

* add databroker service url

* remove cache service

* remove kv

* remove refresh docs

* remove obsolete cache docs

* add databroker url option

* cache: use memberlist to detect multiple instances

* add databroker service url

* wip

* remove groups and refresh test

* fix redirect, signout

* remove databroker client from proxy

* remove unused method

* remove user dashboard test

* handle missing session ids

* session: reject sessions with no id

* sessions: invalidate old sessions via databroker server version (#930)

* session: add a version field tied to the databroker server version that can be used to invalidate sessions

* fix tests

* add log

* authenticate: create user record immediately, call "get" directly in authorize (#931)
This commit is contained in:
Caleb Doxsey 2020-06-19 07:52:44 -06:00 committed by GitHub
parent 39cdb31170
commit dbd7f55b20
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
115 changed files with 8479 additions and 3584 deletions

View file

@ -1,84 +1,91 @@
package pomerium.authz
import data.route_policies
import data.shared_key
default allow = false
route := first_allowed_route(input.url)
http_status = [495, "invalid client certificate"]{
not input.is_valid_client_certificate
}
route := first_allowed_route(input.http.url)
session := input.databroker_data["type.googleapis.com/session.Session"][input.session.id]
user := input.databroker_data["type.googleapis.com/user.User"][session.user_id]
directory_user := input.databroker_data["type.googleapis.com/directory.User"][session.user_id]
# allow public
allow {
route_policies[route].AllowPublicUnauthenticatedAccess == true
data.route_policies[route].AllowPublicUnauthenticatedAccess == true
}
# allow cors preflight
allow {
route_policies[route].CORSAllowPreflight == true
input.method == "OPTIONS"
count(object.get(input.headers, "Access-Control-Request-Method", [])) > 0
count(object.get(input.headers, "Origin", [])) > 0
data.route_policies[route].CORSAllowPreflight == true
input.http.method == "OPTIONS"
count(object.get(input.http.headers, "Access-Control-Request-Method", [])) > 0
count(object.get(input.http.headers, "Origin", [])) > 0
}
# allow by email
allow {
token.payload.email = route_policies[route].allowed_users[_]
token.valid
count(deny)==0
user.email == data.route_policies[route].allowed_users[_]
}
# allow group
allow {
some group
token.payload.groups[group] == route_policies[route].allowed_groups[_]
token.valid
count(deny)==0
directory_user.groups[_] = group
data.route_policies[route].allowed_groups[_] = group
}
# allow by impersonate email
allow {
token.payload.impersonate_email = route_policies[route].allowed_users[_]
token.valid
count(deny)==0
data.route_policies[route].allowed_users[_] = input.session.impersonate_email
}
# allow by impersonate group
allow {
some group
token.payload.impersonate_groups[group] == route_policies[route].allowed_groups[_]
token.valid
count(deny)==0
input.session.impersonate_groups[_] = group
data.route_policies[route].allowed_groups[_] = group
}
# allow by domain
allow {
some domain
email_in_domain(token.payload.email, route_policies[route].allowed_domains[domain])
token.valid
count(deny)==0
email_in_domain(user.email, data.route_policies[route].allowed_domains[domain])
}
# allow by impersonate domain
allow {
some domain
email_in_domain(token.payload.impersonate_email, route_policies[route].allowed_domains[domain])
token.valid
count(deny)==0
email_in_domain(input.session.impersonate_email, data.route_policies[route].allowed_domains[domain])
}
# allow pomerium urls
allow {
contains(input.url, "/.pomerium/")
not contains(input.url,"/.pomerium/admin")
contains(input.http.url, "/.pomerium/")
not contains(input.http.url, "/.pomerium/admin")
}
# allow user is admin
allow {
element_in_list(data.admins, input.user.email)
contains(input.http.url, ".pomerium/admin")
}
# deny non-admin users from accesing admin routes
deny[reason] {
reason = [403, "user is not admin"]
not element_in_list(data.admins, user.email)
contains(input.http.url,".pomerium/admin")
}
deny[reason] {
reason = [495, "invalid client certificate"]
is_boolean(input.is_valid_client_certificate)
not input.is_valid_client_certificate
}
# returns the first matching route
first_allowed_route(input_url) = route {
route := [route | some route ; allowed_route(input.url, route_policies[route])][0]
route := [route | some route ; allowed_route(input.http.url, data.route_policies[route])][0]
}
allowed_route(input_url, policy){
@ -142,53 +149,6 @@ email_in_domain(email, domain) {
x[1] == domain
}
default expired = false
expired {
now_seconds:=time.now_ns()/1e9
expiry < now_seconds
}
deny["token is expired (exp)"]{
expired
}
deny[sprintf("token has bad audience (aud): %s not in %+v",[input.host,audiences])]{
not element_in_list(audiences,input.host)
}
# allow user is admin
allow {
element_in_list(data.admins, token.payload.email)
token.valid
count(deny)==0
contains(input.url,".pomerium/admin")
}
# deny non-admin users from accesing admin routes
deny["user is not admin"]{
not element_in_list(data.admins, token.payload.email)
contains(input.url,".pomerium/admin")
}
token = {"payload": payload, "valid": valid} {
[valid, header, payload] := io.jwt.decode_verify(
input.user, {
"secret": shared_key,
"aud": input.host,
}
)
}
user:=token.payload.user
email:=token.payload.email
groups:=token.payload.groups
audiences:=token.payload.aud
expiry:=token.payload.exp
signed_jwt:=io.jwt.encode_sign({"alg": "ES256"}, token.payload, data.signing_key)
element_in_list(list, elem) {
list[_] = elem
}