Skip to content

Commit

Permalink
Rule Deployment Difference Dialog (#849)
Browse files Browse the repository at this point in the history
Adds an option to display a full difference in the rules changeset
before deployment.

Closes #556
  • Loading branch information
egbicker authored Apr 28, 2023
1 parent 06ffbd5 commit 2834e29
Show file tree
Hide file tree
Showing 6 changed files with 322 additions and 13 deletions.
19 changes: 17 additions & 2 deletions fapolicy_analyzer/glade/confirm_deployment_dialog.glade
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
<property name="position">1</property>
</packing>
</child>
<child>
Expand All @@ -63,7 +63,22 @@
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="expandButton">
<property name="label">Rule Details</property>
<property name="visible">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<signal name="clicked" handler="on_expandButton_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
Expand Down
156 changes: 156 additions & 0 deletions fapolicy_analyzer/glade/rules_difference_dialog.glade
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<!--
Copyright Concurrent Technologies Corporation 2021
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<interface>
<requires lib="gtk+" version="3.22"/>
<object class="GtkDialog" id="rulesDifferenceDialog">
<property name="can-focus">False</property>
<property name="title" translatable="yes">Rule Differences</property>
<property name="modal">True</property>
<property name="window-position">center-on-parent</property>
<property name="default-width">500</property>
<property name="default-height">600</property>
<property name="type-hint">dialog</property>
<child internal-child="vbox">
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox">
<property name="can-focus">False</property>
<property name="layout-style">end</property>
<child>
<object class="GtkButton" id="okBtn">
<property name="label">Ok</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="use-stock">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="spacing">2</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Previous Rules</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="prevContent">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="shadow-type">in</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">New Rules</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="newContent">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="shadow-type">in</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="1">okBtn</action-widget>
</action-widgets>
</object>
</interface>
30 changes: 30 additions & 0 deletions fapolicy_analyzer/tests/rules/test_rules_difference_dialog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Copyright Concurrent Technologies Corporation 2023
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# 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 gi
from fapolicy_analyzer.ui.rules.rules_difference_dialog import RulesDifferenceDialog
from unittest.mock import MagicMock

gi.require_version("GtkSource", "3.0")
from gi.repository import Gtk # isort: skip


def test_creates_widget(mocker):
mocker.patch(
"fapolicy_analyzer.ui.rules.rules_difference_dialog.rules_difference",
return_value="",
)
widget = RulesDifferenceDialog(MagicMock(), MagicMock(), parent=Gtk.Window())
assert type(widget) is RulesDifferenceDialog
18 changes: 16 additions & 2 deletions fapolicy_analyzer/tests/test_confirm_deployment_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@
import context # noqa: F401 # isort: skip

import gi
from fapolicy_analyzer.ui.changeset_wrapper import TrustChangeset
from fapolicy_analyzer.ui.changeset_wrapper import TrustChangeset, RuleChangeset
from fapolicy_analyzer.ui.confirm_deployment_dialog import ConfirmDeploymentDialog
from fapolicy_analyzer.ui.strings import (
CHANGESET_ACTION_ADD_TRUST,
CHANGESET_ACTION_DEL_TRUST,
CHANGESET_ACTION_RULES,
)

from unittest.mock import MagicMock
from helpers import delayed_gui_action

gi.require_version("GtkSource", "3.0")
Expand Down Expand Up @@ -63,3 +64,16 @@ def test_load_path_action_list():
rows = [x for x in view.get_model()]
assert (CHANGESET_ACTION_ADD_TRUST, "/tmp/add.txt") in [(r[0], r[1]) for r in rows]
assert (CHANGESET_ACTION_DEL_TRUST, "/tmp/del.txt") in [(r[0], r[1]) for r in rows]


def test_load_rules(mocker):
changeset = RuleChangeset()
changeset.parse("allow perm=any all : all")
mocker.patch(
"fapolicy_analyzer.ui.rules.rules_difference_dialog.rules_difference",
return_value="+allow perm=any all : all\n-deny perm=any all : all",
)
widget = ConfirmDeploymentDialog([changeset], MagicMock(), MagicMock(), Gtk.Window())
view = widget.get_object("changesTreeView")
rows = [x for x in view.get_model()]
assert (CHANGESET_ACTION_RULES, "1 addition and 1 removal made") in [(r[0], r[1]) for r in rows]
39 changes: 30 additions & 9 deletions fapolicy_analyzer/ui/confirm_deployment_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
from typing import Sequence, Tuple

import gi
from fapolicy_analyzer import System, rules_difference
from fapolicy_analyzer import System
from fapolicy_analyzer.ui.rules.rules_difference_dialog import RulesDifferenceDialog, filter_rule_diff
from fapolicy_analyzer.ui.changeset_wrapper import Changeset, TrustChangeset
from fapolicy_analyzer.ui.configs import Colors
from fapolicy_analyzer.ui.strings import (
Expand Down Expand Up @@ -48,6 +49,8 @@ def __init__(

changes_view = self.get_object("changesTreeView")
self.__config_changes_view(changes_view)
self.__current_system = current_system
self.__previous_system = previous_system
store = self.__load_store(changesets, current_system, previous_system)
changes_view.set_model(store)

Expand All @@ -74,17 +77,26 @@ def __to_path_action_pairs(
) -> Sequence[Tuple[str, str]]:
def rules_changes():
if not previous_system or not current_system:
return []
diffs = rules_difference(previous_system, current_system).split("\n")
adds = len([d for d in diffs if d.startswith("+")])
dels = len([d for d in diffs if d.startswith("-")])
return ([], "")
diffs = ""
diffs = filter_rule_diff(previous_system, current_system)
adds_list = []
dels_list = []
for d in diffs:
if d.startswith("+"):
adds_list += [d]
elif d.startswith("-"):
dels_list += [d]

adds = len(adds_list)
dels = len(dels_list)
if (adds + dels) == 0:
return []
return ([], "")

add_text = f"{adds} addition{'s' if adds > 1 else ''}" if adds else None
del_text = f"{dels} removal{'s' if dels > 1 else ''}" if dels else None
message = " and ".join((m for m in [add_text, del_text] if m)) + " made"
return [(_(message), "Rules")]
return ([(_(message), "Rules")], diffs)

def trust_changes():
return [
Expand All @@ -94,7 +106,11 @@ def trust_changes():
for t in e.serialize().items()
]

return [*trust_changes(), *rules_changes()]
rule_messages, rule_diff = rules_changes()
expand_btn = self.get_object("expandButton")
expand_btn.set_visible(True) if [*rule_messages] else expand_btn.set_visible(False)

return ([*trust_changes(), *rule_messages], rule_diff)

def __load_store(
self,
Expand All @@ -108,7 +124,7 @@ def __load_store(
"Rules": CHANGESET_ACTION_RULES,
}
store = Gtk.ListStore(str, str)
pathActionPairs = self.__to_path_action_pairs(
pathActionPairs, _ = self.__to_path_action_pairs(
changesets, current_system, previous_system
)
for e in pathActionPairs:
Expand All @@ -119,3 +135,8 @@ def __load_store(

def get_save_state(self) -> bool:
return self.get_object("saveStateCbn").get_active()

def on_expandButton_clicked(self, *args):
diff_dialog = RulesDifferenceDialog(self.__current_system, self.__previous_system).get_ref()
diff_dialog.run()
diff_dialog.destroy()
Loading

0 comments on commit 2834e29

Please sign in to comment.