zscams 2.0.7__py3-none-any.whl → 2.0.9__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.
zscams/__main__.py CHANGED
@@ -6,6 +6,7 @@ import asyncio
6
6
  import sys
7
7
  import os
8
8
  from zscams.agent.src.core.backend.bootstrap import bootstrap
9
+ from zscams.agent.src.core.backend.unbootstrap import unbootstrap
9
10
  from zscams.agent.src.core.backend.update_machine_info import update_machine_info
10
11
  from zscams.agent.src.support.logger import get_logger
11
12
  from zscams.agent import init_parser, ensure_bootstrapped, run
@@ -32,6 +33,17 @@ def main():
32
33
  update_machine_info()
33
34
  sys.exit(0)
34
35
 
36
+ if args.unbootstrap:
37
+ try:
38
+ if os.geteuid() != 0:
39
+ logger.error("You are NOT running as root.")
40
+ sys.exit(1)
41
+ unbootstrap()
42
+ sys.exit(0)
43
+ except Exception as exception:
44
+ logger.error(exception)
45
+ sys.exit(1)
46
+
35
47
  try:
36
48
  ensure_bootstrapped()
37
49
  asyncio.run(run())
zscams/agent/__init__.py CHANGED
@@ -22,10 +22,15 @@ def init_parser():
22
22
  action="store_true",
23
23
  help="Run bootstrap process and exit",
24
24
  )
25
+ parser.add_argument(
26
+ "--unbootstrap",
27
+ action="store_true",
28
+ help="Run unbootstrap process and exit",
29
+ )
25
30
  parser.add_argument(
26
31
  "--update-machine-info",
27
32
  action="store_true",
28
- help="Run bootstrap process and exit",
33
+ help="Reinitialize machine info",
29
34
  )
30
35
  return parser
31
36
 
@@ -4,7 +4,7 @@ import sysconfig
4
4
  import sys
5
5
  from typing import cast
6
6
  from zscams.agent.src.core.backend.client import backend_client
7
- from zscams.agent.src.support.configuration import reinitialize
7
+ from zscams.agent.src.support.configuration import reinitialize, CONFIG_PATH
8
8
  from zscams.agent.src.support.logger import get_logger
9
9
  from zscams.agent.src.support.os import create_system_user, install_service, is_freebsd
10
10
  from zscams.agent.src.support.ssh import add_to_authorized_keys
@@ -47,6 +47,8 @@ def bootstrap():
47
47
  f"{equipment_type.lower()}-{customer_name.lower()}-{connector_name.lower()}"
48
48
  )
49
49
  enforced_id = prompt("Enforced ID", "Enforced Agent ID")
50
+ if not os.path.exists(CONFIG_PATH):
51
+ os.remove(CONFIG_PATH)
50
52
  reinitialize(equipment_name=equipment_name, equipment_type=equipment_type)
51
53
  cm_info = backend_client.bootstrap(equipment_name, enforced_id or None)
52
54
 
@@ -0,0 +1,49 @@
1
+ import os
2
+ from zscams.agent.src.support.filesystem import resolve_path
3
+ from zscams.agent.src.support.configuration import get_config, CONFIG_PATH, ROOT_PATH
4
+ from zscams.agent.src.core.backend.client import BackendClient
5
+ from zscams.agent.src.support.logger import get_logger
6
+ from zscams.agent.src.support.os import remove_service, is_freebsd
7
+
8
+ logger = get_logger("Unbootstrap")
9
+
10
+
11
+ def unbootstrap():
12
+ remote_configs = get_config().get("remote", {})
13
+ backend_config = get_config().get("backend", {})
14
+ private_key_path = resolve_path(
15
+ remote_configs.get("client_key"), os.path.dirname(CONFIG_PATH)
16
+ )
17
+
18
+ cert_path = resolve_path(
19
+ remote_configs.get("client_key"), os.path.dirname(CONFIG_PATH)
20
+ )
21
+
22
+ ca_chain_path = resolve_path(
23
+ remote_configs.get("client_key"), os.path.dirname(CONFIG_PATH)
24
+ )
25
+
26
+ cache_path = os.path.join(
27
+ ROOT_PATH.parent,
28
+ backend_config.get("cache_dir"),
29
+ BackendClient.MACHINE_INFO_FILE_NAME,
30
+ )
31
+
32
+ if os.path.exists(private_key_path):
33
+ os.remove(private_key_path)
34
+ logger.debug("Removed private key")
35
+
36
+ if os.path.exists(cert_path):
37
+ os.remove(cert_path)
38
+ logger.debug("Removed certificate")
39
+
40
+ if os.path.exists(ca_chain_path):
41
+ os.remove(ca_chain_path)
42
+ logger.debug("Removed CA Chain")
43
+
44
+ if os.path.exists(cache_path):
45
+ os.remove(cache_path)
46
+ logger.debug("Removed Machine info")
47
+
48
+ remove_service("zscams" if is_freebsd() else "zscams.service")
49
+ logger.debug("Removed ZSCAMs service")
@@ -43,7 +43,7 @@ async def run():
43
43
 
