/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-06 18:30:45 UTC
  • mto: (237.7.594 trunk)
  • mto: This revision was merged to the branch mainline in revision 382.
  • Revision ID: teddy@recompile.se-20190306183045-blmd3hb7vy4q6waj
mandos-ctl: Add test for the --enable option

* mandos-ctl (TestOptions.test_enable): New.

Show diffs side-by-side

added added

removed removed

Lines of Context:
42
42
import json
43
43
import unittest
44
44
import logging
45
 
import io
46
 
import tempfile
47
45
 
48
46
import dbus
49
47
 
316
314
    @value_to_set.setter
317
315
    def value_to_set(self, value):
318
316
        """When setting, convert value to a datetime.timedelta"""
319
 
        self._vts = int(round(value.total_seconds() * 1000))
 
317
        self._vts = string_to_delta(value).total_seconds() * 1000
320
318
 
321
319
# Actual (non-abstract) command classes
322
320
 
477
475
    property = "Host"
478
476
 
479
477
class SetSecretCmd(PropertyCmd, ValueArgumentMixIn):
480
 
    @property
481
 
    def value_to_set(self):
482
 
        return self._vts
483
 
    @value_to_set.setter
484
 
    def value_to_set(self, value):
485
 
        """When setting, read data from supplied file object"""
486
 
        self._vts = value.read()
487
 
        value.close()
488
478
    property = "Secret"
489
479
 
490
480
class SetTimeoutCmd(PropertyCmd, MillisecondsValueArgumentMixIn):
505
495
                             MillisecondsValueArgumentMixIn):
506
496
    property = "ApprovalDuration"
507
497
 
 
498
def has_actions(options):
 
499
    return any((options.enable,
 
500
                options.disable,
 
501
                options.bump_timeout,
 
502
                options.start_checker,
 
503
                options.stop_checker,
 
504
                options.is_enabled,
 
505
                options.remove,
 
506
                options.checker is not None,
 
507
                options.timeout is not None,
 
508
                options.extended_timeout is not None,
 
509
                options.interval is not None,
 
510
                options.approved_by_default is not None,
 
511
                options.approval_delay is not None,
 
512
                options.approval_duration is not None,
 
513
                options.host is not None,
 
514
                options.secret is not None,
 
515
                options.approve,
 
516
                options.deny))
 
517
 
508
518
def add_command_line_options(parser):
509
519
    parser.add_argument("--version", action="version",
510
520
                        version="%(prog)s {}".format(version),
536
546
                        help="Remove client")
537
547
    parser.add_argument("-c", "--checker",
538
548
                        help="Set checker command for client")
