Skip to content

Commit 57710e3

Browse files
author
michael.yak
committed
Verify Pyctuator can register when SBA requires basic-auth
Add tests for verifying Pyctuator's support for basic-auth registration with Spring Boot Admin. Solves #28
1 parent c68b163 commit 57710e3

File tree

2 files changed

+117
-4
lines changed

2 files changed

+117
-4
lines changed

tests/conftest.py

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import logging
2+
import secrets
23
import threading
34
import time
45
from abc import ABC, abstractmethod
@@ -8,9 +9,10 @@
89

910
import pytest
1011
import requests
11-
from fastapi import FastAPI
12+
from fastapi import FastAPI, Depends, HTTPException
13+
from fastapi.security import HTTPBasic, HTTPBasicCredentials
1214
from pydantic import BaseModel
13-
from starlette.requests import Request
15+
from starlette import status
1416
from uvicorn.config import Config
1517
from uvicorn.main import Server
1618

@@ -65,9 +67,21 @@ def boot_admin_server(registration_tracker: RegistrationTrackerFixture) -> Gener
6567
docs_url="/api",
6668
)
6769

68-
# pylint: disable=unused-argument,unused-variable
70+
security = HTTPBasic()
71+
72+
def get_current_username(credentials: HTTPBasicCredentials = Depends(security)) -> str:
73+
correct_username = secrets.compare_digest(credentials.username, "moo")
74+
correct_password = secrets.compare_digest(credentials.password, "haha")
75+
if not (correct_username and correct_password):
76+
raise HTTPException(
77+
status_code=status.HTTP_401_UNAUTHORIZED,
78+
detail="Moo haha",
79+
)
80+
return credentials.username
81+
82+
# pylint: disable=unused-variable
6983
@boot_admin_app.post("/register", tags=["admin-server"])
70-
def register(request: Request, registration: RegistrationRequest) -> Dict[str, str]:
84+
def register(registration: RegistrationRequest) -> Dict[str, str]:
7185
logging.debug("Got registration post %s, %d registrations since %s",
7286
registration, registration_tracker.count, registration_tracker.start_time)
7387
registration_tracker.registration = registration
@@ -76,6 +90,19 @@ def register(request: Request, registration: RegistrationRequest) -> Dict[str, s
7690
registration_tracker.start_time = registration.metadata["startup"]
7791
return {"id": "JB007"}
7892

93+
# pylint: disable=unused-variable
94+
@boot_admin_app.post("/register-with-basic-auth", tags=["admin-server"])
95+
def register_with_basic_auth(
96+
registration: RegistrationRequest,
97+
username: str = Depends(get_current_username)) -> Dict[str, str]:
98+
logging.debug("Got registration post %s from %s, %d registrations since %s",
99+
registration, username, registration_tracker.count, registration_tracker.start_time)
100+
registration_tracker.registration = registration
101+
registration_tracker.count += 1
102+
if registration_tracker.start_time is None:
103+
registration_tracker.start_time = registration.metadata["startup"]
104+
return {"id": "JB007"}
105+
79106
# pylint: disable=unused-argument,unused-variable
80107
@boot_admin_app.delete("/register/{registration_id}", tags=["admin-server"])
81108
def deregister(registration_id: str) -> None:
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
from datetime import datetime
2+
from typing import Optional, Any
3+
4+
import pytest
5+
6+
from pyctuator.auth import Auth, BasicAuth
7+
from pyctuator.impl.spring_boot_admin_registration import BootAdminRegistrationHandler
8+
from tests.conftest import RegistrationTrackerFixture
9+
10+
11+
@pytest.mark.usefixtures("boot_admin_server")
12+
def test_registration_no_auth(registration_tracker: RegistrationTrackerFixture) -> None:
13+
registration_handler = get_registration_handler("http://localhost:8001/register", None)
14+
15+
try:
16+
registration_handler.start()
17+
assert registration_tracker.count == 1
18+
19+
finally:
20+
registration_handler.stop()
21+
22+
23+
@pytest.mark.usefixtures("boot_admin_server")
24+
def test_registration_basic_auth_no_creds(registration_tracker: RegistrationTrackerFixture, caplog: Any) -> None:
25+
registration_handler = get_registration_handler("http://localhost:8001/register-with-basic-auth", None)
26+
27+
try:
28+
registration_handler.start()
29+
assert registration_tracker.count == 0
30+
31+
error_message = "Failed registering with boot-admin, got %s - %s"
32+
assert error_message in [record.msg for record in caplog.records]
33+
34+
error_args = (401, b'{"detail":"Not authenticated"}')
35+
assert error_args in [record.args for record in caplog.records if record.msg == error_message]
36+
37+
finally:
38+
registration_handler.stop()
39+
40+
41+
@pytest.mark.usefixtures("boot_admin_server")
42+
def test_registration_basic_auth_bad_creds(registration_tracker: RegistrationTrackerFixture, caplog: Any) -> None:
43+
registration_handler = get_registration_handler(
44+
"http://localhost:8001/register-with-basic-auth",
45+
BasicAuth("kuki", "puki")
46+
)
47+
48+
try:
49+
registration_handler.start()
50+
assert registration_tracker.count == 0
51+
52+
error_message = "Failed registering with boot-admin, got %s - %s"
53+
assert error_message in [record.msg for record in caplog.records]
54+
55+
error_args = (401, b'{"detail":"Moo haha"}')
56+
assert error_args in [record.args for record in caplog.records if record.msg == error_message]
57+
58+
finally:
59+
registration_handler.stop()
60+
61+
62+
@pytest.mark.usefixtures("boot_admin_server")
63+
def test_registration_basic_auth(registration_tracker: RegistrationTrackerFixture) -> None:
64+
registration_handler = get_registration_handler(
65+
"http://localhost:8001/register-with-basic-auth",
66+
BasicAuth("moo", "haha")
67+
)
68+
69+
try:
70+
registration_handler.start()
71+
assert registration_tracker.count == 1
72+
73+
finally:
74+
registration_handler.stop()
75+
76+
77+
def get_registration_handler(registration_url: str, registration_auth: Optional[Auth]) -> BootAdminRegistrationHandler:
78+
return BootAdminRegistrationHandler(
79+
registration_url=registration_url,
80+
registration_auth=registration_auth,
81+
application_name="noauth",
82+
pyctuator_base_url="http://whatever/pyctuator",
83+
start_time=datetime.now(),
84+
service_url="http://whatever/service",
85+
registration_interval_sec=100
86+
)

0 commit comments

Comments
 (0)