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.
- atomicshop/__init__.py +1 -1
- atomicshop/certificates.py +146 -52
- atomicshop/mitm/config_static.py +12 -3
- atomicshop/mitm/import_config.py +8 -0
- atomicshop/mitm/mitm_main.py +7 -4
- atomicshop/mitm/recs_files.py +0 -1
- atomicshop/process_poller/process_pool.py +0 -1
- atomicshop/process_poller/simple_process_pool.py +0 -1
- atomicshop/wrappers/cryptographyw.py +3 -1
- atomicshop/wrappers/ctyping/msi_windows_installer/extract_msi_main.py +0 -1
- atomicshop/wrappers/elasticsearchw/elasticsearchw.py +2 -20
- atomicshop/wrappers/elasticsearchw/install_elastic.py +7 -7
- atomicshop/wrappers/factw/get_file_data.py +12 -5
- atomicshop/wrappers/githubw.py +0 -1
- atomicshop/wrappers/loggingw/handlers.py +31 -16
- atomicshop/wrappers/loggingw/loggingw.py +3 -0
- atomicshop/wrappers/mongodbw/install_mongodb.py +6 -6
- atomicshop/wrappers/mongodbw/{infrastructure.py → mongo_infra.py} +14 -6
- atomicshop/wrappers/mongodbw/mongodbw.py +174 -24
- atomicshop/wrappers/pywin32w/cert_store.py +89 -0
- atomicshop/wrappers/socketw/socket_server_tester.py +5 -1
- atomicshop/wrappers/socketw/socket_wrapper.py +71 -2
- atomicshop/wrappers/socketw/ssl_base.py +1 -1
- {atomicshop-2.16.14.dist-info → atomicshop-2.16.16.dist-info}/METADATA +1 -2
- {atomicshop-2.16.14.dist-info → atomicshop-2.16.16.dist-info}/RECORD +29 -28
- /atomicshop/wrappers/elasticsearchw/{infrastructure.py → elastic_infra.py} +0 -0
- {atomicshop-2.16.14.dist-info → atomicshop-2.16.16.dist-info}/LICENSE.txt +0 -0
- {atomicshop-2.16.14.dist-info → atomicshop-2.16.16.dist-info}/WHEEL +0 -0
- {atomicshop-2.16.14.dist-info → atomicshop-2.16.16.dist-info}/top_level.txt +0 -0
atomicshop/__init__.py
CHANGED
atomicshop/certificates.py
CHANGED
|
@@ -5,9 +5,10 @@ https://oidref.com/1.3.6.1.5.5.7.3.1
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
import ssl
|
|
8
|
+
from typing import Literal
|
|
8
9
|
|
|
9
10
|
from .wrappers import cryptographyw
|
|
10
|
-
from .
|
|
11
|
+
from .wrappers.pywin32w import cert_store
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
# Valid for 3 years from now
|
|
@@ -16,72 +17,165 @@ from .print_api import print_api
|
|
|
16
17
|
SECONDS_NOT_AFTER_3_YEARS = 3 * 365 * 24 * 60 * 60
|
|
17
18
|
|
|
18
19
|
|
|
19
|
-
def
|
|
20
|
+
def get_pem_certificate_from_string(certificate: str) -> str:
|
|
20
21
|
"""
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
:param certificate:
|
|
24
|
-
:
|
|
25
|
-
The problem that the issuer common name is not unique, so it can be installed multiple times.
|
|
26
|
-
:param thumbprint_only: bool, if True, will check only by the certificate thumbprint is installed in the store.
|
|
27
|
-
The problem that searching by the thumbprint will not tell you if there are multiple certificates with the same
|
|
28
|
-
issuer name.
|
|
29
|
-
:return: bool, True if certificate is installed, False if not.
|
|
22
|
+
Some PEM certificates can contain a private key. This function will return only the certificate part.
|
|
23
|
+
|
|
24
|
+
:param certificate: string, PEM certificate.
|
|
25
|
+
:return: string, certificate part.
|
|
30
26
|
"""
|
|
31
27
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
28
|
+
certificate_lines = certificate.split('\n')
|
|
29
|
+
certificate_part = ''
|
|
30
|
+
start = False
|
|
31
|
+
for line in certificate_lines:
|
|
32
|
+
if 'BEGIN CERTIFICATE' in line:
|
|
33
|
+
start = True
|
|
34
|
+
if start:
|
|
35
|
+
certificate_part += line + '\n'
|
|
36
|
+
if 'END CERTIFICATE' in line:
|
|
37
|
+
break
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
for cert, encoding, trust in ssl.enum_certificates("ROOT"):
|
|
40
|
-
store_certificate = cryptographyw.convert_object_to_x509(cert)
|
|
41
|
-
store_issuer_common_name: str = cryptographyw.get_issuer_common_name_from_x509(store_certificate)
|
|
42
|
-
store_thumbprint = cryptographyw.get_sha1_thumbprint_from_x509(store_certificate)
|
|
43
|
-
|
|
44
|
-
if issuer_only:
|
|
45
|
-
if store_issuer_common_name == issuer_common_name:
|
|
46
|
-
return True, certificate
|
|
47
|
-
elif thumbprint_only:
|
|
48
|
-
if store_thumbprint == thumbprint:
|
|
49
|
-
return True, certificate
|
|
50
|
-
elif not issuer_only and not thumbprint_only:
|
|
51
|
-
if store_thumbprint == thumbprint and store_issuer_common_name == issuer_common_name:
|
|
52
|
-
return True, certificate
|
|
39
|
+
return certificate_part
|
|
53
40
|
|
|
54
41
|
|
|
55
|
-
def
|
|
42
|
+
def write_crt_certificate_file_in_pem_format_from_pem_file(
|
|
43
|
+
pem_file_path: str,
|
|
44
|
+
crt_file_path: str
|
|
45
|
+
):
|
|
56
46
|
"""
|
|
57
|
-
The function will
|
|
47
|
+
The function will read the PEM certificate file and write it to the CRT file in PEM format.
|
|
48
|
+
The function is used to convert the PEM certificate file to the CRT file.
|
|
58
49
|
|
|
59
|
-
|
|
60
|
-
|
|
50
|
+
Basically the point here is that the CRT file is the same as the PEM file, but the extension is different,
|
|
51
|
+
and it doesn't support integrated private key.
|
|
61
52
|
|
|
62
|
-
:
|
|
53
|
+
:param pem_file_path: string, path to the PEM certificate file.
|
|
54
|
+
:param crt_file_path: string, path to the CRT certificate file.
|
|
63
55
|
"""
|
|
64
56
|
|
|
65
|
-
|
|
66
|
-
|
|
57
|
+
with open(pem_file_path, 'r') as f:
|
|
58
|
+
certificate_string = f.read()
|
|
59
|
+
|
|
60
|
+
certificate_pem = get_pem_certificate_from_string(certificate_string)
|
|
61
|
+
|
|
62
|
+
with open(crt_file_path, 'w') as f:
|
|
63
|
+
f.write(certificate_pem)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def is_certificate_in_store(
|
|
67
|
+
certificate: any = None,
|
|
68
|
+
by_cert_issuer: bool = True,
|
|
69
|
+
by_cert_thumbprint: bool = True,
|
|
70
|
+
issuer_name: str = None,
|
|
71
|
+
store_location: str = "ROOT"
|
|
72
|
+
) -> tuple[bool, list]:
|
|
73
|
+
"""
|
|
74
|
+
The function will check if the CA certificate is installed in the Windows certificate Trusted Root store.
|
|
75
|
+
NO ADMIN RIGHTS NEEDED.
|
|
76
|
+
|
|
77
|
+
:param certificate: x509 object, certificate to check. You can search by certificate or by issuer name.
|
|
78
|
+
Supported types:
|
|
79
|
+
string that is path to file will be imported as bytes object abd converted to x509.Certificate
|
|
80
|
+
After check if it's PEM or DER format.
|
|
81
|
+
string that is PEM certificate will be converted to bytes, then x509.Certificate
|
|
82
|
+
bytes of PEM or DER will be converted to x509.Certificate.
|
|
83
|
+
x509.Certificate will be returned as is.
|
|
84
|
+
:param by_cert_issuer: bool, if True, will check only by the certificate issuer common name is installed in the store.
|
|
85
|
+
The problem if the search will be by issuer alone, that the issuer common name is not unique,
|
|
86
|
+
so it can be installed multiple times.
|
|
87
|
+
:param by_cert_thumbprint: bool, if True, will check only by the certificate thumbprint is installed in the store.
|
|
88
|
+
The problem that searching by the thumbprint alone will not tell you if there are multiple
|
|
89
|
+
certificates with the same issuer name.
|
|
90
|
+
:param issuer_name: string, issuer name to search for. You can search by certificate or by issuer name.
|
|
91
|
+
:param store_location: string, store location to search in. Default is "ROOT".
|
|
92
|
+
:return: tuple(bool - True if certificate is installed and False if not, list of certificates found)
|
|
93
|
+
"""
|
|
67
94
|
|
|
68
|
-
|
|
95
|
+
if not by_cert_issuer and not by_cert_thumbprint:
|
|
96
|
+
raise ValueError('At least one of the parameters "by_issuer" or "by_thumbprint" must be True.')
|
|
97
|
+
|
|
98
|
+
if not certificate and not issuer_name:
|
|
99
|
+
raise ValueError('At least one of the parameters "certificate" or "issuer_name" must be provided.')
|
|
100
|
+
elif certificate and issuer_name:
|
|
101
|
+
raise ValueError('Only one of the parameters "certificate" or "issuer_name" must be provided.')
|
|
102
|
+
|
|
103
|
+
if certificate:
|
|
104
|
+
# Make sure the certificate is x509.Certificate object.
|
|
105
|
+
certificate_x509 = cryptographyw.convert_object_to_x509(certificate)
|
|
106
|
+
# Get the certificate thumbprint.
|
|
107
|
+
provided_thumbprint = cryptographyw.get_sha1_thumbprint_from_x509(certificate_x509)
|
|
108
|
+
provided_issuer_common_name: str = cryptographyw.get_issuer_common_name_from_x509(certificate_x509)
|
|
109
|
+
elif issuer_name:
|
|
110
|
+
provided_thumbprint = None
|
|
111
|
+
provided_issuer_common_name = issuer_name
|
|
112
|
+
else:
|
|
113
|
+
raise ValueError('At least one of the parameters "certificate" or "issuer_name" must be provided.')
|
|
69
114
|
|
|
70
|
-
|
|
115
|
+
# Iterate over all certificates in the store specifically in the ROOT.
|
|
116
|
+
# for store in ["CA", "ROOT", "MY"]:
|
|
117
|
+
result_found_list: list = []
|
|
118
|
+
found: bool = False
|
|
119
|
+
for cert, encoding, trust in ssl.enum_certificates(store_location):
|
|
71
120
|
store_certificate = cryptographyw.convert_object_to_x509(cert)
|
|
72
121
|
store_issuer_common_name: str = cryptographyw.get_issuer_common_name_from_x509(store_certificate)
|
|
122
|
+
store_thumbprint = cryptographyw.get_sha1_thumbprint_from_x509(store_certificate)
|
|
73
123
|
|
|
74
|
-
if
|
|
75
|
-
|
|
124
|
+
if certificate:
|
|
125
|
+
if by_cert_issuer and not by_cert_thumbprint:
|
|
126
|
+
if store_issuer_common_name == provided_issuer_common_name:
|
|
127
|
+
result_found_list.append(store_certificate)
|
|
128
|
+
found = True
|
|
129
|
+
elif by_cert_thumbprint and not by_cert_issuer:
|
|
130
|
+
if store_thumbprint == provided_thumbprint:
|
|
131
|
+
result_found_list.append(store_certificate)
|
|
132
|
+
found = True
|
|
133
|
+
elif by_cert_issuer and by_cert_thumbprint:
|
|
134
|
+
if store_thumbprint == provided_thumbprint and store_issuer_common_name == provided_issuer_common_name:
|
|
135
|
+
result_found_list.append(store_certificate)
|
|
136
|
+
found = True
|
|
137
|
+
elif issuer_name:
|
|
138
|
+
if store_issuer_common_name == provided_issuer_common_name:
|
|
139
|
+
result_found_list.append(store_certificate)
|
|
140
|
+
found = True
|
|
141
|
+
|
|
142
|
+
return found, result_found_list
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def delete_certificate_by_issuer_name(
|
|
146
|
+
issuer_name: str,
|
|
147
|
+
store_location: Literal[
|
|
148
|
+
"ROOT",
|
|
149
|
+
"CA",
|
|
150
|
+
"MY"] = "ROOT",
|
|
151
|
+
print_kwargs: dict = None
|
|
152
|
+
):
|
|
153
|
+
"""
|
|
154
|
+
NEED ADMIN RIGHTS.
|
|
155
|
+
The function will remove all certificates with the specified issuer name.
|
|
156
|
+
There can be several certificates with this name.
|
|
76
157
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
158
|
+
:param issuer_name: string, issuer name to search for.
|
|
159
|
+
:param store_location: string, store location to search in. Default is "ROOT".
|
|
160
|
+
:param print_kwargs: dict, print_api kwargs.
|
|
161
|
+
"""
|
|
162
|
+
|
|
163
|
+
cert_store.delete_certificate_by_issuer_name(issuer_name, store_location, print_kwargs)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def install_certificate_file(
|
|
167
|
+
file_path: str,
|
|
168
|
+
store_location: Literal[
|
|
169
|
+
"ROOT", "CA", "MY"] = "ROOT",
|
|
170
|
+
print_kwargs: dict = None
|
|
171
|
+
):
|
|
172
|
+
"""
|
|
173
|
+
The function will install the certificate from the file to the specified store location.
|
|
174
|
+
NEED ADMIN RIGHTS.
|
|
175
|
+
|
|
176
|
+
:param file_path: string, full file path to the certificate file.
|
|
177
|
+
:param store_location: string, store location to install the certificate. Default is "ROOT".
|
|
178
|
+
:param print_kwargs: dict, print_api kwargs.
|
|
179
|
+
"""
|
|
86
180
|
|
|
87
|
-
|
|
181
|
+
cert_store.install_certificate_file(file_path, store_location, print_kwargs)
|
atomicshop/mitm/config_static.py
CHANGED
|
@@ -4,9 +4,9 @@ from dataclasses import dataclass
|
|
|
4
4
|
from . import import_config
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
SCRIPT_VERSION: str = '1.7.
|
|
7
|
+
SCRIPT_VERSION: str = '1.7.6'
|
|
8
8
|
"""
|
|
9
|
-
|
|
9
|
+
added ca cert check and installation
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
12
|
|
|
@@ -23,6 +23,8 @@ LIST_OF_BOOLEANS: list = [
|
|
|
23
23
|
('tcp', 'engines_usage'),
|
|
24
24
|
('tcp', 'server_response_mode'),
|
|
25
25
|
('logrec', 'enable_request_response_recordings_in_logs'),
|
|
26
|
+
('certificates', 'install_ca_certificate_to_root_store'),
|
|
27
|
+
('certificates', 'uninstall_unused_ca_certificates_with_mitm_ca_name'),
|
|
26
28
|
('certificates', 'default_server_certificate_usage'),
|
|
27
29
|
('certificates', 'sni_add_new_domains_to_default_server_certificate'),
|
|
28
30
|
('certificates', 'custom_server_certificate_usage'),
|
|
@@ -55,8 +57,11 @@ class MainConfig:
|
|
|
55
57
|
# Certificates.
|
|
56
58
|
default_server_certificate_name: str = 'default'
|
|
57
59
|
ca_certificate_name: str = 'ElaborateCA'
|
|
60
|
+
ca_certificate_pem_filename: str = f'{ca_certificate_name}.pem'
|
|
61
|
+
ca_certificate_crt_filename: str = f'{ca_certificate_name}_for_manual_installation_not_used_by_script.crt'
|
|
58
62
|
# CA Certificate name and file name without extension.
|
|
59
63
|
ca_certificate_filepath: str = None
|
|
64
|
+
ca_certificate_crt_filepath: str = None
|
|
60
65
|
# Default server certificate file name and path.
|
|
61
66
|
default_server_certificate_filename = f'{default_server_certificate_name}.pem'
|
|
62
67
|
default_server_certificate_filepath: str = None
|
|
@@ -65,7 +70,8 @@ class MainConfig:
|
|
|
65
70
|
def update(cls):
|
|
66
71
|
# This runs after the dataclass is initialized
|
|
67
72
|
cls.ENGINES_DIRECTORY_PATH = cls.SCRIPT_DIRECTORY + os.sep + cls.ENGINES_DIRECTORY_NAME
|
|
68
|
-
cls.ca_certificate_filepath = f'{cls.SCRIPT_DIRECTORY}{os.sep}{cls.
|
|
73
|
+
cls.ca_certificate_filepath = f'{cls.SCRIPT_DIRECTORY}{os.sep}{cls.ca_certificate_pem_filename}'
|
|
74
|
+
cls.ca_certificate_crt_filepath = f'{cls.SCRIPT_DIRECTORY}{os.sep}{cls.ca_certificate_crt_filename}'
|
|
69
75
|
cls.default_server_certificate_filepath = \
|
|
70
76
|
f'{cls.SCRIPT_DIRECTORY}{os.sep}{cls.default_server_certificate_filename}'
|
|
71
77
|
|
|
@@ -115,6 +121,9 @@ class LogRec:
|
|
|
115
121
|
|
|
116
122
|
@dataclass
|
|
117
123
|
class Certificates:
|
|
124
|
+
install_ca_certificate_to_root_store: bool
|
|
125
|
+
uninstall_unused_ca_certificates_with_mitm_ca_name: bool
|
|
126
|
+
|
|
118
127
|
default_server_certificate_usage: bool
|
|
119
128
|
sni_add_new_domains_to_default_server_certificate: bool
|
|
120
129
|
|
atomicshop/mitm/import_config.py
CHANGED
|
@@ -117,6 +117,14 @@ def check_configurations() -> int:
|
|
|
117
117
|
print_api(message, color='red')
|
|
118
118
|
return 1
|
|
119
119
|
|
|
120
|
+
# This is checked directly in the SocketWrapper.
|
|
121
|
+
# if (config_static.Certificates.install_ca_certificate_to_root_store and not is_admin) or \
|
|
122
|
+
# (config_static.Certificates.uninstall_unused_ca_certificates_with_mitm_ca_name and not is_admin):
|
|
123
|
+
# message: str = \
|
|
124
|
+
# "Need to run the script with administrative rights to install or uninstall CA certificate.\nExiting..."
|
|
125
|
+
# print_api(message, color='red')
|
|
126
|
+
# return 1
|
|
127
|
+
|
|
120
128
|
return 0
|
|
121
129
|
|
|
122
130
|
|
atomicshop/mitm/mitm_main.py
CHANGED
|
@@ -263,6 +263,10 @@ def mitm_server_main(config_file_path: str):
|
|
|
263
263
|
listening_port_list=config_static.TCPServer.listening_port_list,
|
|
264
264
|
ca_certificate_name=config_static.MainConfig.ca_certificate_name,
|
|
265
265
|
ca_certificate_filepath=config_static.MainConfig.ca_certificate_filepath,
|
|
266
|
+
ca_certificate_crt_filepath=config_static.MainConfig.ca_certificate_crt_filepath,
|
|
267
|
+
install_ca_certificate_to_root_store=config_static.Certificates.install_ca_certificate_to_root_store,
|
|
268
|
+
uninstall_unused_ca_certificates_with_ca_certificate_name=(
|
|
269
|
+
config_static.Certificates.uninstall_unused_ca_certificates_with_mitm_ca_name),
|
|
266
270
|
default_server_certificate_usage=config_static.Certificates.default_server_certificate_usage,
|
|
267
271
|
default_server_certificate_name=config_static.MainConfig.default_server_certificate_name,
|
|
268
272
|
default_certificate_domain_list=config_static.Certificates.domains_all_times,
|
|
@@ -316,11 +320,10 @@ def mitm_server_main(config_file_path: str):
|
|
|
316
320
|
dns_gateway_server_list = [base.DEFAULT_IPV4]
|
|
317
321
|
set_dns_gateway = True
|
|
318
322
|
|
|
323
|
+
# Get current network interface state.
|
|
324
|
+
global NETWORK_INTERFACE_IS_DYNAMIC, NETWORK_INTERFACE_IPV4_ADDRESS_LIST
|
|
325
|
+
NETWORK_INTERFACE_IS_DYNAMIC, NETWORK_INTERFACE_IPV4_ADDRESS_LIST = dns.get_default_dns_gateway()
|
|
319
326
|
if set_dns_gateway:
|
|
320
|
-
# Get current network interface state.
|
|
321
|
-
global NETWORK_INTERFACE_IS_DYNAMIC, NETWORK_INTERFACE_IPV4_ADDRESS_LIST
|
|
322
|
-
NETWORK_INTERFACE_IS_DYNAMIC, NETWORK_INTERFACE_IPV4_ADDRESS_LIST = dns.get_default_dns_gateway()
|
|
323
|
-
|
|
324
327
|
# Set the DNS gateway to the specified one only if the DNS gateway is dynamic or it is static but different
|
|
325
328
|
# from the one specified in the configuration file.
|
|
326
329
|
if (NETWORK_INTERFACE_IS_DYNAMIC or (not NETWORK_INTERFACE_IS_DYNAMIC and
|
atomicshop/mitm/recs_files.py
CHANGED
|
@@ -3,7 +3,6 @@ import multiprocessing
|
|
|
3
3
|
import time
|
|
4
4
|
from typing import Literal, Union
|
|
5
5
|
|
|
6
|
-
from ..print_api import print_api
|
|
7
6
|
from .tracers import sysmon_etw, event_log
|
|
8
7
|
from .pollers import psutil_pywin32wmi_dll
|
|
9
8
|
from ..wrappers.pywin32w.win_event_log.subscribes import process_terminate
|
|
@@ -36,7 +36,9 @@ def convert_object_to_x509(certificate):
|
|
|
36
36
|
"""
|
|
37
37
|
|
|
38
38
|
# Check if 'certificate' is a string and a path.
|
|
39
|
-
if isinstance(certificate, str)
|
|
39
|
+
if isinstance(certificate, str):
|
|
40
|
+
if not os.path.isfile(certificate):
|
|
41
|
+
raise FileNotFoundError(f'File not found: {certificate}')
|
|
40
42
|
# Import the certificate from the path.
|
|
41
43
|
certificate = file_io.read_file(certificate, file_mode='rb')
|
|
42
44
|
|
|
@@ -6,10 +6,8 @@ from typing import Union
|
|
|
6
6
|
from . import config_basic
|
|
7
7
|
from ...basics import dicts
|
|
8
8
|
|
|
9
|
-
ELASTIC_WRAPPER = None
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
def get_elastic_wrapper(url: str = None, overwrite: bool = False):
|
|
10
|
+
def get_elastic_wrapper(url: str = config_basic.DEFAULT_ELASTIC_URL, overwrite: bool = False):
|
|
13
11
|
"""
|
|
14
12
|
The function initializes the Elasticsearch wrapper.
|
|
15
13
|
|
|
@@ -19,25 +17,9 @@ def get_elastic_wrapper(url: str = None, overwrite: bool = False):
|
|
|
19
17
|
|
|
20
18
|
Usage:
|
|
21
19
|
elastic_wrapper = get_elastic_wrapper()
|
|
22
|
-
or after you initialize it once, you can use it like:
|
|
23
|
-
atomicshop.wrappers.elasticsearchw.elasticsearchw.ELASTIC_WRAPPER
|
|
24
20
|
"""
|
|
25
21
|
|
|
26
|
-
|
|
27
|
-
if url is None:
|
|
28
|
-
url = config_basic.DEFAULT_ELASTIC_URL
|
|
29
|
-
|
|
30
|
-
# Get the global variable.
|
|
31
|
-
global ELASTIC_WRAPPER
|
|
32
|
-
# If the wrapper is not initialized, initialize it.
|
|
33
|
-
if ELASTIC_WRAPPER is None:
|
|
34
|
-
ELASTIC_WRAPPER = Elasticsearch([url])
|
|
35
|
-
# If the wrapper is already initialized, check if it should be overwritten.
|
|
36
|
-
else:
|
|
37
|
-
if overwrite:
|
|
38
|
-
ELASTIC_WRAPPER = Elasticsearch([url])
|
|
39
|
-
|
|
40
|
-
return ELASTIC_WRAPPER
|
|
22
|
+
return Elasticsearch([url])
|
|
41
23
|
|
|
42
24
|
|
|
43
25
|
def test_connection(elastic_wrapper: Elasticsearch = None):
|
|
@@ -4,7 +4,7 @@ from ...print_api import print_api
|
|
|
4
4
|
from ... import process
|
|
5
5
|
from ...permissions import permissions
|
|
6
6
|
from .. import ubuntu_terminal
|
|
7
|
-
from . import config_basic,
|
|
7
|
+
from . import config_basic, elastic_infra
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def install_elastic_kibana_ubuntu(install_elastic: bool = True, install_kibana: bool = True):
|
|
@@ -202,29 +202,29 @@ def install_elastic_kibana_ubuntu(install_elastic: bool = True, install_kibana:
|
|
|
202
202
|
sys.exit(1)
|
|
203
203
|
|
|
204
204
|
# Check if the configuration file exists.
|
|
205
|
-
|
|
205
|
+
elastic_infra.is_elastic_config_file_exists(exit_on_error=True, output_message=True)
|
|
206
206
|
|
|
207
207
|
# Check if the specific setting exists or not and set it to false.
|
|
208
|
-
|
|
208
|
+
elastic_infra.modify_xpack_security_setting(setting=False, output_message=True)
|
|
209
209
|
|
|
210
210
|
# Check if the setting was really set to false.
|
|
211
|
-
if
|
|
211
|
+
if elastic_infra.check_xpack_security_setting() is False:
|
|
212
212
|
print_api(f"The setting is confirmed to be [{config_basic.XPACK_SECURITY_SETTING_NAME}: false].")
|
|
213
213
|
else:
|
|
214
214
|
print_api(f"Failed to set [{config_basic.XPACK_SECURITY_SETTING_NAME}: false].")
|
|
215
215
|
sys.exit(1)
|
|
216
216
|
|
|
217
|
-
|
|
217
|
+
elastic_infra.start_elastic_and_check_service_availability()
|
|
218
218
|
|
|
219
219
|
print_api("Creating custom JVM options file with 4GB memory usage.")
|
|
220
|
-
|
|
220
|
+
elastic_infra.create_jvm_options_custom_4gb_memory_heap_file()
|
|
221
221
|
|
|
222
222
|
if install_kibana:
|
|
223
223
|
# Install Kibana.
|
|
224
224
|
ubuntu_terminal.install_packages([config_basic.UBUNTU_KIBANA_PACKAGE_NAME])
|
|
225
225
|
|
|
226
226
|
# Start and enable Kibana service.
|
|
227
|
-
|
|
227
|
+
elastic_infra.start_kibana_and_check_service_availability()
|
|
228
228
|
|
|
229
229
|
print_api("Installation completed.", color='green')
|
|
230
230
|
if install_elastic:
|
|
@@ -33,11 +33,18 @@ def get_file_data(directory_path: str, firmwares: list = None):
|
|
|
33
33
|
"""
|
|
34
34
|
|
|
35
35
|
if not firmwares:
|
|
36
|
-
firmwares: list = filesystem.
|
|
36
|
+
firmwares: list = filesystem.get_paths_from_directory(
|
|
37
|
+
directory_path, get_file=True, recursive=False, add_file_binary=True, add_file_hash=True)
|
|
37
38
|
|
|
38
39
|
# Add UIDs to the list.
|
|
40
|
+
final_firmwares: list = []
|
|
39
41
|
for firmware in firmwares:
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
uid = get_uid_from_file(file_binary=firmware.binary, sha256_hash=firmware.hash)
|
|
43
|
+
final_firmwares.append({
|
|
44
|
+
'path': firmware.path,
|
|
45
|
+
'hash': firmware.hash,
|
|
46
|
+
'binary': firmware.binary,
|
|
47
|
+
'uid': uid
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
return final_firmwares
|
atomicshop/wrappers/githubw.py
CHANGED
|
@@ -84,27 +84,42 @@ def add_stream_handler(
|
|
|
84
84
|
|
|
85
85
|
# Function to start the interval-based rotation check
|
|
86
86
|
def _start_interval_rotation(handler):
|
|
87
|
+
# def check_rotation():
|
|
88
|
+
# while True:
|
|
89
|
+
# next_rollover = _calculate_next_rollover()
|
|
90
|
+
# while datetime.now() < next_rollover:
|
|
91
|
+
# time.sleep(0.1)
|
|
92
|
+
#
|
|
93
|
+
# # Check if the next_rollover has changed (indicating a rollover by an event)
|
|
94
|
+
# if _calculate_next_rollover() != next_rollover:
|
|
95
|
+
# next_rollover = _calculate_next_rollover()
|
|
96
|
+
# break
|
|
97
|
+
#
|
|
98
|
+
# # Perform manual rollover if needed
|
|
99
|
+
# if datetime.now() >= next_rollover:
|
|
100
|
+
# handler.doRollover()
|
|
101
|
+
#
|
|
102
|
+
# # handler.doRollover()
|
|
103
|
+
#
|
|
104
|
+
# def _calculate_next_rollover():
|
|
105
|
+
# return datetime.fromtimestamp(handler.rolloverAt)
|
|
87
106
|
def check_rotation():
|
|
88
|
-
|
|
89
|
-
next_rollover = _calculate_next_rollover()
|
|
90
|
-
while datetime.now() < next_rollover:
|
|
91
|
-
time.sleep(0.1)
|
|
107
|
+
last_rollover_at = handler.rolloverAt # Initial rollover time
|
|
92
108
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
break
|
|
109
|
+
while True:
|
|
110
|
+
current_time = datetime.now()
|
|
111
|
+
next_rollover = datetime.fromtimestamp(handler.rolloverAt)
|
|
97
112
|
|
|
98
|
-
#
|
|
99
|
-
if
|
|
100
|
-
|
|
113
|
+
# Check if the rollover time has passed and it hasn't been handled yet
|
|
114
|
+
if current_time >= next_rollover and handler.rolloverAt == last_rollover_at:
|
|
115
|
+
# Perform manual rollover
|
|
116
|
+
handler.doRollover()
|
|
101
117
|
|
|
102
|
-
|
|
103
|
-
|
|
118
|
+
# Update last_rollover_at to the new rolloverAt
|
|
119
|
+
last_rollover_at = handler.rolloverAt
|
|
104
120
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
handler.doRollover()
|
|
121
|
+
# Sleep for a short interval before checking again
|
|
122
|
+
time.sleep(0.1)
|
|
108
123
|
|
|
109
124
|
rotation_thread = threading.Thread(target=check_rotation)
|
|
110
125
|
rotation_thread.daemon = True
|
|
@@ -5,6 +5,7 @@ from typing import Literal, Union
|
|
|
5
5
|
from . import loggers, handlers
|
|
6
6
|
|
|
7
7
|
|
|
8
|
+
# noinspection PyPep8Naming
|
|
8
9
|
def create_logger(
|
|
9
10
|
logger_name: str,
|
|
10
11
|
file_path: str = None,
|
|
@@ -74,7 +75,9 @@ def create_logger(
|
|
|
74
75
|
in the formatter in case you provide 'asctime' element.
|
|
75
76
|
:param filehandler_rotate_at_rollover_time: bool,
|
|
76
77
|
If set to True, the log file will be rotated at the rollover time, even if there's nothing to write.
|
|
78
|
+
This behavior overrides the TimedRotatingFileHandler default behavior on doRollover.
|
|
77
79
|
If set to False, the log file will be rotated after 'when' time, but only when event occurs.
|
|
80
|
+
This is the default doRollover behavior of the TimedRotatingFileHandler.
|
|
78
81
|
:param filehandler_rotation_date_format: string, Date format to use for the log file rotation.
|
|
79
82
|
Example for 'when="midnight"': the default date format is '%Y-%m-%d', resulting in filename on rotation like:
|
|
80
83
|
"test.log.2021-11-25"
|
|
@@ -8,7 +8,7 @@ from ... import urls, web
|
|
|
8
8
|
from ...permissions import permissions
|
|
9
9
|
from ...print_api import print_api
|
|
10
10
|
from .. import msiw
|
|
11
|
-
from . import
|
|
11
|
+
from . import mongo_infra
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
MONGODB_DOWNLOAD_PAGE_URL: str = 'https://www.mongodb.com/try/download/community'
|
|
@@ -111,7 +111,7 @@ def download_install_latest_main(
|
|
|
111
111
|
print_api("This function requires administrator privileges.", color='red')
|
|
112
112
|
return 1
|
|
113
113
|
|
|
114
|
-
if
|
|
114
|
+
if mongo_infra.is_service_running():
|
|
115
115
|
print_api("MongoDB service is running - already installed.", color='blue')
|
|
116
116
|
|
|
117
117
|
if not force:
|
|
@@ -119,8 +119,8 @@ def download_install_latest_main(
|
|
|
119
119
|
else:
|
|
120
120
|
print_api("MongoDB is service is not running.")
|
|
121
121
|
|
|
122
|
-
mongo_is_installed: Union[str, None] =
|
|
123
|
-
if
|
|
122
|
+
mongo_is_installed: Union[str, None] = mongo_infra.is_installed()
|
|
123
|
+
if mongo_infra.is_installed():
|
|
124
124
|
message = f"MongoDB is installed in: {mongo_is_installed}\n" \
|
|
125
125
|
f"The service is not running. Fix the service or use the 'force' parameter to reinstall."
|
|
126
126
|
print_api(message, color='yellow')
|
|
@@ -151,11 +151,11 @@ def download_install_latest_main(
|
|
|
151
151
|
|
|
152
152
|
# Check if MongoDB is installed.
|
|
153
153
|
message: str = ''
|
|
154
|
-
mongo_is_installed =
|
|
154
|
+
mongo_is_installed = mongo_infra.is_installed()
|
|
155
155
|
if not mongo_is_installed:
|
|
156
156
|
message += "MongoDB Executable not found.\n"
|
|
157
157
|
|
|
158
|
-
if not
|
|
158
|
+
if not mongo_infra.is_service_running():
|
|
159
159
|
message += "MongoDB service is not running.\n"
|
|
160
160
|
|
|
161
161
|
if message:
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
import os
|
|
1
2
|
from typing import Union
|
|
2
3
|
|
|
3
4
|
from pymongo import MongoClient
|
|
4
5
|
import pymongo.errors
|
|
5
6
|
|
|
6
|
-
from ... import
|
|
7
|
+
from ... import filesystem
|
|
8
|
+
|
|
9
|
+
if os.name == 'nt':
|
|
10
|
+
from ... import get_process_list
|
|
7
11
|
|
|
8
12
|
|
|
9
13
|
WHERE_TO_SEARCH_FOR_MONGODB_EXE: str = 'C:\\Program Files\\MongoDB\\Server\\'
|
|
@@ -34,12 +38,16 @@ def is_service_running() -> bool:
|
|
|
34
38
|
Check if the MongoDB service is running.
|
|
35
39
|
:return: bool, True if the MongoDB service is running, False otherwise.
|
|
36
40
|
"""
|
|
37
|
-
current_processes: dict = (
|
|
38
|
-
get_process_list.GetProcessList(get_method='pywin32', connect_on_init=True).get_processes())
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
if os.name == 'nt':
|
|
43
|
+
current_processes: dict = (
|
|
44
|
+
get_process_list.GetProcessList(get_method='pywin32', connect_on_init=True).get_processes())
|
|
45
|
+
|
|
46
|
+
for pid, process_info in current_processes.items():
|
|
47
|
+
if MONGODB_EXE_NAME in process_info['name']:
|
|
48
|
+
return True
|
|
49
|
+
else:
|
|
50
|
+
raise NotImplementedError("This function is not implemented for this OS.")
|
|
43
51
|
|
|
44
52
|
return False
|
|
45
53
|
|