2023-07-31 20:05:36 +01:00
|
|
|
.. only:: comment
|
|
|
|
|
|
2024-06-05 09:11:37 +01:00
|
|
|
© Crown-owned copyright 2024, Defence Science and Technology Laboratory UK
|
2023-07-31 20:05:36 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
Simulation Structure
|
|
|
|
|
====================
|
|
|
|
|
|
|
|
|
|
The simulation is made up of many smaller components which are related to each other in a tree-like structure. At the
|
2023-08-21 09:49:31 +01:00
|
|
|
top level, there is the :py:meth:`primaite.simulator.sim_container.Simulation`, which keeps track of the physical network
|
|
|
|
|
and a domain controller for managing software and users.
|
|
|
|
|
|
|
|
|
|
Each node of the simulation 'tree' has responsibility for creating, deleting, and updating its direct descendants. Also,
|
|
|
|
|
when a component's ``describe_state()`` method is called, it will include the state of its descendants. The
|
2024-02-23 08:55:32 +00:00
|
|
|
``apply_request()`` method can be used to act on a component or one of its descendants. The diagram below shows the
|
2023-08-21 09:49:31 +01:00
|
|
|
relationship between components.
|
|
|
|
|
|
2024-02-23 08:55:32 +00:00
|
|
|
.. image:: ../../_static/component_relationship.png
|
2023-08-21 09:49:31 +01:00
|
|
|
:width: 500
|
2024-02-23 08:55:32 +00:00
|
|
|
:align: center
|
|
|
|
|
:alt: :: The top level simulation object owns a NetworkContainer and a DomainController. The DomainController has a
|
|
|
|
|
list of accounts. The network container has links and nodes. Nodes can own switchports, NICs, FileSystem,
|
|
|
|
|
Application, Service, and Process.
|
2023-08-07 10:55:29 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
Actions
|
|
|
|
|
=======
|
|
|
|
|
Agents can interact with the simulation by using actions. Actions are standardised with the
|
2023-10-25 23:32:52 +01:00
|
|
|
:py:class:`primaite.simulation.core.RequestType` class, which just holds a reference to two special functions.
|
2023-08-07 10:55:29 +01:00
|
|
|
|
2023-10-25 23:32:52 +01:00
|
|
|
1. The request function itself, it must accept a `request` parameters which is a list of strings that describe what the
|
2023-08-07 10:55:29 +01:00
|
|
|
action should do. It must also accept a `context` dict which can house additional information surrounding the action.
|
|
|
|
|
For example, the context will typically include information about which entity intiated the action.
|
|
|
|
|
2. A validator function. This function should return a boolean value that decides if the request is permitted or not.
|
|
|
|
|
It uses the same paramters as the action function.
|
|
|
|
|
|
|
|
|
|
Action Permissions
|
|
|
|
|
------------------
|
|
|
|
|
When an agent tries to perform an action on a simulation component, that action will only be executed if the request is
|
|
|
|
|
validated. For example, some actions can require that an agent is logged into an admin account. Each action defines its
|
|
|
|
|
own permissions using an instance of :py:class:`primaite.simulation.core.ActionPermissionValidator`. The below code
|
|
|
|
|
snippet demonstrates usage of the ``ActionPermissionValidator``.
|
|
|
|
|
|
|
|
|
|
.. code:: python
|
|
|
|
|
|
2023-10-09 13:24:08 +01:00
|
|
|
from primaite.simulator.core import Action, RequestManager, SimComponent
|
2023-08-07 10:55:29 +01:00
|
|
|
from primaite.simulator.domain.controller import AccountGroup, GroupMembershipValidator
|
|
|
|
|
|
|
|
|
|
class Smartphone(SimComponent):
|
|
|
|
|
name: str
|
|
|
|
|
apps = []
|
|
|
|
|
|
2023-10-09 13:24:08 +01:00
|
|
|
def _init_request_manager(self) -> RequestManager:
|
|
|
|
|
am = super()._init_request_manager()
|
2023-10-10 09:52:40 +01:00
|
|
|
am.add_request(
|
2023-08-07 10:55:29 +01:00
|
|
|
"reset_factory_settings",
|
|
|
|
|
Action(
|
|
|
|
|
func = lambda request, context: self.reset_factory_settings(),
|
2023-08-09 12:34:56 +01:00
|
|
|
validator = GroupMembershipValidator([AccountGroup.DOMAIN_ADMIN]),
|
2023-08-29 11:10:29 +01:00
|
|
|
)
|
2023-08-07 10:55:29 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def reset_factory_settings(self):
|
|
|
|
|
self.apps = []
|
|
|
|
|
|
|
|
|
|
phone = Smartphone(name="phone1")
|
|
|
|
|
|
|
|
|
|
# try to wipe the phone as a domain user, this will have no effect
|
2023-08-09 12:34:56 +01:00
|
|
|
phone.apply_action(["reset_factory_settings"], context={"request_source":{"groups":["DOMAIN_USER"]})
|
2023-08-07 10:55:29 +01:00
|
|
|
|
|
|
|
|
# try to wipe the phone as an admin user, this will wipe the phone
|
2023-08-09 12:34:56 +01:00
|
|
|
phone.apply_action(["reset_factory_settings"], context={"request_source":{"groups":["DOMAIN_ADMIN"]})
|