Skip to content

Commit

Permalink
refactor server client and oidc_admin
Browse files Browse the repository at this point in the history
  • Loading branch information
npalaska committed Feb 14, 2023
1 parent d4d8788 commit 2a94b6f
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 52 deletions.
49 changes: 26 additions & 23 deletions lib/pbench/client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
import requests
from requests.structures import CaseInsensitiveDict

from pbench.client.types import Dataset, JSONMap, JSONOBJECT
from pbench.client.oidc_admin import OIDCAdmin
from pbench.client.types import Dataset, JSONOBJECT


class PbenchClientError(Exception):
Expand Down Expand Up @@ -86,6 +87,7 @@ def __init__(self, host: str):
self.auth_token: Optional[str] = None
self.session: Optional[requests.Session] = None
self.endpoints: Optional[JSONOBJECT] = None
self.oidc_admin: Optional[OIDCAdmin] = None

def _headers(
self, user_headers: Optional[dict[str, str]] = None
Expand Down Expand Up @@ -302,8 +304,13 @@ def delete(
return response

def connect(self, headers: Optional[dict[str, str]] = None) -> None:
"""Connect to the Pbench Server host using the endpoints API to be sure
that it responds, and cache the endpoints response payload.
"""Performs some pre-requisite actions to make server client usable.
1. Connect to the Pbench Server host using the endpoints API to be
sure that it responds, and cache the endpoints response payload.
2. Creates an OIDCAdmin object that server client can use to
perform admin privileged actions on OIDC server.
This also allows the client to add default HTTP headers to the session
which will be used for all operations unless overridden for specific
Expand All @@ -321,31 +328,27 @@ def connect(self, headers: Optional[dict[str, str]] = None) -> None:
self.endpoints = response.json()
assert self.endpoints

def login(self, user: str, password: str) -> JSONMap:
"""Login to a specified username with the password, and store the
resulting authentication token.
# Create an OIDCAdmin object and confirm the connection was successful
self.oidc_admin = OIDCAdmin(server_url=self.endpoints["openid"]["server"])
assert self.oidc_admin.get_admin_token()["access_token"]

def login(self, user: str, password: str):
"""Login to a specified username with the password on OIDC server,
and store the resulting authentication token.
Args:
user: Account username
password: Account password
Returns:
The login response
"""
response = self.post(API.LOGIN, json={"username": user, "password": password})
response.raise_for_status()
json = response.json()
self.username = json["username"]
self.auth_token = json["auth_token"]
return JSONMap(json)

def logout(self) -> None:
"""Logout the currently authenticated user and remove the
authentication token.
"""
self.post(API.LOGOUT)
self.username = None
self.auth_token = None
response = self.oidc_admin.user_login(
client_id=self.endpoints["openid"]["client"],
username=user,
password=password,
)
assert response["access_token"]
auth_token = response["access_token"]
self.username = user
self.auth_token = auth_token

def upload(self, tarball: Path, **kwargs) -> requests.Response:
"""Upload a tarball to the server.
Expand Down
5 changes: 2 additions & 3 deletions lib/pbench/client/oidc_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@


class OIDCAdmin(Connection):
OIDC_REALM = "pbench-server"
OIDC_REALM = os.getenv("OIDC_REALM", "pbench-server")
ADMIN_USERNAME = os.getenv("ADMIN_USERNAME", "admin")
ADMIN_PASSWORD = os.getenv("ADMIN_PASSWORD", "admin")

Expand Down Expand Up @@ -111,8 +111,7 @@ def user_login(self, client_id: str, username: str, password: str) -> dict:
"username": username,
"password": password,
}
response = self.post(path=url_path, data=data, headers=headers)
return response.json()
return self.post(path=url_path, data=data, headers=headers).json()

def get_user(self, username: str, token: str) -> dict:
"""Get the OIDC user representation dict.
Expand Down
38 changes: 16 additions & 22 deletions lib/pbench/test/functional/server/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@

from pbench.client import PbenchServerClient
from pbench.client.oidc_admin import OIDCAdmin
from pbench.client.types import JSONMap

USERNAME: str = "tester"
EMAIL: str = "[email protected]"
PASSWORD: str = "123456"
FIRST_NAME: str = "Test"
LAST_NAME: str = "User"


@pytest.fixture(scope="module")
Expand All @@ -32,20 +37,18 @@ def oidc_admin(server_client: PbenchServerClient):
Used by Pbench Server functional tests to get admin access
on OIDC server.
"""
oidc_endpoints = server_client.endpoints["openid"]
oidc_server = OIDCAdmin(server_url=oidc_endpoints["server"])
return oidc_server
return OIDCAdmin(server_url=server_client.endpoints["openid"]["server"])


@pytest.fixture(scope="module")
def register_test_user(oidc_admin: OIDCAdmin):
"""Create a test user for functional tests."""
response = oidc_admin.create_new_user(
username="tester",
email="[email protected]",
password="123456",
first_name="Test",
last_name="User",
username=USERNAME,
email=EMAIL,
password=PASSWORD,
first_name=FIRST_NAME,
last_name=LAST_NAME,
)

# To allow testing outside our transient CI containers, allow the tester
Expand All @@ -56,17 +59,8 @@ def register_test_user(oidc_admin: OIDCAdmin):


@pytest.fixture
def login_user(
server_client: PbenchServerClient, oidc_admin: OIDCAdmin, register_test_user
):
def login_user(server_client: PbenchServerClient, register_test_user):
"""Log in the test user and return the authentication token"""
oidc_endpoints = server_client.endpoints["openid"]
response = oidc_admin.user_login(
client_id=oidc_endpoints["client"], username="tester", password="123456"
)
auth_token = response["access_token"]
assert auth_token
json = {"username": "tester", "auth_token": auth_token}
server_client.username = "tester"
server_client.auth_token = auth_token
yield JSONMap(json)
server_client.login(USERNAME, PASSWORD)
assert server_client.auth_token
yield
8 changes: 4 additions & 4 deletions server/pbenchinacan/load_keycloak.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ ADMIN_USERNAME=${ADMIN_USERNAME:-"admin"}
ADMIN_PASSWORD=${ADMIN_PASSWORD:-"admin"}
# These values must match the options "realm" and "client in the
# "openid-connect" section of the pbench server configuration file.
REALM=${KEYCLOAK_REALM:-"pbench-server"}
CLIENT=${KEYCLOAK_CLIENT:-"pbench-dashboard"}
REALM=${KEYCLOAK_REALM:-"pbench-server-test"}
CLIENT=${KEYCLOAK_CLIENT:-"pbench-dashboard-test"}

end_in_epoch_secs=$(date --date "2 minutes" +%s)

Expand Down Expand Up @@ -66,7 +66,7 @@ else
fi

# Create a client scope with custom mapper that will instruct Keycloak
# to include the <client_id> (pbench-dashboard) when someone request
# to include the <client_id> (pbench-dashboard) when someone requests
# a token from Keycloak using a <client_id>.
# Having <client_id> in the aud claim of the token is essential for the token
# to be validated.
Expand Down Expand Up @@ -158,7 +158,7 @@ else
echo "Assigned an 'ADMIN' client role to the user 'admin' created above"
fi

# Verify that the user id has a role 'ADMIN' assigned to it
# Verify that the user id has an 'ADMIN' role assigned to it
USER_ROLES=$(curl -s "${KEYCLOAK_HOST_PORT}/admin/realms/${REALM}/users/${USER_ID}/role-mappings/clients/${CLIENT_ID}" \
-H "Authorization: Bearer ${ADMIN_TOKEN}" \
-H "Content-Type: application/json" | jq -r '.[].name')
Expand Down

0 comments on commit 2a94b6f

Please sign in to comment.