135 lines
4.6 KiB
Python
135 lines
4.6 KiB
Python
import json
|
|
from base64 import b64encode
|
|
|
|
from fastapi.testclient import TestClient
|
|
from itsdangerous import TimestampSigner
|
|
|
|
from cert_portal.app import create_app
|
|
from cert_portal.auth_oidc import SESSION_USER_KEY, claims_username, session_user_from_token
|
|
from cert_portal.directory import DirectoryUser
|
|
from cert_portal.exceptions import UserNotFoundError
|
|
from cert_portal.issue import IssuedProfile
|
|
from cert_portal.profile import APPLE_CONFIG_TYPE
|
|
|
|
SESSION_COOKIE = "cert_portal_session"
|
|
|
|
NICK = {
|
|
"sub": "abc",
|
|
"username": "[email protected]",
|
|
"email": "[email protected]",
|
|
"name": "Nick",
|
|
}
|
|
|
|
|
|
def _client(settings, lookup, issuer=None):
|
|
app = create_app(settings, lookup_user=lookup, issuer=issuer)
|
|
return TestClient(app)
|
|
|
|
|
|
def _sign_in(client: TestClient, settings, user: dict) -> None:
|
|
"""Starlette 1.x TestClient no longer has session_transaction; sign the cookie."""
|
|
signer = TimestampSigner(str(settings.session_secret))
|
|
payload = b64encode(json.dumps({SESSION_USER_KEY: user}).encode("utf-8"))
|
|
client.cookies.set(SESSION_COOKIE, signer.sign(payload).decode("utf-8"))
|
|
|
|
|
|
def test_health(settings, directory_user):
|
|
client = _client(settings, lambda username: directory_user)
|
|
response = client.get("/health")
|
|
assert response.status_code == 200
|
|
assert response.json()["status"] == "ok"
|
|
|
|
|
|
def test_home_unauthenticated_shows_login(settings, directory_user):
|
|
client = _client(settings, lambda username: directory_user)
|
|
response = client.get("/")
|
|
assert response.status_code == 200
|
|
assert "Sign in with SSO" in response.text
|
|
|
|
|
|
def test_help_requires_login(settings, directory_user):
|
|
client = _client(settings, lambda username: directory_user)
|
|
response = client.get("/help", follow_redirects=False)
|
|
assert response.status_code == 302
|
|
assert response.headers["location"] == "/"
|
|
|
|
|
|
def test_home_authenticated_shows_sid(settings, directory_user):
|
|
client = _client(settings, lambda username: directory_user)
|
|
_sign_in(client, settings, NICK)
|
|
response = client.get("/")
|
|
assert response.status_code == 200
|
|
assert directory_user.sid in response.text
|
|
assert "Download certificate profile" in response.text
|
|
|
|
|
|
def test_home_directory_error(settings):
|
|
def lookup(username: str) -> DirectoryUser:
|
|
raise UserNotFoundError("No Active Directory user matched your sign-in name.")
|
|
|
|
client = _client(settings, lookup)
|
|
_sign_in(
|
|
client,
|
|
settings,
|
|
{
|
|
"sub": "abc",
|
|
"username": "[email protected]",
|
|
"email": "[email protected]",
|
|
"name": "Missing",
|
|
},
|
|
)
|
|
response = client.get("/")
|
|
assert "No Active Directory user" in response.text
|
|
|
|
|
|
def test_download_returns_signed_mobileconfig(settings, directory_user):
|
|
class FakeIssuer:
|
|
def issue(self, user: DirectoryUser) -> IssuedProfile:
|
|
return IssuedProfile(
|
|
signed_mobileconfig=b"\x30fake-cms",
|
|
filename="[email protected]",
|
|
upn=user.upn,
|
|
sid=user.sid,
|
|
)
|
|
|
|
client = _client(settings, lambda username: directory_user, issuer=FakeIssuer())
|
|
_sign_in(client, settings, NICK)
|
|
response = client.post("/download")
|
|
assert response.status_code == 200
|
|
assert response.content == b"\x30fake-cms"
|
|
assert response.headers["content-type"].startswith(APPLE_CONFIG_TYPE)
|
|
assert "[email protected]" in response.headers["content-disposition"]
|
|
|
|
|
|
def test_download_requires_session(settings, directory_user):
|
|
client = _client(settings, lambda username: directory_user)
|
|
response = client.post("/download", follow_redirects=False)
|
|
assert response.status_code == 302
|
|
|
|
|
|
def test_help_authenticated(settings, directory_user):
|
|
client = _client(settings, lambda username: directory_user)
|
|
_sign_in(client, settings, NICK)
|
|
response = client.get("/help")
|
|
assert response.status_code == 200
|
|
assert "Private key on the server" in response.text
|
|
|
|
|
|
def test_login_oidc_failure_shows_error(settings, directory_user):
|
|
client = _client(settings, lambda username: directory_user)
|
|
response = client.get("/login")
|
|
assert response.status_code == 502
|
|
assert "Could not start sign-in" in response.text
|
|
|
|
|
|
def test_username_claim_fallback():
|
|
assert claims_username({"email": "[email protected]"}, "email") == "[email protected]"
|
|
assert claims_username({"preferred_username": "a"}, "email") == "a"
|
|
|
|
|
|
def test_session_user_from_token():
|
|
token = {"userinfo": {"sub": "1", "email": "[email protected]", "name": "A"}}
|
|
user = session_user_from_token(token, "email")
|
|
assert user["username"] == "[email protected]"
|
|
assert user["name"] == "A"
|