-
Notifications
You must be signed in to change notification settings - Fork 5
Add policy for Tiled scopes and filters #293
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
bdf70df
dc9ab8c
0e9837b
ce394ee
67a04cd
15a31ed
c0e18f7
7397c94
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,40 @@ | ||||||||||||||||||||||||||
| package diamond.policy.tiled | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| import data.diamond.policy.session.access_session | ||||||||||||||||||||||||||
| import data.diamond.policy.token | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| read_scopes := { | ||||||||||||||||||||||||||
| "read:metadata", | ||||||||||||||||||||||||||
| "read:data", | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| write_scopes := { | ||||||||||||||||||||||||||
| "write:metadata", | ||||||||||||||||||||||||||
| "write:data", | ||||||||||||||||||||||||||
| "create", | ||||||||||||||||||||||||||
| "register", | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| scopes_for(claims) := read_scopes | write_scopes if { | ||||||||||||||||||||||||||
| "azp" in object.keys(claims) | ||||||||||||||||||||||||||
| endswith(claims.azp, "-blueapi") | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| scopes_for(claims) := read_scopes if { | ||||||||||||||||||||||||||
| "azp" in object.keys(claims) | ||||||||||||||||||||||||||
| not endswith(claims.azp, "-blueapi") | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| scopes_for(claims) := read_scopes if { | ||||||||||||||||||||||||||
| not "azp" in object.keys(claims) | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
Comment on lines
+23
to
+30
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think these can be combined?
Suggested change
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like it fails the tests when "azp" not in token.claims? Presumably the first line is true, then it checks the second line and it isn't defined, so it returns no scopes? There is already a token if we have made it here, it just doesn't have the azp claim- I believe it is optional, so an authenticated user could have make a request without it (I think right now we're only getting it because our |
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| default scopes := set() | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| scopes := scopes_for(token.claims) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| user_sessions contains user_session if { | ||||||||||||||||||||||||||
| some session in data.diamond.data.sessions | ||||||||||||||||||||||||||
| access_session(token.claims.fedid, session.proposal_number, session.visit_number) | ||||||||||||||||||||||||||
| user_session := sprintf("%s", [session]) | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,129 @@ | ||
| package diamond.policy.tiled_test | ||
|
|
||
| import data.diamond.policy.tiled | ||
| import data.diamond.policy.token | ||
| import rego.v1 | ||
|
|
||
| test_default_no_scopes if { | ||
| tiled.scopes == set() | ||
| } | ||
|
|
||
| test_wrong_azp_read_scopes if { | ||
| tiled.scopes == tiled.read_scopes with token.claims as {} | ||
| tiled.scopes == tiled.read_scopes with token.claims as {"sub": "foo"} | ||
| tiled.scopes == tiled.read_scopes with token.claims as {"azp": "foo"} | ||
| } | ||
|
|
||
| test_blueapi_given_write_scopes if { | ||
| tiled.scopes == { | ||
| "read:metadata", | ||
| "read:data", | ||
| "write:metadata", | ||
| "write:data", | ||
| "create", | ||
| "register", | ||
| } with token.claims as {"azp": "foo-blueapi"} | ||
| } | ||
|
|
||
| diamond_data := { | ||
| "subjects": { | ||
| "alice": { | ||
| "permissions": [], | ||
| "proposals": [1], | ||
| "sessions": [], | ||
| }, | ||
| "bob": { | ||
| "permissions": ["b07_admin"], | ||
| "proposals": [], | ||
| "sessions": [11], | ||
| }, | ||
| "carol": { | ||
| "permissions": ["super_admin"], | ||
| "proposals": [], | ||
| "sessions": [], | ||
| }, | ||
| "desmond": { | ||
| "permissions": [], | ||
| "proposals": [2], | ||
| "sessions": [13], | ||
| }, | ||
| "edna": { | ||
| "permissions": [], | ||
| "proposals": [2], | ||
| "sessions": [13, 14], | ||
| }, | ||
| "oscar": { | ||
| "permissions": [], | ||
| "proposals": [], | ||
| "sessions": [], | ||
| }, | ||
| }, | ||
| "sessions": { | ||
| "11": { | ||
| "beamline": "i03", | ||
| "proposal_number": 1, | ||
| "visit_number": 1, | ||
| }, | ||
| "12": { | ||
| "beamline": "b07", | ||
| "proposal_number": 1, | ||
| "visit_number": 2, | ||
| }, | ||
| "13": { | ||
| "beamline": "b07", | ||
| "proposal_number": 2, | ||
| "visit_number": 1, | ||
| }, | ||
| "14": { | ||
| "beamline": "b07", | ||
| "proposal_number": 2, | ||
| "visit_number": 2, | ||
| }, | ||
| }, | ||
| "proposals": { | ||
| "1": {"sessions": { | ||
| "1": 11, | ||
| "2": 12, | ||
| }}, | ||
| "2": {"sessions": { | ||
| "1": 13, | ||
| "2": 14, | ||
| }}, | ||
| }, | ||
| "beamlines": {"i03": {"sessions": [11]}, "b07": {"sessions": [12, 13, 14]}}, | ||
| "admin": {"b07_admin": ["b07"]}, | ||
| } | ||
|
|
||
| test_user_session_tags if { | ||
| tiled.user_sessions == set() with data.diamond.data as diamond_data | ||
| with data.diamond.policy.token.claims as {"fedid": "oscar"} | ||
| tiled.user_sessions == { | ||
| "{\"beamline\": \"b07\", \"proposal_number\": 1, \"visit_number\": 2}", | ||
| "{\"beamline\": \"i03\", \"proposal_number\": 1, \"visit_number\": 1}", | ||
| } with data.diamond.data as diamond_data | ||
| with data.diamond.policy.token.claims as {"fedid": "alice"} | ||
| tiled.user_sessions == { | ||
| "{\"beamline\": \"b07\", \"proposal_number\": 1, \"visit_number\": 2}", | ||
| "{\"beamline\": \"i03\", \"proposal_number\": 1, \"visit_number\": 1}", | ||
| "{\"beamline\": \"b07\", \"proposal_number\": 2, \"visit_number\": 1}", | ||
| "{\"beamline\": \"b07\", \"proposal_number\": 2, \"visit_number\": 2}", | ||
| } with data.diamond.data as diamond_data | ||
| with data.diamond.policy.token.claims as {"fedid": "bob"} | ||
| tiled.user_sessions == { | ||
| "{\"beamline\": \"b07\", \"proposal_number\": 1, \"visit_number\": 2}", | ||
| "{\"beamline\": \"i03\", \"proposal_number\": 1, \"visit_number\": 1}", | ||
| "{\"beamline\": \"b07\", \"proposal_number\": 2, \"visit_number\": 1}", | ||
| "{\"beamline\": \"b07\", \"proposal_number\": 2, \"visit_number\": 2}", | ||
| } with data.diamond.data as diamond_data | ||
| with data.diamond.policy.token.claims as {"fedid": "carol"} | ||
| tiled.user_sessions == { | ||
| "{\"beamline\": \"b07\", \"proposal_number\": 2, \"visit_number\": 1}", | ||
| "{\"beamline\": \"b07\", \"proposal_number\": 2, \"visit_number\": 2}", | ||
| } with data.diamond.data as diamond_data | ||
| with data.diamond.policy.token.claims as {"fedid": "desmond"} | ||
| tiled.user_sessions == { | ||
| "{\"beamline\": \"b07\", \"proposal_number\": 2, \"visit_number\": 1}", | ||
| "{\"beamline\": \"b07\", \"proposal_number\": 2, \"visit_number\": 2}", | ||
| } with data.diamond.data as diamond_data | ||
| with data.diamond.policy.token.claims as {"fedid": "edna"} | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is azp?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"authorizing party"- the client-id that the token was minted for- i.e. this token has been one that a blueapi instance has set as headers to a request to tiled, not one that has been set in a tiled browser client or tiled login flow.
This of course then only works if your request originated with blueapi, meaning as soon as there's an experiment UI in front of that request it stops working. When we make use of token-exchange flow in keycloak from the incoming request token, I think we can request from keycloak a token with
"aud": ["blueapi", "tiled"]and check that both audiences are present, then configure our services to never give both audiences otherwise? Or make use of some optional scope for the blueapi client - I can't see many other ways of checking that the request has come from a blueapi instance (which should be the only thing permitted to write to tiled) without checking something about the party sending the token.https://www.keycloak.org/securing-apps/token-exchange