otdf-python 0.1.10__py3-none-any.whl → 0.3.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. otdf_python/__init__.py +25 -0
  2. otdf_python/__main__.py +12 -0
  3. otdf_python/address_normalizer.py +84 -0
  4. otdf_python/aesgcm.py +55 -0
  5. otdf_python/assertion_config.py +84 -0
  6. otdf_python/asym_crypto.py +198 -0
  7. otdf_python/auth_headers.py +33 -0
  8. otdf_python/autoconfigure_utils.py +113 -0
  9. otdf_python/cli.py +569 -0
  10. otdf_python/collection_store.py +41 -0
  11. otdf_python/collection_store_impl.py +22 -0
  12. otdf_python/config.py +69 -0
  13. otdf_python/connect_client.py +0 -0
  14. otdf_python/constants.py +1 -0
  15. otdf_python/crypto_utils.py +78 -0
  16. otdf_python/dpop.py +81 -0
  17. otdf_python/ecc_constants.py +176 -0
  18. otdf_python/ecc_mode.py +83 -0
  19. otdf_python/ecdh.py +317 -0
  20. otdf_python/eckeypair.py +75 -0
  21. otdf_python/header.py +181 -0
  22. otdf_python/invalid_zip_exception.py +8 -0
  23. otdf_python/kas_client.py +709 -0
  24. otdf_python/kas_connect_rpc_client.py +213 -0
  25. otdf_python/kas_info.py +25 -0
  26. otdf_python/kas_key_cache.py +52 -0
  27. otdf_python/key_type.py +31 -0
  28. otdf_python/key_type_constants.py +43 -0
  29. otdf_python/manifest.py +215 -0
  30. otdf_python/nanotdf.py +863 -0
  31. otdf_python/nanotdf_ecdsa_struct.py +132 -0
  32. otdf_python/nanotdf_type.py +43 -0
  33. otdf_python/policy_binding_serializer.py +39 -0
  34. otdf_python/policy_info.py +55 -0
  35. otdf_python/policy_object.py +22 -0
  36. otdf_python/policy_stub.py +2 -0
  37. otdf_python/resource_locator.py +172 -0
  38. otdf_python/sdk.py +436 -0
  39. otdf_python/sdk_builder.py +416 -0
  40. otdf_python/sdk_exceptions.py +16 -0
  41. otdf_python/symmetric_and_payload_config.py +30 -0
  42. otdf_python/tdf.py +480 -0
  43. otdf_python/tdf_reader.py +153 -0
  44. otdf_python/tdf_writer.py +23 -0
  45. otdf_python/token_source.py +34 -0
  46. otdf_python/version.py +57 -0
  47. otdf_python/zip_reader.py +47 -0
  48. otdf_python/zip_writer.py +70 -0
  49. otdf_python-0.3.5.dist-info/METADATA +153 -0
  50. otdf_python-0.3.5.dist-info/RECORD +137 -0
  51. {otdf_python-0.1.10.dist-info → otdf_python-0.3.5.dist-info}/WHEEL +1 -2
  52. {otdf_python-0.1.10.dist-info → otdf_python-0.3.5.dist-info/licenses}/LICENSE +1 -1
  53. otdf_python_proto/__init__.py +37 -0
  54. otdf_python_proto/authorization/__init__.py +1 -0
  55. otdf_python_proto/authorization/authorization_pb2.py +80 -0
  56. otdf_python_proto/authorization/authorization_pb2.pyi +161 -0
  57. otdf_python_proto/authorization/authorization_pb2_connect.py +191 -0
  58. otdf_python_proto/authorization/v2/authorization_pb2.py +105 -0
  59. otdf_python_proto/authorization/v2/authorization_pb2.pyi +134 -0
  60. otdf_python_proto/authorization/v2/authorization_pb2_connect.py +233 -0
  61. otdf_python_proto/common/__init__.py +1 -0
  62. otdf_python_proto/common/common_pb2.py +52 -0
  63. otdf_python_proto/common/common_pb2.pyi +61 -0
  64. otdf_python_proto/entity/__init__.py +1 -0
  65. otdf_python_proto/entity/entity_pb2.py +47 -0
  66. otdf_python_proto/entity/entity_pb2.pyi +50 -0
  67. otdf_python_proto/entityresolution/__init__.py +1 -0
  68. otdf_python_proto/entityresolution/entity_resolution_pb2.py +57 -0
  69. otdf_python_proto/entityresolution/entity_resolution_pb2.pyi +55 -0
  70. otdf_python_proto/entityresolution/entity_resolution_pb2_connect.py +149 -0
  71. otdf_python_proto/entityresolution/v2/entity_resolution_pb2.py +55 -0
  72. otdf_python_proto/entityresolution/v2/entity_resolution_pb2.pyi +55 -0
  73. otdf_python_proto/entityresolution/v2/entity_resolution_pb2_connect.py +149 -0
  74. otdf_python_proto/kas/__init__.py +9 -0
  75. otdf_python_proto/kas/kas_pb2.py +103 -0
  76. otdf_python_proto/kas/kas_pb2.pyi +170 -0
  77. otdf_python_proto/kas/kas_pb2_connect.py +192 -0
  78. otdf_python_proto/legacy_grpc/__init__.py +1 -0
  79. otdf_python_proto/legacy_grpc/authorization/authorization_pb2_grpc.py +163 -0
  80. otdf_python_proto/legacy_grpc/authorization/v2/authorization_pb2_grpc.py +206 -0
  81. otdf_python_proto/legacy_grpc/common/common_pb2_grpc.py +4 -0
  82. otdf_python_proto/legacy_grpc/entity/entity_pb2_grpc.py +4 -0
  83. otdf_python_proto/legacy_grpc/entityresolution/entity_resolution_pb2_grpc.py +122 -0
  84. otdf_python_proto/legacy_grpc/entityresolution/v2/entity_resolution_pb2_grpc.py +120 -0
  85. otdf_python_proto/legacy_grpc/kas/kas_pb2_grpc.py +172 -0
  86. otdf_python_proto/legacy_grpc/logger/audit/test_pb2_grpc.py +4 -0
  87. otdf_python_proto/legacy_grpc/policy/actions/actions_pb2_grpc.py +249 -0
  88. otdf_python_proto/legacy_grpc/policy/attributes/attributes_pb2_grpc.py +873 -0
  89. otdf_python_proto/legacy_grpc/policy/kasregistry/key_access_server_registry_pb2_grpc.py +602 -0
  90. otdf_python_proto/legacy_grpc/policy/keymanagement/key_management_pb2_grpc.py +251 -0
  91. otdf_python_proto/legacy_grpc/policy/namespaces/namespaces_pb2_grpc.py +427 -0
  92. otdf_python_proto/legacy_grpc/policy/objects_pb2_grpc.py +4 -0
  93. otdf_python_proto/legacy_grpc/policy/registeredresources/registered_resources_pb2_grpc.py +524 -0
  94. otdf_python_proto/legacy_grpc/policy/resourcemapping/resource_mapping_pb2_grpc.py +516 -0
  95. otdf_python_proto/legacy_grpc/policy/selectors_pb2_grpc.py +4 -0
  96. otdf_python_proto/legacy_grpc/policy/subjectmapping/subject_mapping_pb2_grpc.py +551 -0
  97. otdf_python_proto/legacy_grpc/policy/unsafe/unsafe_pb2_grpc.py +485 -0
  98. otdf_python_proto/legacy_grpc/wellknownconfiguration/wellknown_configuration_pb2_grpc.py +77 -0
  99. otdf_python_proto/logger/__init__.py +1 -0
  100. otdf_python_proto/logger/audit/test_pb2.py +43 -0
  101. otdf_python_proto/logger/audit/test_pb2.pyi +45 -0
  102. otdf_python_proto/policy/__init__.py +1 -0
  103. otdf_python_proto/policy/actions/actions_pb2.py +75 -0
  104. otdf_python_proto/policy/actions/actions_pb2.pyi +87 -0
  105. otdf_python_proto/policy/actions/actions_pb2_connect.py +275 -0
  106. otdf_python_proto/policy/attributes/attributes_pb2.py +234 -0
  107. otdf_python_proto/policy/attributes/attributes_pb2.pyi +328 -0
  108. otdf_python_proto/policy/attributes/attributes_pb2_connect.py +863 -0
  109. otdf_python_proto/policy/kasregistry/key_access_server_registry_pb2.py +266 -0
  110. otdf_python_proto/policy/kasregistry/key_access_server_registry_pb2.pyi +450 -0
  111. otdf_python_proto/policy/kasregistry/key_access_server_registry_pb2_connect.py +611 -0
  112. otdf_python_proto/policy/keymanagement/key_management_pb2.py +79 -0
  113. otdf_python_proto/policy/keymanagement/key_management_pb2.pyi +87 -0
  114. otdf_python_proto/policy/keymanagement/key_management_pb2_connect.py +275 -0
  115. otdf_python_proto/policy/namespaces/namespaces_pb2.py +117 -0
  116. otdf_python_proto/policy/namespaces/namespaces_pb2.pyi +147 -0
  117. otdf_python_proto/policy/namespaces/namespaces_pb2_connect.py +443 -0
  118. otdf_python_proto/policy/objects_pb2.py +150 -0
  119. otdf_python_proto/policy/objects_pb2.pyi +464 -0
  120. otdf_python_proto/policy/registeredresources/registered_resources_pb2.py +139 -0
  121. otdf_python_proto/policy/registeredresources/registered_resources_pb2.pyi +196 -0
  122. otdf_python_proto/policy/registeredresources/registered_resources_pb2_connect.py +527 -0
  123. otdf_python_proto/policy/resourcemapping/resource_mapping_pb2.py +139 -0
  124. otdf_python_proto/policy/resourcemapping/resource_mapping_pb2.pyi +194 -0
  125. otdf_python_proto/policy/resourcemapping/resource_mapping_pb2_connect.py +527 -0
  126. otdf_python_proto/policy/selectors_pb2.py +57 -0
  127. otdf_python_proto/policy/selectors_pb2.pyi +90 -0
  128. otdf_python_proto/policy/subjectmapping/subject_mapping_pb2.py +127 -0
  129. otdf_python_proto/policy/subjectmapping/subject_mapping_pb2.pyi +189 -0
  130. otdf_python_proto/policy/subjectmapping/subject_mapping_pb2_connect.py +569 -0
  131. otdf_python_proto/policy/unsafe/unsafe_pb2.py +113 -0
  132. otdf_python_proto/policy/unsafe/unsafe_pb2.pyi +145 -0
  133. otdf_python_proto/policy/unsafe/unsafe_pb2_connect.py +485 -0
  134. otdf_python_proto/wellknownconfiguration/__init__.py +1 -0
  135. otdf_python_proto/wellknownconfiguration/wellknown_configuration_pb2.py +51 -0
  136. otdf_python_proto/wellknownconfiguration/wellknown_configuration_pb2.pyi +32 -0
  137. otdf_python_proto/wellknownconfiguration/wellknown_configuration_pb2_connect.py +107 -0
  138. otdf_python/_gotdf_python.cpython-312-darwin.so +0 -0
  139. otdf_python/build.py +0 -190
  140. otdf_python/go.py +0 -1478
  141. otdf_python/gotdf_python.py +0 -383
  142. otdf_python-0.1.10.dist-info/METADATA +0 -149
  143. otdf_python-0.1.10.dist-info/RECORD +0 -10
  144. otdf_python-0.1.10.dist-info/top_level.txt +0 -1
