Skip to content

Commit c7ff5a6

Browse files
author
maxim-lixakov
committed
[DOP-21482] - move keycloak test configs to fixtures
1 parent 74fba53 commit c7ff5a6

File tree

9 files changed

+217
-175
lines changed

9 files changed

+217
-175
lines changed

.env.docker

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,15 @@ TEST_HDFS_HOST=test-hive
8080
TEST_HDFS_WEBHDFS_PORT=9870
8181
TEST_HDFS_IPC_PORT=9820
8282

83+
# Keycloack Auth
84+
TEST_AUTH_SERVER_URL=http://localhost:8080
85+
TEST_AUTH_REALM_NAME=manually_created
86+
TEST_AUTH_CLIENT_ID=manually_created
87+
TEST_AUTH_CLIENT_SECRET=generated_by_keycloak
88+
TEST_AUTH_REDIRECT_URI=http://localhost:8000/auth/callback
89+
TEST_AUTH_SCOPE=email
90+
TEST_AUTH_PROVIDER=syncmaster.backend.providers.auth.keycloak_provider.KeycloakAuthProvider
91+
8392
SPARK_CONF_DIR=/app/tests/spark/hive/conf/
8493
HADOOP_CONF_DIR=/app/tests/spark/hadoop/
8594
HIVE_CONF_DIR=/app/tests/spark/hive/conf/

.env.local

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,13 @@ export TEST_HDFS_IPC_PORT=9820
6969
export SPARK_CONF_DIR=./tests/spark/hive/conf/
7070
export HADOOP_CONF_DIR=./tests/spark/hadoop/
7171
export HIVE_CONF_DIR=./tests/spark/hive/conf/
72+
73+
74+
# Keycloack Auth
75+
export TEST_AUTH_SERVER_URL=http://localhost:8080
76+
export TEST_AUTH_REALM_NAME=manually_created
77+
export TEST_AUTH_CLIENT_ID=manually_created
78+
export TEST_AUTH_CLIENT_SECRET=generated_by_keycloak
79+
export TEST_AUTH_REDIRECT_URI=http://localhost:8000/auth/callback
80+
export TEST_AUTH_SCOPE=email
81+
export TEST_AUTH_PROVIDER=syncmaster.backend.providers.auth.keycloak_provider.KeycloakAuthProvider

