Merged PR 520: Backport core changes from internal
This commit is contained in:
@@ -190,8 +190,12 @@ class WebServer404Penalty(AbstractReward):
|
|||||||
def calculate(self, state: Dict, last_action_response: "AgentHistoryItem") -> float:
|
def calculate(self, state: Dict, last_action_response: "AgentHistoryItem") -> float:
|
||||||
"""Calculate the reward for the current state.
|
"""Calculate the reward for the current state.
|
||||||
|
|
||||||
:param state: The current state of the simulation.
|
:param state: Current simulation state
|
||||||
:type state: Dict
|
:type state: Dict
|
||||||
|
:param last_action_response: Current agent history state
|
||||||
|
:type last_action_response: AgentHistoryItem state
|
||||||
|
:return: Reward value
|
||||||
|
:rtype: float
|
||||||
"""
|
"""
|
||||||
web_service_state = access_from_nested_dict(state, self.location_in_state)
|
web_service_state = access_from_nested_dict(state, self.location_in_state)
|
||||||
|
|
||||||
@@ -263,6 +267,12 @@ class WebpageUnavailablePenalty(AbstractReward):
|
|||||||
When the green agent requests to execute the browser application, and that request fails, this reward
|
When the green agent requests to execute the browser application, and that request fails, this reward
|
||||||
component will keep track of that information. In that case, it doesn't matter whether the last webpage
|
component will keep track of that information. In that case, it doesn't matter whether the last webpage
|
||||||
had a 200 status code, because there has been an unsuccessful request since.
|
had a 200 status code, because there has been an unsuccessful request since.
|
||||||
|
:param state: Current simulation state
|
||||||
|
:type state: Dict
|
||||||
|
:param last_action_response: Current agent history state
|
||||||
|
:type last_action_response: AgentHistoryItem state
|
||||||
|
:return: Reward value
|
||||||
|
:rtype: float
|
||||||
"""
|
"""
|
||||||
web_browser_state = access_from_nested_dict(state, self.location_in_state)
|
web_browser_state = access_from_nested_dict(state, self.location_in_state)
|
||||||
|
|
||||||
@@ -519,6 +529,7 @@ class RewardFunction:
|
|||||||
weight = comp_and_weight[1]
|
weight = comp_and_weight[1]
|
||||||
total += weight * comp.calculate(state=state, last_action_response=last_action_response)
|
total += weight * comp.calculate(state=state, last_action_response=last_action_response)
|
||||||
self.current_reward = total
|
self.current_reward = total
|
||||||
|
|
||||||
return self.current_reward
|
return self.current_reward
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -60,13 +60,13 @@ class AirSpaceFrequency(Enum):
|
|||||||
@property
|
@property
|
||||||
def maximum_data_rate_bps(self) -> float:
|
def maximum_data_rate_bps(self) -> float:
|
||||||
"""
|
"""
|
||||||
Retrieves the maximum data transmission rate in bits per second (bps) for the frequency.
|
Retrieves the maximum data transmission rate in bits per second (bps).
|
||||||
|
|
||||||
The maximum rates are predefined for known frequencies:
|
The maximum rates are predefined for frequencies.:
|
||||||
- For WIFI_2_4, it returns 100,000,000 bps (100 Mbps).
|
- WIFI 2.4 supports 100,000,000 bps
|
||||||
- For WIFI_5, it returns 500,000,000 bps (500 Mbps).
|
- WIFI 5 supports 500,000,000 bps
|
||||||
|
|
||||||
:return: The maximum data rate in bits per second. If the frequency is not recognized, returns 0.0.
|
:return: The maximum data rate in bits per second.
|
||||||
"""
|
"""
|
||||||
if self == AirSpaceFrequency.WIFI_2_4:
|
if self == AirSpaceFrequency.WIFI_2_4:
|
||||||
return 100_000_000.0 # 100 Megabits per second
|
return 100_000_000.0 # 100 Megabits per second
|
||||||
|
|||||||
@@ -1149,7 +1149,7 @@ class UserSessionManager(Service):
|
|||||||
local_session_timeout_steps: int = 30
|
local_session_timeout_steps: int = 30
|
||||||
"""The number of steps before a local session times out due to inactivity."""
|
"""The number of steps before a local session times out due to inactivity."""
|
||||||
|
|
||||||
remote_session_timeout_steps: int = 5
|
remote_session_timeout_steps: int = 30
|
||||||
"""The number of steps before a remote session times out due to inactivity."""
|
"""The number of steps before a remote session times out due to inactivity."""
|
||||||
|
|
||||||
max_remote_sessions: int = 3
|
max_remote_sessions: int = 3
|
||||||
@@ -1179,15 +1179,14 @@ class UserSessionManager(Service):
|
|||||||
"""
|
"""
|
||||||
rm = super()._init_request_manager()
|
rm = super()._init_request_manager()
|
||||||
|
|
||||||
# todo add doc about request schemas
|
def _remote_login(request: RequestFormat, context: Dict) -> RequestResponse:
|
||||||
rm.add_request(
|
"""Request should take the form [username, password, remote_ip_address]."""
|
||||||
"remote_login",
|
username, password, remote_ip_address = request
|
||||||
RequestType(
|
response = RequestResponse.from_bool(self.remote_login(username, password, remote_ip_address))
|
||||||
func=lambda request, context: RequestResponse.from_bool(
|
response.data = {"remote_hostname": self.parent.hostname, "username": username}
|
||||||
self.remote_login(username=request[0], password=request[1], remote_ip_address=request[2])
|
return response
|
||||||
)
|
|
||||||
),
|
rm.add_request("remote_login", RequestType(func=_remote_login))
|
||||||
)
|
|
||||||
|
|
||||||
rm.add_request(
|
rm.add_request(
|
||||||
"remote_logout",
|
"remote_logout",
|
||||||
@@ -1422,6 +1421,7 @@ class UserSessionManager(Service):
|
|||||||
self.local_session = None
|
self.local_session = None
|
||||||
|
|
||||||
if not local and remote_session_id:
|
if not local and remote_session_id:
|
||||||
|
self.parent.terminal._disconnect(remote_session_id)
|
||||||
session = self.remote_sessions.pop(remote_session_id)
|
session = self.remote_sessions.pop(remote_session_id)
|
||||||
if session:
|
if session:
|
||||||
self.historic_sessions.append(session)
|
self.historic_sessions.append(session)
|
||||||
|
|||||||
@@ -446,6 +446,7 @@ class AbstractC2(Application, identifier="AbstractC2"):
|
|||||||
if (
|
if (
|
||||||
self.operating_state is ApplicationOperatingState.RUNNING
|
self.operating_state is ApplicationOperatingState.RUNNING
|
||||||
and self.health_state_actual is SoftwareHealthState.GOOD
|
and self.health_state_actual is SoftwareHealthState.GOOD
|
||||||
|
and self.c2_connection_active is True
|
||||||
):
|
):
|
||||||
self.keep_alive_inactivity += 1
|
self.keep_alive_inactivity += 1
|
||||||
self._confirm_remote_connection(timestep)
|
self._confirm_remote_connection(timestep)
|
||||||
|
|||||||
@@ -171,7 +171,8 @@ class Terminal(Service):
|
|||||||
return RequestResponse(
|
return RequestResponse(
|
||||||
status="success",
|
status="success",
|
||||||
data={
|
data={
|
||||||
"ip_address": login.ip_address,
|
"ip_address": str(login.ip_address),
|
||||||
|
"username": request[0],
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@@ -189,15 +190,9 @@ class Terminal(Service):
|
|||||||
if remote_connection:
|
if remote_connection:
|
||||||
outcome = self._disconnect(remote_connection.connection_uuid)
|
outcome = self._disconnect(remote_connection.connection_uuid)
|
||||||
if outcome:
|
if outcome:
|
||||||
return RequestResponse(
|
return RequestResponse(status="success", data={})
|
||||||
status="success",
|
|
||||||
data={},
|
return RequestResponse(status="failure", data={})
|
||||||
)
|
|
||||||
else:
|
|
||||||
return RequestResponse(
|
|
||||||
status="failure",
|
|
||||||
data={"reason": "No remote connection held."},
|
|
||||||
)
|
|
||||||
|
|
||||||
rm.add_request("remote_logoff", request_type=RequestType(func=_remote_logoff))
|
rm.add_request("remote_logoff", request_type=RequestType(func=_remote_logoff))
|
||||||
|
|
||||||
@@ -464,6 +459,10 @@ class Terminal(Service):
|
|||||||
command = payload.ssh_command
|
command = payload.ssh_command
|
||||||
valid_connection = self._check_client_connection(payload.connection_uuid)
|
valid_connection = self._check_client_connection(payload.connection_uuid)
|
||||||
if valid_connection:
|
if valid_connection:
|
||||||
|
remote_session = self.software_manager.node.user_session_manager.remote_sessions.get(
|
||||||
|
payload.connection_uuid
|
||||||
|
)
|
||||||
|
remote_session.last_active_step = self.software_manager.node.user_session_manager.current_timestep
|
||||||
self.execute(command)
|
self.execute(command)
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
@@ -484,7 +483,7 @@ class Terminal(Service):
|
|||||||
|
|
||||||
if payload["type"] == "user_timeout":
|
if payload["type"] == "user_timeout":
|
||||||
connection_id = payload["connection_id"]
|
connection_id = payload["connection_id"]
|
||||||
valid_id = self._check_client_connection(connection_id)
|
valid_id = connection_id in self._connections
|
||||||
if valid_id:
|
if valid_id:
|
||||||
connection = self._connections.pop(connection_id)
|
connection = self._connections.pop(connection_id)
|
||||||
connection.is_active = False
|
connection.is_active = False
|
||||||
@@ -500,11 +499,14 @@ class Terminal(Service):
|
|||||||
:param connection_uuid: Connection ID that we want to disconnect.
|
:param connection_uuid: Connection ID that we want to disconnect.
|
||||||
:return True if successful, False otherwise.
|
:return True if successful, False otherwise.
|
||||||
"""
|
"""
|
||||||
|
# TODO: Handle the possibility of attempting to disconnect
|
||||||
if not self._connections:
|
if not self._connections:
|
||||||
self.sys_log.warning(f"{self.name}: No remote connection present")
|
self.sys_log.warning(f"{self.name}: No remote connection present")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
connection = self._connections.pop(connection_uuid)
|
connection = self._connections.pop(connection_uuid, None)
|
||||||
|
if not connection:
|
||||||
|
return False
|
||||||
connection.is_active = False
|
connection.is_active = False
|
||||||
|
|
||||||
if isinstance(connection, RemoteTerminalConnection):
|
if isinstance(connection, RemoteTerminalConnection):
|
||||||
|
|||||||
Reference in New Issue
Block a user