@@ -0,0 +1,416 @@
1
+ """
2
+ Python port of the SDKBuilder class for OpenTDF platform interaction.
3
+ Provides methods to configure and build SDK instances.
4
+ """
5
+
6
+ import logging
7
+ import ssl
8
+ from dataclasses import dataclass
9
+ from pathlib import Path
10
+
11
+ import httpx
12
+
13
+ from otdf_python.sdk import KAS, SDK
14
+ from otdf_python.sdk_exceptions import AutoConfigureException
15
+
16
+ # Configure logging
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ @dataclass
21
+ class OAuthConfig:
22
+ client_id: str
23
+ client_secret: str
24
+ grant_type: str = "client_credentials"
25
+ scope: str = "openid profile email"
26
+ token_endpoint: str | None = None
27
+ access_token: str | None = None
28
+
29
+
30
+ class SDKBuilder:
31
+ """
32
+ A builder class for creating instances of the SDK class.
33
+ """
34
+
35
+ PLATFORM_ISSUER = "platform_issuer"
36
+
37
+ # Class variable to store the latest platform URL
38
+ _platform_url = None
39
+
40
+ def __init__(self):
41
+ self.platform_endpoint: str | None = None
42
+ self.issuer_endpoint: str | None = None
43
+ self.oauth_config: OAuthConfig | None = None
44
+ self.use_plaintext: bool = False
45
+ self.insecure_skip_verify: bool = False
46
+ self.ssl_context: ssl.SSLContext | None = None
47
+ self.auth_token: str | None = None
48
+ self.cert_paths: list[str] = []
49
+
50
+ @staticmethod
51
+ def new_builder() -> "SDKBuilder":
52
+ """
53
+ Creates a new SDKBuilder instance.
54
+ Returns:
55
+ SDKBuilder: A new builder instance
56
+ """
57
+ return SDKBuilder()
58
+
59
+ @staticmethod
60
+ def get_platform_url() -> str | None:
61
+ """
62
+ Gets the last set platform URL.
63
+ Returns:
64
+ str | None: The platform URL or None if not set
65
+ """
66
+ return SDKBuilder._platform_url
67
+
68
+ def ssl_context_from_directory(self, certs_dir_path: str) -> "SDKBuilder":
69
+ """
70
+ Add SSL Context with trusted certs from certDirPath
71
+ Args:
72
+ certs_dir_path: Path to a directory containing .pem or .crt trusted certs
73
+ Returns:
74
+ self: The builder instance for chaining
75
+ """
76
+ self.cert_paths = []
77
+
78
+ # Find all .pem and .crt files in the directory
79
+ certs_path = Path(certs_dir_path)
80
+ for cert_file in certs_path.iterdir():
81
+ if cert_file.suffix in (".pem", ".crt"):
82
+ self.cert_paths.append(str(cert_file))
83
+
84
+ # Create SSL context with these certificates
85
+ if self.cert_paths:
86
+ context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
87
+ for cert_path in self.cert_paths:
88
+ context.load_verify_locations(cert_path)
89
+ self.ssl_context = context
90
+
91
+ return self
92
+
93
+ def client_secret(self, client_id: str, client_secret: str) -> "SDKBuilder":
94
+ """
95
+ Sets client credentials for OAuth 2.0 client_credentials grant.
96
+ Args:
97
+ client_id: The OAuth client ID
98
+ client_secret: The OAuth client secret
99
+ Returns:
100
+ self: The builder instance for chaining
101
+ """
102
+ self.oauth_config = OAuthConfig(
103
+ client_id=client_id, client_secret=client_secret
104
+ )
105
+ return self
106
+
107
+ def set_platform_endpoint(self, endpoint: str) -> "SDKBuilder":
108
+ """
109
+ Sets the OpenTDF platform endpoint URL.
110
+ Args:
111
+ endpoint: The platform endpoint URL
112
+ Returns:
113
+ self: The builder instance for chaining
114
+ """
115
+ # Normalize the endpoint URL
116
+ if endpoint and not (
117
+ endpoint.startswith("http://") or endpoint.startswith("https://")
118
+ ):
119
+ if self.use_plaintext:
120
+ endpoint = f"http://{endpoint}"
121
+ else:
122
+ endpoint = f"https://{endpoint}"
123
+
124
+ self.platform_endpoint = endpoint
125
+ # Store in class variable for access from other components
126
+ SDKBuilder._platform_url = endpoint
127
+ return self
128
+
129
+ def set_issuer_endpoint(self, issuer: str) -> "SDKBuilder":
130
+ """
131
+ Sets the OpenID Connect issuer endpoint URL.
132
+ Args:
133
+ issuer: The issuer endpoint URL
134
+ Returns:
135
+ self: The builder instance for chaining
136
+ """
137
+ # Normalize the issuer URL
138
+ if issuer and not (
139
+ issuer.startswith("http://") or issuer.startswith("https://")
140
+ ):
141
+ issuer = f"https://{issuer}"
142
+
143
+ self.issuer_endpoint = issuer
144
+ return self
145
+
146
+ def use_insecure_plaintext_connection(
147
+ self, use_plaintext: bool = True
148
+ ) -> "SDKBuilder":
149
+ """
150
+ Configures whether to use plain text (HTTP) connection instead of HTTPS.
151
+ Args:
152
+ use_plaintext: Whether to use plain text connection
153
+ Returns:
154
+ self: The builder instance for chaining
155
+ """
156
+ self.use_plaintext = use_plaintext
157
+
158
+ # Update platform endpoint protocol if necessary
159
+ if self.platform_endpoint:
160
+ if use_plaintext and self.platform_endpoint.startswith("https://"):
161
+ self.platform_endpoint = f"http://{self.platform_endpoint[8:]}"
162
+ elif not use_plaintext and self.platform_endpoint.startswith("http://"):
163
+ self.platform_endpoint = f"https://{self.platform_endpoint[7:]}"
164
+
165
+ # Update the class variable as well since kas() method uses it
166
+ SDKBuilder._platform_url = self.platform_endpoint
167
+
168
+ return self
169
+
170
+ def use_insecure_skip_verify(self, skip_verify: bool = True) -> "SDKBuilder":
171
+ """
172
+ Configures whether to skip SSL verification.
173
+ Args:
174
+ skip_verify: Whether to skip SSL verification
175
+ Returns:
176
+ self: The builder instance for chaining
177
+ """
178
+ self.insecure_skip_verify = skip_verify
179
+
180
+ # If skipping verification, create a default SSL context that does not verify
181
+ if skip_verify:
182
+ self.ssl_context = ssl._create_unverified_context()
183
+
184
+ return self
185
+
186
+ def bearer_token(self, token: str) -> "SDKBuilder":
187
+ """
188
+ Sets a bearer token to use for authorization.
189
+ Args:
190
+ token: The bearer token
191
+ Returns:
192
+ self: The builder instance for chaining
193
+ """
194
+ self.auth_token = token
195
+ return self
196
+
197
+ def _discover_token_endpoint_from_platform(self) -> None:
198
+ """
199
+ Discover token endpoint using OpenTDF platform configuration.
200
+ Raises:
201
+ AutoConfigureException: If discovery fails
202
+ """
203
+ if not self.platform_endpoint or not self.oauth_config:
204
+ return
205
+
206
+ # Try to get OpenTDF configuration first
207
+ well_known_url = f"{self.platform_endpoint}/.well-known/opentdf-configuration"
208
+ response = httpx.get(well_known_url, verify=not self.insecure_skip_verify)
209
+
210
+ if response.status_code != 200:
211
+ raise AutoConfigureException(
212
+ f"Failed to retrieve OpenTDF configuration from {well_known_url} (status: {response.status_code}). "
213
+ "Please provide an explicit issuer endpoint or check platform URL."
214
+ )
215
+
216
+ config_doc = response.json()
217
+ configuration = config_doc.get("configuration", {})
218
+
219
+ # Try to get token endpoint from IDP configuration
220
+ idp_config = configuration.get("idp", {})
221
+ if idp_config.get("token_endpoint"):
222
+ self.oauth_config.token_endpoint = idp_config["token_endpoint"]
223
+ return
224
+
225
+ # Fall back to using platform_issuer for OIDC discovery
226
+ platform_issuer = configuration.get("platform_issuer")
227
+ if not platform_issuer:
228
+ raise AutoConfigureException(
229
+ "No platform_issuer found in OpenTDF configuration"
230
+ )
231
+
232
+ self._discover_token_endpoint_from_issuer(platform_issuer)
233
+
234
+ def _discover_token_endpoint_from_issuer(self, issuer_url: str) -> None:
235
+ """
236
+ Discover token endpoint using OIDC discovery from issuer.
237
+ Args:
238
+ issuer_url: The issuer URL to use for discovery
239
+ Raises:
240
+ AutoConfigureException: If discovery fails
241
+ """
242
+ if not self.oauth_config:
243
+ return
244
+
245
+ oidc_discovery_url = f"{issuer_url}/.well-known/openid-configuration"
246
+ oidc_response = httpx.get(
247
+ oidc_discovery_url, verify=not self.insecure_skip_verify
248
+ )
249
+
250
+ if oidc_response.status_code != 200:
251
+ raise AutoConfigureException(
252
+ f"Failed to retrieve OIDC configuration from {oidc_discovery_url}: {oidc_response.status_code}"
253
+ )
254
+
255
+ oidc_doc = oidc_response.json()
256
+ self.oauth_config.token_endpoint = oidc_doc.get("token_endpoint")
257
+ if not self.oauth_config.token_endpoint:
258
+ raise AutoConfigureException(
259
+ "Token endpoint not found in OIDC discovery document"
260
+ )
261
+
262
+ def _discover_token_endpoint(self) -> None:
263
+ """
264
+ Discover the token endpoint using available configuration.
265
+ Raises:
266
+ AutoConfigureException: If discovery fails
267
+ """
268
+ # Try platform endpoint first
269
+ if self.platform_endpoint:
270
+ try:
271
+ self._discover_token_endpoint_from_platform()
272
+ return
273
+ except Exception as e:
274
+ # If platform fails and we have an explicit issuer, try that
275
+ if self.issuer_endpoint:
276
+ try:
277
+ realm_name = "opentdf" # Default realm name
278
+ issuer_url = f"{self.issuer_endpoint}/realms/{realm_name}"
279
+ self._discover_token_endpoint_from_issuer(issuer_url)
280
+ return
281
+ except Exception:
282
+ # Re-raise the original platform error
283
+ pass
284
+ raise AutoConfigureException(
285
+ f"Error during token endpoint discovery: {e!s}"
286
+ )
287
+
288
+ # Fall back to explicit issuer endpoint
289
+ if self.issuer_endpoint:
290
+ realm_name = "opentdf" # Default realm name
291
+ issuer_url = f"{self.issuer_endpoint}/realms/{realm_name}"
292
+ self._discover_token_endpoint_from_issuer(issuer_url)
293
+ return
294
+
295
+ raise AutoConfigureException(
296
+ "Platform endpoint or issuer endpoint must be configured for OIDC token discovery"
297
+ )
298
+
299
+ def _get_token_from_client_credentials(self) -> str:
300
+ """
301
+ Obtains an OAuth token using client credentials.
302
+ Returns:
303
+ str: The access token
304
+ Raises:
305
+ AutoConfigureException: If token acquisition fails
306
+ """
307
+ if not self.oauth_config:
308
+ raise AutoConfigureException("OAuth configuration is not set")
309
+
310
+ if not self.oauth_config.token_endpoint:
311
+ self._discover_token_endpoint()
312
+
313
+ # Ensure we have a token endpoint before proceeding
314
+ if not self.oauth_config.token_endpoint:
315
+ raise AutoConfigureException("Token endpoint discovery failed")
316
+
317
+ # Request the token
318
+ try:
319
+ token_data = {
320
+ "grant_type": self.oauth_config.grant_type,
321
+ "client_id": self.oauth_config.client_id,
322
+ "client_secret": self.oauth_config.client_secret,
323
+ "scope": self.oauth_config.scope,
324
+ }
325
+
326
+ response = httpx.post(
327
+ self.oauth_config.token_endpoint,
328
+ data=token_data,
329
+ verify=not self.insecure_skip_verify,
330
+ )
331
+
332
+ if response.status_code == 200:
333
+ token_response = response.json()
334
+ access_token = token_response.get("access_token")
335
+ if not access_token:
336
+ raise AutoConfigureException("No access_token in token response")
337
+ return access_token
338
+ else:
339
+ raise AutoConfigureException(
340
+ f"Token request failed: {response.status_code} - {response.text}"
341
+ )
342
+
343
+ except Exception as e:
344
+ raise AutoConfigureException(f"Error during token acquisition: {e!s}")
345
+
346
+ def _create_services(self) -> SDK.Services:
347
+ """
348
+ Creates service client instances.
349
+ Returns:
350
+ SDK.Services: The service client instances
351
+ Raises:
352
+ AutoConfigureException: If service creation fails
353
+ """
354
+ # For now, return a simple implementation of Services
355
+ # In a real implementation, this would create actual service clients
356
+ # connecting to the platform endpoints
357
+
358
+ ssl_verify = not self.insecure_skip_verify
359
+
360
+ class ServicesImpl(SDK.Services):
361
+ def __init__(self, builder_instance):
362
+ self.closed = False
363
+ self._ssl_verify = ssl_verify
364
+ self._builder = builder_instance
365
+
366
+ def kas(self) -> KAS:
367
+ """
368
+ Returns the KAS interface with SSL verification settings.
369
+ """
370
+ platform_url = SDKBuilder.get_platform_url()
371
+
372
+ # Create a token source function that can refresh tokens
373
+ def token_source():
374
+ if self._builder.auth_token:
375
+ return self._builder.auth_token
376
+ elif self._builder.oauth_config:
377
+ return self._builder._get_token_from_client_credentials()
378
+ return None
379
+
380
+ kas_impl = KAS(
381
+ platform_url=platform_url,
382
+ token_source=token_source,
383
+ sdk_ssl_verify=self._ssl_verify,
384
+ use_plaintext=self._builder.use_plaintext,
385
+ )
386
+ return kas_impl
387
+
388
+ def close(self):
389
+ self.closed = True
390
+
391
+ def __exit__(self, exc_type, exc_val, exc_tb):
392
+ self.close()
393
+
394
+ return ServicesImpl(self)
395
+
396
+ def build(self) -> SDK:
397
+ """
398
+ Builds and returns an SDK instance with the configured properties.
399
+ Returns:
400
+ SDK: The configured SDK instance
401
+ Raises:
402
+ AutoConfigureException: If the build fails
403
+ """
404
+ if not self.platform_endpoint:
405
+ raise AutoConfigureException("Platform endpoint is not set")
406
+
407
+ # Create services
408
+ services = self._create_services()
409
+
410
+ # Return the SDK instance, platform_url is set for new_tdf_config
411
+ return SDK(
412
+ services=services,
413
+ platform_url=self.platform_endpoint,
414
+ ssl_verify=not self.insecure_skip_verify,
415
+ use_plaintext=getattr(self, "use_plaintext", False),
416
+ )
@@ -0,0 +1,16 @@
1
+ class SDKException(Exception):
2
+ def __init__(self, message, reason=None):
3
+ super().__init__(message)
4
+ self.reason = reason
5
+
6
+
7
+ class AutoConfigureException(SDKException):
8
+ def __init__(self, message, cause=None):
9
+ super().__init__(message, cause)
10
+
11
+
12
+ class KASBadRequestException(SDKException):
13
+ """Thrown when the KAS returns a bad request response or other client request errors."""
14
+
15
+ def __init__(self, message):
16
+ super().__init__(message)
@@ -0,0 +1,30 @@
1
+ class SymmetricAndPayloadConfig:
2
+ def __init__(
3
+ self,
4
+ cipher_type: int = 0,
5
+ signature_ecc_mode: int = 0,
6
+ has_signature: bool = True,
7
+ ):
8
+ self.cipher_type = cipher_type
9
+ self.signature_ecc_mode = signature_ecc_mode
10
+ self.has_signature = has_signature
11
+
12
+ def set_has_signature(self, flag: bool):
13
+ self.has_signature = flag
14
+
15
+ def set_signature_ecc_mode(self, mode: int):
16
+ self.signature_ecc_mode = mode
17
+
18
+ def set_symmetric_cipher_type(self, cipher_type: int):
19
+ self.cipher_type = cipher_type
20
+
21
+ def get_cipher_type(self) -> int:
22
+ return self.cipher_type
23
+
24
+ def get_symmetric_and_payload_config_as_byte(self) -> int:
25
+ # Most significant bit: has_signature, next 3 bits: signature_ecc_mode, lower 4 bits: cipher_type
26
+ return (
27
+ ((1 if self.has_signature else 0) << 7)
28
+ | ((self.signature_ecc_mode & 0x07) << 4)
29
+ | (self.cipher_type & 0x0F)
30
+ )