forked from yuqiChen94/Swat_Simulator
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrun_simulator.py
More file actions
134 lines (114 loc) · 5.8 KB
/
Copy pathrun_simulator.py
File metadata and controls
134 lines (114 loc) · 5.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#!/usr/bin/env python3
"""
simple-cps run.py
"""
# import logging
from subprocess import Popen
from typing import IO, Dict, Optional, TextIO, Tuple, cast
from mininet.net import Mininet
from nodecli import NodeCLI as CLI
from mininet.link import TCLink
from datetime import datetime
from tqdm import tqdm
from time import sleep, time
from topo import ICSTopo
from common import logger
from typing import List, IO
import argparse
import tempfile
import os, sys
import utils
def wait_progress(popen_partial, max_lines, total_progress, out: IO, wait=True):
popen_partial(stdout=out, stderr=out)
def return_gen(outfile, max, total, wait):
last_tell = 0
while out.tell() < max:
if wait:
sleep(0.1)
diff = (out.tell() - last_tell) * (total / max)
yield diff
last_tell = out.tell()
return out, return_gen(out, max_lines, total_progress, wait=wait)
def start(args):
historian = None
net: Optional[Mininet] = None
started_devices: Dict[str, Tuple[Popen, TextIO, TextIO]] = {}
try:
with tqdm(total=100) as progress, open(os.devnull, 'w') as null, tempfile.NamedTemporaryFile('w+', 64) as man_out:
progress.set_description("Starting topology v2...")
topo = ICSTopo() # nodes=sdn_args.nodes, arg_hosts=sdn_args.hosts, bw=sdn_args.bw, loss=sdn_args.loss, delay=sdn_args.delay, random=sdn_args.random)
progress.update(20)
progress.set_description("Starting Mininet...")
net = Mininet(topo=topo, link=TCLink, autoSetMacs=True, controller=None)
progress.update(20)
progress.set_description("Initializing network...")
net.start()
# setup remote service
hmi, historian = net.get('hmi'), net.get('historian')
progress.set_description("Setting up NAT for remote router...")
net.get('rem_r').cmd('make', 'router-remote')
sleep(0.1)
progress.update(10)
progress.set_description("Setting up NAT for local router...")
net.get('gate_r').cmd('make', 'router-gate')
sleep(0.1)
progress.update(10)
progress.set_description("Starting remote AD servers...")
net.get('rem_dsc').popen('make', 'remote-discovery', cwd="rest-service/compute", stdout=null, stderr=null)
sleep(0.1)
progress.update(10)
net.get('rem_srv').popen('make', 'remote-server', cwd="rest-service/", stdout=null, stderr=null)
sleep(0.1)
progress.update(10)
progress.set_description("Starting remote AD compute service...")
net.get('rem_cpu').popen('make', 'remote-compute', cwd="rest-service/compute", stdout=null, stderr=null)
sleep(0.1)
progress.update(10)
progress.set_description("Starting historian DB...")
"""man_out, wait_gen = wait_progress(
functools.partial(historian.popen, 'make', 'start-historian'),
max_lines=10000, total_progress=progress.total - progress.n, wait=True
)
for diff in wait_gen:
if progress.n + diff > progress.total:
diff = progress.total - progress.n
progress.update(diff)
"""
#client = hmi.popen('make', 'hmi-client', stdout=sys.stdout, stderr=sys.stdout)
progress.update(progress.total - progress.n)
progress.set_description("Setup complete.")
progress.close()
runnable_devices = utils.get_field_devices(net, topo.device_list)
if 'n' not in input("Test OT network status? (Yn): ").lower():
utils.ping_devices(net, runnable_devices, verbose=True, timeout=0.05)
#logger.output("Opening HMI WebView", '\n')
#hmi.popen('make', 'historian-viewer', stdout=null, stderr=null)
# clear argv so that Cmd2 does not use it
sys.argv = sys.argv[:1]
# pass by reference
CLI(net, started_devices=started_devices)
except KeyboardInterrupt:
logger.output("Stopping simulation...", '\n')
except Exception as err:
logger.error(f"Error: [ {str(err).strip()} ]", '\n')
#logger.exception(err, exc_info=True)
finally:
logger.output(f"Shutting down at {datetime.now()}...", '\n')
for popen, out, err in started_devices.values():
popen.terminate()
out.close()
err.close()
if historian is not None:
historian.popen("make", "stop-historian")
if net is not None:
net.stop()
if __name__ == "__main__":
# TODO finish support for these arguments
parser = argparse.ArgumentParser(description="CyberSWaT Runner")
parser.add_argument("--ics-topos", "-t", default=(), nargs='+', help="A list of external ICS OT networks to attach to this simulator, for which a full ICS network (e.g. control/DMZ & admin network) will be attached. "
"Must be Python files with a `get_topo()` function defined in them, which returns the name of a LinuxRouter host.")
parser.add_argument("--other-topos", "-o", default=(), nargs="+", help="A list of other networks to attach to this simulator. Must be Python files with a `get_topo()` function defined in them, which returns a LinuxRouter host. "
"Note: NAT will be enabled on this host, and external routes set up automatically.")
parser.add_argument("--verbose", "-v", action="store_true", help="Sets the log level to DEBUG instead of INFO.")
args = parser.parse_args()
start(args)