protegrity-ai-developer-python 1.2.1__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 (53) hide show
  1. appython/__init__.py +12 -0
  2. appython/protector.py +554 -0
  3. appython/service/auth_provider.py +273 -0
  4. appython/service/auth_token_provider.py +45 -0
  5. appython/service/config.py +209 -0
  6. appython/service/payload_builder.py +141 -0
  7. appython/service/request_handler.py +115 -0
  8. appython/service/response_handler.py +78 -0
  9. appython/stats/__init__.py +3 -0
  10. appython/stats/collector.py +90 -0
  11. appython/stats/writer.py +185 -0
  12. appython/utils/codec_helper.py +86 -0
  13. appython/utils/constants.py +246 -0
  14. appython/utils/exceptions.py +141 -0
  15. appython/utils/input_preprocessor.py +325 -0
  16. appython/utils/output_postprocessor.py +99 -0
  17. protegrity_ai_developer_python-1.2.1.dist-info/METADATA +428 -0
  18. protegrity_ai_developer_python-1.2.1.dist-info/RECORD +53 -0
  19. protegrity_ai_developer_python-1.2.1.dist-info/WHEEL +5 -0
  20. protegrity_ai_developer_python-1.2.1.dist-info/entry_points.txt +2 -0
  21. protegrity_ai_developer_python-1.2.1.dist-info/licenses/LICENSE +21 -0
  22. protegrity_ai_developer_python-1.2.1.dist-info/top_level.txt +3 -0
  23. protegrity_developer_python/__init__.py +4 -0
  24. protegrity_developer_python/scan.py +37 -0
  25. protegrity_developer_python/securefind.py +83 -0
  26. protegrity_developer_python/utils/ccn_processing.py +59 -0
  27. protegrity_developer_python/utils/config.py +60 -0
  28. protegrity_developer_python/utils/constants.py +123 -0
  29. protegrity_developer_python/utils/discover.py +49 -0
  30. protegrity_developer_python/utils/logger.py +23 -0
  31. protegrity_developer_python/utils/pii_processing.py +291 -0
  32. protegrity_developer_python/utils/protector.py +23 -0
  33. protegrity_developer_python/utils/semantic_guardrails.py +240 -0
  34. protegrity_developer_python/utils/transform.py +66 -0
  35. pty_migrate/__init__.py +1 -0
  36. pty_migrate/check_cmd.py +871 -0
  37. pty_migrate/cli.py +93 -0
  38. pty_migrate/config.py +127 -0
  39. pty_migrate/create_policy_cmd.py +795 -0
  40. pty_migrate/payloads/__init__.py +51 -0
  41. pty_migrate/payloads/alphabets.json +42 -0
  42. pty_migrate/payloads/dataelements.json +342 -0
  43. pty_migrate/payloads/datastores.json +7 -0
  44. pty_migrate/payloads/deploy_policy_ta.json +1 -0
  45. pty_migrate/payloads/masks.json +18 -0
  46. pty_migrate/payloads/members.json +62 -0
  47. pty_migrate/payloads/policies.json +13 -0
  48. pty_migrate/payloads/roles.json +32 -0
  49. pty_migrate/payloads/rules.json +1639 -0
  50. pty_migrate/payloads/sources.json +10 -0
  51. pty_migrate/payloads/trusted_apps.json +8 -0
  52. pty_migrate/ppc_client.py +371 -0
  53. pty_migrate/stats_cmd.py +87 -0