44
44
  # Add additional SSH options
45
45
  ssh_cmd += SSH_OPTIONS
46
-
46
+ os.chmod(PRIVATE_KEY, 0o700)
47
47
  logger.info(f"Starting reverse SSH tunnel: {' '.join(ssh_cmd)}")
48
48
 
49
49
  while True:
@@ -45,7 +45,7 @@ async def run():
45
45
 
46
46
  # Add additional SSH options
47
47
  ssh_cmd += SSH_OPTIONS
48
-
48
+ os.chmod(PRIVATE_KEY, 0o700)
49
49
  logger.info(f"Starting reverse SSH tunnel: {' '.join(ssh_cmd)}")
50
50
 
51
51
  while True:
@@ -10,6 +10,7 @@ import socket
10
10
  import platform
11
11
  from zscams.agent.src.support.logger import get_logger
12
12
  from http.client import BadStatusLine, HTTPConnection, HTTPException
13
+
13
14
  logger = get_logger("system_monitor")
14
15
 
15
16
  # Load service-specific params from environment
@@ -30,8 +31,6 @@ SERVICE_NAME = params.get("service_name", "Zscaler-AppConnector")
30
31
  HOSTNAME = platform.node()
31
32
 
32
33
 
33
-
34
-
35
34
  def network():
