diff --git a/.env.production b/.env.production index c197f5c..37c06ec 100644 --- a/.env.production +++ b/.env.production @@ -8,7 +8,5 @@ REDIS_URL=redis://redis:6379/0 OLTP_INSECURE=True#change-me OLTP_COLLECTOR_URL=http://collector:4317 OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS=".*session.*,set-cookie" -PEER_KEY=c3daXP0DDO#change-me PEER_SECRET=4xST4WqrLF6LjE55vyWeaP2w#change-me -PEER_SALT=98fc47e49cb666023f438cbd6582af65#change-me PEERS=server1,server2,server3#change-me diff --git a/horao/__init__.py b/horao/__init__.py index a57c1f7..926a70f 100644 --- a/horao/__init__.py +++ b/horao/__init__.py @@ -45,7 +45,7 @@ import horao.api import horao.api.synchronization import horao.auth -from horao.auth.basic_auth import BasicAuthBackend +from horao.auth.basic import BasicAuthBackend from horao.auth.peer import PeerAuthBackend LoggingInstrumentor().instrument(set_logging_format=True) @@ -121,7 +121,7 @@ async def docs(request): return HTMLResponse(html) -def init_api() -> Starlette: +def init() -> Starlette: """ Initialize the API :return: app instance @@ -154,17 +154,13 @@ def init_api() -> Starlette: middleware.append( Middleware(AuthenticationMiddleware, backend=BasicAuthBackend()) ) + app = Starlette( + routes=routes, + middleware=middleware, + debug=False if os.getenv("DEBUG", "False") == "False" else True, + ) if os.getenv("TELEMETRY", "ON") == "OFF": logger.warning("Telemetry is turned off") - return Starlette( - routes=routes, - middleware=middleware, - debug=False if os.getenv("DEBUG", "False") == "False" else True, - ) - return StarletteInstrumentor.instrument_app( - Starlette( - routes=routes, - middleware=middleware, - debug=False if os.getenv("DEBUG", "False") == "False" else True, - ) - ) + else: + StarletteInstrumentor().instrument_app(app) + return app diff --git a/horao/api/synchronization.py b/horao/api/synchronization.py index aba5898..87cc799 100644 --- a/horao/api/synchronization.py +++ b/horao/api/synchronization.py @@ -10,16 +10,25 @@ from horao.persistance import HoraoDecoder, init_session -@requires("peer") +@requires("authenticated_peer") async def synchronize(request: Request) -> JSONResponse: """ responses: 200: description: synchronize logical infrastructures. examples: - {"LogicalInfrastructure": b"ASc3dGJhcg=="} + { "LogicalInfrastructure": { + "type": "LogicalInfrastructure", + "infrastructure": {}, + "constraints": {}, + "claims": {}, + }} + 400: + description: Error parsing request 403: description: Unauthorized + 500: + description: Error synchronizing """ logging.debug(f"Calling Synchronize ({request})") try: @@ -31,17 +40,17 @@ async def synchronize(request: Request) -> JSONResponse: logical_infrastructure = json.loads(data, cls=HoraoDecoder) session = init_session() for k, v in logical_infrastructure.infrastructure.items(): - local_dc = session.load(k.name) + local_dc = session.load(k.id) if not local_dc: - session.save(k.name, k) + session.save(k.id, k) else: local_dc.merge(k) - local_dc_content = session.load(f"{k.name}.content") + local_dc_content = session.load(f"{k.id}.content") if not local_dc_content: - session.save(f"{k.name}.content", v) + session.save(f"{k.id}.content", v) else: local_dc_content.merge(v) except Exception as e: logging.error(f"Error synchronizing: {e}") - return JSONResponse(status_code=400, content={"error": "Error synchronizing"}) + return JSONResponse(status_code=500, content={"error": "Error synchronizing"}) return JSONResponse(status_code=200, content={"status": "is alive"}) diff --git a/horao/auth/__init__.py b/horao/auth/__init__.py index 46aa4c0..deefd3a 100644 --- a/horao/auth/__init__.py +++ b/horao/auth/__init__.py @@ -5,4 +5,5 @@ only contains authorization. The RBAC module is used to define the roles and permissions of the users. There are various implementations that can be used, but some are only meant for development purpose. """ -from horao.auth.basic_auth import BasicAuthBackend +from horao.auth.basic import BasicAuthBackend +from horao.auth.peer import PeerAuthBackend, Peer diff --git a/horao/auth/basic_auth.py b/horao/auth/basic.py similarity index 100% rename from horao/auth/basic_auth.py rename to horao/auth/basic.py diff --git a/horao/auth/peer.py b/horao/auth/peer.py index 3dc4640..43a1eba 100644 --- a/horao/auth/peer.py +++ b/horao/auth/peer.py @@ -3,123 +3,83 @@ Digest authentication using pre-shared key. """ -import base64 import binascii import logging import os -from typing import Tuple +from typing import Tuple, Union -from cryptography.fernet import Fernet -from cryptography.hazmat.primitives import hashes -from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC +import jwt from starlette.authentication import ( AuthCredentials, AuthenticationBackend, AuthenticationError, - SimpleUser, + BaseUser, ) -def encode(text: str, secret: str, salt: bytes) -> bytes: - """ - This function returns a digest auth token for the given text and secret - :param text: text - :param secret: secret - :param salt: salt - :return: token - """ - kdf = PBKDF2HMAC( - algorithm=hashes.SHA256(), - length=32, - salt=salt, - iterations=390000, - ) - key = base64.urlsafe_b64encode(kdf.derive(secret.encode("utf-8"))) - fernet = Fernet(key) - enc_text = fernet.encrypt(text.encode("utf-8")) - return enc_text +class Peer(BaseUser): + def __init__(self, id: str, token: str, payload, origin: str) -> None: + self.id = id + self.token = token + self.payload = payload + self.origin = origin + @property + def is_authenticated(self) -> bool: + return True -def decode(token: bytes, secret: str, salt: bytes) -> str: - """ - This function returns a digest auth token for the given text and secret - :param token: token - :param secret: secret - :param salt: salt - :return: text - """ - kdf = PBKDF2HMAC( - algorithm=hashes.SHA256(), - length=32, - salt=salt, - iterations=390000, - ) - key = base64.urlsafe_b64encode(kdf.derive(secret.encode("utf-8"))) - fernet = Fernet(key) - return fernet.decrypt(token).decode("utf-8") + @property + def display_name(self) -> str: + return self.origin + @property + def identity(self) -> str: + return self.id -def generate_digest(username: str, password: str, secret: str, salt: bytes) -> bytes: - """ - This function returns a digest auth token for the given username, password, secret and salt - :param username: username - :param password: password - :param secret: secret - :param salt: salt - :return: bytes - """ - return encode(f"{username}{password}", secret, salt) + def is_true(self) -> bool: + return self.id == self.origin - -def extract_username_password( - token: bytes, secret: str, salt: bytes -) -> Tuple[str, str]: - """ - This function returns the username and password from the token - :param token: token - :param secret: secret - :param salt: salt - :return: typle of username and password - """ - result = decode(token, secret, salt) - return ( - result[0 : len(result) - len(os.getenv("PEER_KEY"))], # type: ignore - result[len(result) - len(os.getenv("PEER_KEY")) :], # type: ignore - ) + def __str__(self) -> str: + return f"{self.origin} -> {self.id}" class PeerAuthBackend(AuthenticationBackend): logger = logging.getLogger(__name__) - async def authenticate(self, conn): + async def authenticate(self, conn) -> Union[None, Tuple[AuthCredentials, BaseUser]]: if "Authorization" not in conn.headers: - return + return None + if "PEERS" in os.environ: + return None + if "PEER_SECRET" not in os.environ: + return None + auth = conn.headers["Authorization"] try: - scheme, credentials = auth.split() - if scheme.lower() != "digest": - return + scheme, token = auth.split() + if scheme.lower() != "jwt": + return None peer_match_source = False - for peer in os.getenv("PEERS").split(","): + for peer in os.getenv("PEERS").split(","): # type: ignore if peer in conn.client.host: self.logger.debug(f"Peer {peer} is trying to authenticate") peer_match_source = True if not peer_match_source and os.getenv("PEER_STRICT", "True") == "True": raise AuthenticationError(f"access not allowed for {conn.client.host}") - username, password = extract_username_password( - base64.b64decode(credentials), - os.getenv("PEER_SECRET"), - bytes.fromhex(os.getenv("PEER_SALT")), + payload = jwt.decode(token, os.getenv("PEER_SECRET"), algorithms=["HS256"]) # type: ignore + self.logger.debug(f"valid token for {payload['peer']}") + return AuthCredentials(["authenticated_peer"]), Peer( + id=payload["peer"], + token=token, + payload=payload, + origin=conn.client.host, ) - for peer in os.getenv("PEERS").split(","): - if peer == username and password == os.getenv("PEER_KEY"): - if not peer_match_source: - self.logger.warning( - f"Peer {peer} authenticated from different source {conn.client.host}" - ) - return AuthCredentials(["peer"]), SimpleUser(peer) - except (ValueError, UnicodeDecodeError, binascii.Error) as exc: - self.logger.error(f"Invalid digest credentials for peer ({exc})") + except ( + ValueError, + UnicodeDecodeError, + jwt.InvalidTokenError, + binascii.Error, + ) as exc: + self.logger.error(f"Invalid token for peer ({exc})") raise AuthenticationError(f"access not allowed for {conn.client.host}") - raise AuthenticationError("access not allowed") diff --git a/horao/main.py b/horao/main.py index b6fbde2..8cf9959 100644 --- a/horao/main.py +++ b/horao/main.py @@ -10,7 +10,7 @@ def main(): os.environ["DEBUG"] = "True" os.environ["UI"] = "True" uvicorn.run( - "horao:init_api", + "horao:init", host="127.0.0.1", port=8081, log_level="debug", diff --git a/poetry.lock b/poetry.lock index bfabe20..6891f25 100644 --- a/poetry.lock +++ b/poetry.lock @@ -111,85 +111,6 @@ files = [ {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, ] -[[package]] -name = "cffi" -version = "1.17.1" -description = "Foreign Function Interface for Python calling C code." -optional = false -python-versions = ">=3.8" -files = [ - {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, - {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, - {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, - {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, - {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, - {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, - {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, - {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, - {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, - {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, - {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, - {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, - {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, - {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, - {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, - {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, - {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, - {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, - {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, - {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, - {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, - {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, - {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, - {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, - {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, - {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, - {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, - {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, - {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, - {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, - {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, - {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, - {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, - {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, -] - -[package.dependencies] -pycparser = "*" - [[package]] name = "cfgv" version = "3.4.0" @@ -414,55 +335,6 @@ files = [ [package.extras] toml = ["tomli"] -[[package]] -name = "cryptography" -version = "43.0.3" -description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -optional = false -python-versions = ">=3.7" -files = [ - {file = "cryptography-43.0.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:bf7a1932ac4176486eab36a19ed4c0492da5d97123f1406cf15e41b05e787d2e"}, - {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63efa177ff54aec6e1c0aefaa1a241232dcd37413835a9b674b6e3f0ae2bfd3e"}, - {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e1ce50266f4f70bf41a2c6dc4358afadae90e2a1e5342d3c08883df1675374f"}, - {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:443c4a81bb10daed9a8f334365fe52542771f25aedaf889fd323a853ce7377d6"}, - {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:74f57f24754fe349223792466a709f8e0c093205ff0dca557af51072ff47ab18"}, - {file = "cryptography-43.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9762ea51a8fc2a88b70cf2995e5675b38d93bf36bd67d91721c309df184f49bd"}, - {file = "cryptography-43.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:81ef806b1fef6b06dcebad789f988d3b37ccaee225695cf3e07648eee0fc6b73"}, - {file = "cryptography-43.0.3-cp37-abi3-win32.whl", hash = "sha256:cbeb489927bd7af4aa98d4b261af9a5bc025bd87f0e3547e11584be9e9427be2"}, - {file = "cryptography-43.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:f46304d6f0c6ab8e52770addfa2fc41e6629495548862279641972b6215451cd"}, - {file = "cryptography-43.0.3-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:8ac43ae87929a5982f5948ceda07001ee5e83227fd69cf55b109144938d96984"}, - {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:846da004a5804145a5f441b8530b4bf35afbf7da70f82409f151695b127213d5"}, - {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f996e7268af62598f2fc1204afa98a3b5712313a55c4c9d434aef49cadc91d4"}, - {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:f7b178f11ed3664fd0e995a47ed2b5ff0a12d893e41dd0494f406d1cf555cab7"}, - {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:c2e6fc39c4ab499049df3bdf567f768a723a5e8464816e8f009f121a5a9f4405"}, - {file = "cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e1be4655c7ef6e1bbe6b5d0403526601323420bcf414598955968c9ef3eb7d16"}, - {file = "cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:df6b6c6d742395dd77a23ea3728ab62f98379eff8fb61be2744d4679ab678f73"}, - {file = "cryptography-43.0.3-cp39-abi3-win32.whl", hash = "sha256:d56e96520b1020449bbace2b78b603442e7e378a9b3bd68de65c782db1507995"}, - {file = "cryptography-43.0.3-cp39-abi3-win_amd64.whl", hash = "sha256:0c580952eef9bf68c4747774cde7ec1d85a6e61de97281f2dba83c7d2c806362"}, - {file = "cryptography-43.0.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d03b5621a135bffecad2c73e9f4deb1a0f977b9a8ffe6f8e002bf6c9d07b918c"}, - {file = "cryptography-43.0.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:a2a431ee15799d6db9fe80c82b055bae5a752bef645bba795e8e52687c69efe3"}, - {file = "cryptography-43.0.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:281c945d0e28c92ca5e5930664c1cefd85efe80e5c0d2bc58dd63383fda29f83"}, - {file = "cryptography-43.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:f18c716be16bc1fea8e95def49edf46b82fccaa88587a45f8dc0ff6ab5d8e0a7"}, - {file = "cryptography-43.0.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4a02ded6cd4f0a5562a8887df8b3bd14e822a90f97ac5e544c162899bc467664"}, - {file = "cryptography-43.0.3-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:53a583b6637ab4c4e3591a15bc9db855b8d9dee9a669b550f311480acab6eb08"}, - {file = "cryptography-43.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1ec0bcf7e17c0c5669d881b1cd38c4972fade441b27bda1051665faaa89bdcaa"}, - {file = "cryptography-43.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2ce6fae5bdad59577b44e4dfed356944fbf1d925269114c28be377692643b4ff"}, - {file = "cryptography-43.0.3.tar.gz", hash = "sha256:315b9001266a492a6ff443b61238f956b214dbec9910a081ba5b6646a055a805"}, -] - -[package.dependencies] -cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} - -[package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] -docstest = ["pyenchant (>=1.6.11)", "readme-renderer", "sphinxcontrib-spelling (>=4.0.1)"] -nox = ["nox"] -pep8test = ["check-sdist", "click", "mypy", "ruff"] -sdist = ["build"] -ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi", "cryptography-vectors (==43.0.3)", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] -test-randomorder = ["pytest-randomly"] - [[package]] name = "deprecated" version = "1.2.14" @@ -1214,27 +1086,33 @@ files = [ ] [[package]] -name = "pycparser" -version = "2.22" -description = "C parser in Python" +name = "pyflakes" +version = "3.2.0" +description = "passive checker of Python programs" optional = false python-versions = ">=3.8" files = [ - {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, - {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, + {file = "pyflakes-3.2.0-py2.py3-none-any.whl", hash = "sha256:84b5be138a2dfbb40689ca07e2152deb896a65c3a3e24c251c5c62489568074a"}, + {file = "pyflakes-3.2.0.tar.gz", hash = "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f"}, ] [[package]] -name = "pyflakes" -version = "3.2.0" -description = "passive checker of Python programs" +name = "pyjwt" +version = "2.9.0" +description = "JSON Web Token implementation in Python" optional = false python-versions = ">=3.8" files = [ - {file = "pyflakes-3.2.0-py2.py3-none-any.whl", hash = "sha256:84b5be138a2dfbb40689ca07e2152deb896a65c3a3e24c251c5c62489568074a"}, - {file = "pyflakes-3.2.0.tar.gz", hash = "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f"}, + {file = "PyJWT-2.9.0-py3-none-any.whl", hash = "sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850"}, + {file = "pyjwt-2.9.0.tar.gz", hash = "sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c"}, ] +[package.extras] +crypto = ["cryptography (>=3.4.0)"] +dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx", "sphinx-rtd-theme", "zope.interface"] +docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] +tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] + [[package]] name = "pylint" version = "3.3.1" @@ -1739,4 +1617,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "9d768f9901435d8b0c0c8fade5e775a5e87753d2b59f4adba1eef54e00e86004" +content-hash = "b6382d2ee61632f800354fb5a128240167b7d9dedf2dc668c9ee533b8358bd50" diff --git a/pyproject.toml b/pyproject.toml index e8a1f2a..0d142e4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ uvicorn-worker = "^0.2.0" gunicorn = "^23.0.0" networkx = "^3.4.2" starlette = "^0.41.0" -cryptography = "^43.0.3" +pyjwt = "^2.9.0" opentelemetry-api = "^1.27.0" opentelemetry-sdk = "^1.27.0" opentelemetry-instrumentation-logging = "^0.48b0" diff --git a/tests/test_api.py b/tests/test_api.py index 573bd93..14b99b8 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -1,13 +1,12 @@ # -*- coding: utf-8 -*-# -import base64 import json import os +import jwt from starlette.testclient import TestClient -from horao import init_api -from horao.auth.basic_auth import basic_auth -from horao.auth.peer import encode, generate_digest +from horao import init +from horao.auth.basic import basic_auth from horao.logical.infrastructure import LogicalInfrastructure from horao.persistance import HoraoEncoder from tests.helpers import initialize_logical_infrastructure @@ -15,7 +14,7 @@ def test_ping_service_unauthorized(): os.environ["TELEMETRY"] = "OFF" - ia = init_api() + ia = init() with TestClient(ia) as client: lg = client.get("/ping") assert 403 == lg.status_code @@ -23,7 +22,7 @@ def test_ping_service_unauthorized(): def test_ping_service_authorized(): os.environ["TELEMETRY"] = "OFF" - ia = init_api() + ia = init() with TestClient(ia) as client: lg = client.get( "/ping", headers={"Authorization": basic_auth("netadm", "secret")} @@ -35,29 +34,20 @@ def test_synchronize_simple_structure(): os.environ["TELEMETRY"] = "OFF" os.environ["PEER_STRICT"] = "False" os.environ["PEERS"] = "1,2" - os.environ["PEER_KEY"] = "key" os.environ["PEER_SECRET"] = "secret" - os.environ["PEER_SALT"] = os.urandom(16).hex() dc, dcn = initialize_logical_infrastructure() infrastructure = LogicalInfrastructure({dc: [dcn]}) - token = base64.b64encode( - generate_digest( - "1", - os.getenv("PEER_KEY"), - os.getenv("PEER_SECRET"), - bytes.fromhex(os.getenv("PEER_SALT")), - ) - ).decode("ascii") - ia = init_api() + token = jwt.encode(dict(peer="1"), os.environ["PEER_SECRET"], algorithm="HS256") + ia = init() with TestClient(ia) as client: lg = client.post("/synchronize") assert 403 == lg.status_code lg = client.post( "/synchronize", - headers={"Authorization": f"Digest {token}"}, + headers={"Authorization": f"Token {token}"}, json={ "LogicalInfrastructure": json.dumps(infrastructure, cls=HoraoEncoder) }, ) - # todo fix this + # todo still need to fix # assert 200 == lg.status_code