@@ -0,0 +1,325 @@
1
+ """
2
+ This module provides the InputPreprocessor class, which is responsible for validating and processing
3
+ input parameters for data protection operations such as PROTECT, UNPROTECT, and REPROTECT.
4
+ It ensures that the input data is correctly formatted, handles character sets, and prepares the
5
+ parameters for further processing.
6
+ """
7
+
8
+ from appython.utils.constants import (
9
+ ARGS_PROTECT as args_protect,
10
+ OP_TYPE as op_type,
11
+ ARGS_UNPROTECT as args_unprotect,
12
+ ARGS_REPROTECT as args_reprotect,
13
+ DATATYPES as datatypes,
14
+ ErrorMessage,
15
+ Charset,
16
+ )
17
+ from appython.utils.codec_helper import (
18
+ convert_b64_bytes_b64_string,
19
+ decode_bytes,
20
+ encode_to_base64_string,
21
+ )
22
+
23
+
24
+ def validate_charset(kwargs, response_type):
25
+ """
26
+ Validates the use of the 'charset' keyword argument based on the expected response type.
27
+
28
+ This function ensures that the 'charset' parameter is only used when the response type is 'bytes'.
29
+ If 'charset' is provided in the kwargs and the response type is not bytes, an exception is raised.
30
+
31
+ Parameters:
32
+ kwargs (dict): Dictionary of keyword arguments that may include 'charset'.
33
+ response_type (type): The expected type of the response (e.g., bytes, str).
34
+
35
+ Raises:
36
+ Exception: If 'charset' is specified in kwargs but the response_type is not bytes.
37
+ """
38
+
39
+ if "charset" in kwargs and response_type != bytes:
40
+ raise Exception(ErrorMessage.INVALID_CHARSET_TYPE.value)
41
+ else:
42
+ if "charset" in kwargs and response_type == bytes:
43
+ try:
44
+ if kwargs["charset"].value not in [
45
+ Charset.UTF8.value,
46
+ Charset.UTF16LE.value,
47
+ Charset.UTF16BE.value,
48
+ ]:
49
+ raise Exception(ErrorMessage.UNSUPPORTED_CHARSET.value)
50
+ except Exception:
51
+ raise Exception(ErrorMessage.UNSUPPORTED_CHARSET.value)
52
+
53
+
54
+ class InputPreprocessor:
55
+
56
+ @staticmethod
57
+ def validate_parameters(
58
+ kwargs, inp_type, operation_type: str, user: str, de: str, newde: str = None
59
+ ) -> dict:
60
+ """
61
+ Validates and constructs the parameter dictionary for different data protection operations.
62
+
63
+ This method ensures that the required parameters for PROTECT, UNPROTECT, and REPROTECT operations
64
+ are present and correctly typed. It also encodes optional parameters like external IVs and tweaks
65
+ into base64 strings when necessary.
66
+
67
+ Parameters:
68
+ kwargs (dict): Additional keyword arguments specific to the operation.
69
+ inp_type (type): The expected response type (e.g., str, bytes).
70
+ operation_type (str): The type of operation to perform ('PROTECT', 'UNPROTECT', or 'REPROTECT').
71
+ user (str): The user identifier.
72
+ de (str): The data element name.
73
+ newde (str, optional): The new data element name (required for REPROTECT).
74
+
75
+ Returns:
76
+ dict: A dictionary containing validated and formatted parameters for the operation.
77
+
78
+ Raises:
79
+ Exception: If any required parameter is missing or of an invalid type, or if unsupported
80
+ keyword arguments are provided.
81
+ """
82
+
83
+ argv = {
84
+ "parameters": {
85
+ "user": user,
86
+ "data_element": de,
87
+ "new_data_element": newde,
88
+ "response_type": inp_type,
89
+ }
90
+ }
91
+
92
+ if not isinstance(user, str):
93
+ raise Exception(ErrorMessage.INVALID_USER_NAME.value)
94
+
95
+ operation = op_type[operation_type]
96
+
97
+ if operation in ["PROTECT", "UNPROTECT"]:
98
+
99
+ if de is None or de == "":
100
+ raise Exception(ErrorMessage.DATA_ELEMENT_NONE_EMPTY.value)
101
+ if not isinstance(de, str):
102
+ raise Exception(ErrorMessage.DATA_ELEMENT_NOT_STR.value)
103
+
104
+ if "external_iv" in kwargs:
105
+ if not isinstance(kwargs["external_iv"], bytes):
106
+ raise Exception(
107
+ ErrorMessage.INVALID_KEYWORD_EXTERNAL_IV.value
108
+ + f" Expected: bytes, Actual: {type(kwargs['external_iv'])}"
109
+ )
110
+ argv["parameters"]["external_iv"] = convert_b64_bytes_b64_string(
111
+ kwargs["external_iv"]
112
+ )
113
+
114
+ if "external_tweak" in kwargs:
115
+ if not isinstance(kwargs["external_tweak"], bytes):
116
+ raise Exception(
117
+ ErrorMessage.INVALID_KEYWORD_EXTERNAL_TWEAK.value
118
+ + f" Expected: bytes, Actual: {type(kwargs['external_tweak'])}"
119
+ )
120
+ argv["parameters"]["external_tweak"] = convert_b64_bytes_b64_string(
121
+ kwargs["external_tweak"]
122
+ )
123
+
124
+ if operation == "PROTECT":
125
+ if "encrypt_to" in kwargs:
126
+ if kwargs["encrypt_to"] != bytes:
127
+ raise Exception(
128
+ ErrorMessage.INVALID_ENC_TYPE.value
129
+ + f" - {kwargs['encrypt_to']}"
130
+ )
131
+ argv["parameters"]["response_type"] = bytes
132
+
133
+ validate_charset(kwargs, argv["parameters"]["response_type"])
134
+
135
+ for key in kwargs:
136
+ if key not in args_protect:
137
+ raise Exception(
138
+ f"-1, Invalid Keyword Argument: '{key}'. {ErrorMessage.PROTECT_KEYWORD_EXP.value}"
139
+ )
140
+
141
+ elif operation == "UNPROTECT":
142
+ if "decrypt_to" in kwargs:
143
+ if kwargs["decrypt_to"] not in datatypes:
144
+ raise Exception(
145
+ ErrorMessage.INVALID_DEC_TYPE.value
146
+ + f" - {kwargs['decrypt_to']}"
147
+ )
148
+ argv["parameters"]["response_type"] = kwargs["decrypt_to"]
149
+
150
+ validate_charset(kwargs, argv["parameters"]["response_type"])
151
+
152
+ for key in kwargs:
153
+ if key not in args_unprotect:
154
+ raise Exception(
155
+ f"-1, Invalid Keyword Argument: '{key}'. {ErrorMessage.UNPROTECT_KEYWORD_EXP.value}"
156
+ )
157
+
158
+ elif operation == "REPROTECT":
159
+ if de is None or de == "":
160
+ raise Exception(ErrorMessage.DATA_ELEMENT_NONE_EMPTY.value)
161
+ if not isinstance(de, str):
162
+ raise Exception(ErrorMessage.DATA_ELEMENT_NOT_STR.value)
163
+
164
+ if newde is None or newde == "":
165
+ raise Exception(ErrorMessage.NEW_DATA_ELEMENT_NONE_EMPTY.value)
166
+ if not isinstance(newde, str):
167
+ raise Exception(ErrorMessage.NEW_DATA_ELEMENT_NOT_STR.value)
168
+
169
+ if "old_external_iv" in kwargs and "new_external_iv" in kwargs:
170
+ if not isinstance(kwargs["old_external_iv"], bytes):
171
+ raise Exception(
172
+ ErrorMessage.INVALID_KEYWORD_OLD_EXTERNAL_IV.value
173
+ + f" Expected: bytes, Actual: {type(kwargs['old_external_iv'])}"
174
+ )
175
+ argv["parameters"]["old_external_iv_str"] = (
176
+ convert_b64_bytes_b64_string(kwargs["old_external_iv"])
177
+ )
178
+
179
+ if not isinstance(kwargs["new_external_iv"], bytes):
180
+ raise Exception(
181
+ ErrorMessage.INVALID_KEYWORD_NEW_EXTERNAL_IV.value
182
+ + f" Expected: bytes, Actual: {type(kwargs['new_external_iv'])}"
183
+ )
184
+ argv["parameters"]["new_external_iv"] = convert_b64_bytes_b64_string(
185
+ kwargs["new_external_iv"]
186
+ )
187
+ elif "old_external_iv" in kwargs or "new_external_iv" in kwargs:
188
+ raise Exception(ErrorMessage.MISSING_OLD_EIV_OR_NEW_EIV.value)
189
+
190
+ if "old_external_tweak" in kwargs and "new_external_tweak" in kwargs:
191
+ if not isinstance(kwargs["old_external_tweak"], bytes):
192
+ raise Exception(
193
+ ErrorMessage.INVALID_KEYWORD_OLD_EXTERNAL_TWEAK.value
194
+ + f" Expected: bytes, Actual: {type(kwargs['old_external_tweak'])}"
195
+ )
196
+ argv["parameters"]["old_external_tweak"] = convert_b64_bytes_b64_string(
197
+ kwargs["old_external_tweak"]
198
+ )
199
+
200
+ if not isinstance(kwargs["new_external_tweak"], bytes):
201
+ raise Exception(
202
+ ErrorMessage.INVALID_KEYWORD_NEW_EXTERNAL_TWEAK.value
203
+ + f" Expected: bytes, Actual: {type(kwargs['new_external_tweak'])}"
204
+ )
205
+ argv["parameters"]["new_external_tweak"] = convert_b64_bytes_b64_string(
206
+ kwargs["new_external_tweak"]
207
+ )
208
+ elif "old_external_tweak" in kwargs or "new_external_tweak" in kwargs:
209
+ raise Exception(ErrorMessage.MISSING_OLD_TWEAK_OR_NEW_TWEAK.value)
210
+
211
+ if "encrypt_to" in kwargs:
212
+ if kwargs["encrypt_to"] != bytes:
213
+ raise Exception(
214
+ ErrorMessage.INVALID_ENC_TYPE.value
215
+ + f" - {kwargs['encrypt_to']}"
216
+ )
217
+ argv["parameters"]["response_type"] = bytes
218
+
219
+ validate_charset(kwargs, argv["parameters"]["response_type"])
220
+
221
+ for key in kwargs:
222
+ if key not in args_reprotect:
223
+ raise Exception(
224
+ f"-1, Invalid Keyword Argument: '{key}'. {ErrorMessage.REPROTECT_KEYWORD_EXP.value}"
225
+ )
226
+
227
+ return argv
228
+
229
+ @staticmethod
230
+ def convert_input_to_string(
231
+ input_data, kwargs, data_element, operation_type
232
+ ) -> dict:
233
+ """
234
+ Converts input data into a string or base64-encoded format suitable for protection operations.
235
+
236
+ This method handles both single and bulk inputs, validates data types, and applies encoding
237
+ or decoding based on the data element and operation type. It also respects character set
238
+ preferences provided in kwargs.
239
+
240
+ Parameters:
241
+ input_data (Any): The input data to be processed (can be a single value or a list).
242
+ kwargs (dict): Additional keyword arguments, including optional charset.
243
+ data_element (str): The data element type (used to determine encoding behavior).
244
+ operation_type (str): The operation being performed ('PROTECT', 'UNPROTECT', etc.).
245
+
246
+ Returns:
247
+ dict: A dictionary containing the processed data, its type, original data type,
248
+ charset used, and whether the input was bulk.
249
+
250
+ Raises:
251
+ Exception: If the input data contains unsupported or inconsistent types.
252
+ """
253
+
254
+ curr_input_datatype = None
255
+ is_bulk = False
256
+ input_type = None
257
+ charset = Charset.UTF8
258
+
259
+ if not data_element or not isinstance(data_element, str):
260
+ raise Exception(
261
+ ErrorMessage.DATA_ELEMENT_NONE_EMPTY.value
262
+ if not data_element
263
+ else ErrorMessage.DATA_ELEMENT_NOT_STR.value
264
+ )
265
+
266
+ is_enc = "text" in data_element or "BYTE" in data_element
267
+
268
+ # Preserve charset from kwargs if valid
269
+ if "charset" in kwargs and isinstance(kwargs["charset"], Charset):
270
+ charset = kwargs["charset"]
271
+
272
+ if isinstance(input_data, tuple):
273
+ input_type = type(input_data)
274
+ input_data = list(input_data)
275
+ elif isinstance(input_data, list):
276
+ input_data = input_data.copy()
277
+ input_type = type(input_data)
278
+
279
+ if isinstance(input_data, list):
280
+ is_bulk = True
281
+ for index, data in enumerate(input_data):
282
+ if data is None:
283
+ continue
284
+ type_data = type(data)
285
+ if curr_input_datatype and type_data != curr_input_datatype:
286
+ raise Exception(ErrorMessage.INVALID_BULK_INPUT.value)
287
+ if type_data in datatypes:
288
+ curr_input_datatype = curr_input_datatype or type_data
289
+ if datatypes[type_data] != 5:
290
+ input_data[index] = (
291
+ encode_to_base64_string(data)
292
+ if is_enc and op_type[operation_type] == "PROTECT"
293
+ else str(data)
294
+ )
295
+ else:
296
+ input_data[index] = decode_bytes(
297
+ data, charset, is_enc, operation_type
298
+ )
299
+ else:
300
+ raise Exception(f"-1, Unsupported input data type {type_data} !")
301
+ else:
302
+ type_data = type(input_data)
303
+ input_type = type_data
304
+ if input_data is not None and type_data in datatypes:
305
+ curr_input_datatype = type_data
306
+ if datatypes[type_data] != 5:
307
+ input_data = (
308
+ encode_to_base64_string(input_data)
309
+ if is_enc and op_type[operation_type] == "PROTECT"
310
+ else str(input_data)
311
+ )
312
+ else:
313
+ input_data = decode_bytes(
314
+ input_data, charset, is_enc, operation_type
315
+ )
316
+ elif input_data is not None:
317
+ raise Exception(f"-1, Unsupported input data type {type_data} !")
318
+
319
+ return {
320
+ "data": input_data,
321
+ "type": input_type,
322
+ "input_datatype": curr_input_datatype,
323
+ "charset": charset,
324
+ "is_bulk": is_bulk,
325
+ }
@@ -0,0 +1,99 @@
1
+ """
2
+ This module provides the OutputProcessor class, which is responsible for restoring the original data types
3
+ of protected or transformed values based on specified metadata. It supports various data types including
4
+ strings, integers, floats, bytes with specific charsets, and dates in multiple formats.
5
+ """
6
+
7
+ import base64
8
+ from datetime import date, datetime
9
+ from appython.utils.constants import (
10
+ Charset,
11
+ LOG_RETURN_CODE_UNSUPPORTED as log_return_code
12
+ )
13
+ from appython.utils.codec_helper import get_str_from_b64
14
+
15
+
16
+ class OutputProcessor:
17
+ @staticmethod
18
+ def restore_original_type(data: list, return_type: dict):
19
+ """
20
+ Restores the original data type(s) of protected or transformed values based on the specified return metadata.
21
+
22
+ This method decodes or converts each item in the input list `data` to its intended type as described in
23
+ the `return_type` dictionary. It supports both single and bulk inputs, and handles decoding for base64-encoded
24
+ strings, numeric types, byte strings with specific charsets, and date formats.
25
+
26
+ Parameters:
27
+ data (list): A list of values (usually strings) to be converted back to their original types.
28
+ return_type (dict): Metadata describing the expected output format. Keys include:
29
+ - "is_bulk" (bool): Whether the input is a list of values or a single value.
30
+ - "response_type" (type): The target Python type (e.g., str, int, float, bytes, date).
31
+ - "isENC" (bool): Whether the input values are base64-encoded.
32
+ - "charset" (Charset, optional): Character encoding to use when decoding byte strings.
33
+
34
+ Returns:
35
+ The decoded value(s), either as a single item or a list, depending on the `is_bulk` flag.
36
+
37
+ Raises:
38
+ Exception: If decoding fails or the response type is unsupported.
39
+ """
40
+ try:
41
+ is_bulk = return_type["is_bulk"]
42
+ response_type = return_type["response_type"]
43
+ is_enc = return_type["isENC"]
44
+ charset = return_type.get("charset")
45
+
46
+ def decode(item):
47
+ if item is None:
48
+ return None
49
+ if response_type == str:
50
+ return get_str_from_b64(item) if is_enc else item
51
+ elif response_type == int:
52
+ return int(get_str_from_b64(item)) if is_enc else int(item)
53
+ elif response_type == float:
54
+ return float(get_str_from_b64(item)) if is_enc else float(item)
55
+ elif response_type == bytes:
56
+ if is_enc:
57
+ return base64.b64decode(item)
58
+ if charset.value == Charset.UTF8.value:
59
+ return item.encode("utf-8")
60
+ elif charset.value == Charset.UTF16LE.value:
61
+ return item.encode("utf-16le")
62
+ elif charset.value == Charset.UTF16BE.value:
63
+ return item.encode("utf-16be")
64
+ elif response_type == date:
65
+ date_formats = [
66
+ "%Y-%m-%d", # 2023-12-25
67
+ "%Y/%m/%d", # 2023/12/25
68
+ "%Y/%d/%m", # 2023/25/12
69
+ "%m/%d/%Y", # 12/25/2023
70
+ "%d/%m/%Y", # 25/12/2023
71
+ "%m-%d-%Y", # 12-25-2023
72
+ "%d-%m-%Y", # 25-12-2023
73
+ "%Y%m%d", # 20231225
74
+ "%d.%m.%Y", # 25.12.2023
75
+ "%Y.%m.%d", # 2023.12.25
76
+ ]
77
+
78
+ for fmt in date_formats:
79
+ try:
80
+ return datetime.strptime(item, fmt).date()
81
+ except ValueError:
82
+ continue
83
+
84
+ # If no format worked, raise an error with the original item
85
+ raise ValueError(
86
+ f"Unable to parse date format for: '{item}'. Supported formats: {date_formats}"
87
+ )
88
+ elif response_type == type(None):
89
+ return None
90
+ else:
91
+ raise Exception(f"26, {log_return_code[26]}")
92
+
93
+ if not is_bulk:
94
+ return decode(data[0])
95
+ else:
96
+ return [decode(item) for item in data]
97
+
98
+ except Exception:
99
+ raise Exception(f"26, {log_return_code[26]}")