zscams 2.0.1__py2.py3-none-any.whl → 2.0.3__py2.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.
@@ -0,0 +1,50 @@
1
+ from typing import Optional, cast
2
+ from zscams.agent.src.support.logger import get_logger
3
+
4
+ logger = get_logger("bootstrap")
5
+
6
+
7
+ class RequiredFieldException(Exception):
8
+ pass
9
+
10
+
11
+ class InvalidFieldException(Exception):
12
+ pass
13
+
14
+
15
+ def prompt(
16
+ name: str,
17
+ message: str,
18
+ required=False,
19
+ startswith: Optional[str] = None,
20
+ fail_on_error=False,
21
+ retries_count=3,
22
+ ):
23
+ _message = message
24
+ if not required:
25
+ _message += " (Optional)"
26
+
27
+ _message += ": "
28
+
29
+ val = input(_message)
30
+
31
+ if required and not val:
32
+ if fail_on_error:
33
+ raise RequiredFieldException(f"Missing {name}")
34
+ logger.error(f"{name} is required..")
35
+ retries_count -= 1
36
+ return prompt(
37
+ name, message, required, startswith, fail_on_error=retries_count <= 0
38
+ )
39
+
40
+ if startswith is not None and not val.startswith(startswith):
41
+ error_mesagge = f"The value has to start with {startswith}"
42
+ if fail_on_error:
43
+ raise InvalidFieldException(error_mesagge)
44
+ logger.error(error_mesagge)
45
+ retries_count -= 1
46
+ return prompt(
47
+ name, message, required, startswith, fail_on_error=retries_count <= 0
48
+ )
49
+
50
+ return val
@@ -5,8 +5,9 @@ Configuration loader module
5
5
  import os
6
6
  from pathlib import Path
7
7
  from typing import TypedDict
8
-
8
+ import json
9
9
  import yaml
10
+ from zscams.agent.src.support.yaml import YamlIndentedListsDumper, resolve_placeholders
10
11
 
11
12
 
12
13
  config = {}
@@ -26,6 +27,20 @@ class RemoteConfig(TypedDict):
26
27
  ca_cert: str
27
28
  ca_chain: str
28
29
 
30
+ def reinitialize(**kwargs):
31
+ import zscams
32
+ BASE_DIR = Path(zscams.__file__).resolve().parent
33
+ template_path = f"{BASE_DIR}/agent/configuration/config.j2"
34
+ with open(template_path) as f:
35
+ template = yaml.safe_load(f)
36
+ resolve_placeholders(template, kwargs)
37
+ override_config(template)
38
+
39
+ def save_config(data):
40
+ """Save the YAML config back to disk."""
41
+ with open(CONFIG_PATH, "w", encoding="utf-8") as f:
42
+ yaml.safe_dump(data, f, default_flow_style=False)
43
+
29
44
 
30
45
  def load_config():
31
46
  """
@@ -34,7 +49,7 @@ def load_config():
34
49
  Returns:
35
50
  dict: Configuration dictionary containing remote settings and forwards.
36
51
  """
37
- with open(CONFIG_PATH, "r") as f:
52
+ with open(CONFIG_PATH, "r", encoding="utf-8") as f:
38
53
  config = yaml.safe_load(f)
39
54
  return config
40
55
 
@@ -51,3 +66,21 @@ def get_config():
51
66
  return load_config()
52
67
 
53
68
  return config
69
+
70
+
71
+ def override_config(new_config: dict):
72
+ """
73
+ Override the existing configuration with a new one.
74
+ Args:
75
+ new_config (dict): New configuration dictionary to override the existing one.
76
+ """
77
+ config = new_config
78
+
79
+ with open(CONFIG_PATH, "w", encoding="utf-8") as file:
80
+ yaml.dump(
81
+ config,
82
+ file,
83
+ Dumper=YamlIndentedListsDumper,
84
+ default_flow_style=False,
85
+ explicit_start=True,
86
+ )
@@ -3,8 +3,11 @@ Path utilities for TLS Tunnel Client
3
3
  """
4
4
 
5
5
  import os
6
+ from pathlib import Path
6
7
  from typing import Optional
8
+ from zscams.agent.src.support.logger import get_logger
7
9
 
10
+ logger = get_logger("FileSystem")
8
11
 
9
12
  def resolve_path(path: Optional[str], base_dir: Optional[str] = None) -> Optional[str]:
10
13
  """