36
35
  """
37
36
  Collect network interfaces and their statistics.
@@ -232,7 +231,6 @@ def log():
232
231
  }
233
232
 
234
233
 
235
-
236
234
  # -----------------------------
237
235
  # Helper function to log JSON
238
236
  # -----------------------------
@@ -249,13 +247,14 @@ async def send_json_log(payload: dict):
249
247
 
250
248
 
251
249
  async def schedule_task(interval):
252
- while (True):
250
+ while True:
253
251
  try:
254
252
  await send_json_log(log())
255
253
  except Exception as exception:
256
254
  print(exception)
257
255
  await asyncio.sleep(interval)
258
256
 
257
+
259
258
  if __name__ == "__main__":
260
259
  try:
261
260
  asyncio.run(schedule_task(30))
@@ -48,7 +48,7 @@ def is_file_exists(path, logger, base_dir=None):
48
48
  return False
49
49
 
50
50
 
51
- def append_to_file(path: str | Path, content: str):
51
+ def append_to_file(path, content: str):
52
52
  try:
53
53
  if isinstance(path, str):
54
54
  path = Path(path)
@@ -63,6 +63,6 @@ def append_to_file(path: str | Path, content: str):
63
63
  raise exception
64
64
 
65
65
 
66
- def write_to_file(path: str | Path, content: str):
66
+ def write_to_file(path: str, content: str):
67
67
  with open(path, "w", encoding="utf-8") as f:
68
68
  f.write(content)
@@ -1,3 +1,4 @@
1
+ import os
1
2
  import sys
2
3
  import subprocess
3
4
  import platform
@@ -136,3 +137,53 @@ def install_systemd_service(service_name: str, content: str):
136
137
  service_name,
137
138
  service_name,
138
139
  )
140
+
141
+
142
+ def remove_service(service_name: str):
143
+ """
144
+ Stops, disables, and removes service configurations for Linux and FreeBSD.
145
+ """
146
+ # Standardize name (remove .service suffix if present for consistency)
147
+ clean_name = service_name.replace(".service", "")
148
+
149
+ if is_linux():
150
+ _remove_systemd_service(clean_name)
151
+ elif is_freebsd():
152
+ _remove_rc_service(clean_name)
153
+ else:
154
+ logger.error("Unsupported OS for service removal.")
155
+
156
+
157
+ def _remove_systemd_service(name: str):
158
+ service_file = f"/etc/systemd/system/{name}.service"
159
+ try:
160
+ logger.info("Stopping and disabling systemd service: %s", name)
161
+ subprocess.run(["sudo", "systemctl", "stop", name], check=False)
162
+ subprocess.run(["sudo", "systemctl", "disable", name], check=False)
163
+
164
+ if os.path.exists(service_file):
165
+ subprocess.run(["sudo", "rm", service_file], check=True)
166
+ subprocess.run(["sudo", "systemctl", "daemon-reload"], check=True)
167
+ logger.info("Systemd service %s removed.", name)
168
+ except subprocess.CalledProcessError as e:
169
+ logger.error("Failed to remove systemd service: %s", e)
170
+
171
+
172
+ def _remove_rc_service(name: str):
173
+ rc_file = f"/usr/local/etc/rc.d/{name}"
174
+ try:
175
+ logger.info("Stopping and disabling FreeBSD service: %s", name)
176
+ # 1. Stop the service
177
+ subprocess.run(["sudo", "service", name, "stop"], check=False)
178
+
179
+ # 2. Disable in /etc/rc.conf
180
+ # Using sysrc -x removes the variable entirely from rc.conf
181
+ subprocess.run(["sudo", "sysrc", "-x", f"{name}_enable"], check=False)
182
+
183
+ # 3. Remove the rc.d script
184
+ if os.path.exists(rc_file):
185
+ subprocess.run(["sudo", "rm", rc_file], check=True)
186
+ logger.info("FreeBSD rc script %s removed.", name)
187
+
188
+ except subprocess.CalledProcessError as e:
189
+ logger.error("Failed to remove FreeBSD service: %s", e)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: zscams
3
- Version: 2.0.7
3
+ Version: 2.0.9
4
4
  Summary: Async TLS tunnel client with SNI routing, auto-reconnect, and health checks
5
5
  Author: OCD - Cairo Software Team
6
6
  Maintainer: OCD - Cairo Software Team
@@ -1,6 +1,6 @@
1
1
  zscams/__init__.py,sha256=xAeDJU2cSBrdspt5aVRTYIzAbGSGvn-CtGV4qc7moQ0,59
2
- zscams/__main__.py,sha256=J3ArryUM5B-nVwMMNPmDGRHctehDF9ZaGGHfLHiP1jI,1055
3
- zscams/agent/__init__.py,sha256=CKNRkV_frJyFrnFU0Nrf6xp4Ja4a_w7j7qrja_h8VUU,2976
2
+ zscams/__main__.py,sha256=-vjCPBc7n_M3Gq7GRu5TWhdxJrPcU_NV1sZEXvUZU58,1432
3
+ zscams/agent/__init__.py,sha256=zGhrb1drq8BP9uvuXeq-L8HhtfWW7s-_1VjVJ-jaykY,3105
4
4
  zscams/agent/certificates/.gitkeep,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  zscams/agent/config.yaml,sha256=0DuIENHlSoo6nRg4Xa0ZljHGgDGQiWSEX8b_uRMtpS0,2542
6
6
  zscams/agent/configuration/config.j2,sha256=95lUo1oo_EExGCHIhlBnaeK0cwmr9gUXfh7TYP9WYdg,2633
@@ -9,9 +9,10 @@ zscams/agent/configuration/linux_service.j2,sha256=UOrGrXvBK2mFit_b3QxUAKgZhG-dm
9
9
  zscams/agent/keys/autoport.key,sha256=hZBmtw_nLsZwe11LYlwLL-P_blQ_qpUDpFwvqOZDZFE,1679
10
10
  zscams/agent/src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  zscams/agent/src/core/__init__.py,sha256=CEDwvbxojtNZOfOOFBj-URg4Q0KB0cq9AqIiD0uzPic,24
12
- zscams/agent/src/core/backend/bootstrap.py,sha256=Dvh6Hesy9M-5zX4iQxvSSlX6HD2Ty4vU5EG_nyHWQks,2463
12
+ zscams/agent/src/core/backend/bootstrap.py,sha256=iv06Qoi9TWTA9GjD3L5I-QR6Ydu_f0wArfjoK8nTTjk,2547
13
13
  zscams/agent/src/core/backend/client.py,sha256=xZw2GuOVw6Ek-QI9OaUO4rqzIrs4xGwiPizBLCH89fo,10123
14
14
  zscams/agent/src/core/backend/exceptions.py,sha256=osMbVb_ZGvrGbw5cOCMG1s4yBLukJl7T8TITCcVPyXA,383
15
+ zscams/agent/src/core/backend/unbootstrap.py,sha256=ULY78KGuv-Pcz69L6PyhU_4_xRaMZCrrln1TdejjzBE,1554
15
16
  zscams/agent/src/core/backend/update_machine_info.py,sha256=9chBdvsLeLVf5DsvSHiUO9xQpXSbDgqhdnrUwxyoKUM,474
16
17
  zscams/agent/src/core/prerequisites.py,sha256=5OlXBEg8FaYp6LXjJHtbdcpRaMywR-DBDyvDr_OiVdA,1286
17
18
  zscams/agent/src/core/service_health_check.py,sha256=9VUWQitXcDEwLcHTTeequi6om98OXN-JIIMZCCH5y4A,1733
@@ -20,23 +21,23 @@ zscams/agent/src/core/tunnel/__init__.py,sha256=BvJmqtjliO-UvmEguOwky8KSGLY_w8xq
20
21
  zscams/agent/src/core/tunnel/tls.py,sha256=EIRR7aLq6BkW6jUVseM1YCqm7E_UDVSQ9CffQri2U6U,2006
21
22
  zscams/agent/src/core/tunnels.py,sha256=FwYi9cV3V7c_su5cEgXmyNdr8VyfCBKzU5olvi2MzBw,1736
22
23
  zscams/agent/src/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
- zscams/agent/src/services/reverse_ssh.py,sha256=4NeS8TIq48VoUpq6CFcUrEl97qkd2L1yWAs7qlyvSzE,2272
24
- zscams/agent/src/services/ssh_forwarder.py,sha256=O6V89DRpohkk_Gwg_FrHD4sv9hTS45VpBUcuXv7CRO4,2414
25
- zscams/agent/src/services/system_monitor.py,sha256=7VeSYHbr1Lv8tGVg0AMMd5_o7EgMGuRDlxJjxpGM27g,7529
24
+ zscams/agent/src/services/reverse_ssh.py,sha256=LUbl7FwKltN2irQ-lAsECm-JMr0PRlgb0hcQu_q95Dw,2304
25
+ zscams/agent/src/services/ssh_forwarder.py,sha256=vl3afyWxvYu114o5PTQpg3aok9oaLdVfIwydVxE5bUo,2446
26
+ zscams/agent/src/services/system_monitor.py,sha256=caGexjOD0eH7GVDdQQIBdTlMpYema_YIUEo3F-fG1vM,7526
26
27
  zscams/agent/src/support/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
28
  zscams/agent/src/support/cli.py,sha256=6Y0zokhwhWcsmjEosGqq_kMqF3tn4juPpsBmQax1Oyc,1221
28
29
  zscams/agent/src/support/configuration.py,sha256=hnJhvJLdL5ElZITDFLybTOHVACBHttWgy8sXhmu75Wc,2025
29
- zscams/agent/src/support/filesystem.py,sha256=QoqyvIWm0jgIGx51ikopU_mvupBWke_e5KaW-wnTI4A,1738
30
+ zscams/agent/src/support/filesystem.py,sha256=e2p2xWxitLkTclyVgmDC-2DGROBwowves7dlm0S47Hw,1719
30
31
  zscams/agent/src/support/logger.py,sha256=rKjAVO6vDeXYTM9__q2lcc1PBiJoZUqLzry8yMf71vY,2347
31
32
  zscams/agent/src/support/mac.py,sha256=XVKc5YAYLu4a-5VrMhcwgkMNnP2u6itK3cx-Oxnx4IA,453
32
33
  zscams/agent/src/support/network.py,sha256=VwVVNqykZxvrTPwPYQ3sSVMc_Z2XUwASlo_kd_wdGDs,1453
33
34
  zscams/agent/src/support/openssl.py,sha256=jLSv8ajIw1YfNdBhz4KSvNp-cARLXY9-7qdzne9Zca4,3429
34
- zscams/agent/src/support/os.py,sha256=g2TYgRLvb1snl236m-TKNqFe6jLTFyIT3YOH9cCKY8Y,4769
35
+ zscams/agent/src/support/os.py,sha256=QxAfj8nhC6EIpN14snIsjF5c2i8tWhtCS4DzWIZBSJc,6691
35
36
  zscams/agent/src/support/ssh.py,sha256=J9-XsVc6fGdcTN9CsfmgDRaMnfaWluDUaPGug7BVl6Q,812
36
37
  zscams/agent/src/support/yaml.py,sha256=bKsQzXHAgjCxkGzPR8bgaUPB-QHMR3AMEVuvn4RRpnA,1188
37
38
  zscams/deps.py,sha256=D2WEI7dLoMnPl_OL7NOSXe-k25p1FFeeGsY1Mh7IIEw,3630
38
39
  zscams/lib/.gitkeep,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
- zscams-2.0.7.dist-info/METADATA,sha256=MKMIfFRXQNLJMR-Fzhpn_ezncJJ_gcNyXqARWSFlL4A,6805
40
- zscams-2.0.7.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
41
- zscams-2.0.7.dist-info/entry_points.txt,sha256=IXiMYjEq4q0tUiD9O7eCWhqKBuOssXrMW42siTBAgG8,47
42
- zscams-2.0.7.dist-info/RECORD,,
40
+ zscams-2.0.9.dist-info/METADATA,sha256=axiCExXQy5gZer0CXWD2vfWcICtuxmSG-qQ2nwVVrJU,6805
41
+ zscams-2.0.9.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
42
+ zscams-2.0.9.dist-info/entry_points.txt,sha256=IXiMYjEq4q0tUiD9O7eCWhqKBuOssXrMW42siTBAgG8,47
43
+ zscams-2.0.9.dist-info/RECORD,,
File without changes