/mandos/release

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/release

« back to all changes in this revision

Viewing changes to mandos-ctl

  • Committer: Teddy Hogeborn
  • Date: 2019-03-12 20:24:58 UTC
  • mto: This revision was merged to the branch mainline in revision 382.
  • Revision ID: teddy@recompile.se-20190312202458-14d4f7bvc61kwp2l
mandos-ctl: Refactor

* mandos-ctl (milliseconds_to_string): Move to
  "PrintTableCmd.TableOfClients.milliseconds_to_string".
  (PrintTableCmd.TableOfClients.valuetostring): Change to a class
                                                method to be able to
                                                call
                                         cls.milliseconds_to_string().
  (TestCmd.other_client): Change "ApprovalDuration" to a more odd
                          value to compensate for the removal of
                          "Test_milliseconds_to_string", which
                          contained a test for this value.  All users
                          changed.
  (Test_milliseconds_to_string): Remove.

Show diffs side-by-side

added added

removed removed

Lines of Context:
568
568
        self.mandos.RemoveClient(client.__dbus_object_path__)
569
569
 
570
570
 
571
 
class OutputCmd(Command):
572
 
    """Abstract class for commands outputting client details"""
 
571
class PrintCmd(Command):
 
572
    """Abstract class for commands printing client details"""
