Skip to content

Commit 1476e9c

Browse files
committed
CAIP-79 WIP added basic logic for SKD
1 parent 2727e68 commit 1476e9c

7 files changed

Lines changed: 91 additions & 1 deletion

File tree

symphony/bdk/core/auth/auth_session.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@
55
import logging
66

77
from symphony.bdk.core.auth.exception import AuthInitializationError
8+
from symphony.bdk.core.auth.jwt_helper import extract_session_token_claims
9+
810

911
logger = logging.getLogger(__name__)
1012

1113
EXPIRATION_SAFETY_BUFFER_SECONDS = 5
14+
SKD_FLAG_NAME = "canUseSimplifiedKeyDelivery"
1215

1316

1417
class AuthSession:
@@ -71,6 +74,10 @@ async def key_manager_token(self):
7174
7275
:return: the key manager token
7376
"""
77+
78+
if await self.skd_enabled:
79+
return None
80+
7481
if self._key_manager_token is None:
7582
self._key_manager_token = await self._authenticator.retrieve_key_manager_token()
7683
return self._key_manager_token
@@ -91,6 +98,15 @@ def key_manager_token(self, value):
9198
"""
9299
self._key_manager_token = value
93100

101+
@property
102+
async def skd_enabled(self):
103+
104+
token_data = extract_session_token_claims(await self.session_token)
105+
if not token_data.get(SKD_FLAG_NAME, False):
106+
return False
107+
return self._authenticator.agent_version_service.is_skd_supported()
108+
109+
94110

95111
class OboAuthSession(AuthSession):
96112
"""RSA OBO Authentication session handle to get the OBO session token from.

symphony/bdk/core/auth/bot_authenticator.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from symphony.bdk.core.config.model.bdk_retry_config import BdkRetryConfig
99
from symphony.bdk.core.retry import retry
1010
from symphony.bdk.core.retry.strategy import authentication_retry
11+
from symphony.bdk.core.service.version.agent_version_service import AgentVersionService
1112
from symphony.bdk.gen.api_client import ApiClient
1213
from symphony.bdk.gen.auth_api.certificate_authentication_api import CertificateAuthenticationApi
1314
from symphony.bdk.gen.login_api.authentication_api import AuthenticationApi
@@ -24,6 +25,7 @@ def __init__(self, session_auth_client: ApiClient, key_manager_auth_client: ApiC
2425
self._session_auth_client = session_auth_client
2526
self._key_manager_auth_client = key_manager_auth_client
2627
self._retry_config = retry_config
28+
self._agent_version_service = None
2729

2830
async def retrieve_session_token(self) -> str:
2931
"""Authenticates and retrieves a new session token.
@@ -59,6 +61,15 @@ async def _authenticate_and_get_token(self, api_client: ApiClient) -> str:
5961
:return: the token as a string
6062
"""
6163

64+
@property
65+
def agent_version_service(self) -> Optional[AgentVersionService]:
66+
return self._agent_version_service
67+
68+
@agent_version_service.setter
69+
def agent_version_service(self, agent_version_service: AgentVersionService):
70+
self._agent_version_service = agent_version_service
71+
72+
6273

6374
class BotAuthenticatorRsa(BotAuthenticator):
6475
"""Bot authenticator RSA implementation.

symphony/bdk/core/auth/jwt_helper.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,10 @@ def _parse_public_key_from_x509_cert(certificate: str) -> str:
8383
return public_key.public_bytes(Encoding.PEM, PublicFormat.SubjectPublicKeyInfo).decode()
8484
except ValueError as exc:
8585
raise AuthInitializationError("Unable to parse the certificate. Check certificate format.") from exc
86+
87+
88+
def extract_session_token_claims(session_token):
89+
return jwt.decode(session_token,
90+
algorithms=["RS512"],
91+
options={"verify_signature": False}
92+
)

symphony/bdk/core/service/version/__init__.py

