Merged PR 270: #2258: DoSBot cannot be added via configuration file

## Summary
- Added ability to set DoSBot in nodes via config file
- Fixed missing configuration items in other services/applications
- Created a variable which contains the list of applications and services
- Moved `DatabaseClient` from list of services to list of applications

## Test process
Created a configuration file where a node has all services and applications installed, this is then used by an integration test which loads the configuration file. The test checks to make sure that the configuration file is correctly read and the Service and Application objects are properly created

## Checklist
- [X] PR is linked to a **work item**
- [ ] **acceptance criteria** of linked ticket are met
- [X] performed **self-review** of the code
- [X] written **tests** for any new functionality added with this PR
- [ ] updated the **documentation** if this PR changes or adds functionality
- [ ] written/updated **design docs** if this PR implements new functionality
- [ ] updated the **change log**
- [ ] ran **pre-commit** checks for code style
- [ ] attended to any **TO-DOs** left in the code

Related work items: #2258
This commit is contained in:
Czar Echavez
2024-02-15 09:36:08 +00:00
3 changed files with 428 additions and 26 deletions

View File

@@ -0,0 +1,220 @@
from ipaddress import IPv4Address
from pathlib import Path
from typing import Union
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.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.dos_bot import DoSBot
from primaite.simulator.system.applications.web_browser import WebBrowser
from primaite.simulator.system.services.database.database_service import DatabaseService
from primaite.simulator.system.services.dns.dns_client import DNSClient
from primaite.simulator.system.services.dns.dns_server import DNSServer
from primaite.simulator.system.services.ftp.ftp_client import FTPClient
from primaite.simulator.system.services.ftp.ftp_server import FTPServer
from primaite.simulator.system.services.ntp.ntp_client import NTPClient
from primaite.simulator.system.services.ntp.ntp_server import NTPServer
from primaite.simulator.system.services.web_server.web_server import WebServer
from tests import TEST_ASSETS_ROOT
BASIC_CONFIG = TEST_ASSETS_ROOT / "configs/basic_switched_network.yaml"
def load_config(config_path: Union[str, Path]) -> PrimaiteGame:
"""Returns a PrimaiteGame object which loads the contents of a given yaml path."""
with open(config_path, "r") as f:
cfg = yaml.safe_load(f)
return PrimaiteGame.from_config(cfg)
def test_example_config():
"""Test that the example config can be parsed properly."""
game = load_config(example_config_path())
assert len(game.agents) == 4 # red, blue and 2 green agents
# green agent 1
assert game.agents[0].agent_name == "client_2_green_user"
assert isinstance(game.agents[0], RandomAgent)
# green agent 2
assert game.agents[1].agent_name == "client_1_green_user"
assert isinstance(game.agents[1], RandomAgent)
# red agent
assert game.agents[2].agent_name == "client_1_data_manipulation_red_bot"
assert isinstance(game.agents[2], DataManipulationAgent)
# blue agent
assert game.agents[3].agent_name == "defender"
assert isinstance(game.agents[3], ProxyAgent)
network: Network = game.simulation.network
assert len(network.nodes) == 10 # 10 nodes in example network
assert len(network.routers) == 1 # 1 router in network
assert len(network.switches) == 2 # 2 switches in network
assert len(network.servers) == 5 # 5 servers in network
def test_node_software_install():
"""Test that software can be installed on a node."""
game = load_config(BASIC_CONFIG)
client_1: Computer = game.simulation.network.get_node_by_hostname("client_1")
client_2: Computer = game.simulation.network.get_node_by_hostname("client_2")
system_software = {DNSClient, FTPClient, NTPClient, WebBrowser}
# check that system software is installed on client 1
for software in system_software:
assert client_1.software_manager.software.get(software.__name__) is not None
# check that system software is installed on client 2
for software in system_software:
assert client_2.software_manager.software.get(software.__name__) is not None
# check that applications have been installed on client 1
for applications in APPLICATION_TYPES_MAPPING:
assert client_1.software_manager.software.get(applications) is not None
# check that services have been installed on client 1
for service in SERVICE_TYPES_MAPPING:
assert client_1.software_manager.software.get(service) is not None
def test_web_browser_install():
"""Test that the web browser can be configured via config."""
game = load_config(BASIC_CONFIG)
client_1: Computer = game.simulation.network.get_node_by_hostname("client_1")
web_browser: WebBrowser = client_1.software_manager.software.get("WebBrowser")
assert web_browser.target_url == "http://arcd.com/users/"
def test_database_client_install():
"""Test that the Database Client service can be configured via config."""
game = load_config(BASIC_CONFIG)
client_1: Computer = game.simulation.network.get_node_by_hostname("client_1")
database_client: DatabaseClient = client_1.software_manager.software.get("DatabaseClient")
assert database_client.server_ip_address == IPv4Address("192.168.1.10")
assert database_client.server_password == "arcd"
def test_data_manipulation_bot_install():
"""Test that the data manipulation bot can be configured via config."""
game = load_config(BASIC_CONFIG)
client_1: Computer = game.simulation.network.get_node_by_hostname("client_1")
data_manipulation_bot: DataManipulationBot = client_1.software_manager.software.get("DataManipulationBot")
assert data_manipulation_bot.server_ip_address == IPv4Address("192.168.1.21")
assert data_manipulation_bot.payload == "DELETE"
assert data_manipulation_bot.data_manipulation_p_of_success == 0.8
assert data_manipulation_bot.port_scan_p_of_success == 0.8
assert data_manipulation_bot.server_password == "arcd"
def test_dos_bot_install():
"""Test that the denial of service bot can be configured via config."""
game = load_config(BASIC_CONFIG)
client_1: Computer = game.simulation.network.get_node_by_hostname("client_1")
dos_bot: DoSBot = client_1.software_manager.software.get("DoSBot")
assert dos_bot.target_ip_address == IPv4Address("192.168.10.21")
assert dos_bot.payload == "SPOOF DATA"
assert dos_bot.port_scan_p_of_success == 0.8
assert dos_bot.dos_intensity == 1.0 # default
assert dos_bot.max_sessions == 1000 # default
assert dos_bot.repeat is False # default
def test_dns_client_install():
"""Test that the DNS Client service can be configured via config."""
game = load_config(BASIC_CONFIG)
client_1: Computer = game.simulation.network.get_node_by_hostname("client_1")
dns_client: DNSClient = client_1.software_manager.software.get("DNSClient")
assert dns_client.dns_server == IPv4Address("192.168.1.10")
def test_dns_server_install():
"""Test that the DNS Client service can be configured via config."""
game = load_config(BASIC_CONFIG)
client_1: Computer = game.simulation.network.get_node_by_hostname("client_1")
dns_server: DNSServer = client_1.software_manager.software.get("DNSServer")
assert dns_server.dns_lookup("arcd.com") == IPv4Address("192.168.1.10")
def test_database_service_install():
"""Test that the Database Service can be configured via config."""
game = load_config(BASIC_CONFIG)
client_1: Computer = game.simulation.network.get_node_by_hostname("client_1")
database_service: DatabaseService = client_1.software_manager.software.get("DatabaseService")
assert database_service.backup_server_ip == IPv4Address("192.168.1.10")
def test_web_server_install():
"""Test that the Web Server Service can be configured via config."""
game = load_config(BASIC_CONFIG)
client_1: Computer = game.simulation.network.get_node_by_hostname("client_1")
web_server_service: WebServer = client_1.software_manager.software.get("WebServer")
# config should have also installed database client - web server service should be able to retrieve this
assert web_server_service.software_manager.software.get("DatabaseClient") is not None
def test_ftp_client_install():
"""Test that the FTP Client Service can be configured via config."""
game = load_config(BASIC_CONFIG)
client_1: Computer = game.simulation.network.get_node_by_hostname("client_1")
ftp_client_service: FTPClient = client_1.software_manager.software.get("FTPClient")
assert ftp_client_service is not None
def test_ftp_server_install():
"""Test that the FTP Server Service can be configured via config."""
game = load_config(BASIC_CONFIG)
client_1: Computer = game.simulation.network.get_node_by_hostname("client_1")
ftp_server_service: FTPServer = client_1.software_manager.software.get("FTPServer")
assert ftp_server_service is not None
assert ftp_server_service.server_password == "arcd"
def test_ntp_client_install():
"""Test that the NTP Client Service can be configured via config."""
game = load_config(BASIC_CONFIG)
client_1: Computer = game.simulation.network.get_node_by_hostname("client_1")
ntp_client_service: NTPClient = client_1.software_manager.software.get("NTPClient")
assert ntp_client_service is not None
assert ntp_client_service.ntp_server == IPv4Address("192.168.1.10")
def test_ntp_server_install():
"""Test that the NTP Server Service can be configured via config."""
game = load_config(BASIC_CONFIG)
client_1: Computer = game.simulation.network.get_node_by_hostname("client_1")
ntp_server_service: NTPServer = client_1.software_manager.software.get("NTPServer")
assert ntp_server_service is not None