Skip to content

Commit

Permalink
Fix ancillary trust loading when swapping session files (#840)
Browse files Browse the repository at this point in the history
Fixes some threading/callback issues when a system revert happens
followed by a set of changesets being applied. This happens when a user
loads a new session file with changesets in it, or the system is
reverted using the post-deployment revert option. In both cases an async
trust check is kicked off from the revert. When the changesets are then
applied a trust check using the new System object was not initiated.

closes #828 
closes #827
  • Loading branch information
dorschs57 authored Apr 17, 2023
1 parent 594bee0 commit f7e0f2a
Show file tree
Hide file tree
Showing 8 changed files with 194 additions and 89 deletions.
5 changes: 4 additions & 1 deletion fapolicy_analyzer/tests/features/test_system_feature.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,13 +247,16 @@ def test_request_trust(
mock_received_action = mocker.patch(
f"fapolicy_analyzer.ui.features.system_feature.{receive_action_to_mock.__name__}"
)
mocker.patch(
"fapolicy_analyzer.ui.features.system_feature.time.time", return_value=1
)

mock_system = MagicMock()
init_store(mock_system)
dispatch(action_to_dispatch(*(payload or [])))

mock_system_fn.assert_called()
mock_received_action.assert_called_with(mock_return_value)
mock_received_action.assert_called_with(mock_return_value, 1)


@pytest.mark.parametrize(
Expand Down
19 changes: 15 additions & 4 deletions fapolicy_analyzer/tests/reducers/test_trust_reducer.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

import context # noqa: F401 # isort: skip
import time
from unittest.mock import MagicMock

import pytest
Expand All @@ -27,6 +27,8 @@
handle_trust_load_started,
)

import context # noqa: F401 # isort: skip


@pytest.fixture()
def initial_state():
Expand All @@ -37,6 +39,7 @@ def initial_state():
percent_complete=-1,
last_set_completed=None,
trust_count=0,
timestamp=0,
)


Expand All @@ -49,18 +52,21 @@ def test_handle_request_trust(initial_state):
percent_complete=-1,
last_set_completed=None,
trust_count=0,
timestamp=0,
)


def test_handle_trust_load_started(initial_state):
result = handle_trust_load_started(initial_state, MagicMock(payload=1))
timestamp = time.time()
result = handle_trust_load_started(initial_state, MagicMock(payload=(1, timestamp)))
assert result == TrustState(
error=None,
trust=[],
loading=True,
percent_complete=0,
last_set_completed=None,
trust_count=1,
timestamp=timestamp,
)


Expand All @@ -75,8 +81,9 @@ def test_handle_received_trust_update(initial_state):
"loading": True,
}
)
timestamp = time.time()
result = handle_received_trust_update(
incoming_state, MagicMock(payload=(trust_update, 2))
incoming_state, MagicMock(payload=(trust_update, 2, timestamp))
)
assert result == TrustState(
error=None,
Expand All @@ -85,6 +92,7 @@ def test_handle_received_trust_update(initial_state):
percent_complete=100,
last_set_completed=trust_update,
trust_count=2,
timestamp=timestamp,
)


Expand All @@ -100,14 +108,16 @@ def test_handle_trust_load_complete(initial_state):
"percent_complete": 100,
}
)
result = handle_trust_load_complete(incoming_state, MagicMock())
timestamp = time.time()
result = handle_trust_load_complete(incoming_state, MagicMock(payload=timestamp))
assert result == TrustState(
error=None,
loading=False,
trust=trust,
percent_complete=100,
last_set_completed=None,
trust_count=1,
timestamp=timestamp,
)


Expand All @@ -120,4 +130,5 @@ def test_handle_error_trust(initial_state):
percent_complete=-1,
last_set_completed=None,
trust_count=0,
timestamp=0,
)
68 changes: 39 additions & 29 deletions fapolicy_analyzer/tests/test_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

import context # noqa: F401 # isort: skip
import time
from unittest.mock import MagicMock