Whitespace-only changes.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import re
2+
3+
from symphony.bdk.core.auth.auth_session import AuthSession
4+
from symphony.bdk.core.config.model.bdk_retry_config import BdkRetryConfig
5+
from symphony.bdk.core.retry import retry
6+
from symphony.bdk.gen.agent_api.signals_api import SignalsApi
7+
from symphony.bdk.gen.exceptions import ApiException
8+
9+
MIN_MAJOR_VERSION = 24
10+
MIN_MINOR_VERSION = 12
11+
VERSION_REGEXP = r"Agent-(\d+)\.(\d+)\..*"
12+
13+
14+
class AgentVersionService:
15+
"""Service class has one purpose only. It checks if version of agents supports simplified key delivery mechanism
16+
17+
"""
18+
19+
def __init__(self, signals_api: SignalsApi, auth_session: AuthSession, retry_config: BdkRetryConfig):
20+
self._signals_api = signals_api
21+
self._retry_config = retry_config
22+
23+
@retry
24+
async def is_skd_supported(self) -> bool:
25+
"""
26+
:return: boolean flag if skd supported for agent
27+
"""
28+
try:
29+
agent_info = await self._signals_api.v1_info_get()
30+
except ApiException:
31+
return False
32+
agent_major_version, agent_minor_version = self._parse_version(agent_info.version)
33+
if not agent_major_version:
34+
return False
35+
if agent_major_version == MIN_MAJOR_VERSION:
36+
return agent_minor_version >= MIN_MINOR_VERSION
37+
return agent_major_version > MIN_MAJOR_VERSION
38+
39+
@staticmethod
40+
def _parse_version(version_string):
41+
match = re.match(r"Agent-(\d+)\.(\d+)\..*", version_string)
42+
if match:
43+
return int(match.group(1)), int(match.group(2))
44+
45+
return None, None

symphony/bdk/core/service_factory.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from symphony.bdk.core.service.signal.signal_service import SignalService, OboSignalService
1919
from symphony.bdk.core.service.stream.stream_service import StreamService, OboStreamService
2020
from symphony.bdk.core.service.user.user_service import UserService, OboUserService
21+
from symphony.bdk.core.service.version.agent_version_service import AgentVersionService
2122
from symphony.bdk.gen.agent_api.attachments_api import AttachmentsApi
2223
from symphony.bdk.gen.agent_api.audit_trail_api import AuditTrailApi
2324
from symphony.bdk.gen.agent_api.datafeed_api import DatafeedApi
@@ -203,6 +204,14 @@ def get_presence_service(self) -> PresenceService:
203204
self._config.retry
204205
)
205206

207+
def get_agent_version_service(self) -> AgentVersionService:
208+
"""Returns a fully initialized AgentVersionService
209+
210+
:return: a new AgentVersionService instance
211+
"""
212+
return AgentVersionService(SignalsApi(self._agent_client),
213+
self._config.retry)
214+
206215

207216
class OboServiceFactory:
208217
"""Factory responsible for creating BDK service instances for OBO-enabled endpoints only:

symphony/bdk/core/symphony_bdk.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ def __init__(self, config):
105105
"You can however use services in OBO mode if app authentication is configured.")
106106

107107
def _initialize_bot_services(self):
108-
self._bot_session = AuthSession(self._authenticator_factory.get_bot_authenticator())
108+
bot_authenticator = self._authenticator_factory.get_bot_authenticator()
109+
self._bot_session = AuthSession(bot_authenticator)
109110
self._service_factory = ServiceFactory(self._api_client_factory, self._bot_session, self._config)
110111
self._user_service = self._service_factory.get_user_service()
111112
self._message_service = self._service_factory.get_message_service()
@@ -123,6 +124,7 @@ def _initialize_bot_services(self):
123124
self._datafeed_loop.subscribe(self._activity_registry)
124125
# initialises extension service and register decorated extensions
125126
self._extension_service = ExtensionService(self._api_client_factory, self._bot_session, self._config)
127+
bot_authenticator.agent_version_service = self._service_factory.get_agent_version_service()
126128

127129
@bot_service
128130
def bot_session(self) -> AuthSession:

0 commit comments

Comments
 (0)