@@ -39,3 +42,22 @@ def is_file_exists(path, logger):
39
42
 
40
43
  logger.error(f"File not found: {path}")
41
44
  return False
45
+
46
+
47
+ def append_to_file(path: str | Path, content: str):
48
+ try:
49
+ if isinstance(path, str):
50
+ path = Path(path)
51
+
52
+ if not path.parent.exists():
53
+ os.mkdir(path.parent,0o700)
54
+
55
+ with open(path, "a", encoding="utf-8") as file:
56
+ file.write(content)
57
+ except Exception as exception:
58
+ logger.error(exception)
59
+ raise exception
60
+
61
+ def write_to_file(path: str | Path, content: str):
62
+ with open(path, "w", encoding="utf-8") as f:
63
+ f.write(content)
@@ -2,39 +2,87 @@
2
2
  Logger module for TLS Tunnel Client
3
3
  """
4
4
 
5
- import logging
5
+ """Singleton logger handlers for local logging only"""
6
6
  import sys
7
+ import logging
8
+ import os
9
+ import platform
10
+ from typing import Dict
11
+ from logging import Logger
7
12
 
8
13
  from zscams.agent.src.support.configuration import get_config
9
14
 
15
+ loggers: Dict[str, Logger] = {}
10
16
 
11
- loggers: dict[str, logging.Logger] = {}
17
+ # -------------------- COLOR FORMATTER --------------------
12
18
 
13
19
 
14
- def get_logger(name: str = "tls_tunnel") -> logging.Logger:
15
- """Create a singleton instance for that logger name"""
20
+ class ColorFormatter(logging.Formatter):
21
+ """Formatter adding ANSI colors to console logs only."""
16
22
 
17
- if name in loggers:
18
- return loggers[name]
23
+ COLORS = {
24
+ "DEBUG": "\033[93m", # Yellow
25
+ "INFO": "\033[92m", # Green
26
+ "WARNING": "\033[95m", # Magenta
27
+ "ERROR": "\033[91m", # Red
28
+ "CRITICAL": "\033[41m", # Red background
29
+ }
30
+
31
+ RESET = "\033[0m"
32
+
33
+ def format(self, record):
34
+ color = self.COLORS.get(record.levelname, self.RESET)
35
+ msg = super().format(record)
36
+ return f"{color}{msg}{self.RESET}"
37
+
38
+
39
+ # -------------------- SYSTEM LOG PATH --------------------
40
+
41
+
42
+ def get_default_system_log_path():
43
+ """Returns the system default logging path"""
44
+ system = platform.system()
19
45
 
20
- logger = logging.getLogger(name)
46
+ if system == "Windows":
47
+ return os.path.join(
48
+ os.environ.get("WINDIR", "C:\\Windows"), "System32", "winevt", "Logs"
49
+ )
21
50
 
22
- level = get_config().get("logging", {}).get("level", 10)
51
+ elif system == "Linux":
52
+ return "/var/log"
23
53
 
24
- logger.setLevel(level)
25
- logger.propagate = False
54
+ else:
55
+ return None # unsupported
26
56
 
57
+
58
+ # -------------------- LOGGER FACTORY --------------------
59
+
60
+
61
+ def get_logger(name: str) -> Logger:
62
+ """Create a singleton instance for that logger name"""
63
+ if name in loggers:
64
+ return loggers[name]
65
+
66
+ logger = logging.getLogger(
67
+ f"ZSCAMs - {name}" if name.lower().find("zscams") == -1 else name
68
+ )
69
+ logger.setLevel(get_config().get("logging", {}).get("level", 10))
70
+ logger.propagate = False # Prevent duplicate logs
71
+
72
+ # Cleanup handlers if any
27
73
  if logger.hasHandlers():
28
74
  logger.handlers.clear()
29
75
 
76
+ # -------- Console Handler -------- #
30
77
  console_handler = logging.StreamHandler(sys.stdout)
31
- console_handler.setLevel(level)
78
+ console_handler.setLevel(get_config().get("logging", {}).get("level", 10))
32
79
 
33
- console_formatter = logging.Formatter(
34
- "%(asctime)s [%(levelname)s] %(name)s: %(message)s", "%Y-%m-%d %H:%M:%S"
80
+ console_formatter = ColorFormatter(
81
+ fmt="[%(asctime)s] [%(levelname)s] [%(name)s] %(message)s",
82
+ datefmt="%Y-%m-%d %H:%M:%S",
35
83
  )
36
84
  console_handler.setFormatter(console_formatter)
37
85
  logger.addHandler(console_handler)
38
-
86
+ # Cache singleton
39
87
  loggers[name] = logger
40
88
  return logger
@@ -1,6 +1,6 @@
1
1
  """Module to retrieve the MAC address of the primary network interface."""
2
2
 
3
- from zscams.libs.getmac import get_mac_address as gma
3
+ from zscams.lib.getmac import get_mac_address as gma
4
4
 
5
5
 
6
6
  class MacAddressError(Exception):
@@ -2,6 +2,8 @@
2
2
  This module provides a simple interface for generating RSA key pairs
3
3
  """
