#1943: web server + client + tests + a few improvements to syslogging

This commit is contained in:
Czar.Echavez
2023-10-03 14:59:48 +01:00
parent 161d441ad6
commit 4b5a73bd32
24 changed files with 536 additions and 112 deletions

View File

@@ -714,7 +714,9 @@ class ARPCache:
# Unmatched ARP Request
if arp_packet.target_ip_address != from_nic.ip_address:
self.sys_log.info(f"Ignoring ARP request for {arp_packet.target_ip_address}")
self.sys_log.info(
f"Ignoring ARP request for {arp_packet.target_ip_address}. Current IP address is {from_nic.ip_address}"
)
return
# Matched ARP request
@@ -937,6 +939,12 @@ class Node(SimComponent):
self.arp.nics = self.nics
self.session_manager.software_manager = self.software_manager
self._install_system_software()
def _install_system_software(self):
"""Install System Software - software that is usually provided with the OS."""
pass
def describe_state(self) -> Dict:
"""
Produce a dictionary describing the current state of this object.

View File

@@ -1,4 +1,8 @@
from primaite.simulator.network.hardware.base import NIC, Node
from primaite.simulator.system.applications.web_browser import WebBrowser
from primaite.simulator.system.services.dns.dns_client import DNSClient
from primaite.simulator.system.services.ftp.ftp_client import FTPClient
from primaite.simulator.system.services.ftp.ftp_server import FTPServer
class Computer(Node):
@@ -36,3 +40,18 @@ class Computer(Node):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.connect_nic(NIC(ip_address=kwargs["ip_address"], subnet_mask=kwargs["subnet_mask"]))
self._install_system_software()
def _install_system_software(self):
"""Install System Software - software that is usually provided with the OS."""
# DNS Client
self.software_manager.install(DNSClient)
# FTP
self.software_manager.install(FTPClient)
self.software_manager.install(FTPServer)
# Web Browser
self.software_manager.install(WebBrowser)
super()._install_system_software()

View File

@@ -596,6 +596,8 @@ class Router(Node):
self.arp.nics = self.nics
self.icmp.arp = self.arp
self._install_system_software()
def _get_port_of_nic(self, target_nic: NIC) -> Optional[int]:
"""
Retrieve the port number for a given NIC.

View File

@@ -34,6 +34,8 @@ class Switch(Node):
port.parent = self
port.port_num = port_num
self._install_system_software()
def show(self, markdown: bool = False):
"""
Prints a table of the SwitchPorts on the Switch.

View File

@@ -13,8 +13,8 @@ from primaite.simulator.system.services.database.database_service import Databas
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.red_services.data_manipulation_bot import DataManipulationBot
from primaite.simulator.system.services.web_server.web_server_service import WebServerService
def client_server_routed() -> Network:
@@ -260,6 +260,8 @@ def arcd_uc2_network() -> Network:
database_client.run()
database_client.connect()
web_server.software_manager.install(WebServerService)
# register the web_server to a domain
dns_server_service: DNSServer = domain_controller.software_manager.software["DNSServer"] # noqa
dns_server_service.dns_register("arcd.com", web_server.ip_address)
@@ -275,8 +277,6 @@ def arcd_uc2_network() -> Network:
backup_server.power_on()
network.connect(endpoint_b=backup_server.ethernet_port[1], endpoint_a=switch_1.switch_ports[4])
backup_server.software_manager.install(FTPServer)
# Security Suite
security_suite = Server(
hostname="security_suite",
@@ -305,4 +305,7 @@ def arcd_uc2_network() -> Network:
# Allow FTP requests
router_1.acl.add_rule(action=ACLAction.PERMIT, src_port=Port.FTP, dst_port=Port.FTP, position=2)
# Open port 80 for web server
router_1.acl.add_rule(action=ACLAction.PERMIT, src_port=Port.HTTP, dst_port=Port.HTTP, position=3)
return network

View File

@@ -0,0 +1,61 @@
from enum import Enum
from primaite.simulator.network.protocols.packet import DataPacket
class HTTPRequestMethod(Enum):
"""Enum list of HTTP Request methods that can be handled by the simulation."""
GET = "GET"
"""HTTP GET Method. Requests using GET should only retrieve data."""
HEAD = "HEAD"
"""Asks for a response identical to a GET request, but without the response body."""
POST = "POST"
"""Submit an entity to the specified resource, often causing a change in state or side effects on the server."""
PUT = "PUT"
"""Replace all current representations of the target resource with the request payload."""
DELETE = "DELETE"
"""Delete the specified resource."""
PATCH = "PATCH"
"""Apply partial modifications to a resource."""
class HTTPStatusCode(Enum):
"""List of available HTTP Statuses."""
OK = 200
"""request has succeeded."""
BAD_REQUEST = 400
"""Payload cannot be parsed."""
UNAUTHORIZED = 401
"""Auth required."""
METHOD_NOT_ALLOWED = 405
"""Method is not supported by server."""
INTERNAL_SERVER_ERROR = 500
"""Error on the server side."""
class HTTPRequestPacket(DataPacket):
"""Class that represents an HTTP Request Packet."""
request_method: HTTPRequestMethod
"""The HTTP Request method."""
request_url: str
"""URL of request."""
class HTTPResponsePacket(DataPacket):
"""Class that reprensents an HTTP Response Packet."""
status_code: HTTPStatusCode = None
"""Status code of the HTTP response."""

View File

@@ -1,9 +1,14 @@
from typing import Any
from pydantic import BaseModel
class DataPacket(BaseModel):
"""Data packet abstract class."""
payload: Any = None
"""Payload content of the packet."""
packet_payload_size: float = 0
"""Size of the packet."""