File: test_certdb.py

package info (click to toggle)
freeipa 4.13.1-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 367,240 kB
  • sloc: javascript: 562,763; python: 310,289; ansic: 49,809; sh: 7,176; makefile: 2,589; xml: 343; sed: 16
file content (286 lines) | stat: -rw-r--r-- 8,960 bytes parent folder | download | duplicates (4)
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
from __future__ import absolute_import

import os

import pytest

from ipapython.certdb import (
    NSSDatabase,
    TRUSTED_PEER_TRUST_FLAGS,
    nss_supports_dbm,
)
from ipapython import ipautil
from ipaplatform.osinfo import osinfo

CERTNICK = 'testcert'
CERTSAN = 'testcert.certdb.test'

if osinfo.id == 'fedora':
    if osinfo.version_number >= (28,):
        NSS_DEFAULT = 'sql'
    else:
        NSS_DEFAULT = 'dbm'
else:
    NSS_DEFAULT = None


def create_selfsigned(nssdb):
    # create self-signed cert + key
    noisefile = os.path.join(nssdb.secdir, 'noise')
    with open(noisefile, 'wb') as f:
        f.write(os.urandom(64))
    try:
        nssdb.run_certutil([
            '-S', '-x',
            '-z', noisefile,
            '-k', 'rsa', '-g', '2048', '-Z', 'SHA256',
            '-t', 'CTu,Cu,Cu',
            '-s', 'CN=testcert',
            '-n', CERTNICK,
            '-m', '365',
            '--extSAN', f'dns:{CERTSAN}'
        ])
    finally:
        os.unlink(noisefile)


@pytest.mark.skipif(
    not nss_supports_dbm(),
    reason="NSS is built without support of the legacy database(DBM)",
)
def test_dbm_tmp():
    with NSSDatabase(dbtype='dbm') as nssdb:
        assert nssdb.dbtype == 'dbm'

        for filename in nssdb.filenames:
            assert not os.path.isfile(filename)
        assert not nssdb.exists()

        nssdb.create_db()
        for filename in nssdb.filenames:
            assert os.path.isfile(filename)
            assert os.path.dirname(filename) == nssdb.secdir
        assert nssdb.exists()

        assert os.path.basename(nssdb.certdb) == 'cert8.db'
        assert nssdb.certdb in nssdb.filenames
        assert os.path.basename(nssdb.keydb) == 'key3.db'
        assert os.path.basename(nssdb.secmod) == 'secmod.db'


@pytest.mark.skipif(
    nss_supports_dbm(),
    reason="NSS is built with support of the legacy database(DBM)",
)
def test_dbm_raise():
    with pytest.raises(ValueError) as e:
        NSSDatabase(dbtype="dbm")
    assert (
        "NSS is built without support of the legacy database(DBM)"
        in str(e.value)
    )


def test_sql_tmp():
    with NSSDatabase(dbtype='sql') as nssdb:
        assert nssdb.dbtype == 'sql'

        for filename in nssdb.filenames:
            assert not os.path.isfile(filename)
        assert not nssdb.exists()

        nssdb.create_db()
        for filename in nssdb.filenames:
            assert os.path.isfile(filename)
            assert os.path.dirname(filename) == nssdb.secdir
        assert nssdb.exists()

        assert os.path.basename(nssdb.certdb) == 'cert9.db'
        assert nssdb.certdb in nssdb.filenames
        assert os.path.basename(nssdb.keydb) == 'key4.db'
        assert os.path.basename(nssdb.secmod) == 'pkcs11.txt'


@pytest.mark.skipif(
    not nss_supports_dbm(),
    reason="NSS is built without support of the legacy database(DBM)",
)
def test_convert_db():
    with NSSDatabase(dbtype='dbm') as nssdb:
        assert nssdb.dbtype == 'dbm'

        nssdb.create_db()
        assert nssdb.exists()

        create_selfsigned(nssdb)

        oldcerts = nssdb.list_certs()
        assert len(oldcerts) == 1
        oldkeys = nssdb.list_keys()
        assert len(oldkeys) == 1

        nssdb.convert_db()
        assert nssdb.exists()

        assert nssdb.dbtype == 'sql'
        newcerts = nssdb.list_certs()
        assert len(newcerts) == 1
        assert newcerts == oldcerts
        newkeys = nssdb.list_keys()
        assert len(newkeys) == 1
        assert newkeys == oldkeys

        for filename in nssdb.filenames:
            assert os.path.isfile(filename)
            assert os.path.dirname(filename) == nssdb.secdir

        assert os.path.basename(nssdb.certdb) == 'cert9.db'
        assert nssdb.certdb in nssdb.filenames
        assert os.path.basename(nssdb.keydb) == 'key4.db'
        assert os.path.basename(nssdb.secmod) == 'pkcs11.txt'


