infisicalsdk 1.0.2__py3-none-any.whl → 1.0.4__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.
Potentially problematic release.
This version of infisicalsdk might be problematic. Click here for more details.
- infisical_sdk/api_types.py +75 -3
- infisical_sdk/client.py +180 -4
- infisical_sdk/infisical_requests.py +5 -5
- {infisicalsdk-1.0.2.dist-info → infisicalsdk-1.0.4.dist-info}/METADATA +1 -1
- infisicalsdk-1.0.4.dist-info/RECORD +8 -0
- infisicalsdk-1.0.2.dist-info/RECORD +0 -8
- {infisicalsdk-1.0.2.dist-info → infisicalsdk-1.0.4.dist-info}/WHEEL +0 -0
- {infisicalsdk-1.0.2.dist-info → infisicalsdk-1.0.4.dist-info}/top_level.txt +0 -0
infisical_sdk/api_types.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from dataclasses import dataclass, field
|
|
1
|
+
from dataclasses import dataclass, field, fields
|
|
2
2
|
from typing import Optional, List, Any, Dict
|
|
3
3
|
from enum import Enum
|
|
4
4
|
import json
|
|
@@ -34,7 +34,10 @@ class BaseModel:
|
|
|
34
34
|
@classmethod
|
|
35
35
|
def from_dict(cls, data: Dict) -> 'BaseModel':
|
|
36
36
|
"""Create model from dictionary"""
|
|
37
|
-
|
|
37
|
+
# Get only the fields that exist in the dataclass
|
|
38
|
+
valid_fields = {f.name for f in fields(cls)}
|
|
39
|
+
filtered_data = {k: v for k, v in data.items() if k in valid_fields}
|
|
40
|
+
return cls(**filtered_data)
|
|
38
41
|
|
|
39
42
|
def to_json(self) -> str:
|
|
40
43
|
"""Convert model to JSON string"""
|
|
@@ -70,6 +73,7 @@ class BaseSecret(BaseModel):
|
|
|
70
73
|
secretComment: str
|
|
71
74
|
createdAt: str
|
|
72
75
|
updatedAt: str
|
|
76
|
+
secretMetadata: Optional[Dict[str, Any]] = None
|
|
73
77
|
secretReminderNote: Optional[str] = None
|
|
74
78
|
secretReminderRepeatDays: Optional[int] = None
|
|
75
79
|
skipMultilineEncoding: Optional[bool] = False
|
|
@@ -108,7 +112,7 @@ class SingleSecretResponse(BaseModel):
|
|
|
108
112
|
secret: BaseSecret
|
|
109
113
|
|
|
110
114
|
@classmethod
|
|
111
|
-
def from_dict(cls, data: Dict) -> '
|
|
115
|
+
def from_dict(cls, data: Dict) -> 'SingleSecretResponse':
|
|
112
116
|
return cls(
|
|
113
117
|
secret=BaseSecret.from_dict(data['secret']),
|
|
114
118
|
)
|
|
@@ -121,3 +125,71 @@ class MachineIdentityLoginResponse(BaseModel):
|
|
|
121
125
|
expiresIn: int
|
|
122
126
|
accessTokenMaxTTL: int
|
|
123
127
|
tokenType: str
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class SymmetricEncryption(str, Enum):
|
|
131
|
+
AES_GCM_256 = "aes-256-gcm"
|
|
132
|
+
AES_GCM_128 = "aes-128-gcm"
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class OrderDirection(str, Enum):
|
|
136
|
+
ASC = "asc"
|
|
137
|
+
DESC = "desc"
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class KmsKeysOrderBy(str, Enum):
|
|
141
|
+
NAME = "name"
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
@dataclass
|
|
145
|
+
class KmsKey(BaseModel):
|
|
146
|
+
"""Infisical KMS Key"""
|
|
147
|
+
id: str
|
|
148
|
+
description: str
|
|
149
|
+
isDisabled: bool
|
|
150
|
+
orgId: str
|
|
151
|
+
name: str
|
|
152
|
+
createdAt: str
|
|
153
|
+
updatedAt: str
|
|
154
|
+
projectId: str
|
|
155
|
+
version: int
|
|
156
|
+
encryptionAlgorithm: SymmetricEncryption
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
@dataclass
|
|
160
|
+
class ListKmsKeysResponse(BaseModel):
|
|
161
|
+
"""Complete response model for Kms Keys API"""
|
|
162
|
+
keys: List[KmsKey]
|
|
163
|
+
totalCount: int
|
|
164
|
+
|
|
165
|
+
@classmethod
|
|
166
|
+
def from_dict(cls, data: Dict) -> 'ListKmsKeysResponse':
|
|
167
|
+
"""Create model from dictionary with camelCase keys, handling nested objects"""
|
|
168
|
+
return cls(
|
|
169
|
+
keys=[KmsKey.from_dict(key) for key in data['keys']],
|
|
170
|
+
totalCount=data['totalCount']
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
@dataclass
|
|
175
|
+
class SingleKmsKeyResponse(BaseModel):
|
|
176
|
+
"""Response model for get/create/update/delete API"""
|
|
177
|
+
key: KmsKey
|
|
178
|
+
|
|
179
|
+
@classmethod
|
|
180
|
+
def from_dict(cls, data: Dict) -> 'SingleKmsKeyResponse':
|
|
181
|
+
return cls(
|
|
182
|
+
key=KmsKey.from_dict(data['key']),
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
@dataclass
|
|
187
|
+
class KmsKeyEncryptDataResponse(BaseModel):
|
|
188
|
+
"""Response model for encrypt data API"""
|
|
189
|
+
ciphertext: str
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
@dataclass
|
|
193
|
+
class KmsKeyDecryptDataResponse(BaseModel):
|
|
194
|
+
"""Response model for decrypt data API"""
|
|
195
|
+
plaintext: str
|
infisical_sdk/client.py
CHANGED
|
@@ -12,8 +12,11 @@ from botocore.awsrequest import AWSRequest
|
|
|
12
12
|
from botocore.exceptions import NoCredentialsError
|
|
13
13
|
|
|
14
14
|
from .infisical_requests import InfisicalRequests
|
|
15
|
-
|
|
16
|
-
from .api_types import SingleSecretResponse, BaseSecret
|
|
15
|
+
|
|
16
|
+
from .api_types import ListSecretsResponse, SingleSecretResponse, BaseSecret
|
|
17
|
+
from .api_types import SymmetricEncryption, KmsKeysOrderBy, OrderDirection
|
|
18
|
+
from .api_types import ListKmsKeysResponse, SingleKmsKeyResponse, MachineIdentityLoginResponse
|
|
19
|
+
from .api_types import KmsKey, KmsKeyEncryptDataResponse, KmsKeyDecryptDataResponse
|
|
17
20
|
|
|
18
21
|
|
|
19
22
|
class InfisicalSDKClient:
|
|
@@ -25,6 +28,7 @@ class InfisicalSDKClient:
|
|
|
25
28
|
|
|
26
29
|
self.auth = Auth(self)
|
|
27
30
|
self.secrets = V3RawSecrets(self)
|
|
31
|
+
self.kms = KMS(self)
|
|
28
32
|
|
|
29
33
|
def set_token(self, token: str):
|
|
30
34
|
"""
|
|
@@ -219,7 +223,7 @@ class V3RawSecrets:
|
|
|
219
223
|
}
|
|
220
224
|
|
|
221
225
|
if tag_filters:
|
|
222
|
-
params["
|
|
226
|
+
params["tagSlugs"] = ",".join(tag_filters)
|
|
223
227
|
|
|
224
228
|
result = self.client.api.get(
|
|
225
229
|
path="/api/v3/secrets/raw",
|
|
@@ -307,7 +311,7 @@ class V3RawSecrets:
|
|
|
307
311
|
"secretPath": secret_path,
|
|
308
312
|
"secretValue": secret_value,
|
|
309
313
|
"secretComment": secret_comment,
|
|
310
|
-
"
|
|
314
|
+
"newSecretName": new_secret_name,
|
|
311
315
|
"tagIds": None,
|
|
312
316
|
"skipMultilineEncoding": skip_multiline_encoding,
|
|
313
317
|
"type": "shared",
|
|
@@ -343,3 +347,175 @@ class V3RawSecrets:
|
|
|
343
347
|
)
|
|
344
348
|
|
|
345
349
|
return result.data.secret
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
class KMS:
|
|
353
|
+
def __init__(self, client: InfisicalSDKClient) -> None:
|
|
354
|
+
self.client = client
|
|
355
|
+
|
|
356
|
+
def list_keys(
|
|
357
|
+
self,
|
|
358
|
+
project_id: str,
|
|
359
|
+
offset: int = 0,
|
|
360
|
+
limit: int = 100,
|
|
361
|
+
order_by: KmsKeysOrderBy = KmsKeysOrderBy.NAME,
|
|
362
|
+
order_direction: OrderDirection = OrderDirection.ASC,
|
|
363
|
+
search: str = None) -> ListKmsKeysResponse:
|
|
364
|
+
|
|
365
|
+
params = {
|
|
366
|
+
"projectId": project_id,
|
|
367
|
+
"search": search,
|
|
368
|
+
"offset": offset,
|
|
369
|
+
"limit": limit,
|
|
370
|
+
"orderBy": order_by,
|
|
371
|
+
"orderDirection": order_direction,
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
result = self.client.api.get(
|
|
375
|
+
path="/api/v1/kms/keys",
|
|
376
|
+
params=params,
|
|
377
|
+
model=ListKmsKeysResponse
|
|
378
|
+
)
|
|
379
|
+
|
|
380
|
+
return result.data
|
|
381
|
+
|
|
382
|
+
def get_key_by_id(
|
|
383
|
+
self,
|
|
384
|
+
key_id: str) -> KmsKey:
|
|
385
|
+
|
|
386
|
+
result = self.client.api.get(
|
|
387
|
+
path=f"/api/v1/kms/keys/{key_id}",
|
|
388
|
+
model=SingleKmsKeyResponse
|
|
389
|
+
)
|
|
390
|
+
|
|
391
|
+
return result.data.key
|
|
392
|
+
|
|
393
|
+
def get_key_by_name(
|
|
394
|
+
self,
|
|
395
|
+
key_name: str,
|
|
396
|
+
project_id: str) -> KmsKey:
|
|
397
|
+
|
|
398
|
+
params = {
|
|
399
|
+
"projectId": project_id,
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
result = self.client.api.get(
|
|
403
|
+
path=f"/api/v1/kms/keys/key-name/{key_name}",
|
|
404
|
+
params=params,
|
|
405
|
+
model=SingleKmsKeyResponse
|
|
406
|
+
)
|
|
407
|
+
|
|
408
|
+
return result.data.key
|
|
409
|
+
|
|
410
|
+
def create_key(
|
|
411
|
+
self,
|
|
412
|
+
name: str,
|
|
413
|
+
project_id: str,
|
|
414
|
+
encryption_algorithm: SymmetricEncryption,
|
|
415
|
+
description: str = None) -> KmsKey:
|
|
416
|
+
|
|
417
|
+
request_body = {
|
|
418
|
+
"name": name,
|
|
419
|
+
"projectId": project_id,
|
|
420
|
+
"encryptionAlgorithm": encryption_algorithm,
|
|
421
|
+
"description": description,
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
result = self.client.api.post(
|
|
425
|
+
path="/api/v1/kms/keys",
|
|
426
|
+
json=request_body,
|
|
427
|
+
model=SingleKmsKeyResponse
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
return result.data.key
|
|
431
|
+
|
|
432
|
+
def update_key(
|
|
433
|
+
self,
|
|
434
|
+
key_id: str,
|
|
435
|
+
name: str = None,
|
|
436
|
+
is_disabled: bool = None,
|
|
437
|
+
description: str = None) -> KmsKey:
|
|
438
|
+
|
|
439
|
+
request_body = {
|
|
440
|
+
"name": name,
|
|
441
|
+
"isDisabled": is_disabled,
|
|
442
|
+
"description": description,
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
result = self.client.api.patch(
|
|
446
|
+
path=f"/api/v1/kms/keys/{key_id}",
|
|
447
|
+
json=request_body,
|
|
448
|
+
model=SingleKmsKeyResponse
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
return result.data.key
|
|
452
|
+
|
|
453
|
+
def delete_key(
|
|
454
|
+
self,
|
|
455
|
+
key_id: str) -> KmsKey:
|
|
456
|
+
|
|
457
|
+
result = self.client.api.delete(
|
|
458
|
+
path=f"/api/v1/kms/keys/{key_id}",
|
|
459
|
+
json={},
|
|
460
|
+
model=SingleKmsKeyResponse
|
|
461
|
+
)
|
|
462
|
+
|
|
463
|
+
return result.data.key
|
|
464
|
+
|
|
465
|
+
def encrypt_data(
|
|
466
|
+
self,
|
|
467
|
+
key_id: str,
|
|
468
|
+
base64EncodedPlaintext: str) -> str:
|
|
469
|
+
"""
|
|
470
|
+
Encrypt data with the specified KMS key.
|
|
471
|
+
|
|
472
|
+
:param key_id: The ID of the key to decrypt the ciphertext with
|
|
473
|
+
:type key_id: str
|
|
474
|
+
:param base64EncodedPlaintext: The base64 encoded plaintext to encrypt
|
|
475
|
+
:type plaintext: str
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
:return: The encrypted base64 encoded plaintext (ciphertext)
|
|
479
|
+
:rtype: str
|
|
480
|
+
"""
|
|
481
|
+
|
|
482
|
+
request_body = {
|
|
483
|
+
"plaintext": base64EncodedPlaintext
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
result = self.client.api.post(
|
|
487
|
+
path=f"/api/v1/kms/keys/{key_id}/encrypt",
|
|
488
|
+
json=request_body,
|
|
489
|
+
model=KmsKeyEncryptDataResponse
|
|
490
|
+
)
|
|
491
|
+
|
|
492
|
+
return result.data.ciphertext
|
|
493
|
+
|
|
494
|
+
def decrypt_data(
|
|
495
|
+
self,
|
|
496
|
+
key_id: str,
|
|
497
|
+
ciphertext: str) -> str:
|
|
498
|
+
"""
|
|
499
|
+
Decrypt data with the specified KMS key.
|
|
500
|
+
|
|
501
|
+
:param key_id: The ID of the key to decrypt the ciphertext with
|
|
502
|
+
:type key_id: str
|
|
503
|
+
:param ciphertext: The encrypted base64 plaintext to decrypt
|
|
504
|
+
:type ciphertext: str
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
:return: The base64 encoded plaintext
|
|
508
|
+
:rtype: str
|
|
509
|
+
"""
|
|
510
|
+
|
|
511
|
+
request_body = {
|
|
512
|
+
"ciphertext": ciphertext
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
result = self.client.api.post(
|
|
516
|
+
path=f"/api/v1/kms/keys/{key_id}/decrypt",
|
|
517
|
+
json=request_body,
|
|
518
|
+
model=KmsKeyDecryptDataResponse
|
|
519
|
+
)
|
|
520
|
+
|
|
521
|
+
return result.data.plaintext
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Any, Dict, Generic, Optional, TypeVar
|
|
1
|
+
from typing import Any, Dict, Generic, Optional, TypeVar, Type
|
|
2
2
|
from urllib.parse import urljoin
|
|
3
3
|
import requests
|
|
4
4
|
from dataclasses import dataclass
|
|
@@ -90,7 +90,7 @@ class InfisicalRequests:
|
|
|
90
90
|
def get(
|
|
91
91
|
self,
|
|
92
92
|
path: str,
|
|
93
|
-
model:
|
|
93
|
+
model: Type[T],
|
|
94
94
|
params: Optional[Dict[str, Any]] = None
|
|
95
95
|
) -> APIResponse[T]:
|
|
96
96
|
|
|
@@ -116,7 +116,7 @@ class InfisicalRequests:
|
|
|
116
116
|
def post(
|
|
117
117
|
self,
|
|
118
118
|
path: str,
|
|
119
|
-
model:
|
|
119
|
+
model: Type[T],
|
|
120
120
|
json: Optional[Dict[str, Any]] = None
|
|
121
121
|
) -> APIResponse[T]:
|
|
122
122
|
|
|
@@ -140,7 +140,7 @@ class InfisicalRequests:
|
|
|
140
140
|
def patch(
|
|
141
141
|
self,
|
|
142
142
|
path: str,
|
|
143
|
-
model:
|
|
143
|
+
model: Type[T],
|
|
144
144
|
json: Optional[Dict[str, Any]] = None
|
|
145
145
|
) -> APIResponse[T]:
|
|
146
146
|
|
|
@@ -164,7 +164,7 @@ class InfisicalRequests:
|
|
|
164
164
|
def delete(
|
|
165
165
|
self,
|
|
166
166
|
path: str,
|
|
167
|
-
model:
|
|
167
|
+
model: Type[T],
|
|
168
168
|
json: Optional[Dict[str, Any]] = None
|
|
169
169
|
) -> APIResponse[T]:
|
|
170
170
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
infisical_sdk/__init__.py,sha256=UzssDXpMhK79mFBW4fpSea1bOVjoD_UILjvizFkLNz4,183
|
|
2
|
+
infisical_sdk/api_types.py,sha256=F8Ifv9WUPLd1ivQuUPw9UfLZh3GJoINyoZL6VlUuo1Q,5124
|
|
3
|
+
infisical_sdk/client.py,sha256=AgQu6LQs1I6QuiDDKMfJOnF1iatdhEcs9PVmJ3e-Zug,15561
|
|
4
|
+
infisical_sdk/infisical_requests.py,sha256=7y-0FS2BnlDRjfgZ4eRMXwPhA9-A7hLO3lCSOC63qt4,5661
|
|
5
|
+
infisicalsdk-1.0.4.dist-info/METADATA,sha256=IRt8JUnpG6KQHTU9pcnPjII6BB0ak78nRQInGiENSic,763
|
|
6
|
+
infisicalsdk-1.0.4.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
7
|
+
infisicalsdk-1.0.4.dist-info/top_level.txt,sha256=FvJjMGD1FvxwipO_qFajdH20yNV8n3lJ7G3DkQoPJNU,14
|
|
8
|
+
infisicalsdk-1.0.4.dist-info/RECORD,,
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
infisical_sdk/__init__.py,sha256=UzssDXpMhK79mFBW4fpSea1bOVjoD_UILjvizFkLNz4,183
|
|
2
|
-
infisical_sdk/api_types.py,sha256=2JNC9RA3JYPDwq92BXwBrxTkXi-XuD3G3jBST4-H9qg,3394
|
|
3
|
-
infisical_sdk/client.py,sha256=i1poZEz2tiGJLYZuRePfWONs7hQyP_A5QJJt1UeW8WQ,10936
|
|
4
|
-
infisical_sdk/infisical_requests.py,sha256=mROtB1fuF3E39fU9J6MiH0gQ-LhsK10W-zzEH0knePU,5655
|
|
5
|
-
infisicalsdk-1.0.2.dist-info/METADATA,sha256=pMW354MJanz1LBMM_EiYafLtSzTlfE8lOc0dWP73bKQ,763
|
|
6
|
-
infisicalsdk-1.0.2.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
7
|
-
infisicalsdk-1.0.2.dist-info/top_level.txt,sha256=FvJjMGD1FvxwipO_qFajdH20yNV8n3lJ7G3DkQoPJNU,14
|
|
8
|
-
infisicalsdk-1.0.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|