tests/conftest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
pytest_plugins = [
3434
"tests.test_unit.test_transfers.transfer_fixtures",
35+
"tests.test_unit.test_auth.auth_fixtures",
3536
"tests.test_unit.test_runs.run_fixtures",
3637
"tests.test_unit.test_connections.connection_fixtures",
3738
"tests.test_unit.test_scheduler.scheduler_fixtures",

tests/settings.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ class TestSettings(BaseSettings):
4040
TEST_S3_PROTOCOL: str = "http"
4141
TEST_S3_ADDITIONAL_PARAMS: dict = {}
4242

43+
TEST_AUTH_SERVER_URL: str
44+
TEST_AUTH_REALM_NAME: str
45+
TEST_AUTH_CLIENT_ID: str
46+
TEST_AUTH_CLIENT_SECRET: str
47+
TEST_AUTH_REDIRECT_URI: str
48+
TEST_AUTH_SCOPE: str
49+
TEST_AUTH_PROVIDER: str
50+
4351
@model_validator(mode="before")
4452
def check_sid_and_service_name(cls, values):
4553
sid = values.get("TEST_ORACLE_SID")
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from tests.test_unit.test_auth.auth_fixtures.keycloak_fixture import (
2+
create_session_cookie,
3+
mock_keycloak_realm,
4+
mock_keycloak_well_known,
5+
rsa_keys,
6+
)
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import json
2+
import time
3+
from base64 import b64encode
4+
5+
import pytest
6+
import responses
7+
from cryptography.hazmat.primitives import serialization
8+
from cryptography.hazmat.primitives.asymmetric import rsa
9+
from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
10+
from itsdangerous import TimestampSigner
11+
from jose import jwt
12+
13+
14+
@pytest.fixture(scope="session")
15+
def rsa_keys():
16+
# create private & public keys to emulate Keycloak signing
17+
private_key = rsa.generate_private_key(
18+
public_exponent=65537,
19+
key_size=2048,
20+
)
21+
private_pem = private_key.private_bytes(
22+
encoding=serialization.Encoding.PEM,
23+
format=serialization.PrivateFormat.PKCS8,
24+
encryption_algorithm=serialization.NoEncryption(),
25+
)
26+
public_key = private_key.public_key()
27+
28+
return {
29+
"private_key": private_key,
30+
"private_pem": private_pem,
31+
"public_key": public_key,
32+
}
33+
34+
35+
def get_public_key_pem(public_key):
36+
public_pem = public_key.public_bytes(
37+
encoding=Encoding.PEM,
38+
format=PublicFormat.SubjectPublicKeyInfo,
39+
)
40+
public_pem_str = public_pem.decode("utf-8")
41+
public_pem_str = public_pem_str.replace("-----BEGIN PUBLIC KEY-----\n", "")
42+
public_pem_str = public_pem_str.replace("-----END PUBLIC KEY-----\n", "")
43+
public_pem_str = public_pem_str.replace("\n", "")
44+
return public_pem_str
45+
46+
47+
@pytest.fixture
48+
def create_session_cookie(rsa_keys, settings):
49+
def _create_session_cookie(user, expire_in_msec=1000) -> str:
50+
private_pem = rsa_keys["private_pem"]
51+
session_secret_key = settings.server.session.secret_key
52+
53+
payload = {
54+
"sub": str(user.id),
55+
"preferred_username": user.username,
56+
"email": user.email,
57+
"given_name": user.first_name,
58+
"middle_name": user.middle_name,
59+
"family_name": user.last_name,
60+
"exp": int(time.time()) + (expire_in_msec / 1000),
61+
}
62+
63+
access_token = jwt.encode(payload, private_pem, algorithm="RS256")
64+
refresh_token = "mock_refresh_token"
65+
66+
session_data = {
67+
"access_token": access_token,
68+
"refresh_token": refresh_token,
69+
}
70+
71+
signer = TimestampSigner(session_secret_key)
72+
json_bytes = json.dumps(session_data).encode("utf-8")
73+
base64_bytes = b64encode(json_bytes)
74+
signed_data = signer.sign(base64_bytes)
75+
session_cookie = signed_data.decode("utf-8")
76+
77+
return session_cookie
78+
79+
return _create_session_cookie
80+
81+
82+
@pytest.fixture
83+
def mock_keycloak_well_known(test_settings):
84+
server_url = test_settings.TEST_AUTH_SERVER_URL
85+
realm_name = test_settings.TEST_AUTH_REALM_NAME
86+
well_known_url = f"{server_url}/realms/{realm_name}/.well-known/openid-configuration"
87+
88+
responses.add(
89+
responses.GET,
90+
well_known_url,
91+
json={
92+
"authorization_endpoint": f"{server_url}/realms/{realm_name}/protocol/openid-connect/auth",
93+
"token_endpoint": f"{server_url}/realms/{realm_name}/protocol/openid-connect/token",
94+
"userinfo_endpoint": f"{server_url}/realms/{realm_name}/protocol/openid-connect/userinfo",
95+
"end_session_endpoint": f"{server_url}/realms/{realm_name}/protocol/openid-connect/logout",
96+
"jwks_uri": f"{server_url}/realms/{realm_name}/protocol/openid-connect/certs",
97+
"issuer": f"{server_url}/realms/{realm_name}",
98+
},
99+
status=200,
100+
content_type="application/json",
101+
)
102+
103+
104+
@pytest.fixture
105+
def mock_keycloak_realm(test_settings, rsa_keys):
106+
server_url = test_settings.TEST_AUTH_SERVER_URL
107+
realm_name = test_settings.TEST_AUTH_REALM_NAME
108+
realm_url = f"{server_url}/realms/{realm_name}"
109+
public_pem_str = get_public_key_pem(rsa_keys["public_key"])
110+
111+
responses.add(
112+
responses.GET,
113+
realm_url,
114+
json={
115+
"realm": realm_name,
116+
"public_key": public_pem_str,
117+
"token-service": f"{server_url}/realms/{realm_name}/protocol/openid-connect/token",
118+
"account-service": f"{server_url}/realms/{realm_name}/account",
119+
},
120+
status=200,
121+
content_type="application/json",
122+
)

tests/test_unit/test_auth/mocks/__init__.py

Whitespace-only changes.

tests/test_unit/test_auth/mocks/keycloak.py

Lines changed: 0 additions & 118 deletions
This file was deleted.

0 commit comments

Comments
 (0)