#2769 - add actions and tests for terminal
This commit is contained in:
@@ -458,9 +458,10 @@ def game_and_agent():
|
||||
{"type": "HOST_NIC_DISABLE"},
|
||||
{"type": "NETWORK_PORT_ENABLE"},
|
||||
{"type": "NETWORK_PORT_DISABLE"},
|
||||
{"type": "NODE_ACCOUNTS_CHANGEPASSWORD"},
|
||||
{"type": "NODE_SESSIONS_REMOTE_LOGIN"},
|
||||
{"type": "NODE_SESSIONS_REMOTE_LOGOUT"},
|
||||
{"type": "NODE_ACCOUNTS_CHANGE_PASSWORD"},
|
||||
{"type": "SSH_TO_REMOTE"},
|
||||
{"type": "SSH_LOGOUT_LOGOUT"},
|
||||
{"type": "NODE_SEND_REMOTE_COMMAND"},
|
||||
]
|
||||
|
||||
action_space = ActionManager(
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK
|
||||
from typing import Tuple
|
||||
|
||||
import pytest
|
||||
|
||||
from primaite.game.agent.interface import ProxyAgent
|
||||
from primaite.game.game import PrimaiteGame
|
||||
from primaite.simulator.network.hardware.base import UserManager
|
||||
from primaite.simulator.network.hardware.nodes.host.computer import Computer
|
||||
from primaite.simulator.network.hardware.nodes.host.server import Server
|
||||
from primaite.simulator.system.services.service import ServiceOperatingState
|
||||
from primaite.simulator.system.services.terminal.terminal import RemoteTerminalConnection
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def game_and_agent_fixture(game_and_agent):
|
||||
"""Create a game with a simple agent that can be controlled by the tests."""
|
||||
game, agent = game_and_agent
|
||||
|
||||
client_1: Computer = game.simulation.network.get_node_by_hostname("client_1")
|
||||
client_1.start_up_duration = 3
|
||||
|
||||
return (game, agent)
|
||||
|
||||
|
||||
def test_remote_login(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]):
|
||||
game, agent = game_and_agent_fixture
|
||||
|
||||
server_1: Server = game.simulation.network.get_node_by_hostname("server_1")
|
||||
client_1 = game.simulation.network.get_node_by_hostname("client_1")
|
||||
|
||||
# create a new user account on server_1 that will be logged into remotely
|
||||
server_1_usm: UserManager = server_1.software_manager.software["UserManager"]
|
||||
server_1_usm.add_user("user123", "password", is_admin=True)
|
||||
|
||||
action = (
|
||||
"SSH_TO_REMOTE",
|
||||
{
|
||||
"node_id": 0,
|
||||
"username": "user123",
|
||||
"password": "password",
|
||||
"remote_ip": str(server_1.network_interface[1].ip_address),
|
||||
},
|
||||
)
|
||||
agent.store_action(action)
|
||||
game.step()
|
||||
assert agent.history[-1].response.status == "success"
|
||||
|
||||
connection_established = False
|
||||
for conn_str, conn_obj in client_1.terminal.connections.items():
|
||||
conn_obj: RemoteTerminalConnection
|
||||
if conn_obj.ip_address == server_1.network_interface[1].ip_address:
|
||||
connection_established = True
|
||||
if not connection_established:
|
||||
pytest.fail("Remote SSH connection could not be established")
|
||||
|
||||
|
||||
def test_remote_login_wrong_password(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]):
|
||||
game, agent = game_and_agent_fixture
|
||||
|
||||
server_1: Server = game.simulation.network.get_node_by_hostname("server_1")
|
||||
client_1 = game.simulation.network.get_node_by_hostname("client_1")
|
||||
|
||||
# create a new user account on server_1 that will be logged into remotely
|
||||
server_1_usm: UserManager = server_1.software_manager.software["UserManager"]
|
||||
server_1_usm.add_user("user123", "password", is_admin=True)
|
||||
|
||||
action = (
|
||||
"SSH_TO_REMOTE",
|
||||
{
|
||||
"node_id": 0,
|
||||
"username": "user123",
|
||||
"password": "wrong_password",
|
||||
"remote_ip": str(server_1.network_interface[1].ip_address),
|
||||
},
|
||||
)
|
||||
agent.store_action(action)
|
||||
game.step()
|
||||
assert agent.history[-1].response.status == "failure"
|
||||
|
||||
connection_established = False
|
||||
for conn_str, conn_obj in client_1.terminal.connections.items():
|
||||
conn_obj: RemoteTerminalConnection
|
||||
if conn_obj.ip_address == server_1.network_interface[1].ip_address:
|
||||
connection_established = True
|
||||
if connection_established:
|
||||
pytest.fail("Remote SSH connection was established despite wrong password")
|
||||
|
||||
|
||||
def test_remote_login_change_password(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]):
|
||||
game, agent = game_and_agent_fixture
|
||||
|
||||
server_1: Server = game.simulation.network.get_node_by_hostname("server_1")
|
||||
client_1 = game.simulation.network.get_node_by_hostname("client_1")
|
||||
|
||||
# create a new user account on server_1 that will be logged into remotely
|
||||
server_1_um: UserManager = server_1.software_manager.software["UserManager"]
|
||||
server_1_um.add_user("user123", "password", is_admin=True)
|
||||
|
||||
action = (
|
||||
"NODE_ACCOUNTS_CHANGE_PASSWORD",
|
||||
{
|
||||
"node_id": 1, # server_1
|
||||
"username": "user123",
|
||||
"current_password": "password",
|
||||
"new_password": "different_password",
|
||||
},
|
||||
)
|
||||
agent.store_action(action)
|
||||
game.step()
|
||||
assert agent.history[-1].response.status == "success"
|
||||
assert server_1_um.users["user123"].password == "different_password"
|
||||
|
||||
|
||||
def test_change_password_logs_out_user(game_and_agent_fixture: Tuple[PrimaiteGame, ProxyAgent]):
|
||||
game, agent = game_and_agent_fixture
|
||||
|
||||
server_1: Server = game.simulation.network.get_node_by_hostname("server_1")
|
||||
client_1 = game.simulation.network.get_node_by_hostname("client_1")
|
||||
|
||||
# create a new user account on server_1 that will be logged into remotely
|
||||
server_1_usm: UserManager = server_1.software_manager.software["UserManager"]
|
||||
server_1_usm.add_user("user123", "password", is_admin=True)
|
||||
|
||||
# Log in remotely
|
||||
action = (
|
||||
"SSH_TO_REMOTE",
|
||||
{
|
||||
"node_id": 0,
|
||||
"username": "user123",
|
||||
"password": "password",
|
||||
"remote_ip": str(server_1.network_interface[1].ip_address),
|
||||
},
|
||||
)
|
||||
agent.store_action(action)
|
||||
game.step()
|
||||
|
||||
# Change password
|
||||
action = (
|
||||
"NODE_ACCOUNTS_CHANGE_PASSWORD",
|
||||
{
|
||||
"node_id": 1, # server_1
|
||||
"username": "user123",
|
||||
"current_password": "password",
|
||||
"new_password": "different_password",
|
||||
},
|
||||
)
|
||||
agent.store_action(action)
|
||||
game.step()
|
||||
|
||||
# Assert that the user cannot execute an action
|
||||
# TODO: should the db conn object get destroyed on both nodes? or is that not realistic?
|
||||
action = (
|
||||
"NODE_SEND_REMOTE_COMMAND",
|
||||
{
|
||||
"node_id": 0,
|
||||
"remote_ip": server_1.network_interface[1].ip_address,
|
||||
"command": ["file_system", "create", "file", "folder123", "doggo.pdf", False],
|
||||
},
|
||||
)
|
||||
agent.store_action(action)
|
||||
game.step()
|
||||
|
||||
assert server_1.file_system.get_folder("folder123") is None
|
||||
assert server_1.file_system.get_file("folder123", "doggo.pdf") is None
|
||||
@@ -1,49 +0,0 @@
|
||||
# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK
|
||||
from primaite.simulator.network.hardware.nodes.host.computer import Computer
|
||||
|
||||
|
||||
def test_remote_logon(game_and_agent):
|
||||
"""Test that the remote session login action works."""
|
||||
game, agent = game_and_agent
|
||||
|
||||
client_1: Computer = game.simulation.network.get_node_by_hostname("client_1")
|
||||
|
||||
client_1.user_manager.add_user(username="test_user", password="password", bypass_can_perform_action=True)
|
||||
|
||||
action = (
|
||||
"NODE_SESSIONS_REMOTE_LOGIN",
|
||||
{"node_id": 0, "username": "test_user", "password": "password", "remote_ip": "10.0.2.2"},
|
||||
)
|
||||
agent.store_action(action)
|
||||
game.step()
|
||||
|
||||
assert len(client_1.user_session_manager.remote_sessions) == 1
|
||||
|
||||
|
||||
def test_remote_logoff(game_and_agent):
|
||||
"""Test that the remote session logout action works."""
|
||||
game, agent = game_and_agent
|
||||
|
||||
client_1: Computer = game.simulation.network.get_node_by_hostname("client_1")
|
||||
|
||||
client_1.user_manager.add_user(username="test_user", password="password", bypass_can_perform_action=True)
|
||||
|
||||
action = (
|
||||
"NODE_SESSIONS_REMOTE_LOGIN",
|
||||
{"node_id": 0, "username": "test_user", "password": "password"},
|
||||
)
|
||||
agent.store_action(action)
|
||||
game.step()
|
||||
|
||||
assert len(client_1.user_session_manager.remote_sessions) == 1
|
||||
|
||||
remote_session_id = client_1.user_session_manager.remote_sessions[0].uuid
|
||||
|
||||
action = (
|
||||
"NODE_SESSIONS_REMOTE_LOGOUT",
|
||||
{"node_id": 0, "remote_session_id": remote_session_id},
|
||||
)
|
||||
agent.store_action(action)
|
||||
game.step()
|
||||
|
||||
assert len(client_1.user_session_manager.remote_sessions) == 0
|
||||
@@ -1,23 +0,0 @@
|
||||
# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK
|
||||
from primaite.simulator.network.hardware.nodes.host.computer import Computer
|
||||
|
||||
|
||||
def test_remote_logon(game_and_agent):
|
||||
"""Test that the remote session login action works."""
|
||||
game, agent = game_and_agent
|
||||
|
||||
client_1: Computer = game.simulation.network.get_node_by_hostname("client_1")
|
||||
|
||||
client_1.user_manager.add_user(username="test_user", password="password", bypass_can_perform_action=True)
|
||||
user = next((user for user in client_1.user_manager.users.values() if user.username == "test_user"), None)
|
||||
|
||||
assert user.password == "password"
|
||||
|
||||
action = (
|
||||
"NODE_ACCOUNTS_CHANGEPASSWORD",
|
||||
{"node_id": 0, "username": user.username, "current_password": user.password, "new_password": "test_pass"},
|
||||
)
|
||||
agent.store_action(action)
|
||||
game.step()
|
||||
|
||||
assert user.password == "test_pass"
|
||||
Reference in New Issue
Block a user