#2769: initial commit of user account actions
This commit is contained in:
@@ -52,7 +52,7 @@ license-files = ["LICENSE"]
|
|||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
rl = [
|
rl = [
|
||||||
"ray[rllib] >= 2.20.0, < 3",
|
"ray[rllib] >= 2.32.0, < 3",
|
||||||
"tensorflow==2.12.0",
|
"tensorflow==2.12.0",
|
||||||
"stable-baselines3[extra]==2.1.0",
|
"stable-baselines3[extra]==2.1.0",
|
||||||
"sb3-contrib==2.1.0",
|
"sb3-contrib==2.1.0",
|
||||||
|
|||||||
@@ -1071,6 +1071,39 @@ class NodeNetworkServiceReconAction(AbstractAction):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class NodeAccountsChangePasswordAction(AbstractAction):
|
||||||
|
"""Action which changes the password for a user."""
|
||||||
|
|
||||||
|
def __init__(self, manager: "ActionManager", **kwargs) -> None:
|
||||||
|
super().__init__(manager=manager)
|
||||||
|
|
||||||
|
def form_request(self) -> RequestFormat:
|
||||||
|
"""Return the action formatted as a request which can be ingested by the PrimAITE simulation."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class NodeSessionsRemoteLoginAction(AbstractAction):
|
||||||
|
"""Action which performs a remote session login."""
|
||||||
|
|
||||||
|
def __init__(self, manager: "ActionManager", **kwargs) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def form_request(self, node_id: str) -> RequestFormat:
|
||||||
|
"""Return the action formatted as a request which can be ingested by the PrimAITE simulation."""
|
||||||
|
return ["network", "node", node_id, "remote_logon"]
|
||||||
|
|
||||||
|
|
||||||
|
class NodeSessionsRemoteLogoutAction(AbstractAction):
|
||||||
|
"""Action which performs a remote session logout."""
|
||||||
|
|
||||||
|
def __init__(self, manager: "ActionManager", **kwargs) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def form_request(self, node_id: str) -> RequestFormat:
|
||||||
|
"""Return the action formatted as a request which can be ingested by the PrimAITE simulation."""
|
||||||
|
return ["network", "node", node_id, "remote_logoff"]
|
||||||
|
|
||||||
|
|
||||||
class ActionManager:
|
class ActionManager:
|
||||||
"""Class which manages the action space for an agent."""
|
"""Class which manages the action space for an agent."""
|
||||||
|
|
||||||
@@ -1122,6 +1155,9 @@ class ActionManager:
|
|||||||
"CONFIGURE_DATABASE_CLIENT": ConfigureDatabaseClientAction,
|
"CONFIGURE_DATABASE_CLIENT": ConfigureDatabaseClientAction,
|
||||||
"CONFIGURE_RANSOMWARE_SCRIPT": ConfigureRansomwareScriptAction,
|
"CONFIGURE_RANSOMWARE_SCRIPT": ConfigureRansomwareScriptAction,
|
||||||
"CONFIGURE_DOSBOT": ConfigureDoSBotAction,
|
"CONFIGURE_DOSBOT": ConfigureDoSBotAction,
|
||||||
|
"NODE_ACCOUNTS_CHANGEPASSWORD": NodeAccountsChangePasswordAction,
|
||||||
|
"NODE_SESSIONS_REMOTE_LOGIN": NodeSessionsRemoteLoginAction,
|
||||||
|
"NODE_SESSIONS_REMOTE_LOGOUT": NodeSessionsRemoteLogoutAction,
|
||||||
}
|
}
|
||||||
"""Dictionary which maps action type strings to the corresponding action class."""
|
"""Dictionary which maps action type strings to the corresponding action class."""
|
||||||
|
|
||||||
|
|||||||
@@ -1072,6 +1072,15 @@ class Node(SimComponent):
|
|||||||
"logoff", RequestType(func=lambda request, context: RequestResponse.from_bool(False), validator=_node_is_on)
|
"logoff", RequestType(func=lambda request, context: RequestResponse.from_bool(False), validator=_node_is_on)
|
||||||
) # TODO implement logoff request
|
) # TODO implement logoff request
|
||||||
|
|
||||||
|
rm.add_request(
|
||||||
|
"remote_logon",
|
||||||
|
RequestType(func=lambda request, context: RequestResponse.from_bool(False), validator=_node_is_on),
|
||||||
|
) # TODO implement remote_logon request
|
||||||
|
rm.add_request(
|
||||||
|
"remote_logoff",
|
||||||
|
RequestType(func=lambda request, context: RequestResponse.from_bool(False), validator=_node_is_on),
|
||||||
|
) # TODO implement remote_logoff request
|
||||||
|
|
||||||
self._os_request_manager = RequestManager()
|
self._os_request_manager = RequestManager()
|
||||||
self._os_request_manager.add_request(
|
self._os_request_manager.add_request(
|
||||||
"scan",
|
"scan",
|
||||||
|
|||||||
@@ -458,6 +458,9 @@ def game_and_agent():
|
|||||||
{"type": "HOST_NIC_DISABLE"},
|
{"type": "HOST_NIC_DISABLE"},
|
||||||
{"type": "NETWORK_PORT_ENABLE"},
|
{"type": "NETWORK_PORT_ENABLE"},
|
||||||
{"type": "NETWORK_PORT_DISABLE"},
|
{"type": "NETWORK_PORT_DISABLE"},
|
||||||
|
{"type": "NODE_ACCOUNTS_CHANGEPASSWORD"},
|
||||||
|
{"type": "NODE_SESSIONS_REMOTE_LOGIN"},
|
||||||
|
{"type": "NODE_SESSIONS_REMOTE_LOGOUT"},
|
||||||
]
|
]
|
||||||
|
|
||||||
action_space = ActionManager(
|
action_space = ActionManager(
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK
|
||||||
|
|
||||||
|
|
||||||
|
def test_remote_logon(game_and_agent):
|
||||||
|
"""Test that the remote session login action works."""
|
||||||
|
game, agent = game_and_agent
|
||||||
|
|
||||||
|
action = (
|
||||||
|
"NODE_SESSIONS_REMOTE_LOGIN",
|
||||||
|
{"node_id": 0},
|
||||||
|
)
|
||||||
|
agent.store_action(action)
|
||||||
|
game.step()
|
||||||
|
|
||||||
|
# TODO Assert that there is a logged in user
|
||||||
|
|
||||||
|
|
||||||
|
def test_remote_logoff(game_and_agent):
|
||||||
|
"""Test that the remote session logout action works."""
|
||||||
|
game, agent = game_and_agent
|
||||||
|
|
||||||
|
action = (
|
||||||
|
"NODE_SESSIONS_REMOTE_LOGIN",
|
||||||
|
{"node_id": 0},
|
||||||
|
)
|
||||||
|
agent.store_action(action)
|
||||||
|
game.step()
|
||||||
|
|
||||||
|
# TODO Assert that there is a logged in user
|
||||||
|
|
||||||
|
action = (
|
||||||
|
"NODE_SESSIONS_REMOTE_LOGOUT",
|
||||||
|
{"node_id": 0},
|
||||||
|
)
|
||||||
|
agent.store_action(action)
|
||||||
|
game.step()
|
||||||
|
|
||||||
|
# TODO Assert the user has logged out
|
||||||
Reference in New Issue
Block a user