4
4
 
5
+ import os
6
+
5
7
  from cryptography import x509
6
8
  from cryptography.hazmat.primitives.asymmetric import rsa
7
9
  from cryptography.x509.oid import NameOID
@@ -26,6 +28,8 @@ def generate_private_key(key_path: str):
26
28
  with open(key_path, "wb") as f:
27
29
  f.write(pem_private_key)
28
30
 
31
+ os.chmod(key_path, 0o700)
32
+
29
33
  return pem_private_key
30
34
 
31
35
 
@@ -51,50 +55,60 @@ def generate_csr_from_private_key(
51
55
  )
52
56
 
53
57
  csr_builder = x509.CertificateSigningRequestBuilder()
54
- csr_builder = csr_builder.subject_name(
55
- x509.Name(
56
- [
57
- x509.NameAttribute(NameOID.COUNTRY_NAME, country),
58
- x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, state),
59
- x509.NameAttribute(NameOID.LOCALITY_NAME, locality),
60
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, organization),
61
- x509.NameAttribute(NameOID.COMMON_NAME, common_name),
62
- ]
63
- )).add_extension(
64
- x509.BasicConstraints(ca=False, path_length=None),
65
- critical=False,).add_extension(
66
- x509.UnrecognizedExtension(
67
- x509.ObjectIdentifier("2.16.840.1.113730.1.1"),
68
- b"SSL Client, S/MIME",
69
- ),
70
- critical=False,).add_extension(
71
- x509.UnrecognizedExtension(
72
- x509.ObjectIdentifier("2.16.840.1.113730.1.13"),
73
- b"Generated by OBS/OCD",
74
- ),
75
- critical=False,
76
- ).add_extension(
77
- x509.KeyUsage(
78
- digital_signature=True,
79
- crl_sign=False,
80
- key_encipherment=True,
81
- content_commitment=True,
82
- data_encipherment=False,
83
- key_agreement=False,
84
- key_cert_sign=False,
85
- encipher_only=False,
86
- decipher_only=False,
87
- ),
88
- critical=True,
89
- ).add_extension(
90
- x509.ExtendedKeyUsage(
91
- [
92
- x509.ExtendedKeyUsageOID.CLIENT_AUTH,
93
- x509.ExtendedKeyUsageOID.EMAIL_PROTECTION,
94
- ]
95
- ),
96
- critical=False,
58
+ csr_builder = (
59
+ csr_builder.subject_name(
60
+ x509.Name(
61
+ [
62
+ x509.NameAttribute(NameOID.COUNTRY_NAME, country),
63
+ x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, state),
64
+ x509.NameAttribute(NameOID.LOCALITY_NAME, locality),
65
+ x509.NameAttribute(NameOID.ORGANIZATION_NAME, organization),
66
+ x509.NameAttribute(NameOID.COMMON_NAME, common_name),
67
+ ]
97
68
  )
69
+ )
70
+ .add_extension(
71
+ x509.BasicConstraints(ca=False, path_length=None),
72
+ critical=False,
73
+ )
74
+ .add_extension(
75
+ x509.UnrecognizedExtension(
76
+ x509.ObjectIdentifier("2.16.840.1.113730.1.1"),
77
+ b"SSL Client, S/MIME",
78
+ ),
79
+ critical=False,
80
+ )
81
+ .add_extension(
82
+ x509.UnrecognizedExtension(
83
+ x509.ObjectIdentifier("2.16.840.1.113730.1.13"),
84
+ b"Generated by OBS/OCD",
85
+ ),
86
+ critical=False,
87
+ )
88
+ .add_extension(
89
+ x509.KeyUsage(
90
+ digital_signature=True,
91
+ crl_sign=False,
92
+ key_encipherment=True,
93
+ content_commitment=True,
94
+ data_encipherment=False,
95
+ key_agreement=False,
96
+ key_cert_sign=False,
97
+ encipher_only=False,
98
+ decipher_only=False,
99
+ ),
100
+ critical=True,
101
+ )
102
+ .add_extension(
103
+ x509.ExtendedKeyUsage(
104
+ [
105
+ x509.ExtendedKeyUsageOID.CLIENT_AUTH,
106
+ x509.ExtendedKeyUsageOID.EMAIL_PROTECTION,
107
+ ]
108
+ ),
109
+ critical=False,
110
+ )
111
+ )
98
112
 
