1
1
#!/usr/bin/python3 -bbI
2
# -*- coding: utf-8; lexical-binding: t -*-
4
# Mandos Control - Control or query the Mandos server
6
# Copyright © 2008-2022 Teddy Hogeborn
7
# Copyright © 2008-2022 Björn Påhlsson
2
# -*- after-save-hook: (lambda () (let ((command (if (fboundp 'file-local-name) (file-local-name (buffer-file-name)) (or (file-remote-p (buffer-file-name) 'localname) (buffer-file-name))))) (if (= (progn (if (get-buffer "*Test*") (kill-buffer "*Test*")) (process-file-shell-command (format "%s --check" (shell-quote-argument command)) nil "*Test*")) 0) (let ((w (get-buffer-window "*Test*"))) (if w (delete-window w))) (progn (with-current-buffer "*Test*" (compilation-mode)) (display-buffer "*Test*" '(display-buffer-in-side-window)))))); coding: utf-8 -*-
4
# Mandos Monitor - Control and monitor the Mandos server
6
# Copyright © 2008-2019 Teddy Hogeborn
7
# Copyright © 2008-2019 Björn Påhlsson
9
9
# This file is part of Mandos.
395
395
"""Parse an interval string as documented by Mandos before 1.6.1,
396
396
and return a datetime.timedelta
398
>>> parse_pre_1_6_1_interval("7d") == datetime.timedelta(days=7)
400
>>> parse_pre_1_6_1_interval("60s") == datetime.timedelta(0, 60)
402
>>> parse_pre_1_6_1_interval("60m") == datetime.timedelta(hours=1)
404
>>> parse_pre_1_6_1_interval("24h") == datetime.timedelta(days=1)
406
>>> parse_pre_1_6_1_interval("1w") == datetime.timedelta(days=7)
408
>>> parse_pre_1_6_1_interval("5m 30s") == datetime.timedelta(0, 330)
410
>>> parse_pre_1_6_1_interval("") == datetime.timedelta(0)
398
>>> parse_pre_1_6_1_interval('7d') == datetime.timedelta(days=7)
400
>>> parse_pre_1_6_1_interval('60s') == datetime.timedelta(0, 60)
402
>>> parse_pre_1_6_1_interval('60m') == datetime.timedelta(hours=1)
404
>>> parse_pre_1_6_1_interval('24h') == datetime.timedelta(days=1)
406
>>> parse_pre_1_6_1_interval('1w') == datetime.timedelta(days=7)
408
>>> parse_pre_1_6_1_interval('5m 30s') == datetime.timedelta(0, 330)
410
>>> parse_pre_1_6_1_interval('') == datetime.timedelta(0)
412
412
>>> # Ignore unknown characters, allow any order and repetitions
413
>>> parse_pre_1_6_1_interval("2dxy7zz11y3m5m") == datetime.timedelta(2, 480, 18000)
413
>>> parse_pre_1_6_1_interval('2dxy7zz11y3m5m') == datetime.timedelta(2, 480, 18000)
497
497
self.properties_iface, interface, key,
500
def call_method(self, methodname, busname, objectpath,
502
raise NotImplementedError()
505
500
class MandosBus(SystemBus):
506
501
busname_domain = "se.recompile"
507
502
busname = busname_domain + ".Mandos"
876
869
{key: properties[key]
877
870
for key in self.all_keywords}
878
871
for properties in clients.values()}
879
print(json.dumps(data, indent=4, separators=(",", ": ")))
872
print(json.dumps(data, indent=4, separators=(',', ': ')))
882
875
class PrintTable(Output):
1777
1770
self.call_method(bus, "methodname", "busname",
1778
1771
"objectpath", "interface")
1780
self.assertNotIsInstance(e.exception, dbus.ConnectFailed)
1773
self.assertNotIsInstance(e, dbus.ConnectFailed)
1782
1775
def test_get_converts_to_correct_exception(self):
1783
1776
bus = pydbus_adapter.SystemBus(
2439
2432
busname = "se.recompile.Mandos"
2440
2433
client_interface = "se.recompile.Mandos.Client"
2441
2434
command.Approve().run(self.bus.clients, self.bus)
2442
self.assertTrue(self.bus.clients)
2443
2435
for clientpath in self.bus.clients:
2444
2436
self.assertIn(("Approve", busname, clientpath,
2445
2437
client_interface, (True,)), self.bus.calls)
2448
2440
busname = "se.recompile.Mandos"
2449
2441
client_interface = "se.recompile.Mandos.Client"
2450
2442
command.Deny().run(self.bus.clients, self.bus)
2451
self.assertTrue(self.bus.clients)
2452
2443
for clientpath in self.bus.clients:
2453
2444
self.assertIn(("Approve", busname, clientpath,
2454
2445
client_interface, (False,)),
2455
2446
self.bus.calls)
2457
2448
def test_Remove(self):
2458
busname = "se.recompile.Mandos"
2460
server_interface = "se.recompile.Mandos"
2461
orig_clients = self.bus.clients.copy()
2462
2449
command.Remove().run(self.bus.clients, self.bus)
2463
self.assertFalse(self.bus.clients)
2464
for clientpath in orig_clients:
2465
self.assertIn(("RemoveClient", busname,
2466
server_path, server_interface,
2450
for clientpath in self.bus.clients:
2451
self.assertIn(("RemoveClient", dbus_busname,
2452
dbus_server_path, dbus_server_interface,
2467
2453
(clientpath,)), self.bus.calls)
2469
2455
expected_json = {
2672
2658
cmd_args = [() for x in range(len(self.values_to_get))]
2673
2659
values_to_get = self.values_to_get
2674
self.assertTrue(values_to_get)
2675
2660
for value_to_get, cmd_arg in zip(values_to_get, cmd_args):
2676
2661
for clientpath in self.bus.clients:
2677
2662
self.bus.clients[clientpath][self.propname] = (
2679
2664
self.command(*cmd_arg).run(self.bus.clients, self.bus)
2680
self.assertTrue(self.bus.clients)
2681
2665
for clientpath in self.bus.clients:
2682
2666
value = (self.bus.clients[clientpath]
2683
2667
[self.propname])
2742
2726
class TestSetSecretCmd(TestPropertySetterCmd):
2743
2727
command = command.SetSecret
2744
2728
propname = "Secret"
2745
def __init__(self, *args, **kwargs):
2746
self.values_to_set = [io.BytesIO(b""),
2747
io.BytesIO(b"secret\0xyzzy\nbar")]
2748
self.values_to_get = [f.getvalue() for f in
2750
super(TestSetSecretCmd, self).__init__(*args, **kwargs)
2729
values_to_set = [io.BytesIO(b""),
2730
io.BytesIO(b"secret\0xyzzy\nbar")]
2731
values_to_get = [f.getvalue() for f in values_to_set]
2753
2734
class TestSetTimeoutCmd(TestPropertySetterCmd):
2809
def parse_test_args():
2810
# type: () -> argparse.Namespace
2790
def should_only_run_tests():
2811
2791
parser = argparse.ArgumentParser(add_help=False)
2812
parser.add_argument("--check", action="store_true")
2813
parser.add_argument("--prefix", )
2792
parser.add_argument("--check", action='store_true')
2814
2793
args, unknown_args = parser.parse_known_args()
2816
# Remove test options from sys.argv
2794
run_tests = args.check
2796
# Remove --check argument from sys.argv
2817
2797
sys.argv[1:] = unknown_args
2820
2800
# Add all tests from doctest strings
2821
2801
def load_tests(loader, tests, none):
2826
2806
if __name__ == "__main__":
2827
options = parse_test_args()
2830
extra_test_prefix = options.prefix
2831
if extra_test_prefix is not None:
2832
if not (unittest.main(argv=[""], exit=False)
2833
.result.wasSuccessful()):
2835
class ExtraTestLoader(unittest.TestLoader):
2836
testMethodPrefix = extra_test_prefix
2837
# Call using ./scriptname --check [--verbose]
2838
unittest.main(argv=[""], testLoader=ExtraTestLoader())
2840
unittest.main(argv=[""])
2808
if should_only_run_tests():
2809
# Call using ./tdd-python-script --check [--verbose]
2844
2814
logging.shutdown()
2848
# (lambda (&optional extra)
2849
# (if (not (funcall run-tests-in-test-buffer default-directory
2851
# (funcall show-test-buffer-in-test-window)
2852
# (funcall remove-test-window)
2853
# (if extra (message "Extra tests run successfully!"))))
2854
# run-tests-in-test-buffer:
2855
# (lambda (dir &optional extra)
2856
# (with-current-buffer (get-buffer-create "*Test*")
2857
# (setq buffer-read-only nil
2858
# default-directory dir)
2860
# (compilation-mode))
2861
# (let ((process-result
2862
# (let ((inhibit-read-only t))
2863
# (process-file-shell-command
2864
# (funcall get-command-line extra) nil "*Test*"))))
2865
# (and (numberp process-result)
2866
# (= process-result 0))))
2868
# (lambda (&optional extra)
2869
# (let ((quoted-script
2870
# (shell-quote-argument (funcall get-script-name))))
2872
# (concat "%s --check" (if extra " --prefix=atest" ""))
2876
# (if (fboundp 'file-local-name)
2877
# (file-local-name (buffer-file-name))
2878
# (or (file-remote-p (buffer-file-name) 'localname)
2879
# (buffer-file-name))))
2880
# remove-test-window:
2882
# (let ((test-window (get-buffer-window "*Test*")))
2883
# (if test-window (delete-window test-window))))
2884
# show-test-buffer-in-test-window:
2886
# (when (not (get-buffer-window-list "*Test*"))
2887
# (setq next-error-last-buffer (get-buffer "*Test*"))
2888
# (let* ((side (if (>= (window-width) 146) 'right 'bottom))
2889
# (display-buffer-overriding-action
2890
# `((display-buffer-in-side-window) (side . ,side)
2891
# (window-height . fit-window-to-buffer)
2892
# (window-width . fit-window-to-buffer))))
2893
# (display-buffer "*Test*"))))
2896
# (let* ((run-extra-tests (lambda () (interactive)
2897
# (funcall run-tests t)))
2898
# (inner-keymap `(keymap (116 . ,run-extra-tests))) ; t
2899
# (outer-keymap `(keymap (3 . ,inner-keymap)))) ; C-c
2900
# (setq minor-mode-overriding-map-alist
2901
# (cons `(run-tests . ,outer-keymap)
2902
# minor-mode-overriding-map-alist)))
2903
# (add-hook 'after-save-hook run-tests 90 t))