import pytest
Expand All @@ -40,6 +40,14 @@
ERROR_USERS,
INIT_SYSTEM,
MODIFY_RULES_TEXT,
PROFILER_CLEAR_STATE_CMD,
PROFILER_SET_OUTPUT_CMD,
PROFILING_DONE_EVENT,
PROFILING_EXEC_EVENT,
PROFILING_INIT_EVENT,
PROFILING_KILL_REQUEST,
PROFILING_KILL_RESPONSE,
PROFILING_TICK_EVENT,
RECEIVED_ANCILLARY_TRUST_UPDATE,
RECEIVED_APP_CONFIG,
RECEIVED_EVENTS,
Expand All @@ -59,6 +67,8 @@
REQUEST_USERS,
RESTORE_SYSTEM_CHECKPOINT,
SET_SYSTEM_CHECKPOINT,
START_PROFILING_REQUEST,
START_PROFILING_RESPONSE,
SYSTEM_CHECKPOINT_SET,
SYSTEM_DEPLOYED,
SYSTEM_RECEIVED,
Expand Down Expand Up @@ -86,6 +96,11 @@
error_users,
init_system,
modify_rules_text,
profiler_done,
profiler_exec,
profiler_init,
profiler_tick,
profiling_started,
received_ancillary_trust_update,
received_app_config,
received_events,
Expand All @@ -104,34 +119,21 @@
request_system_trust,
request_users,
restore_system_checkpoint,
set_profiler_output,
set_system_checkpoint,
start_profiling,
stop_profiling,
system_checkpoint_set,
system_deployed,
system_initialization_error,
system_received,
system_trust_load_complete,
system_trust_load_started,
set_profiler_output,
PROFILER_CLEAR_STATE_CMD,
profiler_done,
PROFILER_SET_OUTPUT_CMD,
stop_profiling,
terminating_profiler,
profiler_tick,
PROFILING_KILL_RESPONSE,
PROFILING_KILL_REQUEST,
profiler_exec,
PROFILING_EXEC_EVENT,
PROFILING_TICK_EVENT,
PROFILING_INIT_EVENT,
profiler_init,
start_profiling,
START_PROFILING_REQUEST,
START_PROFILING_RESPONSE,
profiling_started,
PROFILING_DONE_EVENT,
)

import context # noqa: F401 # isort: skip


@pytest.mark.parametrize("notification_type", [t for t in list(NotificationType)])
def test_add_notification(notification_type):
Expand Down Expand Up @@ -192,24 +194,28 @@ def test_request_ancillary_trust():


def test_ancillary_trust_load_started():
action = ancillary_trust_load_started(1)
timestamp = time.time()
action = ancillary_trust_load_started(1, timestamp)
assert type(action) is Action
assert action.type == ANCILLARY_TRUST_LOAD_STARTED
assert action.payload == 1
assert action.payload == (1, timestamp)


def test_received_ancillary_trust_update():
timestamp = time.time()
trust = [MagicMock()]
action = received_ancillary_trust_update((trust, 1))
action = received_ancillary_trust_update(trust, 1, timestamp)
assert type(action) is Action
assert action.type == RECEIVED_ANCILLARY_TRUST_UPDATE
assert action.payload == (trust, 1)
assert action.payload == (trust, 1, timestamp)


def test_ancillary_trust_load_complete():
action = ancillary_trust_load_complete()
timestamp = time.time()
action = ancillary_trust_load_complete(timestamp)
assert type(action) is Action
assert action.type == ANCILLARY_TRUST_LOAD_COMPLETE
assert action.payload == timestamp


def test_error_ancillary_trust():
Expand All @@ -227,24 +233,28 @@ def test_request_system_trust():


def test_system_trust_load_started():
action = system_trust_load_started(1)
timestamp = time.time()
action = system_trust_load_started(1, timestamp)
assert type(action) is Action
assert action.type == SYSTEM_TRUST_LOAD_STARTED
assert action.payload == 1
assert action.payload == (1, timestamp)


def test_received_system_trust_update():
timestamp = time.time()
trust = [MagicMock()]
action = received_system_trust_update((trust, 1))
action = received_system_trust_update(trust, 1, timestamp)
assert type(action) is Action
assert action.type == RECEIVED_SYSTEM_TRUST_UPDATE
assert action.payload == (trust, 1)
assert action.payload == (trust, 1, timestamp)


