atomicshop 2.16.14__py3-none-any.whl → 2.16.16__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 atomicshop might be problematic. Click here for more details.

Files changed (29) hide show
  1. atomicshop/__init__.py +1 -1
  2. atomicshop/certificates.py +146 -52
  3. atomicshop/mitm/config_static.py +12 -3
  4. atomicshop/mitm/import_config.py +8 -0
  5. atomicshop/mitm/mitm_main.py +7 -4
  6. atomicshop/mitm/recs_files.py +0 -1
  7. atomicshop/process_poller/process_pool.py +0 -1
  8. atomicshop/process_poller/simple_process_pool.py +0 -1
  9. atomicshop/wrappers/cryptographyw.py +3 -1
  10. atomicshop/wrappers/ctyping/msi_windows_installer/extract_msi_main.py +0 -1
  11. atomicshop/wrappers/elasticsearchw/elasticsearchw.py +2 -20
  12. atomicshop/wrappers/elasticsearchw/install_elastic.py +7 -7
  13. atomicshop/wrappers/factw/get_file_data.py +12 -5
  14. atomicshop/wrappers/githubw.py +0 -1
  15. atomicshop/wrappers/loggingw/handlers.py +31 -16
  16. atomicshop/wrappers/loggingw/loggingw.py +3 -0
  17. atomicshop/wrappers/mongodbw/install_mongodb.py +6 -6
  18. atomicshop/wrappers/mongodbw/{infrastructure.py → mongo_infra.py} +14 -6
  19. atomicshop/wrappers/mongodbw/mongodbw.py +174 -24
  20. atomicshop/wrappers/pywin32w/cert_store.py +89 -0
  21. atomicshop/wrappers/socketw/socket_server_tester.py +5 -1
  22. atomicshop/wrappers/socketw/socket_wrapper.py +71 -2
  23. atomicshop/wrappers/socketw/ssl_base.py +1 -1
  24. {atomicshop-2.16.14.dist-info → atomicshop-2.16.16.dist-info}/METADATA +1 -2
  25. {atomicshop-2.16.14.dist-info → atomicshop-2.16.16.dist-info}/RECORD +29 -28
  26. /atomicshop/wrappers/elasticsearchw/{infrastructure.py → elastic_infra.py} +0 -0
  27. {atomicshop-2.16.14.dist-info → atomicshop-2.16.16.dist-info}/LICENSE.txt +0 -0
  28. {atomicshop-2.16.14.dist-info → atomicshop-2.16.16.dist-info}/WHEEL +0 -0
  29. {atomicshop-2.16.14.dist-info → atomicshop-2.16.16.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,11 @@
1
+ from typing import Union
2
+ import datetime
3
+
1
4
  import pymongo
2
5
 
3
- from . import infrastructure
6
+ from ...basics import dicts
7
+
8
+ from . import mongo_infra
4
9
 
5
10
 
6
11
  """
@@ -9,7 +14,7 @@ These are good examples to get you started, but can't really cover all the use c
9
14
  """
10
15
 
11
16
 
12
- def connect(uri: str = infrastructure.MONGODB_DEFAULT_URI):
17
+ def connect(uri: str = mongo_infra.MONGODB_DEFAULT_URI):
13
18
  """
14
19
  Connect to a MongoDB database.
15
20
  :param uri: str, the URI of the MongoDB database.
@@ -18,18 +23,23 @@ def connect(uri: str = infrastructure.MONGODB_DEFAULT_URI):
18
23
  return pymongo.MongoClient(uri)
19
24
 
20
25
 
21
- def add_list_of_dicts_to_mongo(
22
- list_of_dicts: list,
26
+ def index(
27
+ object_instance: Union[list[dict], dict],
23
28
  database_name: str,
24
29
  collection_name: str,
30
+ add_timestamp: bool = False,
31
+ convert_mixed_lists_to_strings: bool = False,
25
32
  mongo_client: pymongo.MongoClient = None,
26
33
  close_client: bool = False
27
34
  ):
28
35
  """
29
- Add a list of dictionaries to a MongoDB collection.
30
- :param list_of_dicts: list of dictionaries, the list of dictionaries to add to the collection.
36
+ Add a dictionary or list dictionaries to a MongoDB collection.
37
+ :param object_instance: list of dictionaries or dictionary to add to the collection.
31
38
  :param database_name: str, the name of the database.
32
39
  :param collection_name: str, the name of the collection.
40
+ :param add_timestamp: bool, if True, a current time timestamp will be added to the object.
41
+ :param convert_mixed_lists_to_strings: bool, if True, mixed lists or tuples when entries are strings and integers,
42
+ the integers will be converted to strings.
33
43
  :param mongo_client: pymongo.MongoClient, the connection object.
34
44
  If None, a new connection will be created to default URI.
35
45
  :param close_client: bool, if True, the connection will be closed after the operation.
@@ -37,28 +47,46 @@ def add_list_of_dicts_to_mongo(
37
47
  :return: None
38
48
  """
39
49
 
50
+ _is_object_list_of_dicts_or_dict(object_instance)
51
+
40
52
  if not mongo_client:
41
53
  mongo_client = connect()
54
+ close_client = True
42
55
 
43
56
  db = mongo_client[database_name]
44
57
  collection = db[collection_name]
45
58
 
46
- collection.insert_many(list_of_dicts)
59
+ if convert_mixed_lists_to_strings:
60
+ object_instance = dicts.convert_int_to_str_in_mixed_lists(object_instance)
61
+
62
+ if add_timestamp:
63
+ timestamp = datetime.datetime.now()
64
+ if isinstance(object_instance, dict):
65
+ object_instance['timestamp'] = timestamp
66
+ elif isinstance(object_instance, list):
67
+ for doc in object_instance:
68
+ doc['timestamp'] = timestamp
69
+
70
+ if isinstance(object_instance, dict):
71
+ collection.insert_one(object_instance)
72
+ elif isinstance(object_instance, list):
73
+ collection.insert_many(object_instance)
47
74
 
48
75
  if close_client:
49
76
  mongo_client.close()
50
77
 
51
78
 
52
- def remove_list_of_dicts(
53
- list_of_dicts: list,
79
+ def delete(
80
+ object_instance: Union[list[dict], dict],
54
81
  database_name: str,
55
82
  collection_name: str,
56
83
  mongo_client: pymongo.MongoClient = None,
57
84
  close_client: bool = False
58
85
  ):
59
86
  """
60
- Remove a list of dictionaries from a MongoDB collection.
61
- :param list_of_dicts: list of dictionaries, the list of dictionaries to remove from the collection.
87
+ Remove a list of dictionaries or a dictionary from a MongoDB collection.
88
+
89
+ :param object_instance: list of dictionaries, the list of dictionaries to remove from the collection.
62
90
  :param database_name: str, the name of the database.
63
91
  :param collection_name: str, the name of the collection.
64
92
  :param mongo_client: pymongo.MongoClient, the connection object.
@@ -68,29 +96,74 @@ def remove_list_of_dicts(
68
96
  :return: None
69
97
  """
70
98
 
99
+ _is_object_list_of_dicts_or_dict(object_instance)
100
+
71
101
  if not mongo_client:
72
102
  mongo_client = connect()
103
+ close_client = True
73
104
 
74
105
  db = mongo_client[database_name]
75
106
  collection = db[collection_name]
76
107
 
77
- for doc in list_of_dicts:
78
- collection.delete_one(doc)
108
+ if isinstance(object_instance, dict):
109
+ collection.delete_one(object_instance)
110
+ elif isinstance(object_instance, list):
111
+ for doc in object_instance:
112
+ collection.delete_one(doc)
79
113
 
80
114
  if close_client:
81
115
  mongo_client.close()
82
116
 
83
117
 
84
- def overwrite_list_of_dicts(
85
- list_of_dicts: list,
118
+ def find(
86
119
  database_name: str,
87
120
  collection_name: str,
121
+ query: dict = None,
88
122
  mongo_client: pymongo.MongoClient = None,
89
123
  close_client: bool = False
90
124
  ):
91
125
  """
92
- Overwrite a list of dictionaries in a MongoDB collection.
93
- :param list_of_dicts: list of dictionaries, the list of dictionaries to overwrite in the collection.
126
+ Find entries in a MongoDB collection by query.
127
+ :param database_name: str, the name of the database.
128
+ :param collection_name: str, the name of the collection.
129
+ :param query: dict, the query to search for.
130
+ Example, search for all entries with column name 'name' equal to 'John':
131
+ query = {'name': 'John'}
132
+ Example, return all entries from collection:
133
+ query = None
134
+ :param mongo_client: pymongo.MongoClient, the connection object.
135
+ If None, a new connection will be created to default URI.
136
+ :param close_client: bool, if True, the connection will be closed after the operation.
137
+
138
+ :return: list of dictionaries, the list of entries that match the query.
139
+ """
140
+
141
+ if not mongo_client:
142
+ mongo_client = connect()
143
+ close_client = True
144
+
145
+ db = mongo_client[database_name]
146
+ collection = db[collection_name]
147
+
148
+ if query is None:
149
+ entries: list = list(collection.find())
150
+ else:
151
+ entries: list = list(collection.find(query))
152
+
153
+ if close_client:
154
+ mongo_client.close()
155
+
156
+ return entries
157
+
158
+
159
+ def delete_all_entries_from_collection(
160
+ database_name: str,
161
+ collection_name: str,
162
+ mongo_client: pymongo.MongoClient = None,
163
+ close_client: bool = False
164
+ ):
165
+ """
166
+ Remove all entries from a MongoDB collection.
94
167
  :param database_name: str, the name of the database.
95
168
  :param collection_name: str, the name of the collection.
96
169
  :param mongo_client: pymongo.MongoClient, the connection object.
@@ -102,43 +175,120 @@ def overwrite_list_of_dicts(
102
175
 
103
176
  if not mongo_client:
104
177
  mongo_client = connect()
178
+ close_client = True
105
179
 
106
180
  db = mongo_client[database_name]
107
181
  collection = db[collection_name]
108
182
 
109
183
  collection.delete_many({})
110
- collection.insert_many(list_of_dicts)
111
184
 
112
185
  if close_client:
113
186
  mongo_client.close()
114
187
 
115
188
 
116
- def get_all_entries_from_collection(
189
+ def overwrite_collection(
190
+ object_instance: list,
117
191
  database_name: str,
118
192
  collection_name: str,
193
+ add_timestamp: bool = False,
194
+ convert_mixed_lists_to_strings: bool = False,
119
195
  mongo_client: pymongo.MongoClient = None,
120
196
  close_client: bool = False
121
197
  ):
122
198
  """
123
- Get all entries from a MongoDB collection.
199
+ Overwrite a MongoDB collection with list of dicts or a dict.
200
+ :param object_instance: list of dictionaries, the list of dictionaries to overwrite in the collection.
124
201
  :param database_name: str, the name of the database.
125
202
  :param collection_name: str, the name of the collection.
203
+ :param add_timestamp: bool, if True, a current time timestamp will be added to the object.
204
+ :param convert_mixed_lists_to_strings: bool, if True, mixed lists or tuples when entries are strings and integers,
205
+ the integers will be converted to strings.
206
+ :param mongo_client: pymongo.MongoClient, the connection object.
207
+ If None, a new connection will be created to default URI.
208
+ :param close_client: bool, if True, the connection will be closed after the operation.
209
+
210
+ :return: None
211
+ """
212
+
213
+ _is_object_list_of_dicts_or_dict(object_instance)
214
+
215
+ if not mongo_client:
216
+ mongo_client = connect()
217
+ close_client = True
218
+
219
+ delete_all_entries_from_collection(
220
+ database_name=database_name, collection_name=collection_name,
221
+ mongo_client=mongo_client
222
+ )
223
+
224
+ index(
225
+ object_instance=object_instance,
226
+ database_name=database_name, collection_name=collection_name,
227
+ add_timestamp=add_timestamp, convert_mixed_lists_to_strings=convert_mixed_lists_to_strings,
228
+ mongo_client=mongo_client, close_client=close_client)
229
+
230
+
231
+ def _is_object_list_of_dicts_or_dict(
232
+ object_instance: Union[list[dict], dict]
233
+ ):
234
+ if isinstance(object_instance, dict):
235
+ return True
236
+ elif isinstance(object_instance, list):
237
+ if object_instance and isinstance(object_instance[0], dict):
238
+ return True
239
+ else:
240
+ raise ValueError("List must contain dictionaries.")
241
+ else:
242
+ raise ValueError("Object must be a dictionary or a list of dictionaries.")
243
+
244
+
245
+ def get_stats_db(
246
+ database_name: str,
247
+ mongo_client: pymongo.MongoClient = None,
248
+ close_client: bool = False
249
+ ):
250
+ """
251
+ Get the stats of a MongoDB database.
252
+
253
+ :param database_name: str, the name of the database.
126
254
  :param mongo_client: pymongo.MongoClient, the connection object.
127
255
  If None, a new connection will be created to default URI.
128
256
  :param close_client: bool, if True, the connection will be closed after the operation.
129
257
 
130
- :return: list of dictionaries, the list of entries from the collection.
258
+ :return: dict, the stats of the collection.
131
259
  """
132
260
 
133
261
  if not mongo_client:
134
262
  mongo_client = connect()
263
+ close_client = True
135
264
 
136
265
  db = mongo_client[database_name]
137
- collection = db[collection_name]
138
266
 
139
- entries = list(collection.find())
267
+ stats = db.command("dbStats")
140
268
 
141
269
  if close_client:
142
270
  mongo_client.close()
143
271
 
144
- return entries
272
+ return stats
273
+
274
+
275
+ def get_stats_db_size(
276
+ database_name: str,
277
+ mongo_client: pymongo.MongoClient = None,
278
+ close_client: bool = False
279
+ ):
280
+ """
281
+ Get the size of a MongoDB database in bytes.
282
+
283
+ :param database_name: str, the name of the database.
284
+ :param mongo_client: pymongo.MongoClient, the connection object.
285
+ If None, a new connection will be created to default URI.
286
+ :param close_client: bool, if True, the connection will be closed after the operation.
287
+
288
+ :return: int, the size of the database in bytes.
289
+ """
290
+
291
+ stats = get_stats_db(
292
+ database_name=database_name, mongo_client=mongo_client, close_client=close_client)
293
+
294
+ return stats['dataSize']
@@ -0,0 +1,89 @@
1
+ from typing import Literal
2
+ import win32crypt as wcrypt
3
+
4
+ from ...print_api import print_api
5
+ from ... import certificates
6
+
7
+
8
+ # lpszStoreProvider
9
+ CERT_STORE_PROV_SYSTEM = 0x0000000A
10
+ # dwFlags
11
+ CERT_SYSTEM_STORE_LOCAL_MACHINE = 0x00020000
12
+ CERT_SYSTEM_STORE_CURRENT_USER = 0x00010000
13
+ CERT_CLOSE_STORE_FORCE_FLAG = 0x00000001
14
+ CRYPT_STRING_BASE64HEADER = 0x00000000
15
+ X509_ASN_ENCODING = 0x00000001
16
+ CERT_STORE_ADD_REPLACE_EXISTING = 3
17
+
18
+
19
+ STORE_LOCATION_TO_CERT_SYSTEM_STORE: dict = {
20
+ "ROOT": CERT_SYSTEM_STORE_LOCAL_MACHINE,
21
+ "CA": CERT_SYSTEM_STORE_LOCAL_MACHINE,
22
+ "MY": CERT_SYSTEM_STORE_CURRENT_USER
23
+ }
24
+
25
+
26
+ def delete_certificate_by_issuer_name(
27
+ issuer_name: str,
28
+ store_location: Literal[
29
+ "ROOT",
30
+ "CA",
31
+ "MY"] = "ROOT",
32
+ print_kwargs: dict = None
33
+ ):
34
+ """
35
+ NEED ADMIN RIGHTS.
36
+ The function will remove all certificates with the specified issuer name.
37
+ There can be several certificates with this name.
38
+
39
+ :param issuer_name: string, issuer name to search for.
40
+ :param store_location: string, store location to search in. Default is "ROOT".
41
+ :param print_kwargs: dict, print_api kwargs.
42
+ """
43
+
44
+ store = wcrypt.CertOpenStore(
45
+ CERT_STORE_PROV_SYSTEM, 0, None, STORE_LOCATION_TO_CERT_SYSTEM_STORE[store_location], store_location)
46
+
47
+ for cert in store.CertEnumCertificatesInStore():
48
+ # Certificate properties.
49
+ # cert.CertEnumCertificateContextProperties()
50
+ subject_string: str = wcrypt.CertNameToStr(cert.Subject)
51
+ if subject_string == issuer_name:
52
+ # Remove the certificate.
53
+ cert.CertDeleteCertificateFromStore()
54
+ print_api(f"Removed the Certificate with issuer: {issuer_name}", **(print_kwargs or {}))
55
+
56
+ # There is an exception about store close.
57
+ # store.CertCloseStore()
58
+
59
+
60
+ def install_certificate_file(
61
+ file_path: str,
62
+ store_location: Literal[
63
+ "ROOT", "CA", "MY"] = "ROOT",
64
+ print_kwargs: dict = None
65
+ ):
66
+ """
67
+ NEED ADMIN RIGHTS.
68
+ The function will install the certificate from the file to the specified store location.
69
+
70
+ :param file_path: string, full file path to the certificate file.
71
+ :param store_location: string, store location to install the certificate. Default is "ROOT".
72
+ :param print_kwargs: dict, print_api kwargs.
73
+ """
74
+
75
+ with open(file_path, 'r') as f:
76
+ certificate_string = f.read()
77
+
78
+ certificate_pem = certificates.get_pem_certificate_from_string(certificate_string)
79
+
80
+ certificate_bytes = wcrypt.CryptStringToBinary(certificate_pem, CRYPT_STRING_BASE64HEADER)[0]
81
+
82
+ store = wcrypt.CertOpenStore(
83
+ CERT_STORE_PROV_SYSTEM, 0, None, STORE_LOCATION_TO_CERT_SYSTEM_STORE[store_location], store_location)
84
+
85
+ store.CertAddEncodedCertificateToStore(X509_ASN_ENCODING, certificate_bytes, CERT_STORE_ADD_REPLACE_EXISTING)
86
+ store.CertCloseStore(CERT_CLOSE_STORE_FORCE_FLAG)
87
+
88
+ message = f"Certificate installed to the store: [{store_location}] from file: [{file_path}]"
89
+ print_api(message, **(print_kwargs or {}))
@@ -54,7 +54,11 @@ def execute_test(config_static):
54
54
  config = config_importer.config['config']
55
55
 
56
56
  # SocketClient is working with 'network' logger by default, so we will initialize it.
57
- loggingw.get_logger_with_stream_handler("network")
57
+ loggingw.create_logger(
58
+ logger_name="network",
59
+ add_stream=True,
60
+ formatter_streamhandler='DEFAULT'
61
+ )
58
62
 
59
63
  # Get all the files in requests folder recursively.
60
64
  request_file_list = filesystem.get_paths_from_directory(config['requests_directory'], get_file=True)
@@ -1,10 +1,13 @@
1
1
  import threading
2
2
  import select
3
3
  from typing import Literal, Union
4
+ from pathlib import Path
4
5
 
5
6
  from ..psutilw import networks
7
+ from ..certauthw import certauthw
6
8
  from ...script_as_string_processor import ScriptAsStringProcessor
7
- from ... import queues, filesystem
9
+ from ...permissions import permissions
10
+ from ... import queues, filesystem, certificates
8
11
  from ...basics import booleans
9
12
  from ...print_api import print_api
10
13
 
@@ -30,6 +33,9 @@ class SocketWrapper:
30
33
  forwarding_dns_service_ipv4_list___only_for_localhost: list = None,
31
34
  ca_certificate_name: str = None,
32
35
  ca_certificate_filepath: str = None,
36
+ ca_certificate_crt_filepath: str = None,
37
+ install_ca_certificate_to_root_store: bool = False,
38
+ uninstall_unused_ca_certificates_with_ca_certificate_name: bool = False,
33
39
  default_server_certificate_usage: bool = False,
34
40
  default_server_certificate_name: str = None,
35
41
  default_certificate_domain_list: list = None,
@@ -68,7 +74,13 @@ class SocketWrapper:
68
74
  Example: '0.0.0.0'. For all interfaces.
69
75
  :param listening_port_list: list, of ports that will be listened on.
70
76
  :param ca_certificate_name: CA certificate name.
71
- :param ca_certificate_filepath: CA certificate file path.
77
+ :param ca_certificate_filepath: CA certificate file path with '.pem' extension.
78
+ :param ca_certificate_crt_filepath: CA certificate file path with '.crt' extension.
79
+ This file will be created from the PEM file 'ca_certificate_filepath' for manual installation.
80
+ :param install_ca_certificate_to_root_store: boolean, if True, CA certificate will be installed
81
+ to the root store.
82
+ :param uninstall_unused_ca_certificates_with_ca_certificate_name: boolean, if True, unused CA certificates
83
+ with provided 'ca_certificate_name' will be uninstalled.
72
84
  :param default_server_certificate_usage: boolean, if True, default server certificate will be used
73
85
  for each incoming socket.
74
86
  :param sni_custom_callback_function: callable, custom callback function that will be executed when
@@ -150,6 +162,10 @@ class SocketWrapper:
150
162
  self.listening_port_list: list[int] = listening_port_list
151
163
  self.ca_certificate_name: str = ca_certificate_name
152
164
  self.ca_certificate_filepath: str = ca_certificate_filepath
165
+ self.ca_certificate_crt_filepath: str = ca_certificate_crt_filepath
166
+ self.install_ca_certificate_to_root_store: bool = install_ca_certificate_to_root_store
167
+ self.uninstall_unused_ca_certificates_with_ca_certificate_name: bool = \
168
+ uninstall_unused_ca_certificates_with_ca_certificate_name
153
169
  self.default_server_certificate_usage: bool = default_server_certificate_usage
154
170
  self.default_server_certificate_name: str = default_server_certificate_name
155
171
  self.default_certificate_domain_list: list = default_certificate_domain_list
@@ -270,6 +286,59 @@ class SocketWrapper:
270
286
  error_messages.append(f"Port [{port}] is already in use by process: {process_info}")
271
287
  raise SocketWrapperPortInUseError("\n".join(error_messages))
272
288
 
289
+ if not filesystem.is_file_exists(file_path=self.ca_certificate_filepath):
290
+ # Initialize CertAuthWrapper.
291
+ ca_certificate_directory: str = str(Path(self.ca_certificate_filepath).parent)
292
+ certauth_wrapper = certauthw.CertAuthWrapper(
293
+ ca_certificate_name=self.ca_certificate_name,
294
+ ca_certificate_filepath=self.ca_certificate_filepath,
295
+ server_certificate_directory=ca_certificate_directory
296
+ )
297
+
298
+ # Create CA certificate if it doesn't exist.
299
+ certauth_wrapper.create_use_ca_certificate()
300
+
301
+ certificates.write_crt_certificate_file_in_pem_format_from_pem_file(
302
+ pem_file_path=self.ca_certificate_filepath,
303
+ crt_file_path=self.ca_certificate_crt_filepath)
304
+
305
+ if self.install_ca_certificate_to_root_store:
306
+ if not self.ca_certificate_filepath:
307
+ message = "You set [install_ca_certificate_to_root_store = True],\n" \
308
+ "But you didn't set [ca_certificate_filepath]."
309
+ raise SocketWrapperConfigurationValuesError(message)
310
+
311
+ # Before installation check if there are any unused certificates with the same name.
312
+ if self.uninstall_unused_ca_certificates_with_ca_certificate_name:
313
+ # Check how many certificates with our ca certificate name are installed.
314
+ is_installed_by_name, certificate_list_by_name = certificates.is_certificate_in_store(
315
+ issuer_name=self.ca_certificate_name)
316
+ # If there is more than one certificate with the same name, delete them all.
317
+ if is_installed_by_name and len(certificate_list_by_name) > 1:
318
+ certificates.delete_certificate_by_issuer_name(self.ca_certificate_name)
319
+ # If there is only one certificate with the same name, check if it is the same certificate.
320
+ elif is_installed_by_name and len(certificate_list_by_name) == 1:
321
+ is_installed_by_file, certificate_list_by_file = certificates.is_certificate_in_store(
322
+ certificate=self.ca_certificate_filepath, by_cert_thumbprint=True, by_cert_issuer=True)
323
+ # If the certificate is not the same, delete it.
324
+ if not is_installed_by_file:
325
+ if not permissions.is_admin():
326
+ raise SocketWrapperConfigurationValuesError(
327
+ "You need to run the script with admin rights to uninstall the unused certificates.")
328
+ certificates.delete_certificate_by_issuer_name(
329
+ self.ca_certificate_name, store_location="ROOT", print_kwargs={'logger': self.logger})
330
+
331
+ if self.install_ca_certificate_to_root_store:
332
+ # Install CA certificate to the root store if it is not installed.
333
+ is_installed_by_file, certificate_list_by_file = certificates.is_certificate_in_store(
334
+ certificate=self.ca_certificate_filepath, by_cert_thumbprint=True, by_cert_issuer=True)
335
+ if not is_installed_by_file:
336
+ if not permissions.is_admin():
337
+ raise SocketWrapperConfigurationValuesError(
338
+ "You need to run the script with admin rights to install the CA certificate.")
339
+ certificates.install_certificate_file(
340
+ self.ca_certificate_filepath, store_location="ROOT", print_kwargs={'logger': self.logger})
341
+
273
342
  # Creating listening sockets.
274
343
  def create_socket_ipv4_tcp(self, ip_address: str, port: int):
275
344
  self.sni_execute_extended = True
@@ -60,7 +60,7 @@ def is_tls(client_socket) -> Optional[Tuple[str, str]]:
60
60
  }
61
61
 
62
62
  # Get the tuple of the type and version as strings.
63
- tls_content_and_version_tuple: tuple =\
63
+ tls_content_and_version_tuple: tuple = \
64
64
  content_type_map.get(content_type), version_map.get((version_major, version_minor))
65
65
 
66
66
  # If both parts of the tuple are not None, return the protocol type.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: atomicshop
3
- Version: 2.16.14
3
+ Version: 2.16.16
4
4
  Summary: Atomic functions and classes to make developer life easier
5
5
  Author: Denis Kras
6
6
  License: MIT License
@@ -38,7 +38,6 @@ Requires-Dist: cryptography
38
38
  Requires-Dist: dnslib
39
39
  Requires-Dist: dnspython
40
40
  Requires-Dist: docker
41
- Requires-Dist: elasticsearch
42
41
  Requires-Dist: numpy
43
42
  Requires-Dist: olefile
44
43
  Requires-Dist: openpyxl