/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-07 20:37:15 UTC
  • mto: (237.7.594 trunk)
  • mto: This revision was merged to the branch mainline in revision 382.
  • Revision ID: teddy@recompile.se-20190307203715-nilyilg9adr8q7bm
mandos-ctl: Add tests for short options

* mandos-ctl
  (Test_command_from_options.test_print_table_verbose_short): New.
  (Test_command_from_options.test_enable_short): - '' -
  (Test_command_from_options.test_disable_short): - '' -
  (Test_command_from_options.test_bump_timeout_short): - '' -
  (Test_command_from_options.test_remove_short): - '' -
  (Test_command_from_options.test_checker_short): - '' -
  (Test_command_from_options.test_timeout_short): - '' -
  (Test_command_from_options.test_interval_short): - '' -
  (Test_command_from_options.test_host_short): - '' -
  (Test_command_from_options.test_secret_devnull_short): - '' -
  (Test_command_from_options.test_secret_tempfile_short): - '' -
  (Test_command_from_options.test_approve_short): - '' -
  (Test_command_from_options.test_deny_short): - '' -
  (Test_command_from_options.test_is_enabled_short): - '' -

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
45
47
 
46
48
import dbus
47
49
 
314
316
    @value_to_set.setter
315
317
    def value_to_set(self, value):
316
318
        """When setting, convert value to a datetime.timedelta"""
317
 
        self._vts = string_to_delta(value).total_seconds() * 1000
 
319
        self._vts = int(round(value.total_seconds() * 1000))
318
320
 
319
321
# Actual (non-abstract) command classes
320
322
 
475
477
    property = "Host"
476
478
 
477
479
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()
478
488
    property = "Secret"
479
489
 
480
490
class SetTimeoutCmd(PropertyCmd, MillisecondsValueArgumentMixIn):
495
505
                             MillisecondsValueArgumentMixIn):
496
506
    property = "ApprovalDuration"
497
507
 
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
 
 
518
508
def add_command_line_options(parser):
519
509
    parser.add_argument("--version", action="version",
520
510
                        version="%(prog)s {}".format(version),
546
536
                        help="Remove client")
547
537
    parser.add_argument("-c", "--checker",
548
538
                        help="Set checker command for client")