def test_system_trust_load_complete():
action = system_trust_load_complete()
timestamp = time.time()
action = system_trust_load_complete(timestamp)
assert type(action) is Action
assert action.type == SYSTEM_TRUST_LOAD_COMPLETE
assert action.payload == timestamp


def test_error_system_trust():
Expand Down
35 changes: 20 additions & 15 deletions fapolicy_analyzer/ui/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@

from enum import Enum
from itertools import count
from typing import Any, Dict, Iterator, NamedTuple, Optional, Sequence, Tuple
from typing import Any, Dict, Iterator, NamedTuple, Optional, Sequence

from fapolicy_analyzer import Changeset, Event, Group, Rule, System, Trust, User
from fapolicy_analyzer.redux import Action, create_action


INIT_SYSTEM = "INIT_SYSTEM"
SYSTEM_RECEIVED = "SYSTEM_RECEIVED"
ERROR_SYSTEM_INITIALIZATION = "ERROR_SYSTEM_INITIALIZATION"
Expand Down Expand Up @@ -146,16 +145,18 @@ def request_ancillary_trust() -> Action:
return _create_action(REQUEST_ANCILLARY_TRUST)


def ancillary_trust_load_started(count: int) -> Action:
return _create_action(ANCILLARY_TRUST_LOAD_STARTED, count)
def ancillary_trust_load_started(count: int, timestamp: float) -> Action:
return _create_action(ANCILLARY_TRUST_LOAD_STARTED, (count, timestamp))


def received_ancillary_trust_update(update: Tuple[Sequence[Trust], int]) -> Action:
return _create_action(RECEIVED_ANCILLARY_TRUST_UPDATE, update)
def received_ancillary_trust_update(
update: Sequence[Trust], count: int, timestamp: float
) -> Action:
return _create_action(RECEIVED_ANCILLARY_TRUST_UPDATE, (update, count, timestamp))


def ancillary_trust_load_complete() -> Action:
return _create_action(ANCILLARY_TRUST_LOAD_COMPLETE)
def ancillary_trust_load_complete(timestamp: float) -> Action:
return _create_action(ANCILLARY_TRUST_LOAD_COMPLETE, timestamp)


def error_ancillary_trust(error: str) -> Action:
Expand All @@ -166,16 +167,18 @@ def request_system_trust() -> Action:
return _create_action(REQUEST_SYSTEM_TRUST)


def system_trust_load_started(count: int) -> Action:
return _create_action(SYSTEM_TRUST_LOAD_STARTED, count)
def system_trust_load_started(count: int, timestamp: float) -> Action:
return _create_action(SYSTEM_TRUST_LOAD_STARTED, (count, timestamp))


def received_system_trust_update(update: Tuple[Sequence[Trust], int]) -> Action:
return _create_action(RECEIVED_SYSTEM_TRUST_UPDATE, update)
def received_system_trust_update(
update: Sequence[Trust], count: int, timestamp: float
) -> Action:
return _create_action(RECEIVED_SYSTEM_TRUST_UPDATE, (update, count, timestamp))


def system_trust_load_complete() -> Action:
return _create_action(SYSTEM_TRUST_LOAD_COMPLETE)
def system_trust_load_complete(timestamp: float) -> Action:
return _create_action(SYSTEM_TRUST_LOAD_COMPLETE, timestamp)


def error_system_trust(error: str) -> Action:
Expand Down Expand Up @@ -302,7 +305,9 @@ def profiler_done() -> Action:
return _create_action(PROFILING_DONE_EVENT)


def set_profiler_output(events: Optional[str], stdout: Optional[str], stderr: Optional[str]) -> Action:
def set_profiler_output(
events: Optional[str], stdout: Optional[str], stderr: Optional[str]
) -> Action:
return _create_action(PROFILER_SET_OUTPUT_CMD, (events, stdout, stderr))


Expand Down
Loading

0 comments on commit f7e0f2a

Please sign in to comment.