File: test_allowed_signers.py

package info (click to toggle)
python-sshsig 0.2.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 236 kB
  • sloc: python: 901; sh: 53; makefile: 9
file content (154 lines) | stat: -rw-r--r-- 4,604 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# (c) 2024 E. Castedo Ellerman <castedo@castedo.com>
# Released under the MIT License (https://spdx.org/licenses/MIT)
# fmt: off

from io import StringIO
from pathlib import Path
from unittest import TestCase

from sshsig import PublicKey
from sshsig.allowed_signers import AllowedSigner, load_allowed_signers_file


TESTDATA_DIR = Path(__file__).parent.parent / "testdata"
SSHSIG_CASES = list((TESTDATA_DIR / "sshsig").iterdir())

key0 = [
    "ssh-ed25519",
    "AAAAC3NzaC1lZDI1NTE5AAAAIJY08ynqE/VoH690nSN+MUxMzAbfNcMdUQr+5ltIskMt",
]
key1 = [
    "ssh-ed25519",
    "AAAAC3NzaC1lZDI1NTE5AAAAIIQdQut465od3lkVyVW6038PcD/wSGX/2ij3RcQZTAqt",
]

with open(TESTDATA_DIR / "rsa_key.pub") as f:
    rsa_key = f.read().strip().split()

openssh_keys = [key0, key1, rsa_key]


class PublicKeyParseTests(TestCase):

    def test_bad_base64(self):
        with self.assertRaises(ValueError):
            PublicKey.from_openssh_str("ssh-rsa AAAAB")
        with self.assertRaises(ValueError):
            PublicKey.from_openssh_str("ssh-rsa AAAA")

    def test_parse(self):
        for key in openssh_keys:
            with self.subTest(key=key):
                PublicKey.from_openssh_str(" ".join(key))

    def test_roundtrip(self):
        for key in openssh_keys:
            with self.subTest(key=key):
                key_obj = PublicKey.from_openssh_str(" ".join(key))
                s = key_obj.openssh_str()
                self.assertEqual(key_obj, PublicKey.from_openssh_str(s))


class FileCaseParseTests(TestCase):

    def test_case_0(self):
        load_allowed_signers_file(SSHSIG_CASES[0] / "allowed_signers")


# Many test cases are from the ssh-keygen test code:
# https://archive.softwareheritage.org/
# swh:1:cnt:dae03706d8f0cb09fa8f8cd28f86d06c4693f0c9


class ParseTests(TestCase):

    def test_man_page_example(self):
        # Example "ALLOWED SIGNERS" file from ssh-keygen man page. Man page source:
        # https://archive.softwareheritage.org/
        # swh:1:cnt:06f0555a4ec01caf8daed84b8409dd8cb3278740

        text = StringIO(
            """\
# Comments allowed at start of line
user1@example.com,user2@example.com {} {} {}
# A certificate authority, trusted for all principals in a domain.
*@example.com cert-authority {} {}
# A key that is accepted only for file signing.
user2@example.com namespaces="file" {} {}
""".format(*rsa_key, *key0, *key1)
        )
        expect = [
            AllowedSigner("user1@example.com,user2@example.com", None, *rsa_key),
            AllowedSigner("*@example.com", {'cert-authority': ''}, *key0),
            AllowedSigner("user2@example.com", {'namespaces': "file"}, *key1),
        ]
        got = load_allowed_signers_file(text)
        self.assertEqual(expect, got)

    def test_no_options_and_quotes(self):
        text = StringIO(
            """\
foo@example.com {} {}
"foo@example.com" {} {}
""".format(*key0, *key0)
        )
        same = AllowedSigner("foo@example.com", None, *key0)
        expect = [same, same]
        self.assertEqual(expect, load_allowed_signers_file(text))

    def test_space_in_quotes(self):
        text = StringIO(
            """\
"ssh-keygen parses this" {} {}
""".format(*key0)
        )
        expect = [
            AllowedSigner("ssh-keygen parses this", None, *key0),
        ]
        self.assertEqual(expect, load_allowed_signers_file(text))

    def test_with_comments(self):
        text = StringIO(
            """\
foo@bar {} {} even without options ssh-keygen will ignore the end
""".format(*key1)
        )
        expect = [
            AllowedSigner(
                "foo@bar",
                None,
                *key1,
                "even without options ssh-keygen will ignore the end",
            )
        ]
        self.assertEqual(expect, load_allowed_signers_file(text))

    def test_two_namespaces(self):
        text = StringIO(
            """\
foo@b.ar namespaces="git,got" {} {}
""".format(*key1)
        )
        expect = [
            AllowedSigner(
                "foo@b.ar",
                {'namespaces': "git,got"},
                *key1,
            ),
        ]
        self.assertEqual(expect, load_allowed_signers_file(text))

    def test_dates(self):
        text = StringIO(
            """\
foo@b.ar valid-after="19801201",valid-before="20010201" {} {}
""".format(*key0)
        )
        expect = [
            AllowedSigner(
                "foo@b.ar",
                {"valid-after": "19801201", "valid-before": "20010201"},
                *key0,
            ),
        ]
        self.assertEqual(expect, load_allowed_signers_file(text))