573
573
    all_keywords = ("Name", "Enabled", "Timeout", "LastCheckedOK",
574
574
                    "Created", "Interval", "Host", "KeyID",
575
575
                    "Fingerprint", "CheckerRunning", "LastEnabled",
583
583
        raise NotImplementedError()
584
584
 
585
585
 
586
 
class DumpJSONCmd(OutputCmd):
 
586
class DumpJSONCmd(PrintCmd):
587
587
    def output(self, clients):
588
588
        data = {client["Name"]:
589
589
                {key: self.dbus_boolean_to_bool(client[key])
597
597
        return value
598
598
 
599
599
 
600
 
class PrintTableCmd(OutputCmd):
 
600
class PrintTableCmd(PrintCmd):
601
601
    def __init__(self, verbose=False):
602
602
        self.verbose = verbose
603
603
 
840
840
 
841
841
 
842
842
class Test_check_option_syntax(unittest.TestCase):
843
 
    def setUp(self):
844
 
        self.parser = argparse.ArgumentParser()
845
 
        add_command_line_options(self.parser)
846
 
 
847
 
    def test_actions_requires_client_or_all(self):
848
 
        for action, value in self.actions.items():
849
 
            options = self.parser.parse_args()
850
 
            setattr(options, action, value)
851
 
            with self.assertParseError():
852
 
                self.check_option_syntax(options)
853
 
 
854
843
    # This mostly corresponds to the definition from has_actions() in
855
844
    # check_option_syntax()
856
845
    actions = {
877
866
        "deny": True,
878
867
    }
879
868
 
 
869
    def setUp(self):
 
870
        self.parser = argparse.ArgumentParser()
 
871
        add_command_line_options(self.parser)
 
872
 
880
873
    @contextlib.contextmanager
881
874
    def assertParseError(self):
882
875
        with self.assertRaises(SystemExit) as e:
904
897
    def check_option_syntax(self, options):
905
898
        check_option_syntax(self.parser, options)
906
899
 
 
900
    def test_actions_requires_client_or_all(self):
 
901
        for action, value in self.actions.items():
 
902
            options = self.parser.parse_args()
 
903
            setattr(options, action, value)
 
904
            with self.assertParseError():
 
905
                self.check_option_syntax(options)
 
906
 
907
907
    def test_actions_conflicts_with_verbose(self):
908
908
        for action, value in self.actions.items():
909
909
            options = self.parser.parse_args()
971
971
                self.check_option_syntax(options)
972
972
 
973
973
 
974
 
class Test_commands_from_options(unittest.TestCase):
 
974
class Test_command_from_options(unittest.TestCase):
975
975
    def setUp(self):
976
976
        self.parser = argparse.ArgumentParser()
977
977
        add_command_line_options(self.parser)
978
 
 
979
 
    def test_is_enabled(self):
980
 
        self.assert_command_from_args(["--is-enabled", "foo"],
981
 
                                      IsEnabledCmd)
982
 
 
983
978
    def assert_command_from_args(self, args, command_cls,
984
979
                                 **cmd_attrs):
985
980
        """Assert that parsing ARGS should result in an instance of
992
987
        self.assertIsInstance(command, command_cls)
993
988
        for key, value in cmd_attrs.items():
994
989
            self.assertEqual(getattr(command, key), value)
995
 
 
996
 
    def test_is_enabled_short(self):
997
 
        self.assert_command_from_args(["-V", "foo"], IsEnabledCmd)
998
 
 
999
 
    def test_approve(self):
1000
 
        self.assert_command_from_args(["--approve", "foo"],
1001
 
                                      ApproveCmd)
1002
 
 
1003
 
    def test_approve_short(self):
1004
 
        self.assert_command_from_args(["-A", "foo"], ApproveCmd)
1005
 
 
1006
 
    def test_deny(self):
1007
 
        self.assert_command_from_args(["--deny", "foo"], DenyCmd)
1008
 
 
1009
 
    def test_deny_short(self):
1010
 
        self.assert_command_from_args(["-D", "foo"], DenyCmd)
1011
 
 
1012
 
    def test_remove(self):
1013
 
        self.assert_command_from_args(["--remove", "foo"],
1014
 
                                      RemoveCmd)
1015
 
 
1016
 
    def test_deny_before_remove(self):
1017
 
        options = self.parser.parse_args(["--deny", "--remove",
1018
 
                                          "foo"])
1019
 
        check_option_syntax(self.parser, options)
1020
 
        commands = commands_from_options(options)
1021
 
        self.assertEqual(len(commands), 2)
1022
 
        self.assertIsInstance(commands[0], DenyCmd)
1023
 
        self.assertIsInstance(commands[1], RemoveCmd)
1024
 
 
1025
 
    def test_deny_before_remove_reversed(self):
1026
 
        options = self.parser.parse_args(["--remove", "--deny",
1027
 
                                          "--all"])
1028
 
        check_option_syntax(self.parser, options)
1029
 
        commands = commands_from_options(options)
1030
 
        self.assertEqual(len(commands), 2)
1031
 
        self.assertIsInstance(commands[0], DenyCmd)
1032
 
        self.assertIsInstance(commands[1], RemoveCmd)
1033
 
 
1034
 
    def test_remove_short(self):
1035
 
        self.assert_command_from_args(["-r", "foo"], RemoveCmd)
1036
 
 
1037
 
    def test_dump_json(self):
1038
 
        self.assert_command_from_args(["--dump-json"], DumpJSONCmd)
 
990
    def test_print_table(self):
 
991
        self.assert_command_from_args([], PrintTableCmd,
 
992
                                      verbose=False)
 
993
 
 
994
    def test_print_table_verbose(self):
 
995
        self.assert_command_from_args(["--verbose"], PrintTableCmd,
 
996
                                      verbose=True)
 
997
 
 
998
    def test_print_table_verbose_short(self):
 
999
        self.assert_command_from_args(["-v"], PrintTableCmd,
 
1000
                                      verbose=True)
1039
1001
 
1040
1002
    def test_enable(self):
1041
1003
        self.assert_command_from_args(["--enable", "foo"], EnableCmd)
1065
1027
        self.assert_command_from_args(["--stop-checker", "foo"],
1066
1028
                                      StopCheckerCmd)
1067
1029
 
1068
 
    def test_approve_by_default(self):
1069
 
        self.assert_command_from_args(["--approve-by-default", "foo"],
1070
 
                                      ApproveByDefaultCmd)
 
1030
    def test_remove(self):
 
1031
        self.assert_command_from_args(["--remove", "foo"],
 
1032
                                      RemoveCmd)
1071
1033
 
1072
 
    def test_deny_by_default(self):
1073
 
        self.assert_command_from_args(["--deny-by-default", "foo"],
1074
 
                                      DenyByDefaultCmd)
 
1034
    def test_remove_short(self):
 
1035
        self.assert_command_from_args(["-r", "foo"], RemoveCmd)
1075
1036
 
1076
1037
    def test_checker(self):
1077
1038
        self.assert_command_from_args(["--checker", ":", "foo"],
1085
1046
        self.assert_command_from_args(["-c", ":", "foo"],
1086
1047
                                      SetCheckerCmd, value_to_set=":")
1087
1048
 
1088
 
    def test_host(self):
1089
 
        self.assert_command_from_args(["--host", "foo.example.org",
1090
 
                                       "foo"], SetHostCmd,
1091
 
                                      value_to_set="foo.example.org")
1092
 
 
1093
 
    def test_host_short(self):
1094
 
        self.assert_command_from_args(["-H", "foo.example.org",
1095
 
                                       "foo"], SetHostCmd,
1096
 
                                      value_to_set="foo.example.org")
1097
 
 
1098
 
    def test_secret_devnull(self):
1099
 
        self.assert_command_from_args(["--secret", os.path.devnull,
1100
 
                                       "foo"], SetSecretCmd,
1101
 
                                      value_to_set=b"")
1102
 
 
1103
 
    def test_secret_tempfile(self):
1104
 
        with tempfile.NamedTemporaryFile(mode="r+b") as f:
1105
 
            value = b"secret\0xyzzy\nbar"
1106
 
            f.write(value)
1107
 
            f.seek(0)
1108
 
            self.assert_command_from_args(["--secret", f.name,
1109
 
                                           "foo"], SetSecretCmd,
1110
 
                                          value_to_set=value)
1111
 
 
1112
 
    def test_secret_devnull_short(self):
1113
 
        self.assert_command_from_args(["-s", os.path.devnull, "foo"],
1114
 
                                      SetSecretCmd, value_to_set=b"")
1115
 
 
1116
 
    def test_secret_tempfile_short(self):
1117
 
        with tempfile.NamedTemporaryFile(mode="r+b") as f:
1118
 
            value = b"secret\0xyzzy\nbar"
1119
 
            f.write(value)
1120
 
            f.seek(0)
1121
 
            self.assert_command_from_args(["-s", f.name, "foo"],
1122
 
                                          SetSecretCmd,
1123
 
                                          value_to_set=value)
1124
 
 
1125
1049
    def test_timeout(self):
1126
1050
        self.assert_command_from_args(["--timeout", "PT5M", "foo"],
1127
1051
                                      SetTimeoutCmd,
1148
1072
                                      SetIntervalCmd,
1149
1073
                                      value_to_set=120000)
1150
1074
 
 
1075
    def test_approve_by_default(self):
 
1076
        self.assert_command_from_args(["--approve-by-default", "foo"],
 
1077
                                      ApproveByDefaultCmd)
 
1078
 
 
1079
    def test_deny_by_default(self):
 
1080
        self.assert_command_from_args(["--deny-by-default", "foo"],
 
1081
                                      DenyByDefaultCmd)
 
1082
 
1151
1083
    def test_approval_delay(self):
1152
1084
        self.assert_command_from_args(["--approval-delay", "PT30S",
1153
1085
                                       "foo"], SetApprovalDelayCmd,
1158
1090
                                       "foo"], SetApprovalDurationCmd,
1159
1091
                                      value_to_set=1000)
1160
1092
 
1161
 
    def test_print_table(self):
1162
 
        self.assert_command_from_args([], PrintTableCmd,
1163
 
                                      verbose=False)
1164
 
 
1165
 
    def test_print_table_verbose(self):
1166
 
        self.assert_command_from_args(["--verbose"], PrintTableCmd,
1167
 
                                      verbose=True)
1168
 
 
1169
 
    def test_print_table_verbose_short(self):
1170
 
        self.assert_command_from_args(["-v"], PrintTableCmd,
1171
 
                                      verbose=True)
 
1093
    def test_host(self):
 
1094
        self.assert_command_from_args(["--host", "foo.example.org",
 
1095
                                       "foo"], SetHostCmd,
 
1096
                                      value_to_set="foo.example.org")
 
1097
 
 
1098
    def test_host_short(self):
 
1099
        self.assert_command_from_args(["-H", "foo.example.org",
 
1100
                                       "foo"], SetHostCmd,
 
1101
                                      value_to_set="foo.example.org")
 
1102
 
 
1103
    def test_secret_devnull(self):
 
1104
        self.assert_command_from_args(["--secret", os.path.devnull,
 
1105
                                       "foo"], SetSecretCmd,
 
1106
                                      value_to_set=b"")
 
1107
 
 
1108
    def test_secret_tempfile(self):
 
1109
        with tempfile.NamedTemporaryFile(mode="r+b") as f:
 
1110
            value = b"secret\0xyzzy\nbar"
 
1111
            f.write(value)
 
1112
            f.seek(0)
 
1113
            self.assert_command_from_args(["--secret", f.name,
 
1114
                                           "foo"], SetSecretCmd,
 
1115
                                          value_to_set=value)
 
1116
 
 
1117
    def test_secret_devnull_short(self):
 
1118
        self.assert_command_from_args(["-s", os.path.devnull, "foo"],
 
1119
                                      SetSecretCmd, value_to_set=b"")
 
1120
 
 
1121
    def test_secret_tempfile_short(self):
 
1122
        with tempfile.NamedTemporaryFile(mode="r+b") as f:
 
1123
            value = b"secret\0xyzzy\nbar"
 
1124
            f.write(value)
 
1125
            f.seek(0)
 
1126
            self.assert_command_from_args(["-s", f.name, "foo"],
 
1127
                                          SetSecretCmd,
 
1128
                                          value_to_set=value)
 
1129
 
 
1130
    def test_approve(self):
 
1131
        self.assert_command_from_args(["--approve", "foo"],
 
1132
                                      ApproveCmd)
 
1133
 
 
1134
    def test_approve_short(self):
 
1135
        self.assert_command_from_args(["-A", "foo"], ApproveCmd)
 
1136
 
 
1137
    def test_deny(self):
 
1138
        self.assert_command_from_args(["--deny", "foo"], DenyCmd)
 
1139
 
 
1140
    def test_deny_short(self):
 
1141
        self.assert_command_from_args(["-D", "foo"], DenyCmd)
 
1142
 
 
1143
    def test_dump_json(self):
 
1144
        self.assert_command_from_args(["--dump-json"], DumpJSONCmd)
 
1145
 
 
1146
    def test_is_enabled(self):
 
1147
        self.assert_command_from_args(["--is-enabled", "foo"],
 
1148
                                      IsEnabledCmd)
 
1149
 
 
1150
    def test_is_enabled_short(self):
 
1151
        self.assert_command_from_args(["-V", "foo"], IsEnabledCmd)
 
1152
 
 
1153
    def test_deny_before_remove(self):
 
1154
        options = self.parser.parse_args(["--deny", "--remove",
 
1155
                                          "foo"])
 
1156
        check_option_syntax(self.parser, options)
 
1157
        commands = commands_from_options(options)
 
1158
        self.assertEqual(len(commands), 2)
 
1159
        self.assertIsInstance(commands[0], DenyCmd)
 
1160
        self.assertIsInstance(commands[1], RemoveCmd)
 
1161
 
 
1162
    def test_deny_before_remove_reversed(self):
 
1163
        options = self.parser.parse_args(["--remove", "--deny",
 
1164
                                          "--all"])
 
1165
        check_option_syntax(self.parser, options)
 
1166
        commands = commands_from_options(options)
 
1167
        self.assertEqual(len(commands), 2)
 
1168
        self.assertIsInstance(commands[0], DenyCmd)
 
1169
        self.assertIsInstance(commands[1], RemoveCmd)
1172
1170
 
1173
1171
 
1174
1172
class TestCmd(unittest.TestCase):
1487
1485
        self.assertEqual(output, expected_output)
1488
1486
    def test_one_client(self):
1489
1487
        output = PrintTableCmd().output(self.one_client.values())
1490
 
        expected_output = "\n".join((
1491
 
            "Name Enabled Timeout  Last Successful Check",
1492
 
            "foo  Yes     00:05:00 2019-02-03T00:00:00  ",
1493
 
        ))
 
1488
        expected_output = """
 
1489
Name Enabled Timeout  Last Successful Check
 
1490
foo  Yes     00:05:00 2019-02-03T00:00:00  
 
1491
"""[1:-1]
1494
1492
        self.assertEqual(output, expected_output)
1495
1493
 
1496
1494
 
1523
1521
        self.command().run(clients, self.bus)
1524
1522
 
1525
1523
 
1526
 
class TestEnableCmd(TestPropertyCmd):
1527
 
    command = EnableCmd
1528
 
    propname = "Enabled"
1529
 
    values_to_set = [dbus.Boolean(True)]
1530
 
 
1531
 
 
1532
 
class TestDisableCmd(TestPropertyCmd):
1533
 
    command = DisableCmd
1534
 
    propname = "Enabled"
1535
 
    values_to_set = [dbus.Boolean(False)]
 
1524
class TestEnableCmd(TestCmd):
 
1525
    def test_enable(self):
 
1526
        for clientpath in self.clients:
 
1527
            client = self.bus.get_object(dbus_busname, clientpath)
 
1528
            client.attributes["Enabled"] = False
 
1529
 
 
1530
        EnableCmd().run(self.clients, self.bus)
 
1531
 
 
1532
        for clientpath in self.clients:
 
1533
            client = self.bus.get_object(dbus_busname, clientpath)
 
1534
            self.assertTrue(client.attributes["Enabled"])
 
1535
 
 
1536
 
 
1537
class TestDisableCmd(TestCmd):
 
1538
    def test_disable(self):
 
1539
        DisableCmd().run(self.clients, self.bus)
 
1540
        for clientpath in self.clients:
 
1541
            client = self.bus.get_object(dbus_busname, clientpath)
 
1542
            self.assertFalse(client.attributes["Enabled"])
1536
1543
 
1537
1544
 
1538
1545
class TestBumpTimeoutCmd(TestPropertyCmd):