#2257: added common node attributes page + ability to set node operating state via config + tests
This commit is contained in:
35
docs/source/configuration/simulation/nodes/common/common.rst
Normal file
35
docs/source/configuration/simulation/nodes/common/common.rst
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
.. only:: comment
|
||||||
|
|
||||||
|
© Crown-owned copyright 2023, Defence Science and Technology Laboratory UK
|
||||||
|
|
||||||
|
.. _Node Attributes:
|
||||||
|
|
||||||
|
Common Attributes
|
||||||
|
#################
|
||||||
|
|
||||||
|
Node Attributes
|
||||||
|
===============
|
||||||
|
|
||||||
|
Attributes that are shared by all nodes.
|
||||||
|
|
||||||
|
.. include:: common_node_attributes.rst
|
||||||
|
|
||||||
|
.. _Network Node Attributes:
|
||||||
|
|
||||||
|
Network Node Attributes
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Attributes that are shared by nodes that inherit from :py:mod:`primaite.simulator.network.hardware.nodes.network.network_node.NetworkNode`
|
||||||
|
|
||||||
|
.. include:: common_host_node_attributes.rst
|
||||||
|
|
||||||
|
.. _Host Node Attributes:
|
||||||
|
|
||||||
|
Host Node Attributes
|
||||||
|
====================
|
||||||
|
|
||||||
|
Attributes that are shared by nodes that inherit from :py:mod:`primaite.simulator.network.hardware.nodes.host.host_node.HostNode`
|
||||||
|
|
||||||
|
.. include:: common_host_node_attributes.rst
|
||||||
|
|
||||||
|
.. |NODE| replace:: node
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
© Crown-owned copyright 2023, Defence Science and Technology Laboratory UK
|
© Crown-owned copyright 2023, Defence Science and Technology Laboratory UK
|
||||||
|
|
||||||
|
.. _common_host_node_attributes:
|
||||||
|
|
||||||
``ip_address``
|
``ip_address``
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
@@ -19,13 +21,6 @@ The subnet mask for the |NODE| to use.
|
|||||||
|
|
||||||
The IP address that the |NODE| will use as the default gateway. Typically, this is the IP address of the closest router that the |NODE| is connected to.
|
The IP address that the |NODE| will use as the default gateway. Typically, this is the IP address of the closest router that the |NODE| is connected to.
|
||||||
|
|
||||||
``dns_server``
|
|
||||||
--------------
|
|
||||||
|
|
||||||
Optional. Default value is ``None``
|
|
||||||
|
|
||||||
The IP address of the node which holds an instance of the :ref:`DNSServer`. Some applications may use a domain name e.g. the :ref:`WebBrowser`
|
|
||||||
|
|
||||||
.. include:: ../software/applications.rst
|
.. include:: ../software/applications.rst
|
||||||
|
|
||||||
.. include:: ../software/services.rst
|
.. include:: ../software/services.rst
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
© Crown-owned copyright 2023, Defence Science and Technology Laboratory UK
|
© Crown-owned copyright 2023, Defence Science and Technology Laboratory UK
|
||||||
|
|
||||||
|
.. _common_network_node_attributes:
|
||||||
|
|
||||||
``routes``
|
``routes``
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
© Crown-owned copyright 2023, Defence Science and Technology Laboratory UK
|
© Crown-owned copyright 2023, Defence Science and Technology Laboratory UK
|
||||||
|
|
||||||
|
.. _common_node_attributes:
|
||||||
|
|
||||||
``ref``
|
``ref``
|
||||||
-------
|
-------
|
||||||
|
|
||||||
@@ -11,3 +13,43 @@ Human readable name used as reference for the |NODE|. Not used in code.
|
|||||||
------------
|
------------
|
||||||
|
|
||||||
The hostname of the |NODE|. This will be used to reference the |NODE|.
|
The hostname of the |NODE|. This will be used to reference the |NODE|.
|
||||||
|
|
||||||
|
``operating_state``
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
The initial operating state of the node.
|
||||||
|
|
||||||
|
Optional. Default value is ``ON``.
|
||||||
|
|
||||||
|
Options available are:
|
||||||
|
|
||||||
|
- ``ON``
|
||||||
|
- ``OFF``
|
||||||
|
- ``BOOTING``
|
||||||
|
- ``SHUTTING_DOWN``
|
||||||
|
|
||||||
|
Note that YAML may assume non quoted ``ON`` and ``OFF`` as ``True`` and ``False`` respectively. To prevent this, use ``"ON"`` or ``"OFF"``
|
||||||
|
|
||||||
|
See :py:mod:`primaite.simulator.network.hardware.node_operating_state.NodeOperatingState`
|
||||||
|
|
||||||
|
|
||||||
|
``dns_server``
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Optional. Default value is ``None``.
|
||||||
|
|
||||||
|
The IP address of the node which holds an instance of the :ref:`DNSServer`. Some applications may use a domain name e.g. the :ref:`WebBrowser`
|
||||||
|
|
||||||
|
``start_up_duration``
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Optional. Default value is ``3``.
|
||||||
|
|
||||||
|
The number of time steps required to occur in order for the node to cycle from ``OFF`` to ``BOOTING_UP`` and then finally ``ON``.
|
||||||
|
|
||||||
|
``shut_down_duration``
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Optional. Default value is ``3``.
|
||||||
|
|
||||||
|
The number of time steps required to occur in order for the node to cycle from ``ON`` to ``SHUTTING_DOWN`` and then finally ``OFF``.
|
||||||
|
|||||||
@@ -12,34 +12,22 @@ complex, specialized hardware components inherit from and build upon.
|
|||||||
|
|
||||||
The key elements defined in ``base.py`` are:
|
The key elements defined in ``base.py`` are:
|
||||||
|
|
||||||
NetworkInterface
|
``NetworkInterface``
|
||||||
================
|
====================
|
||||||
|
|
||||||
- Abstract base class for network interfaces like NICs. Defines common attributes like MAC address, speed, MTU.
|
- Abstract base class for network interfaces like NICs. Defines common attributes like MAC address, speed, MTU.
|
||||||
- Requires subclasses to implement ``enable()``, ``disable()``, ``send_frame()`` and ``receive_frame()``.
|
- Requires subclasses to implement ``enable()``, ``disable()``, ``send_frame()`` and ``receive_frame()``.
|
||||||
- Provides basic state description and request handling capabilities.
|
- Provides basic state description and request handling capabilities.
|
||||||
|
|
||||||
Node
|
``Node``
|
||||||
====
|
========
|
||||||
The Node class stands as a central component in ``base.py``, acting as the superclass for all network nodes within a
|
The Node class stands as a central component in ``base.py``, acting as the superclass for all network nodes within a
|
||||||
PrimAITE simulation.
|
PrimAITE simulation.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Node Attributes
|
Node Attributes
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
See :ref:`Node Attributes`
|
||||||
- **hostname**: The network hostname of the node.
|
|
||||||
- **operating_state**: Indicates the current hardware state of the node.
|
|
||||||
- **network_interfaces**: Maps interface names to NetworkInterface objects on the node.
|
|
||||||
- **network_interface**: Maps port IDs to ``NetworkInterface`` objects on the node.
|
|
||||||
- **dns_server**: Specifies DNS servers for domain name resolution.
|
|
||||||
- **start_up_duration**: The time it takes for the node to become fully operational after being powered on.
|
|
||||||
- **shut_down_duration**: The time required for the node to properly shut down.
|
|
||||||
- **sys_log**: A system log for recording events related to the node.
|
|
||||||
- **session_manager**: Manages user sessions within the node.
|
|
||||||
- **software_manager**: Controls the installation and management of software and services on the node.
|
|
||||||
|
|
||||||
.. _Node Start up and Shut down:
|
.. _Node Start up and Shut down:
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ Python
|
|||||||
data_manipulation_bot.configure(server_ip_address=IPv4Address("192.168.1.14"), payload="DELETE")
|
data_manipulation_bot.configure(server_ip_address=IPv4Address("192.168.1.14"), payload="DELETE")
|
||||||
data_manipulation_bot.run()
|
data_manipulation_bot.run()
|
||||||
|
|
||||||
This would connect to the database service at 192.168.1.14, authenticate, and execute the SQL statement to drop the 'users' table.
|
This would connect to the database service at 192.168.1.14, authenticate, and execute the SQL statement to delete database contents.
|
||||||
|
|
||||||
Example with ``DataManipulationAgent``
|
Example with ``DataManipulationAgent``
|
||||||
""""""""""""""""""""""""""""""""""""""
|
""""""""""""""""""""""""""""""""""""""
|
||||||
|
|||||||
@@ -24,12 +24,6 @@ Usage
|
|||||||
- Retrieve results in a dictionary.
|
- Retrieve results in a dictionary.
|
||||||
- Disconnect when finished.
|
- Disconnect when finished.
|
||||||
|
|
||||||
To create database backups:
|
|
||||||
|
|
||||||
- Configure the backup server on the :ref:`DatabaseService` by providing the Backup server ``IPv4Address`` with ``configure_backup``
|
|
||||||
- Create a backup using ``backup_database``. This fails if the backup server is not configured.
|
|
||||||
- Restore a backup using ``restore_backup``. By default, this uses the database created via ``backup_database``.
|
|
||||||
|
|
||||||
Implementation
|
Implementation
|
||||||
==============
|
==============
|
||||||
|
|
||||||
|
|||||||
@@ -13,4 +13,4 @@ The list of applications that are considered system software are:
|
|||||||
|
|
||||||
- ``WebBrowser``
|
- ``WebBrowser``
|
||||||
|
|
||||||
More info :py:mod:`primaite.simulator.network.hardware.nodes.host.host_node.SYSTEM_SOFTWARE`
|
More info :py:mod:`primaite.simulator.network.hardware.nodes.host.host_node.HostNode.SYSTEM_SOFTWARE`
|
||||||
|
|||||||
@@ -15,4 +15,4 @@ The list of services that are considered system software are:
|
|||||||
- ``FTPClient``
|
- ``FTPClient``
|
||||||
- ``NTPClient``
|
- ``NTPClient``
|
||||||
|
|
||||||
More info :py:mod:`primaite.simulator.network.hardware.nodes.host.host_node.SYSTEM_SOFTWARE`
|
More info :py:mod:`primaite.simulator.network.hardware.nodes.host.host_node.HostNode.SYSTEM_SOFTWARE`
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ Software
|
|||||||
Base Software
|
Base Software
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
All software which inherits ``IOSoftware`` installed on a node will not work unless the node has been turned on.
|
Software which inherits ``IOSoftware`` installed on a node will not work unless the node has been turned on.
|
||||||
|
|
||||||
See :ref:`Node Start up and Shut down`
|
See :ref:`Node Start up and Shut down`
|
||||||
|
|
||||||
|
|||||||
@@ -234,7 +234,9 @@ class PrimaiteGame:
|
|||||||
subnet_mask=IPv4Address(node_cfg.get("subnet_mask", "255.255.255.0")),
|
subnet_mask=IPv4Address(node_cfg.get("subnet_mask", "255.255.255.0")),
|
||||||
default_gateway=node_cfg["default_gateway"],
|
default_gateway=node_cfg["default_gateway"],
|
||||||
dns_server=node_cfg.get("dns_server", None),
|
dns_server=node_cfg.get("dns_server", None),
|
||||||
operating_state=NodeOperatingState.ON,
|
operating_state=NodeOperatingState.ON
|
||||||
|
if not (p := node_cfg.get("operating_state"))
|
||||||
|
else NodeOperatingState[p.upper()],
|
||||||
)
|
)
|
||||||
elif n_type == "server":
|
elif n_type == "server":
|
||||||
new_node = Server(
|
new_node = Server(
|
||||||
@@ -243,13 +245,17 @@ class PrimaiteGame:
|
|||||||
subnet_mask=IPv4Address(node_cfg.get("subnet_mask", "255.255.255.0")),
|
subnet_mask=IPv4Address(node_cfg.get("subnet_mask", "255.255.255.0")),
|
||||||
default_gateway=node_cfg["default_gateway"],
|
default_gateway=node_cfg["default_gateway"],
|
||||||
dns_server=node_cfg.get("dns_server", None),
|
dns_server=node_cfg.get("dns_server", None),
|
||||||
operating_state=NodeOperatingState.ON,
|
operating_state=NodeOperatingState.ON
|
||||||
|
if not (p := node_cfg.get("operating_state"))
|
||||||
|
else NodeOperatingState[p.upper()],
|
||||||
)
|
)
|
||||||
elif n_type == "switch":
|
elif n_type == "switch":
|
||||||
new_node = Switch(
|
new_node = Switch(
|
||||||
hostname=node_cfg["hostname"],
|
hostname=node_cfg["hostname"],
|
||||||
num_ports=int(node_cfg.get("num_ports", "8")),
|
num_ports=int(node_cfg.get("num_ports", "8")),
|
||||||
operating_state=NodeOperatingState.ON,
|
operating_state=NodeOperatingState.ON
|
||||||
|
if not (p := node_cfg.get("operating_state"))
|
||||||
|
else NodeOperatingState[p.upper()],
|
||||||
)
|
)
|
||||||
elif n_type == "router":
|
elif n_type == "router":
|
||||||
new_node = Router.from_config(node_cfg)
|
new_node = Router.from_config(node_cfg)
|
||||||
@@ -359,6 +365,8 @@ class PrimaiteGame:
|
|||||||
new_node.shut_down_duration = 0
|
new_node.shut_down_duration = 0
|
||||||
|
|
||||||
net.add_node(new_node)
|
net.add_node(new_node)
|
||||||
|
# run through the power on step if the node is to be turned on at the start
|
||||||
|
if new_node.operating_state == NodeOperatingState.ON:
|
||||||
new_node.power_on()
|
new_node.power_on()
|
||||||
game.ref_map_nodes[node_ref] = new_node.uuid
|
game.ref_map_nodes[node_ref] = new_node.uuid
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# flake8: noqa
|
# flake8: noqa
|
||||||
"""Core of the PrimAITE Simulator."""
|
"""Core of the PrimAITE Simulator."""
|
||||||
from abc import ABC, abstractmethod
|
from abc import abstractmethod
|
||||||
from typing import Callable, ClassVar, Dict, List, Optional, Union
|
from typing import Callable, Dict, List, Optional, Union
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
from pydantic import BaseModel, ConfigDict, Field
|
from pydantic import BaseModel, ConfigDict, Field
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from ipaddress import IPv4Address
|
from ipaddress import IPv4Address
|
||||||
from typing import Any, Dict, Optional
|
from typing import Any, ClassVar, Dict, Optional
|
||||||
|
|
||||||
from primaite import getLogger
|
from primaite import getLogger
|
||||||
from primaite.simulator.network.hardware.base import IPWiredNetworkInterface, Link, Node
|
from primaite.simulator.network.hardware.base import IPWiredNetworkInterface, Link, Node
|
||||||
@@ -253,17 +253,6 @@ class NIC(IPWiredNetworkInterface):
|
|||||||
return f"Port {self.port_num}: {self.mac_address}/{self.ip_address}"
|
return f"Port {self.port_num}: {self.mac_address}/{self.ip_address}"
|
||||||
|
|
||||||
|
|
||||||
SYSTEM_SOFTWARE = {
|
|
||||||
"HostARP": HostARP,
|
|
||||||
"ICMP": ICMP,
|
|
||||||
"DNSClient": DNSClient,
|
|
||||||
"FTPClient": FTPClient,
|
|
||||||
"NTPClient": NTPClient,
|
|
||||||
"WebBrowser": WebBrowser,
|
|
||||||
}
|
|
||||||
"""List of system software that is automatically installed on nodes."""
|
|
||||||
|
|
||||||
|
|
||||||
class HostNode(Node):
|
class HostNode(Node):
|
||||||
"""
|
"""
|
||||||
Represents a host node in the network.
|
Represents a host node in the network.
|
||||||
@@ -308,6 +297,16 @@ class HostNode(Node):
|
|||||||
* Web Browser: Provides web browsing capabilities.
|
* Web Browser: Provides web browsing capabilities.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
SYSTEM_SOFTWARE: ClassVar[Dict] = {
|
||||||
|
"HostARP": HostARP,
|
||||||
|
"ICMP": ICMP,
|
||||||
|
"DNSClient": DNSClient,
|
||||||
|
"FTPClient": FTPClient,
|
||||||
|
"NTPClient": NTPClient,
|
||||||
|
"WebBrowser": WebBrowser,
|
||||||
|
}
|
||||||
|
"""List of system software that is automatically installed on nodes."""
|
||||||
|
|
||||||
network_interfaces: Dict[str, NIC] = {}
|
network_interfaces: Dict[str, NIC] = {}
|
||||||
"The Network Interfaces on the node."
|
"The Network Interfaces on the node."
|
||||||
network_interface: Dict[int, NIC] = {}
|
network_interface: Dict[int, NIC] = {}
|
||||||
@@ -324,7 +323,7 @@ class HostNode(Node):
|
|||||||
This method equips the host with essential network services and applications, preparing it for various
|
This method equips the host with essential network services and applications, preparing it for various
|
||||||
network-related tasks and operations.
|
network-related tasks and operations.
|
||||||
"""
|
"""
|
||||||
for _, software_class in SYSTEM_SOFTWARE.items():
|
for _, software_class in self.SYSTEM_SOFTWARE.items():
|
||||||
self.software_manager.install(software_class)
|
self.software_manager.install(software_class)
|
||||||
|
|
||||||
super()._install_system_software()
|
super()._install_system_software()
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ from primaite.simulator.network.hardware.nodes.network.router import (
|
|||||||
RouterInterface,
|
RouterInterface,
|
||||||
)
|
)
|
||||||
from primaite.simulator.network.transmission.data_link_layer import Frame
|
from primaite.simulator.network.transmission.data_link_layer import Frame
|
||||||
|
from primaite.simulator.network.transmission.network_layer import IPProtocol
|
||||||
|
from primaite.simulator.network.transmission.transport_layer import Port
|
||||||
from primaite.simulator.system.core.sys_log import SysLog
|
from primaite.simulator.system.core.sys_log import SysLog
|
||||||
from primaite.utils.validators import IPV4Address
|
from primaite.utils.validators import IPV4Address
|
||||||
|
|
||||||
@@ -479,7 +481,12 @@ class Firewall(Router):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def from_config(cls, cfg: dict) -> "Firewall":
|
def from_config(cls, cfg: dict) -> "Firewall":
|
||||||
"""Create a firewall based on a config dict."""
|
"""Create a firewall based on a config dict."""
|
||||||
firewall = Firewall(hostname=cfg["hostname"], operating_state=NodeOperatingState.ON)
|
firewall = Firewall(
|
||||||
|
hostname=cfg["hostname"],
|
||||||
|
operating_state=NodeOperatingState.ON
|
||||||
|
if not (p := cfg.get("operating_state"))
|
||||||
|
else NodeOperatingState[p.upper()],
|
||||||
|
)
|
||||||
if "ports" in cfg:
|
if "ports" in cfg:
|
||||||
internal_port = cfg["ports"]["internal_port"]
|
internal_port = cfg["ports"]["internal_port"]
|
||||||
external_port = cfg["ports"]["external_port"]
|
external_port = cfg["ports"]["external_port"]
|
||||||
@@ -505,34 +512,82 @@ class Firewall(Router):
|
|||||||
if "acl" in cfg:
|
if "acl" in cfg:
|
||||||
# acl rules for internal_inbound_acl
|
# acl rules for internal_inbound_acl
|
||||||
if cfg["acl"]["internal_inbound_acl"]:
|
if cfg["acl"]["internal_inbound_acl"]:
|
||||||
firewall.internal_inbound_acl.max_acl_rules
|
for r_num, r_cfg in cfg["acl"]["internal_inbound_acl"].items():
|
||||||
firewall.internal_inbound_acl._default_config = cfg["acl"]["internal_inbound_acl"]
|
firewall.internal_inbound_acl.add_rule(
|
||||||
firewall.internal_inbound_acl._reset_rules_to_default()
|
action=ACLAction[r_cfg["action"]],
|
||||||
|
src_port=None if not (p := r_cfg.get("src_port")) else Port[p],
|
||||||
|
dst_port=None if not (p := r_cfg.get("dst_port")) else Port[p],
|
||||||
|
protocol=None if not (p := r_cfg.get("protocol")) else IPProtocol[p],
|
||||||
|
src_ip_address=r_cfg.get("src_ip"),
|
||||||
|
dst_ip_address=r_cfg.get("dst_ip"),
|
||||||
|
position=r_num,
|
||||||
|
)
|
||||||
|
|
||||||
# acl rules for internal_outbound_acl
|
# acl rules for internal_outbound_acl
|
||||||
if cfg["acl"]["internal_outbound_acl"]:
|
if cfg["acl"]["internal_outbound_acl"]:
|
||||||
firewall.internal_outbound_acl._default_config = cfg["acl"]["internal_outbound_acl"]
|
for r_num, r_cfg in cfg["acl"]["internal_outbound_acl"].items():
|
||||||
firewall.internal_outbound_acl._reset_rules_to_default()
|
firewall.internal_outbound_acl.add_rule(
|
||||||
|
action=ACLAction[r_cfg["action"]],
|
||||||
|
src_port=None if not (p := r_cfg.get("src_port")) else Port[p],
|
||||||
|
dst_port=None if not (p := r_cfg.get("dst_port")) else Port[p],
|
||||||
|
protocol=None if not (p := r_cfg.get("protocol")) else IPProtocol[p],
|
||||||
|
src_ip_address=r_cfg.get("src_ip"),
|
||||||
|
dst_ip_address=r_cfg.get("dst_ip"),
|
||||||
|
position=r_num,
|
||||||
|
)
|
||||||
|
|
||||||
# acl rules for dmz_inbound_acl
|
# acl rules for dmz_inbound_acl
|
||||||
if cfg["acl"]["dmz_inbound_acl"]:
|
if cfg["acl"]["dmz_inbound_acl"]:
|
||||||
firewall.dmz_inbound_acl._default_config = cfg["acl"]["dmz_inbound_acl"]
|
for r_num, r_cfg in cfg["acl"]["dmz_inbound_acl"].items():
|
||||||
firewall.dmz_inbound_acl._reset_rules_to_default()
|
firewall.dmz_inbound_acl.add_rule(
|
||||||
|
action=ACLAction[r_cfg["action"]],
|
||||||
|
src_port=None if not (p := r_cfg.get("src_port")) else Port[p],
|
||||||
|
dst_port=None if not (p := r_cfg.get("dst_port")) else Port[p],
|
||||||
|
protocol=None if not (p := r_cfg.get("protocol")) else IPProtocol[p],
|
||||||
|
src_ip_address=r_cfg.get("src_ip"),
|
||||||
|
dst_ip_address=r_cfg.get("dst_ip"),
|
||||||
|
position=r_num,
|
||||||
|
)
|
||||||
|
|
||||||
# acl rules for dmz_outbound_acl
|
# acl rules for dmz_outbound_acl
|
||||||
if cfg["acl"]["dmz_outbound_acl"]:
|
if cfg["acl"]["dmz_outbound_acl"]:
|
||||||
firewall.dmz_outbound_acl._default_config = cfg["acl"]["dmz_outbound_acl"]
|
for r_num, r_cfg in cfg["acl"]["dmz_outbound_acl"].items():
|
||||||
firewall.dmz_outbound_acl._reset_rules_to_default()
|
firewall.dmz_outbound_acl.add_rule(
|
||||||
|
action=ACLAction[r_cfg["action"]],
|
||||||
|
src_port=None if not (p := r_cfg.get("src_port")) else Port[p],
|
||||||
|
dst_port=None if not (p := r_cfg.get("dst_port")) else Port[p],
|
||||||
|
protocol=None if not (p := r_cfg.get("protocol")) else IPProtocol[p],
|
||||||
|
src_ip_address=r_cfg.get("src_ip"),
|
||||||
|
dst_ip_address=r_cfg.get("dst_ip"),
|
||||||
|
position=r_num,
|
||||||
|
)
|
||||||
|
|
||||||
# acl rules for external_inbound_acl
|
# acl rules for external_inbound_acl
|
||||||
if cfg["acl"]["external_inbound_acl"]:
|
if cfg["acl"]["external_inbound_acl"]:
|
||||||
firewall.external_inbound_acl._default_config = cfg["acl"]["external_inbound_acl"]
|
for r_num, r_cfg in cfg["acl"]["external_inbound_acl"].items():
|
||||||
firewall.external_inbound_acl._reset_rules_to_default()
|
firewall.external_inbound_acl.add_rule(
|
||||||
|
action=ACLAction[r_cfg["action"]],
|
||||||
|
src_port=None if not (p := r_cfg.get("src_port")) else Port[p],
|
||||||
|
dst_port=None if not (p := r_cfg.get("dst_port")) else Port[p],
|
||||||
|
protocol=None if not (p := r_cfg.get("protocol")) else IPProtocol[p],
|
||||||
|
src_ip_address=r_cfg.get("src_ip"),
|
||||||
|
dst_ip_address=r_cfg.get("dst_ip"),
|
||||||
|
position=r_num,
|
||||||
|
)
|
||||||
|
|
||||||
# acl rules for external_outbound_acl
|
# acl rules for external_outbound_acl
|
||||||
if cfg["acl"]["external_outbound_acl"]:
|
if cfg["acl"]["external_outbound_acl"]:
|
||||||
firewall.external_outbound_acl._default_config = cfg["acl"]["external_outbound_acl"]
|
for r_num, r_cfg in cfg["acl"]["external_outbound_acl"].items():
|
||||||
firewall.external_outbound_acl._reset_rules_to_default()
|
firewall.external_outbound_acl.add_rule(
|
||||||
|
action=ACLAction[r_cfg["action"]],
|
||||||
|
src_port=None if not (p := r_cfg.get("src_port")) else Port[p],
|
||||||
|
dst_port=None if not (p := r_cfg.get("dst_port")) else Port[p],
|
||||||
|
protocol=None if not (p := r_cfg.get("protocol")) else IPProtocol[p],
|
||||||
|
src_ip_address=r_cfg.get("src_ip"),
|
||||||
|
dst_ip_address=r_cfg.get("dst_ip"),
|
||||||
|
position=r_num,
|
||||||
|
)
|
||||||
|
|
||||||
if "routes" in cfg:
|
if "routes" in cfg:
|
||||||
for route in cfg.get("routes"):
|
for route in cfg.get("routes"):
|
||||||
firewall.route_table.add_route(
|
firewall.route_table.add_route(
|
||||||
|
|||||||
@@ -1401,7 +1401,9 @@ class Router(NetworkNode):
|
|||||||
router = Router(
|
router = Router(
|
||||||
hostname=cfg["hostname"],
|
hostname=cfg["hostname"],
|
||||||
num_ports=int(cfg.get("num_ports", "5")),
|
num_ports=int(cfg.get("num_ports", "5")),
|
||||||
operating_state=NodeOperatingState.ON,
|
operating_state=NodeOperatingState.ON
|
||||||
|
if not (p := cfg.get("operating_state"))
|
||||||
|
else NodeOperatingState[p.upper()],
|
||||||
)
|
)
|
||||||
if "ports" in cfg:
|
if "ports" in cfg:
|
||||||
for port_num, port_cfg in cfg["ports"].items():
|
for port_num, port_cfg in cfg["ports"].items():
|
||||||
|
|||||||
@@ -141,6 +141,17 @@ simulation:
|
|||||||
default_gateway: 192.168.10.1
|
default_gateway: 192.168.10.1
|
||||||
dns_server: 192.168.1.10
|
dns_server: 192.168.1.10
|
||||||
# pre installed services and applications
|
# pre installed services and applications
|
||||||
|
- ref: client_3
|
||||||
|
type: computer
|
||||||
|
hostname: client_3
|
||||||
|
ip_address: 192.168.10.23
|
||||||
|
subnet_mask: 255.255.255.0
|
||||||
|
default_gateway: 192.168.10.1
|
||||||
|
dns_server: 192.168.1.10
|
||||||
|
start_up_duration: 0
|
||||||
|
shut_down_duration: 0
|
||||||
|
operating_state: "OFF"
|
||||||
|
# pre installed services and applications
|
||||||
|
|
||||||
links:
|
links:
|
||||||
- ref: switch_1___client_1
|
- ref: switch_1___client_1
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
from primaite.config.load import example_config_path
|
from primaite.config.load import example_config_path
|
||||||
from primaite.simulator.network.container import Network
|
from primaite.simulator.network.container import Network
|
||||||
from tests.integration_tests.configuration_file_parsing import DMZ_NETWORK, load_config
|
from primaite.simulator.network.hardware.node_operating_state import NodeOperatingState
|
||||||
|
from primaite.simulator.network.hardware.nodes.host.computer import Computer
|
||||||
|
from tests.integration_tests.configuration_file_parsing import BASIC_CONFIG, DMZ_NETWORK, load_config
|
||||||
|
|
||||||
|
|
||||||
def test_example_config():
|
def test_example_config():
|
||||||
@@ -24,3 +26,19 @@ def test_dmz_config():
|
|||||||
assert len(network.routers) == 2 # 2 routers in network
|
assert len(network.routers) == 2 # 2 routers in network
|
||||||
assert len(network.switches) == 3 # 3 switches in network
|
assert len(network.switches) == 3 # 3 switches in network
|
||||||
assert len(network.servers) == 2 # 2 servers in network
|
assert len(network.servers) == 2 # 2 servers in network
|
||||||
|
|
||||||
|
|
||||||
|
def test_basic_config():
|
||||||
|
"""Test that the basic_switched_network config can be parsed properly."""
|
||||||
|
game = load_config(BASIC_CONFIG)
|
||||||
|
network: Network = game.simulation.network
|
||||||
|
assert len(network.nodes) == 4 # 4 nodes in network
|
||||||
|
|
||||||
|
client_1: Computer = network.get_node_by_hostname("client_1")
|
||||||
|
assert client_1.operating_state == NodeOperatingState.ON
|
||||||
|
client_2: Computer = network.get_node_by_hostname("client_2")
|
||||||
|
assert client_2.operating_state == NodeOperatingState.ON
|
||||||
|
|
||||||
|
# client 3 should not be online
|
||||||
|
client_3: Computer = network.get_node_by_hostname("client_3")
|
||||||
|
assert client_3.operating_state == NodeOperatingState.OFF
|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
from ipaddress import IPv4Address
|
from ipaddress import IPv4Address
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
from primaite.game.game import APPLICATION_TYPES_MAPPING, SERVICE_TYPES_MAPPING
|
import yaml
|
||||||
|
|
||||||
|
from primaite.config.load import example_config_path
|
||||||
|
from primaite.game.agent.data_manipulation_bot import DataManipulationAgent
|
||||||
|
from primaite.game.agent.interface import ProxyAgent, RandomAgent
|
||||||
|
from primaite.game.game import APPLICATION_TYPES_MAPPING, PrimaiteGame, SERVICE_TYPES_MAPPING
|
||||||
|
from primaite.simulator.network.container import Network
|
||||||
from primaite.simulator.network.hardware.nodes.host.computer import Computer
|
from primaite.simulator.network.hardware.nodes.host.computer import Computer
|
||||||
from primaite.simulator.system.applications.database_client import DatabaseClient
|
from primaite.simulator.system.applications.database_client import DatabaseClient
|
||||||
from primaite.simulator.system.applications.red_applications.data_manipulation_bot import DataManipulationBot
|
from primaite.simulator.system.applications.red_applications.data_manipulation_bot import DataManipulationBot
|
||||||
|
|||||||
Reference in New Issue
Block a user