@pytest.mark.skipif(
    not nss_supports_dbm(),
    reason="NSS is built without support of the legacy database(DBM)",
)
def test_convert_db_nokey():
    with NSSDatabase(dbtype='dbm') as nssdb:
        assert nssdb.dbtype == 'dbm'
        nssdb.create_db()

        create_selfsigned(nssdb)

        assert len(nssdb.list_certs()) == 1
        assert len(nssdb.list_keys()) == 1
        # remove key, readd cert
        cert = nssdb.get_cert(CERTNICK)
        nssdb.run_certutil(['-F', '-n', CERTNICK])
        nssdb.add_cert(cert, CERTNICK, TRUSTED_PEER_TRUST_FLAGS)
        assert len(nssdb.list_keys()) == 0
        oldcerts = nssdb.list_certs()
        assert len(oldcerts) == 1

        nssdb.convert_db()
        assert nssdb.dbtype == 'sql'
        newcerts = nssdb.list_certs()
        assert len(newcerts) == 1
        assert newcerts == oldcerts
        assert nssdb.get_cert(CERTNICK) == cert
        newkeys = nssdb.list_keys()
        assert newkeys == ()

        for filename in nssdb.filenames:
            assert os.path.isfile(filename)
            assert os.path.dirname(filename) == nssdb.secdir

        old = os.path.join(nssdb.secdir, 'cert8.db')
        assert not os.path.isfile(old)
        assert os.path.isfile(old + '.migrated')

        assert os.path.basename(nssdb.certdb) == 'cert9.db'
        assert nssdb.certdb in nssdb.filenames
        assert os.path.basename(nssdb.keydb) == 'key4.db'
        assert os.path.basename(nssdb.secmod) == 'pkcs11.txt'


def test_auto_db():
    with NSSDatabase() as nssdb:
        assert nssdb.dbtype == 'auto'
        assert nssdb.filenames is None
        assert not nssdb.exists()
        with pytest.raises(RuntimeError):
            nssdb.list_certs()

        nssdb.create_db()
        assert nssdb.dbtype in ('dbm', 'sql')
        if NSS_DEFAULT is not None:
            assert nssdb.dbtype == NSS_DEFAULT
        assert nssdb.filenames is not None
        assert nssdb.exists()
        nssdb.list_certs()


def test_delete_cert_and_key():
    """Test that delete_cert + delete_key always deletes everything

    Test with a NSSDB that contains:
    - cert + key
    - key only
    - cert only
    - none of them
    """
    cmd = ipautil.run(['mktemp'], capture_output=True)
    p12file = cmd.output.strip()

    try:
        with NSSDatabase() as nssdb:
            nssdb.create_db()

            # 1. Test delete_key_and_cert when cert + key are present
            # Create a NSS DB with cert + key
            create_selfsigned(nssdb)
            # Save both in a p12 file for latter use
            ipautil.run(
                [
                    'pk12util',
                    '-o', p12file, '-n', CERTNICK, '-d', nssdb.secdir,
                    '-k', nssdb.pwd_file,
                    '-w', nssdb.pwd_file
                ])
            # Delete cert and key
            nssdb.delete_key_and_cert(CERTNICK)
            # make sure that everything was deleted
            assert len(nssdb.list_keys()) == 0
            assert len(nssdb.list_certs()) == 0

            # 2. Test delete_key_and_cert when only key is present
            # Import cert and key then remove cert
            import_args = [
                'pk12util',
                '-i', p12file, '-d', nssdb.secdir,
                '-k', nssdb.pwd_file,
                '-w', nssdb.pwd_file]
            ipautil.run(import_args)
            nssdb.delete_cert(CERTNICK)
            # Delete cert and key
            nssdb.delete_key_and_cert(CERTNICK)
            # make sure that everything was deleted
            assert len(nssdb.list_keys()) == 0
            assert len(nssdb.list_certs()) == 0

            # 3. Test delete_key_and_cert when only cert is present
            # Import cert and key then remove key
            ipautil.run(import_args)
            nssdb.delete_key_only(CERTNICK)
            # make sure the db contains only the cert
            assert len(nssdb.list_keys()) == 0
            assert len(nssdb.list_certs()) == 1

            # Delete cert and key when key is not present
            nssdb.delete_key_and_cert(CERTNICK)
            # make sure that everything was deleted
            assert len(nssdb.list_keys()) == 0
            assert len(nssdb.list_certs()) == 0

            # 4. Test delete_key_and_cert with a wrong nickname
            # Import cert and key
            ipautil.run(import_args)
            # Delete cert and key
            nssdb.delete_key_and_cert('wrongnick')
            # make sure that nothing was deleted
            assert len(nssdb.list_keys()) == 1
            assert len(nssdb.list_certs()) == 1
    finally:
        os.unlink(p12file)


def test_check_validity():
    with NSSDatabase() as nssdb:
        nssdb.create_db()
        create_selfsigned(nssdb)
        with pytest.raises(ValueError):
            nssdb.verify_ca_cert_validity(CERTNICK)
        nssdb.verify_server_cert_validity(CERTNICK, CERTSAN)
        with pytest.raises(ValueError):
            nssdb.verify_server_cert_validity(CERTNICK, 'invalid.example')