99
113
  csr = csr_builder.sign(private_key, hashes.SHA256())
100
114
  return csr.public_bytes(serialization.Encoding.PEM).decode("utf-8")
@@ -0,0 +1,85 @@
1
+ import sys
2
+ import subprocess
3
+
4
+ from zscams.agent.src.support.logger import get_logger
5
+
6
+ from .filesystem import write_to_file
7
+
8
+ logger = get_logger("os_support")
9
+
10
+
11
+ def is_linux():
12
+ if sys.platform.startswith("linux"):
13
+ return True
14
+ return False
15
+
16
+
17
+ def system_user_exists(username: str):
18
+ try:
19
+ subprocess.run(
20
+ ["id", username],
21
+ check=True,
22
+ stdout=subprocess.DEVNULL,
23
+ stderr=subprocess.DEVNULL,
24
+ )
25
+ logger.debug("found the system user %s", username)
26
+ return True
27
+ except subprocess.CalledProcessError:
28
+ return False
29
+
30
+
31
+ def create_system_user(username: str):
32
+ if not is_linux():
33
+ logger.error(
34
+ "Error creating system user: This script is intended to run on Linux systems."
35
+ )
36
+ return
37
+
38
+ if not username:
39
+ logger.error("Error creating system user: Username must be provided.")
40
+ return
41
+
42
+ if system_user_exists(username):
43
+ logger.warning("User '%s' already exists.", username)
44
+ return
45
+
46
+ try:
47
+ subprocess.run(["sudo", "useradd","-m", "-s", "/bin/bash", username], check=True)
48
+ logger.info("System user '%s' created successfully.", username)
49
+ except subprocess.CalledProcessError as e:
50
+ logger.error("Failed to create user '%s': %s", username, e)
51
+
52
+
53
+ def install_systemd_service(service_name: str, content: str):
54
+ if not is_linux():
55
+ logger.error(
56
+ "Error installing systemd service: This script is intended to run on Linux systems."
57
+ )
58
+ return
59
+
60
+ service_path = f"/etc/systemd/system/{service_name}"
61
+
62
+ try:
63
+ logger.debug("Installing service '%s' content", service_name)
64
+ write_to_file(service_path, content)
65
+ logger.debug(f"Installed {service_name}")
66
+ except PermissionError:
67
+ logger.warning("Permission denied: trying to write with sudo...")
68
+ echo_cmd = f"echo '{content}' | sudo tee {service_path}"
69
+ subprocess.run(echo_cmd, shell=True, check=True, stdout=subprocess.DEVNULL)
70
+ logger.debug("Wrote the service")
71
+ except Exception as e:
72
+ logger.error("Failed to install service %s. %s", service_name, e)
73
+ return
74
+
75
+ try:
76
+ logger.debug("Enabling %s...", service_name)
77
+ subprocess.run(["sudo", "systemctl", "enable", service_name], check=True)
78
+ logger.debug("Starting %s...", service_name)
79
+ subprocess.run(["sudo", "systemctl", "start", service_name], check=True)
80
+ except subprocess.CalledProcessError:
81
+ logger.error(
82
+ "Failed to enable/restart zscams service, You might need to do that manually by running\nsudo systemctl enable %s && sudo systemctl start %s",
83
+ service_name,
84
+ service_name,
85
+ )
@@ -0,0 +1,24 @@
1
+ from zscams.agent.src.support.configuration import get_config
2
+ from zscams.agent.src.support.filesystem import append_to_file
3
+ from zscams.agent.src.support.logger import get_logger
4
+
5
+
6
+ logger = get_logger("ssh_support")
7
+
8
+
9
+ def add_to_known_hosts(hostname: str, pub_key: str):
10
+ logger.debug("Appending '%s' to known hosts...", pub_key)
11
+ append_to_file(
12
+ get_config().get("ssh", {}).get("known_hosts_file_path"),
13
+ f"{hostname} {pub_key}\n",
14
+ )
15
+ logger.debug("Appended key to known hosts")
16
+
17
+
18
+ def add_to_authorized_keys(user, pub_key):
19
+ logger.debug(f"Appending to public key to {user}")
20
+ key = pub_key.split(' ')[1] if len(pub_key.split(' ')) >= 2 else pub_key
21
+ append_to_file(
22
+ f"/home/{user}/.ssh/authorized_keys",
23
+ f"ssh-rsa {key} zscams@orangecyberdefense\n",
24
+ )
@@ -0,0 +1,37 @@
1
+ import yaml
2
+
3
+
4
+ class YamlIndentedListsDumper(yaml.Dumper):
5
+ def increase_indent(self, flow=False, indentless=False):
6
+ return super(YamlIndentedListsDumper, self).increase_indent(flow, False)
7
+
8
+ def resolve_placeholders( obj, values: dict[str, int]):
9
+ """
10
+ Recursively replace '{key}' strings with values[key]
11
+ in dicts, lists, and strings.
12
+ """
13
+ if isinstance(obj, dict):
14
+ for k, v in obj.items():
15
+ obj[k] = resolve_placeholders(v, values)
16
+
17
+ elif isinstance(obj, list):
18
+ for i, v in enumerate(obj):
19
+ obj[i] = resolve_placeholders(v, values)
20
+
21
+ elif isinstance(obj, str):
22
+ for key, value in values.items():
23
+ placeholder = f"{{{key}}}"
24
+ if obj == placeholder:
25
+ return value
26
+ return obj
27
+
28
+ return obj
29
+ def assert_no_placeholders_left(obj):
30
+ if isinstance(obj, dict):
31
+ for v in obj.values():
32
+ assert_no_placeholders_left(v)
33
+ elif isinstance(obj, list):
34
+ for v in obj:
35
+ assert_no_placeholders_left(v)
36
+ elif isinstance(obj, str) and obj.startswith("{") and obj.endswith("}"):
37
+ raise ValueError(f"Unresolved placeholder: {obj}")
zscams/lib/.gitkeep ADDED
File without changes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: zscams
3
- Version: 2.0.1
3
+ Version: 2.0.3
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
@@ -20,6 +20,7 @@ Classifier: Programming Language :: Python :: 3.13
20
20
  Requires-Dist: PyYAML
