zscams 2.0.4__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/__init__.py +3 -0
- zscams/__main__.py +43 -0
- zscams/agent/__init__.py +93 -0
- zscams/agent/certificates/.gitkeep +0 -0
- zscams/agent/config.yaml +103 -0
- zscams/agent/configuration/config.j2 +103 -0
- zscams/agent/configuration/service.j2 +12 -0
- zscams/agent/keys/autoport.key +27 -0
- zscams/agent/src/__init__.py +0 -0
- zscams/agent/src/core/__init__.py +1 -0
- zscams/agent/src/core/backend/bootstrap.py +76 -0
- zscams/agent/src/core/backend/client.py +281 -0
- zscams/agent/src/core/backend/exceptions.py +10 -0
- zscams/agent/src/core/backend/update_machine_info.py +16 -0
- zscams/agent/src/core/prerequisites.py +36 -0
- zscams/agent/src/core/service_health_check.py +49 -0
- zscams/agent/src/core/services.py +86 -0
- zscams/agent/src/core/tunnel/__init__.py +144 -0
- zscams/agent/src/core/tunnel/tls.py +56 -0
- zscams/agent/src/core/tunnels.py +55 -0
- zscams/agent/src/services/__init__.py +0 -0
- zscams/agent/src/services/reverse_ssh.py +73 -0
- zscams/agent/src/services/ssh_forwarder.py +75 -0
- zscams/agent/src/services/system_monitor.py +264 -0
- zscams/agent/src/support/__init__.py +0 -0
- zscams/agent/src/support/cli.py +50 -0
- zscams/agent/src/support/configuration.py +86 -0
- zscams/agent/src/support/filesystem.py +63 -0
- zscams/agent/src/support/logger.py +88 -0
- zscams/agent/src/support/mac.py +18 -0
- zscams/agent/src/support/network.py +49 -0
- zscams/agent/src/support/openssl.py +114 -0
- zscams/agent/src/support/os.py +138 -0
- zscams/agent/src/support/ssh.py +24 -0
- zscams/agent/src/support/yaml.py +37 -0
- zscams/deps.py +86 -0
- zscams/lib/.gitkeep +0 -0
- zscams-2.0.4.dist-info/METADATA +114 -0
- zscams-2.0.4.dist-info/RECORD +41 -0
- zscams-2.0.4.dist-info/WHEEL +4 -0
- zscams-2.0.4.dist-info/entry_points.txt +3 -0
zscams/__init__.py
ADDED
zscams/__main__.py
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Main entry point for ZSCAMs Agent
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
import sys
|
|
7
|
+
import os
|
|
8
|
+
from zscams.agent.src.core.backend.bootstrap import bootstrap
|
|
9
|
+
from zscams.agent.src.core.backend.update_machine_info import update_machine_info
|
|
10
|
+
from zscams.agent.src.support.logger import get_logger
|
|
11
|
+
from zscams.agent import init_parser, ensure_bootstrapped, run
|
|
12
|
+
|
|
13
|
+
logger = get_logger("ZSCAMs")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def main():
|
|
17
|
+
"""Main function to run the asynchronous main."""
|
|
18
|
+
args = init_parser().parse_args()
|
|
19
|
+
|
|
20
|
+
if args.bootstrap:
|
|
21
|
+
try:
|
|
22
|
+
if os.geteuid() != 0:
|
|
23
|
+
logger.error("You are NOT running as root.")
|
|
24
|
+
sys.exit(1)
|
|
25
|
+
bootstrap()
|
|
26
|
+
sys.exit(0)
|
|
27
|
+
except Exception as exception:
|
|
28
|
+
logger.error(exception)
|
|
29
|
+
sys.exit(1)
|
|
30
|
+
|
|
31
|
+
if args.update_machine_info:
|
|
32
|
+
update_machine_info()
|
|
33
|
+
sys.exit(0)
|
|
34
|
+
|
|
35
|
+
try:
|
|
36
|
+
ensure_bootstrapped()
|
|
37
|
+
asyncio.run(run())
|
|
38
|
+
except KeyboardInterrupt:
|
|
39
|
+
logger.info("Exiting TLS Tunnel Client")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
if __name__ == "__main__":
|
|
43
|
+
main()
|
zscams/agent/__init__.py
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import asyncio
|
|
3
|
+
import sys
|
|
4
|
+
import argparse
|
|
5
|
+
from zscams.agent.src.support.configuration import get_config, CONFIG_PATH
|
|
6
|
+
from zscams.agent.src.support.filesystem import is_file_exists, resolve_path
|
|
7
|
+
from zscams.agent.src.core.tunnel.tls import create_ssl_context
|
|
8
|
+
from zscams.agent.src.core.tunnels import start_all_tunnels
|
|
9
|
+
from zscams.agent.src.core.services import start_all_services
|
|
10
|
+
from zscams.agent.src.core.service_health_check import monitor_services
|
|
11
|
+
from zscams.agent.src.core.backend.client import backend_client
|
|
12
|
+
from zscams.agent.src.support.logger import get_logger
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
logger = get_logger("tls_tunnel_main")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def init_parser():
|
|
19
|
+
parser = argparse.ArgumentParser(description="ZSCAMs Agent")
|
|
20
|
+
parser.add_argument(
|
|
21
|
+
"--bootstrap",
|
|
22
|
+
action="store_true",
|
|
23
|
+
help="Run bootstrap process and exit",
|
|
24
|
+
)
|
|
25
|
+
parser.add_argument(
|
|
26
|
+
"--update-machine-info",
|
|
27
|
+
action="store_true",
|
|
28
|
+
help="Run bootstrap process and exit",
|
|
29
|
+
)
|
|
30
|
+
return parser
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def ensure_bootstrapped():
|
|
34
|
+
"""Ensure the agent is bootstrapped with the backend."""
|
|
35
|
+
|
|
36
|
+
config = get_config()
|
|
37
|
+
remote_cfg = config["remote"]
|
|
38
|
+
config_dir = os.path.dirname(CONFIG_PATH)
|
|
39
|
+
|
|
40
|
+
files_to_ensure = [
|
|
41
|
+
resolve_path(remote_cfg.get("ca_cert"), config_dir),
|
|
42
|
+
resolve_path(remote_cfg.get("client_cert"), config_dir),
|
|
43
|
+
resolve_path(remote_cfg.get("client_key"), config_dir),
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
has_missing_file = False
|
|
47
|
+
|
|
48
|
+
for file in files_to_ensure:
|
|
49
|
+
if not is_file_exists(file, logger):
|
|
50
|
+
has_missing_file = True
|
|
51
|
+
break
|
|
52
|
+
|
|
53
|
+
bootstrapped = backend_client.is_bootstrapped()
|
|
54
|
+
|
|
55
|
+
logger.debug("Agent has entry on server: %s", bootstrapped)
|
|
56
|
+
|
|
57
|
+
if not bootstrapped or has_missing_file:
|
|
58
|
+
logger.error(
|
|
59
|
+
"Agent is not bootstrapped. Please run `zscams --bootstrap` to start the bootstrap process.",
|
|
60
|
+
)
|
|
61
|
+
sys.exit(1)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
async def run():
|
|
65
|
+
"""Asynchronous main function to start tunnels and services."""
|
|
66
|
+
|
|
67
|
+
config = get_config()
|
|
68
|
+
config_dir = os.path.dirname(CONFIG_PATH)
|
|
69
|
+
ssl_context = create_ssl_context(config["remote"], config_dir=config_dir)
|
|
70
|
+
remote_host = config["remote"]["host"]
|
|
71
|
+
remote_port = config["remote"]["port"]
|
|
72
|
+
|
|
73
|
+
# Start tunnels and wait for readiness
|
|
74
|
+
tunnel_tasks = await start_all_tunnels(
|
|
75
|
+
config.get("forwards", []), remote_host, remote_port, ssl_context
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
# Start services that depend on tunnels
|
|
79
|
+
service_tasks = asyncio.create_task(
|
|
80
|
+
start_all_services(config.get("services", []), config_dir=config_dir)
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
# Start health checks
|
|
84
|
+
monitor_task = asyncio.create_task(
|
|
85
|
+
monitor_services(
|
|
86
|
+
config.get("services", []),
|
|
87
|
+
config_dir=config_dir,
|
|
88
|
+
interval=config.get("general", {}).get("health_check_interval", 300),
|
|
89
|
+
)
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
logger.info("[*] All tunnels and services started. Press Ctrl+C to stop.")
|
|
93
|
+
await asyncio.gather(*tunnel_tasks, service_tasks, monitor_task)
|
|
File without changes
|
zscams/agent/config.yaml
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
backend:
|
|
3
|
+
base_url: http://22.0.122.40:5000/api
|
|
4
|
+
cache_dir: .cache
|
|
5
|
+
bootstrap_info:
|
|
6
|
+
blacklist_ports: []
|
|
7
|
+
cert_issuer: ZSCAMs
|
|
8
|
+
csr:
|
|
9
|
+
country: FR
|
|
10
|
+
default_common_name: zscams-agent.orangecyberdefense.com
|
|
11
|
+
locality: Paris
|
|
12
|
+
organization: zscams-agent.orangecyberdefense.com
|
|
13
|
+
state: Ile-de-France
|
|
14
|
+
forwards:
|
|
15
|
+
- description: Forward to SSH backend
|
|
16
|
+
local_port: 4422
|
|
17
|
+
sni_hostname: ssh-tunnel
|
|
18
|
+
- description: Forward to Seculogs
|
|
19
|
+
local_port: 4423
|
|
20
|
+
sni_hostname: monitor-tunnel
|
|
21
|
+
general:
|
|
22
|
+
health_check_interval: 30
|
|
23
|
+
logging:
|
|
24
|
+
level: 10
|
|
25
|
+
remote:
|
|
26
|
+
ca_cert: certificates/ca_chain.pem
|
|
27
|
+
ca_chain: certificates/ca_chain.pem
|
|
28
|
+
client_cert: certificates/client.crt
|
|
29
|
+
client_key: certificates/client.key
|
|
30
|
+
host: 81.255.240.214
|
|
31
|
+
port: 443
|
|
32
|
+
verify_cert: false
|
|
33
|
+
services:
|
|
34
|
+
- args: []
|
|
35
|
+
custom_port_name: reverse_port
|
|
36
|
+
health:
|
|
37
|
+
host: localhost
|
|
38
|
+
port: 22
|
|
39
|
+
name: Reverse SSH
|
|
40
|
+
params:
|
|
41
|
+
local_port: 4422
|
|
42
|
+
private_key: zscams/agent/keys/autoport.key
|
|
43
|
+
remote_host: localhost
|
|
44
|
+
reverse_port: 10000
|
|
45
|
+
server_ssh_user: ssh_user
|
|
46
|
+
ssh_options:
|
|
47
|
+
- -o LogLevel=error
|
|
48
|
+
- -o UserKnownHostsFile=/dev/null
|
|
49
|
+
- -o StrictHostKeyChecking=no
|
|
50
|
+
- -o ServerAliveInterval=30
|
|
51
|
+
- -o ServerAliveCountMax=2
|
|
52
|
+
port: 22
|
|
53
|
+
prerequisites:
|
|
54
|
+
files:
|
|
55
|
+
- zscams/agent/keys/autoport.key
|
|
56
|
+
ports:
|
|
57
|
+
- 22
|
|
58
|
+
services: []
|
|
59
|
+
script: src/services/reverse_ssh.py
|
|
60
|
+
- args: []
|
|
61
|
+
custom_port_name: forwarder_port
|
|
62
|
+
health:
|
|
63
|
+
host: localhost
|
|
64
|
+
port: 10001
|
|
65
|
+
name: Monitor Forwarder
|
|
66
|
+
params:
|
|
67
|
+
forwarder_port: 10001
|
|
68
|
+
local_port: 4423
|
|
69
|
+
private_key: zscams/agent/keys/autoport.key
|
|
70
|
+
remote_host: 194.51.14.159
|
|
71
|
+
remote_port: 530
|
|
72
|
+
server_ssh_user: ssh_user
|
|
73
|
+
ssh_options:
|
|
74
|
+
- -o LogLevel=error
|
|
75
|
+
- -o UserKnownHostsFile=/dev/null
|
|
76
|
+
- -o StrictHostKeyChecking=no
|
|
77
|
+
- -o ServerAliveInterval=30
|
|
78
|
+
- -o ServerAliveCountMax=2
|
|
79
|
+
port: 530
|
|
80
|
+
prerequisites:
|
|
81
|
+
files:
|
|
82
|
+
- zscams/agent/keys/autoport.key
|
|
83
|
+
ports: []
|
|
84
|
+
services: []
|
|
85
|
+
script: src/services/ssh_forwarder.py
|
|
86
|
+
- args: []
|
|
87
|
+
health:
|
|
88
|
+
host: localhost
|
|
89
|
+
port: 10001
|
|
90
|
+
name: Monitor Service
|
|
91
|
+
params:
|
|
92
|
+
equipment_name: zpa-orange-swec-dev-01
|
|
93
|
+
equipment_type: zpa
|
|
94
|
+
remote_host: localhost
|
|
95
|
+
remote_port: 10001
|
|
96
|
+
service_name: Zscaler-AppConnector
|
|
97
|
+
port: 10001
|
|
98
|
+
prerequisites:
|
|
99
|
+
files: []
|
|
100
|
+
ports:
|
|
101
|
+
- 10001
|
|
102
|
+
services: []
|
|
103
|
+
script: src/services/system_monitor.py
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
backend:
|
|
3
|
+
base_url: http://22.0.122.40:5000/api
|
|
4
|
+
cache_dir: .cache
|
|
5
|
+
bootstrap_info:
|
|
6
|
+
blacklist_ports: []
|
|
7
|
+
cert_issuer: ZSCAMs
|
|
8
|
+
csr:
|
|
9
|
+
country: FR
|
|
10
|
+
default_common_name: zscams-agent.orangecyberdefense.com
|
|
11
|
+
locality: Paris
|
|
12
|
+
organization: zscams-agent.orangecyberdefense.com
|
|
13
|
+
state: Ile-de-France
|
|
14
|
+
forwards:
|
|
15
|
+
- description: Forward to SSH backend
|
|
16
|
+
local_port: 4422
|
|
17
|
+
sni_hostname: ssh-tunnel
|
|
18
|
+
- description: Forward to Seculogs
|
|
19
|
+
local_port: 4423
|
|
20
|
+
sni_hostname: monitor-tunnel
|
|
21
|
+
general:
|
|
22
|
+
health_check_interval: 30
|
|
23
|
+
logging:
|
|
24
|
+
level: 10
|
|
25
|
+
remote:
|
|
26
|
+
ca_cert: certificates/ca_chain.pem
|
|
27
|
+
ca_chain: certificates/ca_chain.pem
|
|
28
|
+
client_cert: certificates/client.crt
|
|
29
|
+
client_key: certificates/client.key
|
|
30
|
+
host: 81.255.240.214
|
|
31
|
+
port: 443
|
|
32
|
+
verify_cert: false
|
|
33
|
+
services:
|
|
34
|
+
- args: []
|
|
35
|
+
health:
|
|
36
|
+
host: localhost
|
|
37
|
+
port: 22
|
|
38
|
+
name: Reverse SSH
|
|
39
|
+
custom_port_name: "reverse_port"
|
|
40
|
+
params:
|
|
41
|
+
local_port: 4422
|
|
42
|
+
private_key: zscams/agent/keys/autoport.key
|
|
43
|
+
remote_host: localhost
|
|
44
|
+
reverse_port: "{reverse_port}"
|
|
45
|
+
server_ssh_user: ssh_user
|
|
46
|
+
ssh_options:
|
|
47
|
+
- -o LogLevel=error
|
|
48
|
+
- -o UserKnownHostsFile=/dev/null
|
|
49
|
+
- -o StrictHostKeyChecking=no
|
|
50
|
+
- -o ServerAliveInterval=30
|
|
51
|
+
- -o ServerAliveCountMax=2
|
|
52
|
+
port: 22
|
|
53
|
+
prerequisites:
|
|
54
|
+
files:
|
|
55
|
+
- zscams/agent/keys/autoport.key
|
|
56
|
+
ports:
|
|
57
|
+
- 22
|
|
58
|
+
services: []
|
|
59
|
+
script: src/services/reverse_ssh.py
|
|
60
|
+
- args: []
|
|
61
|
+
health:
|
|
62
|
+
host: localhost
|
|
63
|
+
port: "{forwarder_port}"
|
|
64
|
+
name: Monitor Forwarder
|
|
65
|
+
custom_port_name: "forwarder_port"
|
|
66
|
+
params:
|
|
67
|
+
forwarder_port: "{forwarder_port}"
|
|
68
|
+
local_port: 4423
|
|
69
|
+
private_key: zscams/agent/keys/autoport.key
|
|
70
|
+
remote_host: 194.51.14.159
|
|
71
|
+
remote_port: 530
|
|
72
|
+
server_ssh_user: ssh_user
|
|
73
|
+
ssh_options:
|
|
74
|
+
- -o LogLevel=error
|
|
75
|
+
- -o UserKnownHostsFile=/dev/null
|
|
76
|
+
- -o StrictHostKeyChecking=no
|
|
77
|
+
- -o ServerAliveInterval=30
|
|
78
|
+
- -o ServerAliveCountMax=2
|
|
79
|
+
port: 530
|
|
80
|
+
prerequisites:
|
|
81
|
+
files:
|
|
82
|
+
- zscams/agent/keys/autoport.key
|
|
83
|
+
ports: []
|
|
84
|
+
services: []
|
|
85
|
+
script: src/services/ssh_forwarder.py
|
|
86
|
+
- args: []
|
|
87
|
+
health:
|
|
88
|
+
host: localhost
|
|
89
|
+
port: "{forwarder_port}"
|
|
90
|
+
name: Monitor Service
|
|
91
|
+
params:
|
|
92
|
+
equipment_name: "{equipment_name}"
|
|
93
|
+
equipment_type: "{equipment_type}"
|
|
94
|
+
remote_host: localhost
|
|
95
|
+
remote_port: "{forwarder_port}"
|
|
96
|
+
service_name: Zscaler-AppConnector
|
|
97
|
+
port: "{forwarder_port}"
|
|
98
|
+
prerequisites:
|
|
99
|
+
files: []
|
|
100
|
+
ports:
|
|
101
|
+
- "{forwarder_port}"
|
|
102
|
+
services: []
|
|
103
|
+
script: src/services/system_monitor.py
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
-----BEGIN RSA PRIVATE KEY-----
|
|
2
|
+
MIIEpQIBAAKCAQEA4kpci9i3k9OhuYpC1+0OSQCpXVRThIjtmwl9Nl4oRSsse9zj
|
|
3
|
+
vkzPShMvlZwvEzzZ/Y3hVDHLD5W3hhy63pyi75uxC9RDzb/7ckc1SdunTzj0mtAt
|
|
4
|
+
FhV+cXFZfv79NfaluN/WZwrbpMO+7+uATuEFIGe/t05PgYX9CzhaagCsC355jFHt
|
|
5
|
+
t2z/9Ul40mJkpMZwr+pk6BOSo/DeW7LNikFljqU8BjoZmGuwGuIHzF6ivhDA8hRz
|
|
6
|
+
aKVfw3e+BuxSyOH3xWxzpHSYiZGU5x9hHk8VEbkP7lISxqYdncCw1Is0O6awfXs0
|
|
7
|
+
azx7yzfUumjDdNSmrwpb5/ard30x/aE96upnRwIDAQABAoIBAQC2ghUcMWD2WDTS
|
|
8
|
+
iSGaNzZTSLZQcKefeDRy23didxRxnP2WtLP2EssIymqRdtM859JFPr4igrpsymqn
|
|
9
|
+
Ptq0mo6LQ/3KNZuuAQ4SwD3JYOAS9DPL/OSwMAu4ARyWYZ/lexV0AwxQNSCrRbjk
|
|
10
|
+
lgL5G2FgHm0wsXdMVr2c5Al//yTDauzgOJtQfi/LzuHusnz05iHzEp0ByBfiRL8z
|
|
11
|
+
xKQ9LFW7pIYUsgn4kXry5tQokH6NwDZ7vGPcjAQLD0lLDfAHF9HOiwpkQYXw8q91
|
|
12
|
+
lNvhaFHxa9jyfvuG9e66Q72YCevsCGBEl8Hvmbpz5/9oBZ6Pt82BZKjSouYh7Cya
|
|
13
|
+
a+JVxQcxAoGBAPSKdJdMXH6hCi5DBYhWnGSpDKvRwvxb2PgntCwajkaEZmuITj4y
|
|
14
|
+
dk9IH89ryl0yAmF6q2pKLyWHOir0fVX1HsnC9m2SErhMuSrhSVpcOLiI09wFwcAM
|
|
15
|
+
PRbS/6g1h/Q+MoaVuD0h9ElO8GkONBIBrmiVYqOifotXuPXjMMGT8oNpAoGBAOzk
|
|
16
|
+
+OSilwjwtwv/MkLOXqGFymSnG7l5zmt/KGxMCThjxY9b1DzyvXcUvojCRjFl4L0W
|
|
17
|
+
OyDbKRiEJZHSH6jV1gj2N8/53b3C1ziCRvHWvix7MJ7DeDfZLp0QEYZBm6Xm7mG+
|
|
18
|
+
TZ27kya0Hprev/t960UfOpwhb8+MNd1dxdgspC8vAoGBALcGpcrTyWqxZ2hGm252
|
|
19
|
+
vKkOacBzyAePSu448T4NRi17TRjwtPcSV8BxD/X0DEsCcgu5f3CXQ4BIHP4nbWOX
|
|
20
|
+
icqi1EQgD0jHi9OPOJKb8YwURNUpreDqiBJ8LAMexbnFj5Vxm6qNrkPsBD3s9oX/
|
|
21
|
+
oiT+ogwtQ59RMcs/lq9b5yf5AoGAbPmYFXVGDXLOgdJPiLPujFdDl7HX6ybBcmn4
|
|
22
|
+
ank/9JTRGPWhWLhBuDnuvHLCX48CJ3nGkYLAEOsZbU9ACSb1YwIBAsdq3hR3dSNZ
|
|
23
|
+
B39F1KiG4UICV46tBsuRhDVCKLtnBcfJZLoZI0DQo2W84zA1voJzL8eh69QQI1kz
|
|
24
|
+
3hILJTkCgYEAwT+XKnxX8jExNvpe71O2pm3mit6UyOHXB1KyT4Y3UuKjDxwZZ4w1
|
|
25
|
+
vPp6eQ3VcI+4+mpf0qs1cgDz8w35EInt60nKy0+0hwQaM7N0EmsguASHRprESZR9
|
|
26
|
+
dAPDJQ1UJlAMSJxZxFzTvMzDQHY+86GGh5mdoNwJDb0142etE7rSFUI=
|
|
27
|
+
-----END RSA PRIVATE KEY-----
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
running_services = set()
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
import sysconfig
|
|
4
|
+
import sys
|
|
5
|
+
from typing import cast
|
|
6
|
+
from zscams.agent.src.core.backend.client import backend_client
|
|
7
|
+
from zscams.agent.src.support.configuration import reinitialize
|
|
8
|
+
from zscams.agent.src.support.logger import get_logger
|
|
9
|
+
from zscams.agent.src.support.os import create_system_user, install_service
|
|
10
|
+
from zscams.agent.src.support.ssh import add_to_authorized_keys
|
|
11
|
+
from zscams.agent.src.support.cli import prompt
|
|
12
|
+
|
|
13
|
+
logger = get_logger("bootstrap")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def bootstrap():
|
|
17
|
+
"""Ensure the agent is bootstrapped with the backend."""
|
|
18
|
+
|
|
19
|
+
if backend_client.is_bootstrapped():
|
|
20
|
+
logger.info("Agent ID %s is already bootstrapped.", backend_client.agent_id)
|
|
21
|
+
return
|
|
22
|
+
|
|
23
|
+
username = input("Username: ")
|
|
24
|
+
totp = input("One Time Password (OTP): ")
|
|
25
|
+
|
|
26
|
+
backend_client.login(username, totp)
|
|
27
|
+
|
|
28
|
+
customer_name = prompt(
|
|
29
|
+
"Customer Name",
|
|
30
|
+
"Customer Name",
|
|
31
|
+
required=True,
|
|
32
|
+
startswith="",
|
|
33
|
+
)
|
|
34
|
+
connector_name = prompt(
|
|
35
|
+
"Connector Name",
|
|
36
|
+
"Connector Name [Unique name for this connector]",
|
|
37
|
+
required=True,
|
|
38
|
+
startswith="",
|
|
39
|
+
)
|
|
40
|
+
equipment_type = prompt(
|
|
41
|
+
"Equipment Type",
|
|
42
|
+
"Equipment Type [Can be ZPA|VZEN|PSE]",
|
|
43
|
+
required=True,
|
|
44
|
+
startswith="",
|
|
45
|
+
)
|
|
46
|
+
equipment_name = (
|
|
47
|
+
f"{equipment_type.lower()}-{customer_name.lower()}-{connector_name.lower()}"
|
|
48
|
+
)
|
|
49
|
+
enforced_id = prompt("Enforced ID", "Enforced Agent ID")
|
|
50
|
+
reinitialize(equipment_name=equipment_name, equipment_type=equipment_type)
|
|
51
|
+
cm_info = backend_client.bootstrap(equipment_name, enforced_id or None)
|
|
52
|
+
|
|
53
|
+
sys_user = cast(str, cm_info.get("ssh_user"))
|
|
54
|
+
|
|
55
|
+
create_system_user(sys_user)
|
|
56
|
+
add_to_authorized_keys(sys_user, cm_info.get("server_ssh_pub_key"))
|
|
57
|
+
install_zscams_systemd_service(sys_user)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def install_zscams_systemd_service(user_to_run_as: str):
|
|
61
|
+
|
|
62
|
+
data = {
|
|
63
|
+
"pythonpath": sysconfig.get_paths()["purelib"],
|
|
64
|
+
"python_exec": sys.executable,
|
|
65
|
+
"user_to_run_as": user_to_run_as,
|
|
66
|
+
}
|
|
67
|
+
import zscams
|
|
68
|
+
|
|
69
|
+
BASE_DIR = Path(zscams.__file__).resolve().parent
|
|
70
|
+
template_path = f"{BASE_DIR}/agent/configuration/service.j2"
|
|
71
|
+
with open(template_path) as f:
|
|
72
|
+
template = f.read()
|
|
73
|
+
|
|
74
|
+
rendered_config = template.format(**data)
|
|
75
|
+
|
|
76
|
+
install_service("zscams.service", rendered_config)
|