539
 
    parser.add_argument("-t", "--timeout", type=string_to_delta,
 
549
    parser.add_argument("-t", "--timeout",
540
550
                        help="Set timeout for client")
541
 
    parser.add_argument("--extended-timeout", type=string_to_delta,
 
551
    parser.add_argument("--extended-timeout",
542
552
                        help="Set extended timeout for client")
543
 
    parser.add_argument("-i", "--interval", type=string_to_delta,
 
553
    parser.add_argument("-i", "--interval",
544
554
                        help="Set checker interval for client")
545
555
    approve_deny_default = parser.add_mutually_exclusive_group()
546
556
    approve_deny_default.add_argument(
551
561
        "--deny-by-default", action="store_false",
552
562
        dest="approved_by_default",
553
563
        help="Set client to be denied by default")
554
 
    parser.add_argument("--approval-delay", type=string_to_delta,
 
564
    parser.add_argument("--approval-delay",
555
565
                        help="Set delay before client approve/deny")
556
 
    parser.add_argument("--approval-duration", type=string_to_delta,
 
566
    parser.add_argument("--approval-duration",
557
567
                        help="Set duration of one client approval")
558
568
    parser.add_argument("-H", "--host", help="Set host for client")
559
569
    parser.add_argument("-s", "--secret",
599
609
        commands.append(RemoveCmd())
600
610
 
601
611
    if options.checker is not None:
602
 
        commands.append(SetCheckerCmd(options.checker))
 
612
        commands.append(SetCheckerCmd())
603
613
 
604
614
    if options.timeout is not None:
605
615
        commands.append(SetTimeoutCmd(options.timeout))
609
619
            SetExtendedTimeoutCmd(options.extended_timeout))
610
620
 
611
621
    if options.interval is not None:
612
 
        commands.append(SetIntervalCmd(options.interval))
 
622
        command.append(SetIntervalCmd(options.interval))
613
623
 
614
624
    if options.approved_by_default is not None:
615
625
        if options.approved_by_default:
616
 
            commands.append(ApproveByDefaultCmd())
 
626
            command.append(ApproveByDefaultCmd())
617
627
        else:
618
 
            commands.append(DenyByDefaultCmd())
 
628
            command.append(DenyByDefaultCmd())
619
629
 
620
630
    if options.approval_delay is not None:
621
 
        commands.append(SetApprovalDelayCmd(options.approval_delay))
 
631
        command.append(SetApprovalDelayCmd(options.approval_delay))
622
632
 
623
633
    if options.approval_duration is not None:
624
 
        commands.append(
 
634
        command.append(
625
635
            SetApprovalDurationCmd(options.approval_duration))
626
636
 
627
637
    if options.host is not None:
628
 
        commands.append(SetHostCmd(options.host))
 
638
        command.append(SetHostCmd(options.host))
629
639
 
630
640
    if options.secret is not None:
631
 
        commands.append(SetSecretCmd(options.secret))
 
641
        command.append(SetSecretCmd(options.secret))
632
642
 
633
643
    if options.approve:
634
644
        commands.append(ApproveCmd())
651
661
 
652
662
    options = parser.parse_args()
653
663
 
654
 
    def has_actions(options):
655
 
        return any((options.enable,
656
 
                    options.disable,
657
 
                    options.bump_timeout,
658
 
                    options.start_checker,
659
 
                    options.stop_checker,
660
 
                    options.is_enabled,
661
 
                    options.remove,
662
 
                    options.checker is not None,
663
 
                    options.timeout is not None,
664
 
                    options.extended_timeout is not None,
665
 
                    options.interval is not None,
666
 
                    options.approved_by_default is not None,
667
 
                    options.approval_delay is not None,
668
 
                    options.approval_duration is not None,
669
 
                    options.host is not None,
670
 
                    options.secret is not None,
671
 
                    options.approve,
672
 
                    options.deny))
673
 
 
674
664
    if has_actions(options) and not (options.client or options.all):
675
665
        parser.error("Options require clients names or --all.")
676
666
    if options.verbose and has_actions(options):
1093
1083
class TestSetSecretCmd(TestValueArgumentPropertyCmd):
1094
1084
    command = SetSecretCmd
1095
1085
    property = "Secret"
1096
 
    values_to_set = [open("/dev/null", "rb"),
1097
 
                     io.BytesIO(b"secret\0xyzzy\nbar")]
1098
 
    values_to_get = [b"", b"secret\0xyzzy\nbar"]
 
1086
    values_to_set = [b"", b"secret"]
1099
1087
 
1100
1088
class TestSetTimeoutCmd(TestValueArgumentPropertyCmd):
1101
1089
    command = SetTimeoutCmd
1102
1090
    property = "Timeout"
1103
 
    values_to_set = [datetime.timedelta(),
1104
 
                     datetime.timedelta(minutes=5),
1105
 
                     datetime.timedelta(seconds=1),
1106
 
                     datetime.timedelta(weeks=1),
1107
 
                     datetime.timedelta(weeks=52)]
1108
 
    values_to_get = [0, 300000, 1000, 604800000, 31449600000]
 
1091
    values_to_set = ["P0D", "PT5M", "PT1S", "PT120S", "P1Y"]
 
1092
    values_to_get = [0, 300000, 1000, 120000, 31449600000]
1109
1093
 
1110
1094
class TestSetExtendedTimeoutCmd(TestValueArgumentPropertyCmd):
1111
1095
    command = SetExtendedTimeoutCmd
1112
1096
    property = "ExtendedTimeout"
1113
 
    values_to_set = [datetime.timedelta(),
1114
 
                     datetime.timedelta(minutes=5),
1115
 
                     datetime.timedelta(seconds=1),
1116
 
                     datetime.timedelta(weeks=1),
1117
 
                     datetime.timedelta(weeks=52)]
1118
 
    values_to_get = [0, 300000, 1000, 604800000, 31449600000]
 
1097
    values_to_set = ["P0D", "PT5M", "PT1S", "PT120S", "P1Y"]
 
1098
    values_to_get = [0, 300000, 1000, 120000, 31449600000]
1119
1099
 
1120
1100
class TestSetIntervalCmd(TestValueArgumentPropertyCmd):
1121
1101
    command = SetIntervalCmd
1122
1102
    property = "Interval"
1123
 
    values_to_set = [datetime.timedelta(),
1124
 
                     datetime.timedelta(minutes=5),
1125
 
                     datetime.timedelta(seconds=1),
1126
 
                     datetime.timedelta(weeks=1),
1127
 
                     datetime.timedelta(weeks=52)]
1128
 
    values_to_get = [0, 300000, 1000, 604800000, 31449600000]
 
1103
    values_to_set = ["P0D", "PT5M", "PT1S", "PT120S", "P1Y"]
 
1104
    values_to_get = [0, 300000, 1000, 120000, 31449600000]
1129
1105
 
1130
1106
class TestSetApprovalDelayCmd(TestValueArgumentPropertyCmd):
1131
1107
    command = SetApprovalDelayCmd
1132
1108
    property = "ApprovalDelay"
1133
 
    values_to_set = [datetime.timedelta(),
1134
 
                     datetime.timedelta(minutes=5),
1135
 
                     datetime.timedelta(seconds=1),
1136
 
                     datetime.timedelta(weeks=1),
1137
 
                     datetime.timedelta(weeks=52)]
1138
 
    values_to_get = [0, 300000, 1000, 604800000, 31449600000]
 
1109
    values_to_set = ["P0D", "PT5M", "PT1S", "PT120S", "P1Y"]
 
1110
    values_to_get = [0, 300000, 1000, 120000, 31449600000]
1139
1111
 
1140
1112
class TestSetApprovalDurationCmd(TestValueArgumentPropertyCmd):
1141
1113
    command = SetApprovalDurationCmd
1142
1114
    property = "ApprovalDuration"
1143
 
    values_to_set = [datetime.timedelta(),
1144
 
                     datetime.timedelta(minutes=5),
1145
 
                     datetime.timedelta(seconds=1),
1146
 
                     datetime.timedelta(weeks=1),
1147
 
                     datetime.timedelta(weeks=52)]
1148
 
    values_to_get = [0, 300000, 1000, 604800000, 31449600000]
 
1115
    values_to_set = ["P0D", "PT5M", "PT1S", "PT120S", "P1Y"]
 
1116
    values_to_get = [0, 300000, 1000, 120000, 31449600000]
1149
1117
 
1150
 
class Test_command_from_options(unittest.TestCase):
 
1118
class TestOptions(unittest.TestCase):
1151
1119
    def setUp(self):
1152
1120
        self.parser = argparse.ArgumentParser()
1153
1121
        add_command_line_options(self.parser)
1154
 
    def assert_command_from_args(self, args, command_cls, **cmd_attrs):
1155
 
        """Assert that parsing ARGS should result in an instance of
1156
 
COMMAND_CLS with (optionally) all supplied attributes (CMD_ATTRS)."""
1157
 
        options = self.parser.parse_args(args)
1158
 
        commands = commands_from_options(options)
1159
 
        self.assertEqual(len(commands), 1)
1160
 
        command = commands[0]
1161
 
        self.assertIsInstance(command, command_cls)
1162
 
        for key, value in cmd_attrs.items():
1163
 
            self.assertEqual(getattr(command, key), value)
1164
 
    def test_print_table(self):
1165
 
        self.assert_command_from_args([], PrintTableCmd,
1166
 
                                      verbose=False)
1167
 
 
1168
 
    def test_print_table_verbose(self):
1169
 
        self.assert_command_from_args(["--verbose"], PrintTableCmd,
1170
 
                                      verbose=True)
1171
 
 
1172
 
    def test_print_table_verbose_short(self):
1173
 
        self.assert_command_from_args(["-v"], PrintTableCmd,
1174
 
                                      verbose=True)
1175
 
 
 
1122
    def commands_from_args(self, args):
 
1123
        self.options = self.parser.parse_args(args)
 
1124
        return commands_from_options(self.options)
 
1125
    def test_default_is_show_table(self):
 
1126
        commands = self.commands_from_args([])
 
1127
        self.assertEqual(len(commands), 1)
 
1128
        command = commands[0]
 
1129
        self.assertIsInstance(command, PrintTableCmd)
 
1130
        self.assertEqual(command.verbose, False)
 
1131
    def test_show_table_verbose(self):
 
1132
        commands = self.commands_from_args(["--verbose"])
 
1133
        self.assertEqual(len(commands), 1)
 
1134
        command = commands[0]
 
1135
        self.assertIsInstance(command, PrintTableCmd)
 
1136
        self.assertEqual(command.verbose, True)
1176
1137
    def test_enable(self):
1177
 
        self.assert_command_from_args(["--enable", "foo"], EnableCmd)
1178
 
 
1179
 
    def test_enable_short(self):
1180
 
        self.assert_command_from_args(["-e", "foo"], EnableCmd)
1181
 
 
1182
 
    def test_disable(self):
1183
 
        self.assert_command_from_args(["--disable", "foo"],
1184
 
                                      DisableCmd)
1185
 
 
1186
 
    def test_disable_short(self):
1187
 
        self.assert_command_from_args(["-d", "foo"], DisableCmd)
1188
 
 
1189
 
    def test_bump_timeout(self):
1190
 
        self.assert_command_from_args(["--bump-timeout", "foo"],
1191
 
                                      BumpTimeoutCmd)
1192
 
 
1193
 
    def test_bump_timeout_short(self):
1194
 
        self.assert_command_from_args(["-b", "foo"], BumpTimeoutCmd)
1195
 
 
1196
 
    def test_start_checker(self):
1197
 
        self.assert_command_from_args(["--start-checker", "foo"],
1198
 
                                      StartCheckerCmd)
1199
 
 
1200
 
    def test_stop_checker(self):
1201
 
        self.assert_command_from_args(["--stop-checker", "foo"],
1202
 
                                      StopCheckerCmd)
1203
 
 
1204
 
    def test_remove(self):
1205
 
        self.assert_command_from_args(["--remove", "foo"],
1206
 
                                      RemoveCmd)
1207
 
 
1208
 
    def test_remove_short(self):
1209
 
        self.assert_command_from_args(["-r", "foo"], RemoveCmd)
1210
 
 
1211
 
    def test_checker(self):
1212
 
        self.assert_command_from_args(["--checker", ":", "foo"],
1213
 
                                      SetCheckerCmd, value_to_set=":")
1214
 
 
1215
 
    def test_checker_empty(self):
1216
 
        self.assert_command_from_args(["--checker", "", "foo"],
1217
 
                                      SetCheckerCmd, value_to_set="")
1218
 
 
1219
 
    def test_checker_short(self):
1220
 
        self.assert_command_from_args(["-c", ":", "foo"],
1221
 
                                      SetCheckerCmd, value_to_set=":")
1222
 
 
1223
 
    def test_timeout(self):
1224
 
        self.assert_command_from_args(["--timeout", "PT5M", "foo"],
1225
 
                                      SetTimeoutCmd,
1226
 
                                      value_to_set=300000)
1227
 
 
1228
 
    def test_timeout_short(self):
1229
 
        self.assert_command_from_args(["-t", "PT5M", "foo"],
1230
 
                                      SetTimeoutCmd,
1231
 
                                      value_to_set=300000)
1232
 
 
1233
 
    def test_extended_timeout(self):
1234
 
        self.assert_command_from_args(["--extended-timeout", "PT15M",
1235
 
                                       "foo"],
1236
 
                                      SetExtendedTimeoutCmd,
1237
 
                                      value_to_set=900000)
1238
 
 
1239
 
    def test_interval(self):
1240
 
        self.assert_command_from_args(["--interval", "PT2M", "foo"],
1241
 
                                      SetIntervalCmd,
1242
 
                                      value_to_set=120000)
1243
 
 
1244
 
    def test_interval_short(self):
1245
 
        self.assert_command_from_args(["-i", "PT2M", "foo"],
1246
 
                                      SetIntervalCmd,
1247
 
                                      value_to_set=120000)
1248
 
 
1249
 
    def test_approve_by_default(self):
1250
 
        self.assert_command_from_args(["--approve-by-default", "foo"],
1251
 
                                      ApproveByDefaultCmd)
1252
 
 
1253
 
    def test_deny_by_default(self):
1254
 
        self.assert_command_from_args(["--deny-by-default", "foo"],
1255
 
                                      DenyByDefaultCmd)
1256
 
 
1257
 
    def test_approval_delay(self):
1258
 
        self.assert_command_from_args(["--approval-delay", "PT30S",
1259
 
                                       "foo"], SetApprovalDelayCmd,
1260
 
                                      value_to_set=30000)
1261
 
 
1262
 
    def test_approval_duration(self):
1263
 
        self.assert_command_from_args(["--approval-duration", "PT1S",
1264
 
                                       "foo"], SetApprovalDurationCmd,
1265
 
                                      value_to_set=1000)
1266
 
 
1267
 
    def test_host(self):
1268
 
        self.assert_command_from_args(["--host", "foo.example.org",
1269
 
                                       "foo"], SetHostCmd,
1270
 
                                      value_to_set="foo.example.org")
1271
 
 
1272
 
    def test_host_short(self):
1273
 
        self.assert_command_from_args(["-H", "foo.example.org",
1274
 
                                       "foo"], SetHostCmd,
1275
 
                                      value_to_set="foo.example.org")
1276
 
 
1277
 
    def test_secret_devnull(self):
1278
 
        self.assert_command_from_args(["--secret", os.path.devnull,
1279
 
                                       "foo"], SetSecretCmd,
1280
 
                                      value_to_set=b"")
1281
 
 
1282
 
    def test_secret_tempfile(self):
1283
 
        with tempfile.NamedTemporaryFile(mode="r+b") as f:
1284
 
            value = b"secret\0xyzzy\nbar"
1285
 
            f.write(value)
1286
 
            f.seek(0)
1287
 
            self.assert_command_from_args(["--secret", f.name,
1288
 
                                           "foo"], SetSecretCmd,
1289
 
                                          value_to_set=value)
1290
 
 
1291
 
    def test_secret_devnull_short(self):
1292
 
        self.assert_command_from_args(["-s", os.path.devnull, "foo"],
1293
 
                                      SetSecretCmd, value_to_set=b"")
1294
 
 
1295
 
    def test_secret_tempfile_short(self):
1296
 
        with tempfile.NamedTemporaryFile(mode="r+b") as f:
1297
 
            value = b"secret\0xyzzy\nbar"
1298
 
            f.write(value)
1299
 
            f.seek(0)
1300
 
            self.assert_command_from_args(["-s", f.name, "foo"],
1301
 
                                          SetSecretCmd,
1302
 
                                          value_to_set=value)
1303
 
 
1304
 
    def test_approve(self):
1305
 
        self.assert_command_from_args(["--approve", "foo"],
1306
 
                                      ApproveCmd)
1307
 
 
1308
 
    def test_approve_short(self):
1309
 
        self.assert_command_from_args(["-A", "foo"], ApproveCmd)
1310
 
 
1311
 
    def test_deny(self):
1312
 
        self.assert_command_from_args(["--deny", "foo"], DenyCmd)
1313
 
 
1314
 
    def test_deny_short(self):
1315
 
        self.assert_command_from_args(["-D", "foo"], DenyCmd)
1316
 
 
1317
 
    def test_dump_json(self):
1318
 
        self.assert_command_from_args(["--dump-json"], DumpJSONCmd)
1319
 
 
1320
 
    def test_is_enabled(self):
1321
 
        self.assert_command_from_args(["--is-enabled", "foo"],
1322
 
                                      IsEnabledCmd)
1323
 
 
1324
 
    def test_is_enabled_short(self):
1325
 
        self.assert_command_from_args(["-V", "foo"], IsEnabledCmd)
 
1138
        commands = self.commands_from_args(["--enable", "foo"])
 
1139
        self.assertEqual(len(commands), 1)
 
1140
        command = commands[0]
 
1141
        self.assertIsInstance(command, EnableCmd)
 
1142
        self.assertEqual(self.options.client, ["foo"])
1326
1143
 
1327
1144
 
1328
1145