Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
affedf8
Validate tiled service account configuration at startup
tpoliaw May 21, 2026
0482d81
Add tests for tiled check
tpoliaw May 28, 2026
170e3d1
Add opa dependency function to create OpaUserClient
tpoliaw May 26, 2026
b3254ea
test opa dependency function
tpoliaw May 28, 2026
fcad0af
Add can_submit_task auth check method and config
tpoliaw May 26, 2026
171de82
feat: add authz dependency injection
shree-iyengar-dls May 15, 2026
ddfeab0
feat: add auth check dependency injections to task endpoints
shree-iyengar-dls May 18, 2026
37524eb
feat: create new access task permission fns and add as dependencies
shree-iyengar-dls May 20, 2026
13093f6
refactor: update rest api version
shree-iyengar-dls May 20, 2026
d7d57ae
comment out dependency addition in set_state
shree-iyengar-dls May 20, 2026
4ef3365
refactor: add admin check and check to set state function
May 20, 2026
659cf58
Update dependency names
tpoliaw May 26, 2026
a669903
Add missing admin check
tpoliaw May 26, 2026
d1cb939
Handle missing opa and fix tests
tpoliaw May 26, 2026
b889e20
Remove old admin method
tpoliaw May 26, 2026
3eb315a
Use starlette statuses directly
tpoliaw May 28, 2026
086953f
test task submission authz
tpoliaw May 28, 2026
2d3a564
Use _config instead of _conf
tpoliaw Jun 5, 2026
83ae2a6
Re-use instrument session regex
tpoliaw Jun 5, 2026
029bc89
remove task access check
tpoliaw Jun 5, 2026
4e12a23
Add match to raises check
tpoliaw Jun 5, 2026
850682b
Add exception detail
tpoliaw Jun 5, 2026
2f1d3eb
Let admin see all tasks
tpoliaw Jun 5, 2026
e720bc4
Start of api authz tests
tpoliaw Jun 5, 2026
d73d01a
Make get_tasks async to access authz check
tpoliaw Jun 8, 2026
d1b7302
Parametrise filter test to check with and without admin
tpoliaw Jun 8, 2026
02eba88
Add test for deleting tasks
tpoliaw Jun 8, 2026
b34600a
Add test for submit without permission
tpoliaw Jun 8, 2026
6967b16
Test setting other user's task active
tpoliaw Jun 9, 2026
49b1b97
Test getting other users task
tpoliaw Jun 9, 2026
0139c0b
Add tests for set state
tpoliaw Jun 9, 2026
55c9886
Remove print debugging
tpoliaw Jun 10, 2026
c9fd7d2
Merge remote-tracking branch 'origin/main' into add_system_test
ZohebShaikh Jun 26, 2026
c3fa597
refactor: update rest api version
shree-iyengar-dls May 20, 2026
8c6c481
comment out dependency addition in set_state
shree-iyengar-dls May 20, 2026
9392e18
refactor: add admin check and check to set state function
May 20, 2026
25afaad
Update dependency names
tpoliaw May 26, 2026
5b8ed01
Add missing admin check
tpoliaw May 26, 2026
d795c5f
Handle missing opa and fix tests
tpoliaw May 26, 2026
5b79bb9
Remove old admin method
tpoliaw May 26, 2026
ba66305
Use starlette statuses directly
tpoliaw May 28, 2026
d98149d
test task submission authz
tpoliaw May 28, 2026
97ee31a
Use _config instead of _conf
tpoliaw Jun 5, 2026
9f9335f
Re-use instrument session regex
tpoliaw Jun 5, 2026
27c605c
remove task access check
tpoliaw Jun 5, 2026
8f2ede0
Add match to raises check
tpoliaw Jun 5, 2026
ea3d734
Add exception detail
tpoliaw Jun 5, 2026
7393985
Let admin see all tasks
tpoliaw Jun 5, 2026
ecd6fb3
Start of api authz tests
tpoliaw Jun 5, 2026
7fe6303
Make get_tasks async to access authz check
tpoliaw Jun 8, 2026
2486063
Parametrise filter test to check with and without admin
tpoliaw Jun 8, 2026
af15716
Add test for deleting tasks
tpoliaw Jun 8, 2026
12709ff
Add test for submit without permission
tpoliaw Jun 8, 2026
8585f4d
Test setting other user's task active
tpoliaw Jun 9, 2026
ce1b652
Test getting other users task
tpoliaw Jun 9, 2026
082be79
Add tests for set state
tpoliaw Jun 9, 2026
e2cbd6d
Remove print debugging
tpoliaw Jun 10, 2026
2155ea1
Merge branch 'add_depedency_injection' into add_system_test
ZohebShaikh Jun 29, 2026
0eb1214
WIP: checkpoint work
ZohebShaikh Jul 1, 2026
61821da
Merge remote-tracking branch 'origin/add_depedency_injection' into ad…
ZohebShaikh Jul 1, 2026
9a32828
remove this error check because it does not add anything new
ZohebShaikh Jul 1, 2026
27d5d41
EOD commit
ZohebShaikh Jul 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"env": {
"OTLP_EXPORT_ENABLED": "false"
},
"envFile": "${workspaceFolder}/example-services/.env"
},
{
"name": "Blueapi Controller",
Expand Down
1 change: 1 addition & 0 deletions tests/system_tests/compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ services:
network_mode: host # Port 8181
volumes:
- "./services/opa_config:/mnt"
- "/scratch/ckk43848/authz/policy:/mnt/policy/"
environment:
- ISSUER=http://localhost:8081/realms/master
entrypoint: "sh /mnt/entrypoint.sh"
Expand Down
5 changes: 5 additions & 0 deletions tests/system_tests/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,8 @@ oidc:
issuer: "http://localhost:8081/realms/master"
client_id: "ixx-cli-blueapi"
client_audience: "ixx-blueapi"
opa:
root: "http://localhost:8181/v1/data/diamond/policy/"
tiled_service_account_check: "blueapi/tiled_service_account_for_beamline"
submit_task_check: "blueapi/write_to_beamline_visit"
admin_check: "admin/admin"
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
{
"protocolMappers": [
{
"name": "fedid",
"name": "username",
"protocol": "openid-connect",
"protocolMapper": "oidc-hardcoded-claim-mapper",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"consentRequired": false,
"config": {
"aggregate.attrs": "false",
"introspection.token.claim": "true",
"claim.value": "__CLAIM_VALUE__",
"multivalued": "false",
"userinfo.token.claim": "true",
"user.attribute": "username",
"id.token.claim": "true",
"lightweight.claim": "false",
"access.token.claim": "true",
"claim.name": "fedid",
"jsonType.label": "String"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"protocolMappers": [
{
"name": "fedid",
"protocol": "openid-connect",
"protocolMapper": "oidc-hardcoded-claim-mapper",
"config": {
"introspection.token.claim": "true",
"claim.value": "__CLAIM_VALUE__",
"userinfo.token.claim": "true",
"id.token.claim": "true",
"access.token.claim": "true",
"claim.name": "fedid",
"jsonType.label": "String"
}
},
{
"name": "audience-mapper",
"protocol": "openid-connect",
"protocolMapper": "oidc-audience-mapper",
"config": {
"introspection.token.claim": "true",
"access.token.claim": "true",
"included.custom.audience": "__AUDIENCE__"
}
}
]
}
65 changes: 47 additions & 18 deletions tests/system_tests/services/keycloak_config/startup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ export PATH=$PATH:/opt/keycloak/bin
# --- Config ---
export KC_CLI_PASSWORD="admin"
SERVER="http://localhost:8080"
TEMPLATE="/tmp/config/mappers-template.json"
GENERAL_TEMPLATE="/tmp/config/mappers-template.json"
BEAMLINE_SERVICE_TEMPLATE="/tmp/config/service-account-beamline.json"
USER_SERVICE_TEMPLATE="/tmp/config/service-account-user.json"
REALM="master"

# Wait for Keycloak
sleep 30
until kcadm.sh config credentials --server $SERVER --realm master --user admin; do sleep 1; done
sleep 5
until kcadm.sh config credentials --server $SERVER --realm $REALM --user admin; do sleep 3; done

# Cleanup logic
for type in "Allowed Protocol Mapper Types" "Allowed Client Scopes"; do
Expand All @@ -17,14 +20,30 @@ for type in "Allowed Protocol Mapper Types" "Allowed Client Scopes"; do
done
done

kcreg.sh config credentials --server $SERVER --realm master --user admin

USERS=("alice:alice" "bob:bob")

for entry in "${USERS[@]}"; do
# Split the string into username and password
username="${entry%%:*}"
password="${entry##*:}"
# Create the user
kcadm.sh create users -r "$REALM" -s username="$username" -s enabled=true
# Set the password
kcadm.sh set-password -r "$REALM" --username "$username" --new-password "$password"
echo "User '$username' created successfully."
done

kcreg.sh config credentials --server $SERVER --realm $REALM --user admin

# --- Client Creation Function ---
# Args: client_id, audience, extra_flags
# Args: client_id, audience, type, fedid, extra_flags
create_client() {
local client_id=$1
local aud=$2
shift 2 # The rest are Keycloak attributes (-s key=value)
local type=$3
local fedid=$4
shift 4 # The rest are Keycloak attributes (-s key=value)

if kcreg.sh get "$client_id" >/dev/null 2>&1; then
echo ">> Skipping $client_id (exists)"
Expand All @@ -34,11 +53,13 @@ create_client() {
echo ">> Creating $client_id..."
local tmpfile=$(mktemp)

if [[ "$client_id" == "tiled-writer" ]]; then
cp /tmp/config/service-account.json "$tmpfile"
if [[ "$type" == "BEAMLINE_SERVICE_ACCOUNT" ]]; then
cp $BEAMLINE_SERVICE_TEMPLATE "$tmpfile"
elif [[ "$type" == "USER_SERVICE_ACCOUNT" ]]; then
sed "s/__AUDIENCE__/$aud/g; s/__CLAIM_VALUE__/$fedid/g" "$USER_SERVICE_TEMPLATE" > "$tmpfile"
else
# Use sed to replace placeholders in the JSON template
sed "s/__AUDIENCE__/$aud/g; s/__CLAIM_VALUE__/alice/g" "$TEMPLATE" > "$tmpfile"
sed "s/__AUDIENCE__/$aud/g;" "$GENERAL_TEMPLATE" > "$tmpfile"
fi

kcreg.sh create -x -s clientId="$client_id" -f "$tmpfile" "$@"
Expand All @@ -47,31 +68,39 @@ create_client() {

# --- Create Clients ---

# System Test
create_client "system-test-blueapi" "ixx-blueapi" \
-s secret="secret" -s standardFlowEnabled=false -s serviceAccountsEnabled=true -s 'redirectUris=["/*"]'

# ixx CLI
create_client "ixx-cli-blueapi" "ixx-blueapi" \
create_client "ixx-cli-blueapi" "ixx-blueapi" "" "" \
-s standardFlowEnabled=false -s publicClient=true -s 'redirectUris=["/*"]' \
-s 'attributes={"frontchannel.logout.session.required":"true","oauth2.device.authorization.grant.enabled":"true","use.refresh.tokens":"true","backchannel.logout.session.required":"true"}'

# ixx BlueAPI
create_client "ixx-blueapi" "ixx-blueapi" \
create_client "ixx-blueapi" "ixx-blueapi" "" "" \
-s standardFlowEnabled=true -s secret="blueapi-secret" -s rootUrl="http://localhost:4180" \
-s 'redirectUris=["http://localhost:4180/*"]' \
-s 'attributes={"frontchannel.logout.session.required":"true","use.refresh.tokens":"true"}'

# Tiled
create_client "tiled" "tiled" \
create_client "tiled" "tiled" "" "" \
-s standardFlowEnabled=true -s secret="tiled-secret" -s rootUrl="http://localhost:4181" \
-s 'redirectUris=["http://localhost:4181/*"]'

# Tiled CLI
create_client "tiled-cli" "tiled" \
create_client "tiled-cli" "tiled" "" ""\
-s standardFlowEnabled=false -s publicClient=true -s 'redirectUris=["/*"]' \
-s 'attributes={"frontchannel.logout.session.required":"true","oauth2.device.authorization.grant.enabled":"true","use.refresh.tokens":"true","backchannel.logout.session.required":"true"}'

# Service account tiled-writer
create_client "tiled-writer" "" \
create_client "tiled-writer" "" "BEAMLINE_SERVICE_ACCOUNT" "" \
-s secret="secret" -s standardFlowEnabled=false -s serviceAccountsEnabled=true -s 'redirectUris=["/*"]'

# System Test admin
create_client "system-test-blueapi-admin" "ixx-blueapi" "USER_SERVICE_ACCOUNT" "admin" \
-s secret="secret" -s standardFlowEnabled=false -s serviceAccountsEnabled=true -s 'redirectUris=["/*"]'

# System Test alice
create_client "system-test-blueapi-alice" "ixx-blueapi" "USER_SERVICE_ACCOUNT" "alice"\
-s secret="secret" -s standardFlowEnabled=false -s serviceAccountsEnabled=true -s 'redirectUris=["/*"]'

# System Test bob
create_client "system-test-blueapi-bob" "ixx-blueapi" "USER_SERVICE_ACCOUNT" "bob"\
-s secret="secret" -s standardFlowEnabled=false -s serviceAccountsEnabled=true -s 'redirectUris=["/*"]'
2 changes: 1 addition & 1 deletion tests/system_tests/services/opa_config/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/bin/sh
/opa build -b /mnt/opa_data -o /tmp/bundle.tar.gz
/opa run --server --addr localhost:8181 -b /tmp/bundle.tar.gz --config-file /mnt/config.yaml
/opa run --server --addr localhost:8181 -b /tmp/bundle.tar.gz /mnt/policy/
24 changes: 20 additions & 4 deletions tests/system_tests/services/opa_config/opa_data/data.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"proposals": {
"12345": {
"sessions": {
"1": 1
"1": 1,
"2": 2
}
}
},
Expand All @@ -20,17 +21,32 @@
"beamline": "adsim",
"proposal_number": 12345,
"visit_number": 1
},
"2": {
"beamline": "adsim",
"proposal_number": 12345,
"visit_number": 2
}
},
"subjects": {
"admin": {
"permissions": ["super_admin"],
"proposals": [],
"sessions": []
},
"alice": {
"permissions": [],
"proposals": [
12345
],
"proposals": [],
"sessions": [
1
]
},
"bob": {
"permissions": [],
"proposals": [],
"sessions": [
2
]
}
}
}
Expand Down
15 changes: 4 additions & 11 deletions tests/system_tests/test_blueapi_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
WorkerTask,
)
from blueapi.worker.event import (
TaskError,
TaskResult,
TaskStatus,
WorkerEvent,
Expand Down Expand Up @@ -94,12 +93,12 @@ def load_config(path: Path) -> ApplicationConfig:
return loader.load()


def get_access_token() -> str:
def get_access_token(user: str = "alice") -> str:
token_url = "http://localhost:8081/realms/master/protocol/openid-connect/token"
response = requests.post(
token_url,
data={
"client_id": "system-test-blueapi",
"client_id": "system-test-blueapi-" + user,
"client_secret": "secret",
"grant_type": "client_credentials",
},
Expand Down Expand Up @@ -612,14 +611,8 @@ def on_event(event: AnyEvent) -> None:
if event.name == "stream_resource":
resource.put_nowait(event.doc)

outcome = client_with_stomp.run_task(task, on_event)
assert outcome.task_failed
assert outcome.task_complete
assert isinstance(outcome.result, TaskError)
assert outcome.result.type == "ClientError"
assert outcome.result.message.startswith(
"403: Access policy rejects the provided access blob"
)
with pytest.raises(UnauthorisedAccessError, match="Not authorized to submit task"):
client_with_stomp.run_task(task, on_event)


# Regression test for #1480
Expand Down
Loading