549
 
    parser.add_argument("-t", "--timeout",
 
539
    parser.add_argument("-t", "--timeout", type=string_to_delta,
550
540
                        help="Set timeout for client")
551
 
    parser.add_argument("--extended-timeout",
 
541
    parser.add_argument("--extended-timeout", type=string_to_delta,
552
542
                        help="Set extended timeout for client")
553
 
    parser.add_argument("-i", "--interval",
 
543
    parser.add_argument("-i", "--interval", type=string_to_delta,
554
544
                        help="Set checker interval for client")
555
545
    approve_deny_default = parser.add_mutually_exclusive_group()
556
546
    approve_deny_default.add_argument(
561
551
        "--deny-by-default", action="store_false",
562
552
        dest="approved_by_default",
563
553
        help="Set client to be denied by default")
564
 
    parser.add_argument("--approval-delay",
 
554
    parser.add_argument("--approval-delay", type=string_to_delta,
565
555
                        help="Set delay before client approve/deny")
566
 
    parser.add_argument("--approval-duration",
 
556
    parser.add_argument("--approval-duration", type=string_to_delta,
567
557
                        help="Set duration of one client approval")
568
558
    parser.add_argument("-H", "--host", help="Set host for client")
569
559
    parser.add_argument("-s", "--secret",
609
599
        commands.append(RemoveCmd())
610
600
 
611
601
    if options.checker is not None:
612
 
        commands.append(SetCheckerCmd())
 
602
        commands.append(SetCheckerCmd(options.checker))
613
603
 
614
604
    if options.timeout is not None:
615
605
        commands.append(SetTimeoutCmd(options.timeout))
619
609
            SetExtendedTimeoutCmd(options.extended_timeout))
620
610
 
621
611
    if options.interval is not None:
622
 
        command.append(SetIntervalCmd(options.interval))
 
612
        commands.append(SetIntervalCmd(options.interval))
623
613
 
624
614
    if options.approved_by_default is not None:
625
615
        if options.approved_by_default:
626
 
            command.append(ApproveByDefaultCmd())
 
616
            commands.append(ApproveByDefaultCmd())
627
617
        else:
628
 
            command.append(DenyByDefaultCmd())
 
618
            commands.append(DenyByDefaultCmd())
629
619
 
630
620
    if options.approval_delay is not None:
631
 
        command.append(SetApprovalDelayCmd(options.approval_delay))
 
621
        commands.append(SetApprovalDelayCmd(options.approval_delay))
632
622
 
633
623
    if options.approval_duration is not None:
634
 
        command.append(
 
624
        commands.append(
635
625
            SetApprovalDurationCmd(options.approval_duration))
636
626
 
637
627
    if options.host is not None:
638
 
        command.append(SetHostCmd(options.host))
 
628
        commands.append(SetHostCmd(options.host))
639
629
 
640
630
    if options.secret is not None:
641
 
        command.append(SetSecretCmd(options.secret))
 
631
        commands.append(SetSecretCmd(options.secret))
642
632
 
643
633
    if options.approve:
644
634
        commands.append(ApproveCmd())
661
651
 
662
652
    options = parser.parse_args()
663
653
 
 
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
 
664
674
    if has_actions(options) and not (options.client or options.all):
665
675
        parser.error("Options require clients names or --all.")
666
676
    if options.verbose and has_actions(options):
1083
1093
class TestSetSecretCmd(TestValueArgumentPropertyCmd):
1084
1094
    command = SetSecretCmd
1085
1095
    property = "Secret"
1086
 
    values_to_set = [b"", b"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"]
1087
1099
 
1088
1100
class TestSetTimeoutCmd(TestValueArgumentPropertyCmd):
1089
1101
    command = SetTimeoutCmd
1090
1102
    property = "Timeout"
1091
 
    values_to_set = ["P0D", "PT5M", "PT1S", "PT120S", "P1Y"]
1092
 
    values_to_get = [0, 300000, 1000, 120000, 31449600000]
 
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]
1093
1109
 
1094
1110
class TestSetExtendedTimeoutCmd(TestValueArgumentPropertyCmd):
1095
1111
    command = SetExtendedTimeoutCmd
1096
1112
    property = "ExtendedTimeout"
1097
 
    values_to_set = ["P0D", "PT5M", "PT1S", "PT120S", "P1Y"]
1098
 
    values_to_get = [0, 300000, 1000, 120000, 31449600000]
 
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]
1099
1119
 
1100
1120
class TestSetIntervalCmd(TestValueArgumentPropertyCmd):
1101
1121
    command = SetIntervalCmd
1102
1122
    property = "Interval"
1103
 
    values_to_set = ["P0D", "PT5M", "PT1S", "PT120S", "P1Y"]
1104
 
    values_to_get = [0, 300000, 1000, 120000, 31449600000]
 
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]
1105
1129
 
1106
1130
class TestSetApprovalDelayCmd(TestValueArgumentPropertyCmd):
1107
1131
    command = SetApprovalDelayCmd
1108
1132
    property = "ApprovalDelay"
1109
 
    values_to_set = ["P0D", "PT5M", "PT1S", "PT120S", "P1Y"]
1110
 
    values_to_get = [0, 300000, 1000, 120000, 31449600000]
 
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]
1111
1139
 
1112
1140
class TestSetApprovalDurationCmd(TestValueArgumentPropertyCmd):
1113
1141
    command = SetApprovalDurationCmd
1114
1142
    property = "ApprovalDuration"
1115
 
    values_to_set = ["P0D", "PT5M", "PT1S", "PT120S", "P1Y"]
1116
 
    values_to_get = [0, 300000, 1000, 120000, 31449600000]
 
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]
1117
1149
 
1118
 
class TestOptions(unittest.TestCase):
 
1150
class Test_command_from_options(unittest.TestCase):
1119
1151
    def setUp(self):
1120
1152
        self.parser = argparse.ArgumentParser()
1121
1153
        add_command_line_options(self.parser)
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)
 
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
 
1137
1176
    def test_enable(self):
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"])
 
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)
1143
1326
 
1144
1327
 
1145
1328