#1800 - Synced with dev.
- Added the UC2 network. - Added a Computer class.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
from typing import Any, Dict, Union
|
||||
from typing import Any, Dict, Union, Optional
|
||||
|
||||
from primaite import getLogger
|
||||
from primaite.simulator.core import Action, ActionManager, AllowAllValidator, SimComponent
|
||||
@@ -58,6 +58,19 @@ class Network(SimComponent):
|
||||
node.parent = self
|
||||
_LOGGER.info(f"Added node {node.uuid} to Network {self.uuid}")
|
||||
|
||||
def get_node_by_hostname(self, hostname: str) -> Optional[Node]:
|
||||
"""
|
||||
Get a Node from the Network by its hostname.
|
||||
|
||||
.. note:: Assumes hostnames on the network are unique.
|
||||
|
||||
:param hostname: The Node hostname.
|
||||
:return: The Node if it exists in the network.
|
||||
"""
|
||||
for node in self.nodes.values():
|
||||
if node.hostname == hostname:
|
||||
return node
|
||||
|
||||
def remove_node(self, node: Node) -> None:
|
||||
"""
|
||||
Remove a node from the network.
|
||||
@@ -72,7 +85,8 @@ class Network(SimComponent):
|
||||
node.parent = None
|
||||
_LOGGER.info(f"Removed node {node.uuid} from network {self.uuid}")
|
||||
|
||||
def connect(self, endpoint_a: Union[NIC, SwitchPort], endpoint_b: Union[NIC, SwitchPort], **kwargs) -> None:
|
||||
def connect(self, endpoint_a: Union[Node, NIC, SwitchPort], endpoint_b: Union[Node, NIC, SwitchPort], **kwargs) -> \
|
||||
None:
|
||||
"""Connect two nodes on the network by creating a link between an NIC/SwitchPort of each one.
|
||||
|
||||
:param endpoint_a: The endpoint to which to connect the link on the first node
|
||||
@@ -81,16 +95,19 @@ class Network(SimComponent):
|
||||
:type endpoint_b: Union[NIC, SwitchPort]
|
||||
:raises RuntimeError: _description_
|
||||
"""
|
||||
node_a = endpoint_a.parent
|
||||
node_b = endpoint_b.parent
|
||||
node_a: Node = endpoint_a.parent if not isinstance(endpoint_a, Node) else endpoint_a
|
||||
node_b: Node = endpoint_b.parent if not isinstance(endpoint_b, Node) else endpoint_b
|
||||
if node_a not in self:
|
||||
self.add_node(node_a)
|
||||
if node_b not in self:
|
||||
self.add_node(node_b)
|
||||
if node_a is node_b:
|
||||
_LOGGER.warn(f"Cannot link endpoint {endpoint_a} to {endpoint_b} because they belong to the same node.")
|
||||
_LOGGER.warning(f"Cannot link endpoint {endpoint_a} to {endpoint_b} because they belong to the same node.")
|
||||
return
|
||||
|
||||
if isinstance(endpoint_a, Node) and len(endpoint_a.nics) == 1:
|
||||
endpoint_a = list(endpoint_a.nics.values())[0]
|
||||
if isinstance(endpoint_b, Node) and len(endpoint_b.nics) == 1:
|
||||
endpoint_b = list(endpoint_b.nics.values())[0]
|
||||
link = Link(endpoint_a=endpoint_a, endpoint_b=endpoint_b, **kwargs)
|
||||
self.links[link.uuid] = link
|
||||
link.parent = self
|
||||
|
||||
44
src/primaite/simulator/network/hardware/nodes/computer.py
Normal file
44
src/primaite/simulator/network/hardware/nodes/computer.py
Normal file
@@ -0,0 +1,44 @@
|
||||
from ipaddress import IPv4Address
|
||||
|
||||
from primaite.simulator.network.hardware.base import Node, NIC
|
||||
|
||||
|
||||
class Computer(Node):
|
||||
"""
|
||||
A basic computer class.
|
||||
|
||||
Example:
|
||||
>>> pc_a = Computer(
|
||||
hostname="pc_a",
|
||||
ip_address="192.168.1.10",
|
||||
subnet_mask="255.255.255.0",
|
||||
default_gateway="192.168.1.1"
|
||||
)
|
||||
>>> pc_a.power_on()
|
||||
|
||||
Instances of computer come 'pre-packaged' with the following:
|
||||
|
||||
* Core Functionality:
|
||||
* ARP.
|
||||
* ICMP.
|
||||
* Packet Capture.
|
||||
* Sys Log.
|
||||
* Services:
|
||||
* DNS Client.
|
||||
* FTP Client.
|
||||
* LDAP Client.
|
||||
* NTP Client.
|
||||
* Applications:
|
||||
* Email Client.
|
||||
* Web Browser.
|
||||
* Processes:
|
||||
* Placeholder.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
for key in {"ip_address", "subnet_mask", "default_gateway"}:
|
||||
if key in kwargs:
|
||||
if not isinstance(kwargs[key], IPv4Address):
|
||||
kwargs[key] = IPv4Address(kwargs[key])
|
||||
super().__init__(**kwargs)
|
||||
self.connect_nic(NIC(ip_address=kwargs["ip_address"], subnet_mask=kwargs["subnet_mask"]))
|
||||
154
src/primaite/simulator/network/networks.py
Normal file
154
src/primaite/simulator/network/networks.py
Normal file
@@ -0,0 +1,154 @@
|
||||
from primaite.simulator.network.container import Network
|
||||
from primaite.simulator.network.hardware.base import Switch, NIC
|
||||
from primaite.simulator.network.hardware.nodes.computer import Computer
|
||||
from primaite.simulator.network.hardware.nodes.router import Router, ACLAction
|
||||
from primaite.simulator.network.transmission.network_layer import IPProtocol
|
||||
from primaite.simulator.network.transmission.transport_layer import Port
|
||||
|
||||
|
||||
def arcd_uc2_network() -> Network:
|
||||
"""
|
||||
Models the ARCD Use Case 2 Network.
|
||||
|
||||
+------------+
|
||||
| domain_ |
|
||||
+------------+ controller |
|
||||
| | |
|
||||
| +------------+
|
||||
|
|
||||
|
|
||||
+------------+ | +------------+
|
||||
| | | | |
|
||||
| client_1 +---------+ | +---------+ web_server |
|
||||
| | | | | | |
|
||||
+------------+ | | | +------------+
|
||||
+--+---------+ +------------+ +------+--+--+
|
||||
| | | | | |
|
||||
| switch_2 +------+ router_1 +------+ switch_1 |
|
||||
| | | | | |
|
||||
+--+------+--+ +------------+ +--+---+--+--+
|
||||
+------------+ | | | | | +------------+
|
||||
| | | | | | | | database |
|
||||
| client_2 +---------+ | | | +---------+ _server |
|
||||
| | | | | | |
|
||||
+------------+ | | | +------------+
|
||||
| +------------+ | |
|
||||
| | security | | |
|
||||
+---------+ _suite +---------+ | +------------+
|
||||
| | | | backup_ |
|
||||
+------------+ +------------+ server |
|
||||
| |
|
||||
+------------+
|
||||
|
||||
Example:
|
||||
>>> network = arcd_uc2_network()
|
||||
>>> network.get_node_by_hostname("client_1").ping("192.168.1.10")
|
||||
|
||||
"""
|
||||
network = Network()
|
||||
|
||||
# Router 1
|
||||
router_1 = Router(hostname="router_1", num_ports=5)
|
||||
router_1.power_on()
|
||||
router_1.configure_port(port=1, ip_address="192.168.1.1", subnet_mask="255.255.255.0")
|
||||
router_1.configure_port(port=2, ip_address="192.168.10.1", subnet_mask="255.255.255.0")
|
||||
|
||||
# Switch 1
|
||||
switch_1 = Switch(hostname="switch_1", num_ports=8)
|
||||
switch_1.power_on()
|
||||
network.connect(endpoint_a=router_1.ethernet_ports[1], endpoint_b=switch_1.switch_ports[8])
|
||||
router_1.enable_port(1)
|
||||
|
||||
# Switch 2
|
||||
switch_2 = Switch(hostname="switch_2", num_ports=8)
|
||||
switch_2.power_on()
|
||||
network.connect(endpoint_a=router_1.ethernet_ports[2], endpoint_b=switch_2.switch_ports[8])
|
||||
router_1.enable_port(2)
|
||||
|
||||
# Client 1
|
||||
client_1 = Computer(
|
||||
hostname="client_1",
|
||||
ip_address="192.168.10.21",
|
||||
subnet_mask="255.255.255.0",
|
||||
default_gateway="192.168.10.1"
|
||||
)
|
||||
client_1.power_on()
|
||||
network.connect(endpoint_a=client_1, endpoint_b=switch_2.switch_ports[1])
|
||||
|
||||
# Client 2
|
||||
client_2 = Computer(
|
||||
hostname="client_2",
|
||||
ip_address="192.168.10.22",
|
||||
subnet_mask="255.255.255.0",
|
||||
default_gateway="192.168.10.1"
|
||||
)
|
||||
client_2.power_on()
|
||||
network.connect(endpoint_a=client_2, endpoint_b=switch_2.switch_ports[2])
|
||||
|
||||
# Domain Controller
|
||||
domain_controller = Computer(
|
||||
hostname="domain_controller",
|
||||
ip_address="192.168.1.10",
|
||||
subnet_mask="255.255.255.0",
|
||||
default_gateway="192.168.1.1"
|
||||
)
|
||||
domain_controller.power_on()
|
||||
network.connect(endpoint_a=domain_controller, endpoint_b=switch_1.switch_ports[1])
|
||||
|
||||
# Web Server
|
||||
web_server = Computer(
|
||||
hostname="web_server",
|
||||
ip_address="192.168.1.12",
|
||||
subnet_mask="255.255.255.0",
|
||||
default_gateway="192.168.1.1"
|
||||
)
|
||||
web_server.power_on()
|
||||
network.connect(endpoint_a=web_server, endpoint_b=switch_1.switch_ports[2])
|
||||
|
||||
# Database Server
|
||||
database_server = Computer(
|
||||
hostname="database_server",
|
||||
ip_address="192.168.1.14",
|
||||
subnet_mask="255.255.255.0",
|
||||
default_gateway="192.168.1.1"
|
||||
)
|
||||
database_server.power_on()
|
||||
network.connect(endpoint_a=database_server, endpoint_b=switch_1.switch_ports[3])
|
||||
|
||||
# Backup Server
|
||||
backup_server = Computer(
|
||||
hostname="backup_server",
|
||||
ip_address="192.168.1.16",
|
||||
subnet_mask="255.255.255.0",
|
||||
default_gateway="192.168.1.1"
|
||||
)
|
||||
backup_server.power_on()
|
||||
network.connect(endpoint_a=backup_server, endpoint_b=switch_1.switch_ports[4])
|
||||
|
||||
# Security Suite
|
||||
security_suite = Computer(
|
||||
hostname="security_suite",
|
||||
ip_address="192.168.1.110",
|
||||
subnet_mask="255.255.255.0",
|
||||
default_gateway="192.168.1.1"
|
||||
)
|
||||
security_suite.power_on()
|
||||
network.connect(endpoint_a=security_suite, endpoint_b=switch_1.switch_ports[7])
|
||||
security_suite_external_nic = NIC(ip_address="192.168.10.110", subnet_mask="255.255.255.0")
|
||||
security_suite.connect_nic(security_suite_external_nic)
|
||||
network.connect(endpoint_a=security_suite_external_nic, endpoint_b=switch_2.switch_ports[7])
|
||||
|
||||
router_1.acl.add_rule(
|
||||
action=ACLAction.PERMIT,
|
||||
src_port=Port.ARP,
|
||||
dst_port=Port.ARP,
|
||||
position=22
|
||||
)
|
||||
|
||||
router_1.acl.add_rule(
|
||||
action=ACLAction.PERMIT,
|
||||
protocol=IPProtocol.ICMP,
|
||||
position=23
|
||||
)
|
||||
|
||||
return network
|
||||
Reference in New Issue
Block a user