21
21
  Requires-Dist: cryptography
22
22
  Requires-Dist: psutil
23
+ Requires-Dist: requests
23
24
  Description-Content-Type: text/markdown
24
25
 
25
26
  # Agent
@@ -0,0 +1,44 @@
1
+ zscams/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ zscams/__main__.py,sha256=J3ArryUM5B-nVwMMNPmDGRHctehDF9ZaGGHfLHiP1jI,1055
3
+ zscams/agent/__init__.py,sha256=CKNRkV_frJyFrnFU0Nrf6xp4Ja4a_w7j7qrja_h8VUU,2976
4
+ zscams/agent/certificates/.gitkeep,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ zscams/agent/config.yaml,sha256=S50bDUpyNg8gqM338TlYbX4d27mR2RrFajWINpkSliE,2555
6
+ zscams/agent/configuration/config.j2,sha256=DLkSd-opbPzFLvNipnPLx-OsUpISlZprPzabYjPF1-E,2659
7
+ zscams/agent/configuration/service.j2,sha256=B8t9eCmMbDOEu5kS3pIRdYb7Eh65Vacq0qSqoILgeC8,212
8
+ zscams/agent/keys/autoport.key,sha256=hZBmtw_nLsZwe11LYlwLL-P_blQ_qpUDpFwvqOZDZFE,1679
9
+ zscams/agent/src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ zscams/agent/src/core/__init__.py,sha256=CEDwvbxojtNZOfOOFBj-URg4Q0KB0cq9AqIiD0uzPic,24
11
+ zscams/agent/src/core/backend/bootstrap.py,sha256=rsfGbZuvpt299_oWrQQHbJeXz4swwzoS54pr0nwBpvo,2340
12
+ zscams/agent/src/core/backend/client.py,sha256=xZw2GuOVw6Ek-QI9OaUO4rqzIrs4xGwiPizBLCH89fo,10123
13
+ zscams/agent/src/core/backend/exceptions.py,sha256=osMbVb_ZGvrGbw5cOCMG1s4yBLukJl7T8TITCcVPyXA,383
14
+ zscams/agent/src/core/backend/update_machine_info.py,sha256=9chBdvsLeLVf5DsvSHiUO9xQpXSbDgqhdnrUwxyoKUM,474
15
+ zscams/agent/src/core/prerequisites.py,sha256=LNPjDj2AQhZ3xBiLDNurG2osBTjepcU6tzDIm5PT_GA,1159
16
+ zscams/agent/src/core/service_health_check.py,sha256=9VUWQitXcDEwLcHTTeequi6om98OXN-JIIMZCCH5y4A,1733
17
+ zscams/agent/src/core/services.py,sha256=GvAYODh1Pg_FatnZO_8iqReiIeBfq7Hfwj9zxlXYm-0,2840
18
+ zscams/agent/src/core/tunnel/__init__.py,sha256=BvJmqtjliO-UvmEguOwky8KSGLY_w8xqM67Q3v2_jc0,4658
19
+ zscams/agent/src/core/tunnel/tls.py,sha256=EIRR7aLq6BkW6jUVseM1YCqm7E_UDVSQ9CffQri2U6U,2006
20
+ zscams/agent/src/core/tunnels.py,sha256=FwYi9cV3V7c_su5cEgXmyNdr8VyfCBKzU5olvi2MzBw,1736
21
+ zscams/agent/src/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
+ zscams/agent/src/services/reverse_ssh.py,sha256=-q9RJwyUvzSDftP7NNSmfHJHbx-2vmYrMy9KEjUmlyU,2081
23
+ zscams/agent/src/services/ssh_forwarder.py,sha256=BZ7-9i2YxdxtVfaxu5JDkwhFyNKDruIkph10bT6Ms-g,2223
24
+ zscams/agent/src/services/system_monitor.py,sha256=7VeSYHbr1Lv8tGVg0AMMd5_o7EgMGuRDlxJjxpGM27g,7529
25
+ zscams/agent/src/support/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
+ zscams/agent/src/support/cli.py,sha256=6Y0zokhwhWcsmjEosGqq_kMqF3tn4juPpsBmQax1Oyc,1221
27
+ zscams/agent/src/support/configuration.py,sha256=hnJhvJLdL5ElZITDFLybTOHVACBHttWgy8sXhmu75Wc,2025
28
+ zscams/agent/src/support/filesystem.py,sha256=jSVsnBFFBx8dFT3LzuVkGkK9CF1PScLxbyC_0vPkrRg,1587
29
+ zscams/agent/src/support/logger.py,sha256=rKjAVO6vDeXYTM9__q2lcc1PBiJoZUqLzry8yMf71vY,2347
30
+ zscams/agent/src/support/mac.py,sha256=EVlcxlgfPybH6S2IcC93MRNj9Dqc6_d6J14r8pW0PF0,464
31
+ zscams/agent/src/support/network.py,sha256=VwVVNqykZxvrTPwPYQ3sSVMc_Z2XUwASlo_kd_wdGDs,1453
32
+ zscams/agent/src/support/openssl.py,sha256=jLSv8ajIw1YfNdBhz4KSvNp-cARLXY9-7qdzne9Zca4,3429
33
+ zscams/agent/src/support/os.py,sha256=j7BtZ3D1pEEezZBw9eT8lWUBojMhIuovFbvNV0nLsdg,2766
34
+ zscams/agent/src/support/ssh.py,sha256=J9-XsVc6fGdcTN9CsfmgDRaMnfaWluDUaPGug7BVl6Q,812
35
+ zscams/agent/src/support/yaml.py,sha256=bKsQzXHAgjCxkGzPR8bgaUPB-QHMR3AMEVuvn4RRpnA,1188
36
+ zscams/lib/.gitkeep,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
+ zscams/lib/getmac/__init__.py,sha256=iunkDFEtpGaRw1Y0lzr9OZ7LsZ-GH81E836ZJQC25Vg,80
38
+ zscams/lib/getmac/__main__.py,sha256=PTkcTMZSbvJ-qwMyVuo-Bf-RKI47y7Kwxqroo92EVS4,3547
39
+ zscams/lib/getmac/getmac.py,sha256=bFYx0WNBojEtNbIWKfNMm4mWI1Q2YLOx67Qluhs-fWU,64504
40
+ zscams/lib/getmac/shutilwhich.py,sha256=cTd3vGTZqKB44FOQhk7UG5M-Vb3qKg9HmuIy6hxkus0,2627
41
+ zscams-2.0.3.dist-info/METADATA,sha256=ULtW-vGMYs52TLIm3oCyxGOTtO1I5dxmIWeCnKwgqtI,7180
42
+ zscams-2.0.3.dist-info/WHEEL,sha256=iAMR_6Qh95yyjYIwRxyjpiFq4FhDPemrEV-SyWIQB3U,92
43
+ zscams-2.0.3.dist-info/entry_points.txt,sha256=IXiMYjEq4q0tUiD9O7eCWhqKBuOssXrMW42siTBAgG8,47
44
+ zscams-2.0.3.dist-info/RECORD,,
@@ -1,21 +0,0 @@
1
- from zscams.agent.src.core.api.backend.client import backend_client
2
- from zscams.agent.src.support.logger import get_logger
3
-
4
- logger = get_logger("agent_bootstrap")
5
-
6
-
7
- def bootstrap():
8
- """Ensure the agent is bootstrapped with the backend."""
9
-
10
- if backend_client.is_bootstrapped():
11
- logger.info("Agent ID %s is already bootstrapped.", backend_client.agent_id)
12
- return
13
-
14
- username = input("LDAP Username: ")
15
- totp = input("TOTP: ")
16
-
17
- backend_client.login(username, totp)
18
-
19
- equipment_name = input("Equipment Name: ")
20
- enforced_id = input("Enforced Agent ID (Optional): ")
21
- backend_client.bootstrap(equipment_name, enforced_id or None)
@@ -1,37 +0,0 @@
1
- zscams/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- zscams/__main__.py,sha256=gawDyVPTo-ef-7IStyvS93Ch9cCmGxdhkvc-rBxq8sg,3105
3
- zscams/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- zscams/agent/certificates/.gitkeep,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- zscams/agent/config.yaml,sha256=6_nYDe0CuOxcCdYWWnoA7kZiPLLhK504QyoaaVuZ7z4,3556
6
- zscams/agent/keys/autoport.key,sha256=hZBmtw_nLsZwe11LYlwLL-P_blQ_qpUDpFwvqOZDZFE,1679
7
- zscams/agent/src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- zscams/agent/src/core/__init__.py,sha256=CEDwvbxojtNZOfOOFBj-URg4Q0KB0cq9AqIiD0uzPic,24
9
- zscams/agent/src/core/api/backend/bootstrap.py,sha256=MJ1ceskHmlRpan1Oj6nN2HQdMuwwSxNWCUPPsCXcmNs,667
10
- zscams/agent/src/core/api/backend/client.py,sha256=0vjLOUXEMrrPERPKGsan8LzjQICIDsTKDbcGVrPBWGY,8542
11
- zscams/agent/src/core/api/backend/exceptions.py,sha256=osMbVb_ZGvrGbw5cOCMG1s4yBLukJl7T8TITCcVPyXA,383
12
- zscams/agent/src/core/api/backend/update_machine_info.py,sha256=9s2lmTwXqSJPrOq46ZUFHQ3dcOGZ45wzk11gLYJKA20,478
13
- zscams/agent/src/core/prerequisites.py,sha256=LNPjDj2AQhZ3xBiLDNurG2osBTjepcU6tzDIm5PT_GA,1159
14
- zscams/agent/src/core/service_health_check.py,sha256=9VUWQitXcDEwLcHTTeequi6om98OXN-JIIMZCCH5y4A,1733
15
- zscams/agent/src/core/services.py,sha256=GvAYODh1Pg_FatnZO_8iqReiIeBfq7Hfwj9zxlXYm-0,2840
16
- zscams/agent/src/core/tunnel/__init__.py,sha256=BvJmqtjliO-UvmEguOwky8KSGLY_w8xqM67Q3v2_jc0,4658
17
- zscams/agent/src/core/tunnel/tls.py,sha256=EIRR7aLq6BkW6jUVseM1YCqm7E_UDVSQ9CffQri2U6U,2006
18
- zscams/agent/src/core/tunnels.py,sha256=FwYi9cV3V7c_su5cEgXmyNdr8VyfCBKzU5olvi2MzBw,1736
19
- zscams/agent/src/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
- zscams/agent/src/services/reverse_ssh.py,sha256=-q9RJwyUvzSDftP7NNSmfHJHbx-2vmYrMy9KEjUmlyU,2081
21
- zscams/agent/src/services/ssh_forwarder.py,sha256=BZ7-9i2YxdxtVfaxu5JDkwhFyNKDruIkph10bT6Ms-g,2223
22
- zscams/agent/src/services/system_monitor.py,sha256=7VeSYHbr1Lv8tGVg0AMMd5_o7EgMGuRDlxJjxpGM27g,7529
23
- zscams/agent/src/support/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
- zscams/agent/src/support/configuration.py,sha256=gipsCDDjHH-ncxEURcu5b_ws4wmq9R58sRL-Fgx2O_Y,939
25
- zscams/agent/src/support/filesystem.py,sha256=Cts8Sx1mr5Ndd15K9OQpvgAMgylBtZDUZIQtGibK7qI,962
26
- zscams/agent/src/support/logger.py,sha256=lDkj-eTCdOlhyYO-ySH9UT_C4xh9S_jyMWM51N4i0xI,931
27
- zscams/agent/src/support/mac.py,sha256=tCn6kB4m0VfrrQ04JEZrgOPEngLEZd5vDPdVdtFtvcg,465
28
- zscams/agent/src/support/network.py,sha256=VwVVNqykZxvrTPwPYQ3sSVMc_Z2XUwASlo_kd_wdGDs,1453
29
- zscams/agent/src/support/openssl.py,sha256=_Rd76Y2168hkLjeQlC7alvjUoWbiUWBum4yVpEfmVfw,3399
30
- zscams/libs/getmac/__init__.py,sha256=iunkDFEtpGaRw1Y0lzr9OZ7LsZ-GH81E836ZJQC25Vg,80
31
- zscams/libs/getmac/__main__.py,sha256=PTkcTMZSbvJ-qwMyVuo-Bf-RKI47y7Kwxqroo92EVS4,3547
32
- zscams/libs/getmac/getmac.py,sha256=bFYx0WNBojEtNbIWKfNMm4mWI1Q2YLOx67Qluhs-fWU,64504
33
- zscams/libs/getmac/shutilwhich.py,sha256=cTd3vGTZqKB44FOQhk7UG5M-Vb3qKg9HmuIy6hxkus0,2627
34
- zscams-2.0.1.dist-info/METADATA,sha256=DX3VqzEC6Z32uJbOocIgiyEBYQg3k-YSn_CoF9uJt14,7156
35
- zscams-2.0.1.dist-info/WHEEL,sha256=iAMR_6Qh95yyjYIwRxyjpiFq4FhDPemrEV-SyWIQB3U,92
36
- zscams-2.0.1.dist-info/entry_points.txt,sha256=IXiMYjEq4q0tUiD9O7eCWhqKBuOssXrMW42siTBAgG8,47
37
- zscams-2.0.1.dist-info/RECORD,,
File without changes
File without changes
File without changes
File without changes
File without changes