diff --git a/encryption_jwt/codec_server.py b/encryption_jwt/codec_server.py index d0bba91d..495a3a91 100644 --- a/encryption_jwt/codec_server.py +++ b/encryption_jwt/codec_server.py @@ -2,20 +2,22 @@ import os import ssl -import grpc import jwt import requests from aiohttp import hdrs, web from google.protobuf import json_format from jwt.algorithms import RSAAlgorithm -from temporalio.api.cloud.cloudservice.v1 import request_response_pb2, service_pb2_grpc -from temporalio.api.common.v1 import Payload, Payloads +from temporalio.api.cloud.cloudservice.v1 import GetUsersRequest +from temporalio.api.common.v1 import Payloads +from temporalio.client import CloudOperationsClient from encryption_jwt.codec import EncryptionCodec AUTHORIZED_ACCOUNT_ACCESS_ROLES = ["owner", "admin"] AUTHORIZED_NAMESPACE_ACCESS_ROLES = ["read", "write", "admin"] +TEMPORAL_CLIENT_CLOUD_API_VERSION = "2024-05-13-00" + temporal_ops_address = "saas-api.tmprl.cloud:443" if os.environ.get("TEMPORAL_OPS_ADDRESS"): temporal_ops_address = os.environ.get("TEMPORAL_OPS_ADDRESS") @@ -45,44 +47,32 @@ async def cors_options(req: web.Request) -> web.Response: return resp - def decryption_authorized(email: str, namespace: str) -> bool: - credentials = grpc.composite_channel_credentials( - grpc.ssl_channel_credentials(), - grpc.access_token_call_credentials(os.environ.get("TEMPORAL_API_KEY")), + async def decryption_authorized(email: str, namespace: str) -> bool: + client = await CloudOperationsClient.connect( + api_key=os.environ.get("TEMPORAL_API_KEY"), + version=TEMPORAL_CLIENT_CLOUD_API_VERSION, ) - with grpc.secure_channel(temporal_ops_address, credentials) as channel: - client = service_pb2_grpc.CloudServiceStub(channel) - request = request_response_pb2.GetUsersRequest() - - response = client.GetUsers( - request, - metadata=( - ( - "temporal-cloud-api-version", - os.environ.get("TEMPORAL_OPS_API_VERSION"), - ), - ), - ) + response = await client.cloud_service.get_users( + GetUsersRequest(namespace=namespace) + ) - for user in response.users: - if user.spec.email.lower() == email.lower(): - if ( - user.spec.access.account_access.role - in AUTHORIZED_ACCOUNT_ACCESS_ROLES - ): - return True - else: - if namespace in user.spec.access.namespace_accesses: - if ( - user.spec.access.namespace_accesses[ - namespace - ].permission - in AUTHORIZED_NAMESPACE_ACCESS_ROLES - ): - return True - - return False + for user in response.users: + if user.spec.email.lower() == email.lower(): + if ( + user.spec.access.account_access.role + in AUTHORIZED_ACCOUNT_ACCESS_ROLES + ): + return True + else: + if namespace in user.spec.access.namespace_accesses: + if ( + user.spec.access.namespace_accesses[namespace].permission + in AUTHORIZED_NAMESPACE_ACCESS_ROLES + ): + return True + + return False def make_handler(fn: str): async def handler(req: web.Request): @@ -122,7 +112,7 @@ async def handler(req: web.Request): ) # Use the email to determine if the user is authorized to decrypt the payload - authorized = decryption_authorized( + authorized = await decryption_authorized( decoded["https://saas-api.tmprl.cloud/user/email"], namespace ) diff --git a/poetry.lock b/poetry.lock index fd859826..ee5188bb 100644 --- a/poetry.lock +++ b/poetry.lock @@ -54,13 +54,13 @@ files = [ [[package]] name = "aiohappyeyeballs" -version = "2.4.2" +version = "2.4.3" description = "Happy Eyeballs for asyncio" optional = false python-versions = ">=3.8" files = [ - {file = "aiohappyeyeballs-2.4.2-py3-none-any.whl", hash = "sha256:8522691d9a154ba1145b157d6d5c15e5c692527ce6a53c5e5f9876977f6dab2f"}, - {file = "aiohappyeyeballs-2.4.2.tar.gz", hash = "sha256:4ca893e6c5c1f5bf3888b04cb5a3bee24995398efef6e0b9f747b5e89d84fd74"}, + {file = "aiohappyeyeballs-2.4.3-py3-none-any.whl", hash = "sha256:8a7a83727b2756f394ab2895ea0765a0a8c475e3c71e98d43d76f22b4b435572"}, + {file = "aiohappyeyeballs-2.4.3.tar.gz", hash = "sha256:75cf88a15106a5002a8eb1dab212525c00d1f4c0fa96e551c9fbe6f09a621586"}, ] [[package]] @@ -3370,4 +3370,4 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "a9690e47f6ca197e0cfa67e26243b4d7dd8e8dbc01c0976bcd261a6061100bbd" +content-hash = "f129cbacbfaa51878f7337a90d8586f0bc043c67b80efc22f1d56db2d1ab6959" diff --git a/pyproject.toml b/pyproject.toml index e8d6dc24..15566c81 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,7 +45,7 @@ dependencies = { cryptography = "^38.0.1", aiohttp = "^3.8.1" } [tool.poetry.group.encryption_jwt] optional = true -dependencies = { cryptography = "^38.0.1", aiohttp = "^3.8.1", pyjwt = "^2.9.0", grpcio = "^1.66.1", aioboto3 = "^13.1.1", "requests" = "^2.32.3" } +dependencies = { cryptography = "^38.0.1", aiohttp = "^3.8.1", pyjwt = "^2.9.0", aioboto3 = "^13.1.1", "requests" = "^2.32.3" } [tool.poetry.group.gevent] optional = true