#2769 - Make changing password disconnect remote sessions
This commit is contained in:
@@ -1134,8 +1134,18 @@ class NodeSendRemoteCommandAction(AbstractAction):
|
|||||||
super().__init__(manager=manager)
|
super().__init__(manager=manager)
|
||||||
|
|
||||||
def form_request(self, node_id: int, remote_ip: str, command: RequestFormat) -> RequestFormat:
|
def form_request(self, node_id: int, remote_ip: str, command: RequestFormat) -> RequestFormat:
|
||||||
|
"""Return the action formatted as a request which can be ingested by the PrimAITE simulation."""
|
||||||
node_name = self.manager.get_node_name_by_idx(node_id)
|
node_name = self.manager.get_node_name_by_idx(node_id)
|
||||||
return ["network", "node", node_name, "service", "Terminal", "send_remote_command", remote_ip, command]
|
return [
|
||||||
|
"network",
|
||||||
|
"node",
|
||||||
|
node_name,
|
||||||
|
"service",
|
||||||
|
"Terminal",
|
||||||
|
"send_remote_command",
|
||||||
|
remote_ip,
|
||||||
|
{"command": command},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class ActionManager:
|
class ActionManager:
|
||||||
|
|||||||
@@ -990,6 +990,7 @@ class UserManager(Service):
|
|||||||
if user and user.password == current_password:
|
if user and user.password == current_password:
|
||||||
user.password = new_password
|
user.password = new_password
|
||||||
self.sys_log.info(f"{self.name}: Password changed for {username}")
|
self.sys_log.info(f"{self.name}: Password changed for {username}")
|
||||||
|
self._user_session_manager._logout_user(user=user)
|
||||||
return True
|
return True
|
||||||
self.sys_log.info(f"{self.name}: Password change failed for {username}")
|
self.sys_log.info(f"{self.name}: Password change failed for {username}")
|
||||||
return False
|
return False
|
||||||
@@ -1027,6 +1028,10 @@ class UserManager(Service):
|
|||||||
self.sys_log.info(f"{self.name}: Failed to enable user: {username}")
|
self.sys_log.info(f"{self.name}: Failed to enable user: {username}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _user_session_manager(self) -> "UserSessionManager":
|
||||||
|
return self.software_manager.software["UserSessionManager"] # noqa
|
||||||
|
|
||||||
|
|
||||||
class UserSession(SimComponent):
|
class UserSession(SimComponent):
|
||||||
"""
|
"""
|
||||||
@@ -1435,6 +1440,19 @@ class UserSessionManager(Service):
|
|||||||
"""
|
"""
|
||||||
return self._logout(local=False, remote_session_id=remote_session_id)
|
return self._logout(local=False, remote_session_id=remote_session_id)
|
||||||
|
|
||||||
|
def _logout_user(self, user: Union[str, User]) -> bool:
|
||||||
|
"""End a user session by username or user object."""
|
||||||
|
if isinstance(user, str):
|
||||||
|
user = self._user_manager.users[user] # grab user object from username
|
||||||
|
for sess_id, session in self.remote_sessions.items():
|
||||||
|
if session.user is user:
|
||||||
|
self._logout(local=False, remote_session_id=sess_id)
|
||||||
|
return True
|
||||||
|
if self.local_user_logged_in and self.local_session.user is user:
|
||||||
|
self.local_logout()
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def local_user_logged_in(self) -> bool:
|
def local_user_logged_in(self) -> bool:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ from primaite.simulator.system.core.software_manager import SoftwareManager
|
|||||||
from primaite.simulator.system.services.service import Service, ServiceOperatingState
|
from primaite.simulator.system.services.service import Service, ServiceOperatingState
|
||||||
|
|
||||||
|
|
||||||
|
# TODO 2824: Since remote terminal connections and remote user sessions are the same thing, we could refactor
|
||||||
|
# the terminal to leverage the user session manager's list. This way we avoid potential bugs and code ducplication
|
||||||
class TerminalClientConnection(BaseModel):
|
class TerminalClientConnection(BaseModel):
|
||||||
"""
|
"""
|
||||||
TerminalClientConnection Class.
|
TerminalClientConnection Class.
|
||||||
@@ -232,7 +234,7 @@ class Terminal(Service):
|
|||||||
def remote_execute_request(request: RequestFormat, context: Dict) -> RequestResponse:
|
def remote_execute_request(request: RequestFormat, context: Dict) -> RequestResponse:
|
||||||
"""Execute an instruction."""
|
"""Execute an instruction."""
|
||||||
ip_address: IPv4Address = IPv4Address(request[0])
|
ip_address: IPv4Address = IPv4Address(request[0])
|
||||||
command: str = request[1]
|
command: str = request[1]["command"]
|
||||||
remote_connection = self._get_connection_from_ip(ip_address=ip_address)
|
remote_connection = self._get_connection_from_ip(ip_address=ip_address)
|
||||||
if remote_connection:
|
if remote_connection:
|
||||||
outcome = remote_connection.execute(command)
|
outcome = remote_connection.execute(command)
|
||||||
@@ -328,6 +330,9 @@ class Terminal(Service):
|
|||||||
|
|
||||||
def _check_client_connection(self, connection_id: str) -> bool:
|
def _check_client_connection(self, connection_id: str) -> bool:
|
||||||
"""Check that client_connection_id is valid."""
|
"""Check that client_connection_id is valid."""
|
||||||
|
if not self.parent.user_session_manager.validate_remote_session_uuid(connection_id):
|
||||||
|
self._disconnect(connection_id)
|
||||||
|
return False
|
||||||
return connection_id in self._connections
|
return connection_id in self._connections
|
||||||
|
|
||||||
def _send_remote_login(
|
def _send_remote_login(
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ from primaite.game.game import PrimaiteGame
|
|||||||
from primaite.simulator.network.hardware.base import UserManager
|
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.computer import Computer
|
||||||
from primaite.simulator.network.hardware.nodes.host.server import Server
|
from primaite.simulator.network.hardware.nodes.host.server import Server
|
||||||
|
from primaite.simulator.network.hardware.nodes.network.router import ACLAction
|
||||||
|
from primaite.simulator.network.transmission.transport_layer import Port
|
||||||
from primaite.simulator.system.services.service import ServiceOperatingState
|
from primaite.simulator.system.services.service import ServiceOperatingState
|
||||||
from primaite.simulator.system.services.terminal.terminal import RemoteTerminalConnection
|
from primaite.simulator.system.services.terminal.terminal import RemoteTerminalConnection
|
||||||
|
|
||||||
@@ -17,8 +19,8 @@ def game_and_agent_fixture(game_and_agent):
|
|||||||
"""Create a game with a simple agent that can be controlled by the tests."""
|
"""Create a game with a simple agent that can be controlled by the tests."""
|
||||||
game, agent = game_and_agent
|
game, agent = game_and_agent
|
||||||
|
|
||||||
client_1: Computer = game.simulation.network.get_node_by_hostname("client_1")
|
router = game.simulation.network.get_node_by_hostname("router")
|
||||||
client_1.start_up_duration = 3
|
router.acl.add_rule(action=ACLAction.PERMIT, src_port=Port.SSH, dst_port=Port.SSH, position=4)
|
||||||
|
|
||||||
return (game, agent)
|
return (game, agent)
|
||||||
|
|
||||||
@@ -154,7 +156,7 @@ def test_change_password_logs_out_user(game_and_agent_fixture: Tuple[PrimaiteGam
|
|||||||
"NODE_SEND_REMOTE_COMMAND",
|
"NODE_SEND_REMOTE_COMMAND",
|
||||||
{
|
{
|
||||||
"node_id": 0,
|
"node_id": 0,
|
||||||
"remote_ip": server_1.network_interface[1].ip_address,
|
"remote_ip": str(server_1.network_interface[1].ip_address),
|
||||||
"command": ["file_system", "create", "file", "folder123", "doggo.pdf", False],
|
"command": ["file_system", "create", "file", "folder123", "doggo.pdf", False],
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user