Projekt

Obecné

Profil

« Předchozí | Další » 

Revize e39e138f

Přidáno uživatelem Stanislav Král před asi 4 roky(ů)

Re #8472 - Improved SQL connection/cursor fixtures in such way that connection to DB happens only once per test module

Zobrazit rozdíly:

src/db/init_queries.py
1
SCHEMA_SQL = """
2
/* ---------------------------------------------------- */
3
/*  Generated by Enterprise Architect Version 13.5 		*/
4
/*  Created On : 01-dub-2021 15:16:53 				*/
5
/*  DBMS       : SQLite 								*/
6
/* ---------------------------------------------------- */
7

  
8
/* Drop Tables */
9

  
10
DROP TABLE IF EXISTS 'PrivateKeys'
11
;
12

  
13
DROP TABLE IF EXISTS 'CertificateTypes'
14
;
15

  
16
DROP TABLE IF EXISTS 'UsageTypes'
17
;
18

  
19
DROP TABLE IF EXISTS 'Certificates'
20
;
21

  
22
DROP TABLE IF EXISTS 'CertificateUsages'
23
;
24

  
25
/* Create Tables with Primary and Foreign Keys, Check and Unique Constraints */
26

  
27
CREATE TABLE 'PrivateKeys'
28
(
29
	'id' INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
30
	'private_key' TEXT NOT NULL,
31
	'password' TEXT NULL
32
)
33
;
34

  
35
CREATE TABLE 'CertificateTypes'
36
(
37
	'id' INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
38
	'certificate_type' TEXT NOT NULL
39
)
40
;
41

  
42
CREATE TABLE 'UsageTypes'
43
(
44
	'id' INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
45
	'usage_type' TEXT NOT NULL
46
)
47
;
48

  
49
CREATE TABLE 'Certificates'
50
(
51
	'id' INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
52
	'common_name' TEXT NOT NULL,
53
	'valid_from' TEXT NOT NULL,
54
	'valid_to' TEXT NOT NULL,
55
	'pem_data' TEXT NOT NULL,
56
	'private_key_id' INTEGER NOT NULL,
57
	'certificate_type_id' INTEGER NOT NULL,
58
	'parent_certificate_id' INTEGER NOT NULL,
59
	CONSTRAINT 'FK_Certificates' FOREIGN KEY ('parent_certificate_id') REFERENCES 'Certificates' ('id') ON DELETE No Action ON UPDATE No Action,
60
	CONSTRAINT 'FK_CertificateTypes' FOREIGN KEY ('certificate_type_id') REFERENCES 'CertificateTypes' ('id') ON DELETE No Action ON UPDATE No Action,
61
	CONSTRAINT 'FK_PrivateKeys' FOREIGN KEY ('private_key_id') REFERENCES 'PrivateKeys' ('id') ON DELETE No Action ON UPDATE No Action
62
)
63
;
64

  
65
CREATE TABLE 'CertificateUsages'
66
(
67
	'id' INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
68
	'certificate_id' INTEGER NOT NULL,
69
	'usage_type_id' INTEGER NOT NULL,
70
	CONSTRAINT 'FK_Certificates' FOREIGN KEY ('certificate_id') REFERENCES 'Certificates' ('id') ON DELETE Cascade ON UPDATE No Action,
71
	CONSTRAINT 'FK_UsageTypes' FOREIGN KEY ('usage_type_id') REFERENCES 'UsageTypes' ('id') ON DELETE No Action ON UPDATE No Action
72
)
73
;
74

  
75
"""
76

  
77
DEFAULT_VALUES_SQL = """
78
/* ---------------------------------------------------- */
79
/*  Generated by Enterprise Architect Version 13.5 		*/
80
/*  Created On : 26-bře-2021 13:33:05 				*/
81
/*  DBMS       : SQLite 								*/
82
/* ---------------------------------------------------- */
83

  
84
/* Insert default values */
85

  
86
INSERT INTO CertificateTypes(certificate_type) VALUES('ROOT_CA');
87
INSERT INTO CertificateTypes(certificate_type) VALUES('INTERMEDIATE_CA');
88
INSERT INTO CertificateTypes(certificate_type) VALUES('CERTIFICATE');
89

  
90
INSERT INTO UsageTypes(usage_type) VALUES('CA');
91
INSERT INTO UsageTypes(usage_type) VALUES('SSL');
92
INSERT INTO UsageTypes(usage_type) VALUES('SIGNATURE');
93
INSERT INTO UsageTypes(usage_type) VALUES('AUTHENTICATION');
94

  
95
"""
tests/dao/certificate_repository/conftest.py
1
import pytest
2
import sqlite3
3
from sqlite3 import Connection, Cursor
4

  
5
from src.dao.certificate_repository import CertificateRepository
6
from src.constants import DATABASE_FILE
7

  
8

  
9
@pytest.fixture
10
def repository():
11
    connection: Connection = sqlite3.connect("../../../" + DATABASE_FILE)
12
    cursor: Cursor = connection.cursor()
13
    return CertificateRepository(connection, cursor)
tests/dao/certificate_repository/create_certificate.py
1
import pytest
2
from src.constants import *
3

  
4

  
5
def test_connection(repository):
6
    sql = f"SELECT * FROM {TAB_CERTIFICATE_TYPES}"
7
    repository.cursor.execute(sql)
8
    selected_rows = repository.cursor.fetchall()
9

  
10
    assert len(selected_rows) > 1
11
    assert selected_rows[ROOT_CA_ID - 1][1] == "ROOT_CA"
12
    assert selected_rows[INTERMEDIATE_CA_ID - 1][1] == "INTERMEDIATE_CA"
13
    assert selected_rows[CERTIFICATE_ID - 1][1] == "CERTIFICATE"
tests/integration_tests/dao/certificate_repository/conftest.py
1
import pytest
2
import sqlite3
3
from sqlite3 import Connection, Cursor
4

  
5
from src.dao.certificate_repository import CertificateRepository
6
from src.constants import DATABASE_FILE
7

  
8

  
9
@pytest.fixture
10
def repository():
11
    connection: Connection = sqlite3.connect("../../../" + DATABASE_FILE)
12
    cursor: Cursor = connection.cursor()
13
    return CertificateRepository(connection, cursor)
tests/integration_tests/dao/certificate_repository/create_certificate.py
1
import pytest
2
from src.constants import *
3

  
4

  
5
def test_connection(repository):
6
    sql = f"SELECT * FROM {TAB_CERTIFICATE_TYPES}"
7
    repository.cursor.execute(sql)
8
    selected_rows = repository.cursor.fetchall()
9

  
10
    assert len(selected_rows) > 1
11
    assert selected_rows[ROOT_CA_ID - 1][1] == "ROOT_CA"
12
    assert selected_rows[INTERMEDIATE_CA_ID - 1][1] == "INTERMEDIATE_CA"
13
    assert selected_rows[CERTIFICATE_ID - 1][1] == "CERTIFICATE"
tests/integration_tests/services/certificate_key_service_test.py
1
from src.model.subject import Subject
2

  
3

  
4
def test_connection(private_key_service, certificate_service):
5
    private_key = private_key_service.create_new_key(passphrase="foobar")
6

  
7
    cert = certificate_service.create_root_ca(private_key,
8
                                              Subject(common_name="FooName", organization_unit="Department of Foo"))
9

  
10

  
11
def test_connection_2(private_key_service, certificate_service):
12
    private_key = private_key_service.create_new_key(passphrase="foobarbaz")
13

  
14
    certificate_service.create_root_ca(private_key,
15
                                       Subject(common_name="FooNameD", organization_unit="Department of Foo"))
tests/integration_tests/services/conftest.py
1
import os
2
import sqlite3
3
from sqlite3 import Connection
4

  
5
import pytest
6

  
7
from src.dao.certificate_repository import CertificateRepository
8
from src.dao.private_key_repository import PrivateKeyRepository
9
from src.db.init_queries import SCHEMA_SQL, DEFAULT_VALUES_SQL
10
from src.services.certificate_service import CertificateService
11
from src.services.cryptography import CryptographyService
12
from src.services.key_service import KeyService
13

  
14

  
15
# scope="module" means that this fixture is run once per module
16
@pytest.fixture(scope="module")
17
def connection():
18
    print("Creating a new SQLITE connection to the test DB")
19
    test_db_file = "test.sqlite"
20
    connection: Connection = sqlite3.connect(test_db_file)
21

  
22
    # yield the created connection
23
    yield connection
24

  
25
    # after tests have finished delete the created db file
26
    try:
27
        print("Deleting the test DB")
28
        os.unlink(test_db_file)
29
    except FileNotFoundError:
30
        print(f"Could not delete {test_db_file} file containing the test DB")
31
        pass
32

  
33

  
34
@pytest.fixture(scope="module")
35
def cursor(connection):
36
    cursor = connection.cursor()
37

  
38
    # execute db initialisation script
39
    cursor.executescript(SCHEMA_SQL)
40

  
41
    # insert default values
42
    cursor.executescript(DEFAULT_VALUES_SQL)
43

  
44
    return cursor
45

  
46

  
47
# scope defaults to "function" which means that the fixture is run once per test (function)
48
@pytest.fixture
49
def certificate_repository(connection, cursor):
50
    return CertificateRepository(connection, cursor)
51

  
52

  
53
@pytest.fixture
54
def private_key_repository(connection, cursor):
55
    return PrivateKeyRepository(connection, cursor)
56

  
57

  
58
@pytest.fixture
59
def cryptography_service():
60
    return CryptographyService()
61

  
62

  
63
@pytest.fixture
64
def private_key_service(private_key_repository, cryptography_service):
65
    return KeyService(cryptography_service, private_key_repository)
66

  
67

  
68
@pytest.fixture
69
def certificate_service(certificate_repository, cryptography_service):
70
    return CertificateService(cryptography_service, certificate_repository)
tests/services/certificate/conftest.py
1
import pytest
2
import sqlite3
3
import os
4
from sqlite3 import Connection, Cursor
5

  
6
from src.dao.certificate_repository import CertificateRepository
7
from src.dao.private_key_repository import PrivateKeyRepository
8
from src.services.certificate_service import CertificateService
9
from src.services.cryptography import CryptographyService
10
from src.services.key_service import KeyService
11

  
12

  
13
@pytest.fixture
14
def connection():
15
    try:
16
        os.remove("../../../test.sqlite")
17
    except FileNotFoundError:
18
        pass
19
    connection: Connection = sqlite3.connect("../../../" + "test.sqlite")
20
    return connection
21

  
22

  
23
@pytest.fixture
24
def cursor(connection):
25
    cursor = connection.cursor()
26

  
27
    # execute db initialisation script
28
    with open('../../../SQLite_database.sql', 'r') as sql_file:
29
        sql_script = sql_file.read()
30
        cursor.executescript(sql_script)
31

  
32
    # insert default values
33
    with open('../../../SQLite_default_values.sql', 'r') as sql_file:
34
        sql_script = sql_file.read()
35
        cursor.executescript(sql_script)
36

  
37
    return cursor
38

  
39

  
40
@pytest.fixture
41
def certificate_repository(connection, cursor):
42
    return CertificateRepository(connection, cursor)
43

  
44

  
45
@pytest.fixture
46
def private_key_repository(connection, cursor):
47
    return PrivateKeyRepository(connection, cursor)
48

  
49

  
50
@pytest.fixture
51
def cryptography_service():
52
    return CryptographyService()
53

  
54

  
55
@pytest.fixture
56
def private_key_service(private_key_repository, cryptography_service):
57
    return KeyService(cryptography_service, private_key_repository)
58

  
59

  
60
@pytest.fixture
61
def certificate_service(certificate_repository, cryptography_service):
62
    return CertificateService(cryptography_service, certificate_repository)
tests/services/certificate/integration_test.py
1
from src.model.subject import Subject
2

  
3

  
4
def test_connection(private_key_service, certificate_service):
5
    private_key = private_key_service.create_new_key(passphrase="foobar")
6

  
7
    certificate_service.create_root_ca(private_key,
8
                                       Subject(common_name="FooName", organization_unit="Department of Foo"))
tests/services/cryptography/conftest.py
1
import pytest
2

  
3
from src.services.cryptography import CryptographyService
4

  
5

  
6
@pytest.fixture
7
def service():
8
    # provide a CryptographyService fixture
9
    return CryptographyService()
tests/services/cryptography/create_crt_test.py
1
import subprocess
2

  
3
import pytest
4

  
5
from src.model.subject import Subject
6
from src.services.cryptography import CryptographyException
7

  
8

  
9
def export_crt(crt):
10
    return subprocess.check_output(["openssl", "x509", "-noout", "-text", "-in", "-"],
11
                                   input=bytes(crt, encoding="utf-8"), stderr=subprocess.STDOUT).decode()
12

  
13

  
14
def test_sign_cst(service):
15
    # create root CA
16
    root_key = service.create_private_key()
17
    root_ca = service.create_sscrt(Subject(common_name="foo"), root_key)
18

  
19
    # create a private key to be used to make a CSR for the intermediate CA
20
    inter_key = service.create_private_key()
21

  
22
    # create a CA using the root CA
23
    inter_ca = service.create_crt(Subject(common_name="bar", country="CZ"), inter_key, root_ca, root_key)
24

  
25
    inter_ca_printed = export_crt(inter_ca)
26

  
27
    # assert fields
28
    assert "Issuer: CN = foo" in inter_ca_printed
29
    assert "Subject: CN = bar, C = CZ" in inter_ca_printed
30

  
31

  
32
def test_sign_crt_passphrase(service):
33
    # create root CA and encrypt the private key of the root CA
34
    root_key_passphrase = "barbaz"
35
    root_key = service.create_private_key(passphrase=root_key_passphrase)
36
    root_ca = service.create_sscrt(Subject(common_name="foo"), root_key, key_pass=root_key_passphrase)
37

  
38
    # create a private key to be used to make a CSR for the intermediate CA
39
    inter_key_passphrase = "foobazbar"
40
    inter_key = service.create_private_key(passphrase=inter_key_passphrase)
41

  
42
    # create a CA using the root CA
43
    inter_ca = service.create_crt(Subject(common_name="bar", country="CZ"), inter_key, root_ca, root_key,
44
                                  subject_key_pass=inter_key_passphrase, issuer_key_pass=root_key_passphrase)
45

  
46
    inter_ca_printed = export_crt(inter_ca)
47

  
48
    # assert fields
49
    assert "Issuer: CN = foo" in inter_ca_printed
50
    assert "Subject: CN = bar, C = CZ" in inter_ca_printed
51

  
52
    # some basic incorrect passphrase combinations
53
    passphrases = [
54
        (inter_key, None),
55
        (inter_key, "foofoobarbar"),
56
        (None, root_key),
57
        ("foofoobarbar", root_key),
58
        ("foofoobarbar", "foofoobarbar"),
59
        (None, None)
60
    ]
61

  
62
    for (key_pass, issuer_key_pass) in passphrases:
63
        # try to create it using a wrong issuer passphrase
64
        with pytest.raises(CryptographyException) as e:
65
            inter_ca = service.create_crt(Subject(common_name="bar", country="CZ"), inter_key, root_ca, root_key,
66
                                          subject_key_pass=key_pass, issuer_key_pass=issuer_key_pass)
67
        assert "bad decrypt" in e.value.message
68

  
69

  
70
def test_sign_crt_extensions(service):
71
    # create root CA and encrypt the private key of the root CA
72
    root_key_passphrase = "barbaz"
73
    root_key = service.create_private_key(passphrase=root_key_passphrase)
74
    root_ca = service.create_sscrt(Subject(common_name="foo"), root_key, key_pass=root_key_passphrase)
75

  
76
    # create a private key to be used to make a CSR for the intermediate CA
77
    inter_key_passphrase = "foofoo"
78
    inter_key = service.create_private_key()
79

  
80
    # create a CA using the root CA
81
    inter_ca = service.create_crt(Subject(common_name="bar", country="CZ"), inter_key, root_ca, root_key,
82
                                  subject_key_pass=inter_key_passphrase, issuer_key_pass=root_key_passphrase,
83
                                  extensions="authorityInfoAccess = caIssuers;URI:bar.cz/baz/cert\nbasicConstraints=critical,CA:TRUE")
84

  
85
    inter_ca_printed = export_crt(inter_ca)
86

  
87
    # assert fields
88
    assert "Issuer: CN = foo" in inter_ca_printed
89
    assert "Subject: CN = bar, C = CZ" in inter_ca_printed
90

  
91
    # assert extensions
92
    expected_extensions = """        X509v3 extensions:
93
            Authority Information Access: 
94
                CA Issuers - URI:bar.cz/baz/cert
95

  
96
            X509v3 Basic Constraints: critical
97
                CA:TRUE"""
98
    assert expected_extensions in inter_ca_printed
tests/services/cryptography/create_csr_test.py
1
import subprocess
2

  
3
from src.model.subject import Subject
4

  
5

  
6
def get_csr_pem(csr):
7
    return subprocess.check_output(["openssl", "req", "-noout", "-text", "-verify", "-in", "-"],
8
                                   input=bytes(csr, encoding="utf-8"), stderr=subprocess.STDOUT).decode()
9

  
10

  
11
def test_make_csr(service):
12
    private_key = service.create_private_key()
13

  
14
    subject = Subject(common_name="foo", country="CZ")
15
    csr = service._CryptographyService__create_csr(subject, private_key)
16

  
17
    assert "Subject: CN = foo, C = CZ" in get_csr_pem(csr)
18

  
19

  
20
def test_make_csr_pkey_passphrase(service):
21
    private_key = service.create_private_key(passphrase="foobar")
22

  
23
    subject = Subject(common_name="foo", country="CZ", organization_unit="Mysterious Unit")
24
    csr = service._CryptographyService__create_csr(subject, private_key, key_pass="foobar")
25

  
26
    assert "Subject: CN = foo, C = CZ, OU = Mysterious Unit" in get_csr_pem(csr)
tests/services/cryptography/parse_cert_pem_test.py
1
from src.model.subject import Subject
2

  
3

  
4
def test_parse_cert_pem(service):
5
    cert_pem = """
6
-----BEGIN CERTIFICATE-----
7

  
8
MIIGITCCBAmgAwIBAgIUb7xAdXd6AkevhmeQqy2BASDqv/IwDQYJKoZIhvcNAQEL
9
BQAwgZ8xCzAJBgNVBAYTAkNaMRYwFAYDVQQIDA1QaWxzZW4gUmVnaW9uMQ8wDQYD
10
VQQHDAZQaWxzZW4xFjAUBgNVBAoMDVJvb3RpbmcgUm9vdHMxHDAaBgNVBAsME0Rl
11
cGFydG1lbnQgb2YgUk9vdHMxFDASBgNVBAMMC01haW4gUm9vdGVyMRswGQYJKoZI
12
hvcNAQkBFgxyb290QHJvb3QuY3owHhcNMjEwMzIxMTAwMTUyWhcNMjYwMzIxMTAw
13
MTUyWjCBnzELMAkGA1UEBhMCQ1oxFjAUBgNVBAgMDVBpbHNlbiBSZWdpb24xDzAN
14
BgNVBAcMBlBpbHNlbjEWMBQGA1UECgwNUm9vdGluZyBSb290czEcMBoGA1UECwwT
15
RGVwYXJ0bWVudCBvZiBST290czEUMBIGA1UEAwwLTWFpbiBSb290ZXIxGzAZBgkq
16
hkiG9w0BCQEWDHJvb3RAcm9vdC5jejCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC
17
AgoCggIBAMKozynv+ja1VkNWpldsrl6tEGYrkNuG9umyqF0ZOZmzWzR7PiszV8DW
18
o+OQ3SY7MQ7o3qoE/pSiaApmNFxgarWvGxnVgouncrai1AKB92tFY1VnVfQYICD3
19
gdjSzo4Lbfc8+67DHTPc0N70oBZuMueQ6ifUQhrjuVaONwAOsZBdal+VWvctJcrf
20
fd+s6Jkgb/qWuld21Bzea36PLmgwoe8/RNyS9yzspC8jwdU68BemAPy9NBf9Q8Is
21
0R7aZ0YwKPsdln3lR5GixrNy+sQl0qwy0NgklWIbqpGbMAInJBbTBmBGIbS0zV3t
22
Nwi+g1u2WaFn63NeoUswAoDtHDm6FXBFI2BabG5tFVRNdfzGU1PEbILprqk214rt
23
5+j5xTtpaI07akjozYJfal8c6igKXmNJf+xxtASq5EESNLT0YHwVPlT1S/odGvkN
24
Hk6OJv2dmcH6nHCgT72aUhaVPP9aUIxlnchPD/iprMqkOkfm/k/LZLmPTsZbfmax
25
VB1PWRFSWozAR4R562QFNRLLzZBlqiN++XMRBnjX4rRNTjZZyrYG3rIv8SytY8N7
26
UU0Ya/k+iYs5inbbHBkC3vI2DT6evxlfaXw8b1QTL4mNwR0aK0HjmVU6XdNcmGYr
27
/PAxyZNNDM+k9wkcj+Xf4iqVrmk9pHEfkRHHjRpOXvFaLogmx/drAgMBAAGjUzBR
28
MB0GA1UdDgQWBBQSP3MTbRoAP80MfEriCKa9qoqlFDAfBgNVHSMEGDAWgBQSP3MT
29
bRoAP80MfEriCKa9qoqlFDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUA
30
A4ICAQCXV3PxhN6U/vhRaXriAOr4RNhvGjdT7XnAC7r21GsfyH3omXPqD/RrrUov
31
9ZWinxTiQ4xg3f+Iz9DCLXOmwmWoEpPU/LPa2UMENey2XOloQSO4JfdrbVVItWm6
32
F0W0aqdMxR9lzt7xoOwT/5wkAEJtHkUyCHB0xv6ZVRJYt07FGt8oipaJl3SlkyhH
33
onKiCPsjwfcZ7W/lJ4PAFRY1DOLL+2CsLQjE9N2TAViY1HBpI3BfzfsDnXKEV2hS
34
bNS25bpXbyLKGHqhcD9Y/wQID3fmKQilSSKezEn0nnPfnnb2WF32rWFR2pzgeym/
35
Q5vWcJRGSKcD0W58Ob1eLF8pG/FOijgjvHxWiotl2bB2rdEAR8BDJrzhRVxYavft
36
zpLWb5NGJSjPO29cJ170OyBhXYS+/kpgFf3sxDtOacS6k7LOXcydlckAAHGFwllb
37
0jkyZ0A2q+RGHIKirs1hWQpOb1O6Pvw+mNtxfghZsq8lnceHIUG9BduTXzWm0MEc
38
Gh+KpX/I0JzuOc91ydNtvMEOjfIAp8mjLAqDCWRd0OzvE45rPbBAHJXPc4P76B1A
39
XXwUYr8GuSFQZb1Q4BpCayCYvTLj+7q3z72BCqAA+jMJYV/qU0EpsuFjPvzU8apg
40
7l9NhB7vf/qhW0XHDa4pv5+d+CXUiHPlW+UTIlni1AfgAel1Ww==
41
-----END CERTIFICATE-----
42
    """
43

  
44
    # parse a certificate supplied in a PEM format
45
    subj, n_before, n_after = service.parse_cert_pem(cert_pem)
46

  
47
    assert 3 == n_before.tm_mon
48
    assert 21 == n_before.tm_mday
49
    assert 10 == n_before.tm_hour
50
    assert 1 == n_before.tm_min
51
    assert 52 == n_before.tm_sec
52
    assert 2021 == n_before.tm_year
53

  
54
    assert 3 == n_after.tm_mon
55
    assert 21 == n_after.tm_mday
56
    assert 10 == n_after.tm_hour
57
    assert 1 == n_after.tm_min
58
    assert 52 == n_after.tm_sec
59
    assert 2026 == n_after.tm_year
60

  
61
    assert "CZ" == subj.country
62
    assert "Pilsen Region" == subj.state
63
    assert "Pilsen" == subj.locality
64
    assert "Rooting Roots" == subj.organization
65
    assert "Department of ROots" == subj.organization_unit
66
    assert "Main Rooter" == subj.common_name
67
    assert "root@root.cz" == subj.email_address
68

  
69

  
70
def test_parse_cert_pen_2(service):
71
    cert_pem = """
72
-----BEGIN CERTIFICATE-----
73
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
103
-----END CERTIFICATE-----
104
    """
105

  
106
    # parse a certificate supplied in a PEM format
107
    subj, n_before, n_after = service.parse_cert_pem(cert_pem)
108

  
109
    assert 3 == n_before.tm_mon
110
    assert 23 == n_before.tm_mday
111
    assert 21 == n_before.tm_hour
112
    assert 32 == n_before.tm_min
113
    assert 59 == n_before.tm_sec
114
    assert 2021 == n_before.tm_year
115

  
116
    assert 3 == n_after.tm_mon
117
    assert 23 == n_after.tm_mday
118
    assert 21 == n_after.tm_hour
119
    assert 32 == n_after.tm_min
120
    assert 59 == n_after.tm_sec
121
    assert 2024 == n_after.tm_year
122

  
123
    assert "AU" == subj.country
124
    assert "Some-State" == subj.state
125
    assert "Internet Widgits Pty Ltd" == subj.organization
126
    assert "NCHILD_2" == subj.common_name
127
    assert None is subj.locality
128
    assert None is subj.organization_unit
129
    assert None is subj.email_address
130

  
131

  
132
def test_parse_cert_pen_empty(service):
133
    cert_pem = """
134
-----BEGIN CERTIFICATE-----
135
MIIDczCCAlugAwIBAgIUPM++Jj33iag4uaOMIzED4/rMTB4wDQYJKoZIhvcNAQEL
136
BQAwSTELMAkGA1UEBhMCICAxCzAJBgNVBAgMAiAgMQowCAYDVQQKDAEgMQswCQYD
137
VQQDDAIgIDEUMBIGCSqGSIb3DQEJARYFIGZvbyAwHhcNMjEwNDAzMjMzMDEwWhcN
138
MjEwNTAzMjMzMDEwWjBJMQswCQYDVQQGEwIgIDELMAkGA1UECAwCICAxCjAIBgNV
139
BAoMASAxCzAJBgNVBAMMAiAgMRQwEgYJKoZIhvcNAQkBFgUgZm9vIDCCASIwDQYJ
140
KoZIhvcNAQEBBQADggEPADCCAQoCggEBALI9Ksw85aFLBw2wAeRUoxMQarXkWWbw
141
FyvGCb426EcdKYEiax4BYsK+VLxJpJsIo4DnSM1c0EKNJmN4w+l93CBVhHvmA+qo
142
3LYShf/DgNeKZD7KJgAWwPHBnA1eOA/8kUX0YT9Z76JpJN46KFfqaY9Scb9GBU/m
143
Kr/Lm2Rkg/LehMObPfNQm3XGOvcRjHON9VoB7hZW8zt2lvWTkhia9t46p/kY90eg
144
3iw5JRR/MeYBiYeikjT4g5pMZDkymWUp7eahOsoR4kGYGLkpdXVN66evWzTikUKV
145
QSHdzUZOiTJ7GFJ70qqh+gAEMCf/Lx8EDbDcuz7ZH40Lr6knY2+9xe8CAwEAAaNT
146
MFEwHQYDVR0OBBYEFChHMZUZ2fyOrclVGjtopKn7f/mSMB8GA1UdIwQYMBaAFChH
147
MZUZ2fyOrclVGjtopKn7f/mSMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
148
BQADggEBAETfyBYSS6drAyGY1/+z7fWKV3aS1Ocd8c/7oj1seFZ8AH+b0zktTynv
149
khprZhxRGRR6cHhyVmMexSWucWb7zlJZNcO9F0/FIgoqcKODtdNczTJyrC9raeuf
150
8pAqhaxXcNXXUSB8vNQKHLRtRnPCB3nZE7xSl5RRmSPyPGZyyAYygxRnLjMFgJEU
151
4c1FOpvRcfRS5yWviOS6dFv+cGA8hoUMXkpIW88GfwgdO6nMSQB1wUdqKoPnaIFc
152
3vjtLMWkuVZFYqvp3NN6GtyI5pw1O0FzjkLZsAeuHZyIkwpKkMsnGlGW8lz1svZ+
153
7AQMsDl5rA4ZVlnLXSQlq3YXVuXZlAI=
154
-----END CERTIFICATE-----
155
    """
156

  
157
    # parse a certificate supplied in a PEM format
158
    subj, n_before, n_after = service.parse_cert_pem(cert_pem)
159

  
160
    assert 4 == n_before.tm_mon
161
    assert 3 == n_before.tm_mday
162
    assert 23 == n_before.tm_hour
163
    assert 30 == n_before.tm_min
164
    assert 10 == n_before.tm_sec
165
    assert 2021 == n_before.tm_year
166

  
167
    assert 5 == n_after.tm_mon
168
    assert 3 == n_after.tm_mday
169
    assert 23 == n_after.tm_hour
170
    assert 30 == n_after.tm_min
171
    assert 10 == n_after.tm_sec
172
    assert 2021 == n_after.tm_year
173

  
174
    # TODO improve parsing of fields within quotes
175
    assert "\"  \"" == subj.country
176
    assert "\"  \"" == subj.state
177
    assert "\" \"" == subj.organization
178
    assert "\"  \"" == subj.common_name
179
    assert None is subj.locality
180
    assert None is subj.organization_unit
181
    assert "\" foo \"" == subj.email_address
182

  
183

  
184
def test_create_and_parse_cert(service):
185
    # create a private key
186
    key = service.create_private_key(passphrase="foobar")
187

  
188
    # create a certificate
189
    cert = service.create_sscrt(Subject(common_name="Foo CN", email_address="foo@bar.cz"), key, key_pass="foobar")
190

  
191
    # parse the subject
192
    parsed_subj, n_before, n_after = service.parse_cert_pem(cert)
193

  
194
    assert "Foo CN" == parsed_subj.common_name
195
    assert "foo@bar.cz" == parsed_subj.email_address
tests/services/cryptography/private_keys_test.py
1
import subprocess
2

  
3
import pytest
4

  
5

  
6
def test_private_key(service):
7
    private_key = service.create_private_key()
8

  
9
    # verify the private key
10
    subprocess.check_output(["openssl", "rsa", "-in", "-", "-check"], input=bytes(private_key, encoding="utf-8"),
11
                            stderr=subprocess.STDOUT)
12

  
13

  
14
def test_encrypted_private_key(service):
15
    private_key = service.create_private_key(passphrase="foobar")
16

  
17
    # verify the private key providing a correct passphrase
18
    subprocess.check_output(["openssl", "rsa", "-in", "-", "-passin", "pass:foobar", "-check"],
19
                            input=bytes(private_key, encoding="utf-8"), stderr=subprocess.STDOUT)
20

  
21

  
22
def test_encrypted_private_key_incorrect_pass(service):
23
    private_key = service.create_private_key(passphrase="foobar")
24

  
25
    # incorrect passphrase provided
26
    with pytest.raises(subprocess.CalledProcessError):
27
        subprocess.check_output(["openssl", "rsa", "-in", "-", "-passin", "pass:bazbaz", "-check"],
28
                                input=bytes(private_key, encoding="utf-8"), stderr=subprocess.STDOUT)
tests/services/cryptography/run_for_output_test.py
1
import pytest
2

  
3
from src.services.cryptography import CryptographyException
4

  
5

  
6
def test_simple_exec(service):
7
    out = service._CryptographyService__run_for_output(["version"])
8
    assert "OpenSSL" in out.decode()
9

  
10

  
11
def test_simple_exec_without_parameters(service):
12
    out = service._CryptographyService__run_for_output()
13
    assert "OpenSSL>" in out.decode()
14

  
15

  
16
def test_nonexistent_executable(service):
17
    with pytest.raises(CryptographyException) as e:
18
        service._CryptographyService__run_for_output(executable="nonexistent_executable#")
19
    assert """"nonexistent_executable#" not found in the current PATH.""" in e.value.message
20

  
21

  
22
def test_exception_str(service):
23
    with pytest.raises(CryptographyException) as e:
24
        service._CryptographyService__run_for_output(executable="nonexistent_executable")
25
    assert """EXECUTABLE: nonexistent_executable
26
        ARGS: ('nonexistent_executable',)
27
        MESSAGE: "nonexistent_executable" not found in the current PATH.""" in e.value.__str__()
tests/services/cryptography/self_signed_cert_test.py
1
import subprocess
2

  
3
import pytest
4

  
5
from src.model.subject import Subject
6
from src.services.cryptography import CryptographyException
7

  
8

  
9
def test_create_sscrt(service):
10
    # create a self signed certificate using configuration and extensions
11
    private_key = service.create_private_key(passphrase="foobar")
12

  
13
    # distinguished_name is always required
14
    config = """
15
    # Simple Root CA
16

  
17
    [ req ]
18
    distinguished_name      = ca_dn                 # DN section
19

  
20
    [ ca_dn ]
21

  
22
    [ root_ca_ext ]
23
    keyUsage                = critical,keyCertSign,cRLSign
24
    basicConstraints        = critical,CA:true
25
    subjectKeyIdentifier    = hash
26
    authorityKeyIdentifier  = keyid:always
27
    """
28

  
29
    cert = service.create_sscrt(Subject(common_name="Topnax",
30
                                        country="CZ",
31
                                        locality="My Locality",
32
                                        state="My state",
33
                                        organization="Mysterious Org.",
34
                                        organization_unit="Department of Mysteries",
35
                                        email_address="mysterious@box.cz"), private_key, config=config,
36
                                extensions="root_ca_ext", key_pass="foobar")
37

  
38
    cert_printed = subprocess.check_output(["openssl", "x509", "-noout", "-text", "-in", "-"],
39
                                           input=bytes(cert, encoding="utf-8"), stderr=subprocess.STDOUT).decode()
40

  
41
    assert "Certificate Sign, CRL Sign" in cert_printed
42
    assert "X509v3 Key Usage: critical" in cert_printed
43
    assert "CA:TRUE" in cert_printed
44

  
45
    assert "Issuer: CN = Topnax, C = CZ, L = My Locality, ST = My state, O = Mysterious Org., OU = Department of Mysteries, emailAddress = mysterious@box.cz" in cert_printed
46
    assert "Subject: CN = Topnax, C = CZ, L = My Locality, ST = My state, O = Mysterious Org., OU = Department of Mysteries, emailAddress = mysterious@box.cz" in cert_printed
47

  
48

  
49
def test_create_sscrt_config_without_extensions(service):
50
    # create a self signed certificate without specifying extensions
51
    private_key = service.create_private_key()
52

  
53
    config = """
54
    # Simple Root CA
55

  
56
    [ req ]
57
    distinguished_name      = ca_dn                 # DN section
58

  
59
    [ ca_dn ]
60

  
61
    """
62

  
63
    cert = service.create_sscrt(Subject(common_name="Topnax", country="CZ"), private_key, config=config)
64

  
65
    cert_printed = subprocess.check_output(["openssl", "x509", "-noout", "-text", "-in", "-"],
66
                                           input=bytes(cert, encoding="utf-8"), stderr=subprocess.STDOUT).decode()
67

  
68
    # TODO pass something in the configuration that can be asserted
69
    assert "Issuer: CN = Topnax, C = CZ" in cert_printed
70
    assert "Subject: CN = Topnax, C = CZ" in cert_printed
71

  
72

  
73
def test_create_sscrt_plain(service):
74
    # create a self signed certificate without configuration
75
    private_key = service.create_private_key()
76

  
77
    cert = service.create_sscrt(Subject(common_name="Topnax", country="CZ"), private_key)
78

  
79
    cert_printed = subprocess.check_output(["openssl", "x509", "-noout", "-text", "-in", "-"],
80
                                           input=bytes(cert, encoding="utf-8"), stderr=subprocess.STDOUT).decode()
81

  
82
    assert "Issuer: CN = Topnax, C = CZ" in cert_printed
83
    assert "Subject: CN = Topnax, C = CZ" in cert_printed
84

  
85

  
86
def test_create_sscrt_passphrase(service):
87
    # create a self signed certificate with a PK that is protected by a passphrase
88
    private_key = service.create_private_key(passphrase="foobar")
89

  
90
    cert = service.create_sscrt(Subject(common_name="Topnax", country="CZ"), private_key, key_pass="foobar")
91

  
92
    cert_printed = subprocess.check_output(["openssl", "x509", "-noout", "-text", "-in", "-"],
93
                                           input=bytes(cert, encoding="utf-8"), stderr=subprocess.STDOUT).decode()
94

  
95
    assert "Issuer: CN = Topnax, C = CZ" in cert_printed
96
    assert "Subject: CN = Topnax, C = CZ" in cert_printed
97

  
98

  
99
def test_create_sscrt_incorrect_passphrase(service):
100
    # make an attempt to create a self signed certificate using a private key with specifying wrong key passphrase or
101
    # no passphrase at all
102
    private_key = service.create_private_key(passphrase="foobar")
103

  
104
    # incorrect passphrase provided when using a protected private key
105
    with pytest.raises(CryptographyException) as e:
106
        service.create_sscrt(Subject(common_name="Topnax", country="CZ"), private_key, key_pass="bazfoo")
107
    assert "bad decrypt" in e.value.message
108

  
109
    # no passphrase provided when using a protected private key
110
    with pytest.raises(CryptographyException) as e:
111
        service.create_sscrt(Subject(common_name="Topnax", country="CZ"), private_key)
112
    assert "bad decrypt" in e.value.message
tests/services/cryptography/sign_csr_test.py
1
import subprocess
2

  
3
import pytest
4

  
5
from src.model.subject import Subject
6
from src.services.cryptography import CryptographyException
7

  
8

  
9
def export_crt(csr):
10
    return subprocess.check_output(["openssl", "x509", "-noout", "-text", "-in", "-"],
11
                                   input=bytes(csr, encoding="utf-8"), stderr=subprocess.STDOUT).decode()
12

  
13

  
14
def test_sign_csr(service):
15
    # create root CA
16
    root_key = service.create_private_key()
17
    root_ca = service.create_sscrt(Subject(common_name="foo"), root_key)
18

  
19
    # create a private key to be used to make a CSR for the intermediate CA
20
    inter_key = service.create_private_key()
21
    csr = service._CryptographyService__create_csr(Subject(common_name="bar", country="CZ"), inter_key)
22

  
23
    # sign the created CSR with root CA
24
    inter_ca = service._CryptographyService__sign_csr(csr, root_ca, root_key)
25

  
26
    inter_ca_printed = export_crt(inter_ca)
27

  
28
    # assert fields
29
    assert "Issuer: CN = foo" in inter_ca_printed
30
    assert "Subject: CN = bar, C = CZ" in inter_ca_printed
31

  
32

  
33
def test_sign_csr_passphrase(service):
34
    # create root CA and encrypt the private key of the root CA
35
    root_key_passphrase = "barbaz"
36
    root_key = service.create_private_key(passphrase=root_key_passphrase)
37
    root_ca = service.create_sscrt(Subject(common_name="foo"), root_key, key_pass=root_key_passphrase)
38

  
39
    # create a private key to be used to make a CSR for the intermediate CA
40
    inter_key = service.create_private_key()
41
    csr = service._CryptographyService__create_csr(Subject(common_name="bar", country="CZ"), inter_key)
42

  
43
    # sign the created CSR with root CA and specify root key passphrase
44
    inter_ca = service._CryptographyService__sign_csr(csr, root_ca, root_key, issuer_key_pass=root_key_passphrase)
45

  
46
    inter_ca_printed = export_crt(inter_ca)
47

  
48
    # assert fields
49
    assert "Issuer: CN = foo" in inter_ca_printed
50
    assert "Subject: CN = bar, C = CZ" in inter_ca_printed
51

  
52
    # try to sign it using a wrong passphrase
53
    with pytest.raises(CryptographyException) as e:
54
        service._CryptographyService__sign_csr(csr, root_ca, root_key,
55
                                               extensions="authorityInfoAccess = caIssuers;URI:bar.cz/baz.cert",
56
                                               issuer_key_pass="bazbaz")
57
    assert "bad decrypt" in e.value.message
58

  
59
    # try to sign it without specifying a passphrase
60
    with pytest.raises(CryptographyException) as e:
61
        service._CryptographyService__sign_csr(csr, root_ca, root_key,
62
                                               extensions="authorityInfoAccess = caIssuers;URI:bar.cz/baz.cert")
63
    assert "bad decrypt" in e.value.message
64

  
65

  
66
def test_sign_csr_extensions(service):
67
    # create root CA and encrypt the private key of the root CA
68
    root_key_passphrase = "barbaz"
69
    root_key = service.create_private_key(passphrase=root_key_passphrase)
70
    root_ca = service.create_sscrt(Subject(common_name="foo"), root_key, key_pass=root_key_passphrase)
71

  
72
    # create a private key to be used to make a CSR for the intermediate CA
73
    inter_key = service.create_private_key()
74
    csr = service._CryptographyService__create_csr(Subject(common_name="bar", country="CZ"), inter_key)
75

  
76
    # sign the created CSR with root CA and specify root key passphrase and specify extensions (AIA and CA)
77
    inter_ca = service._CryptographyService__sign_csr(csr, root_ca, root_key,
78
                                                      extensions="authorityInfoAccess = caIssuers;URI:bar.cz/baz/cert\nbasicConstraints=critical,CA:TRUE",
79
                                                      issuer_key_pass=root_key_passphrase)
80

  
81
    inter_ca_printed = export_crt(inter_ca)
82

  
83
    # assert fields
84
    assert "Issuer: CN = foo" in inter_ca_printed
85
    assert "Subject: CN = bar, C = CZ" in inter_ca_printed
86

  
87
    # assert extensions
88
    expected_extensions = """        X509v3 extensions:
89
            Authority Information Access: 
90
                CA Issuers - URI:bar.cz/baz/cert
91

  
92
            X509v3 Basic Constraints: critical
93
                CA:TRUE"""
94
    assert expected_extensions in inter_ca_printed
tests/services/cryptography/verify_ca_test.py
1
import pytest
2

  
3
from src.model.subject import Subject
4
from src.services.cryptography import CryptographyException
5

  
6

  
7
def test_verify_valid_ca(service):
8
    # verify validation of valid certificates
9
    private_key = service.create_private_key()
10
    root_cert = service.create_sscrt(Subject(common_name="foo"), private_key)
11
    child_cert = service.create_crt(Subject(common_name="Expired Foo"), private_key, root_cert, private_key, days=1)
12

  
13
    assert service.verify_cert(root_cert)
14
    assert service.verify_cert(child_cert)
15

  
16

  
17
def test_verify_invalid_ca(service):
18
    # test whether expired certificate will fail to get verified
19
    private_key = service.create_private_key()
20
    root_cert = service.create_sscrt(Subject(common_name="foo"), private_key)
21

  
22
    expired_cert = service.create_crt(Subject(common_name="Expired Foo"), private_key, root_cert, private_key, days=0)
23

  
24
    assert not service.verify_cert(expired_cert)
25

  
26

  
27
def test_verify_invalid_cert_format(service):
28
    # verify that certificate in invalid format raises <CryptographyException>
29

  
30
    with pytest.raises(CryptographyException):
31
        service.verify_cert("invalid cert")
tests/unit_tests/services/cryptography/conftest.py
1
import pytest
2

  
3
from src.services.cryptography import CryptographyService
4

  
5

  
6
@pytest.fixture
7
def service():
8
    # provide a CryptographyService fixture
9
    return CryptographyService()
tests/unit_tests/services/cryptography/create_crt_test.py
1
import subprocess
2

  
3
import pytest
4

  
5
from src.model.subject import Subject
6
from src.services.cryptography import CryptographyException
7

  
8

  
9
def export_crt(crt):
10
    return subprocess.check_output(["openssl", "x509", "-noout", "-text", "-in", "-"],
11
                                   input=bytes(crt, encoding="utf-8"), stderr=subprocess.STDOUT).decode()
12

  
13

  
14
def test_sign_cst(service):
15
    # create root CA
16
    root_key = service.create_private_key()
17
    root_ca = service.create_sscrt(Subject(common_name="foo"), root_key)
18

  
19
    # create a private key to be used to make a CSR for the intermediate CA
20
    inter_key = service.create_private_key()
21

  
22
    # create a CA using the root CA
23
    inter_ca = service.create_crt(Subject(common_name="bar", country="CZ"), inter_key, root_ca, root_key)
24

  
25
    inter_ca_printed = export_crt(inter_ca)
26

  
27
    # assert fields
28
    assert "Issuer: CN = foo" in inter_ca_printed
29
    assert "Subject: CN = bar, C = CZ" in inter_ca_printed
30

  
31

  
32
def test_sign_crt_passphrase(service):
33
    # create root CA and encrypt the private key of the root CA
34
    root_key_passphrase = "barbaz"
35
    root_key = service.create_private_key(passphrase=root_key_passphrase)
36
    root_ca = service.create_sscrt(Subject(common_name="foo"), root_key, key_pass=root_key_passphrase)
37

  
38
    # create a private key to be used to make a CSR for the intermediate CA
39
    inter_key_passphrase = "foobazbar"
40
    inter_key = service.create_private_key(passphrase=inter_key_passphrase)
41

  
42
    # create a CA using the root CA
43
    inter_ca = service.create_crt(Subject(common_name="bar", country="CZ"), inter_key, root_ca, root_key,
44
                                  subject_key_pass=inter_key_passphrase, issuer_key_pass=root_key_passphrase)
45

  
46
    inter_ca_printed = export_crt(inter_ca)
47

  
48
    # assert fields
49
    assert "Issuer: CN = foo" in inter_ca_printed
50
    assert "Subject: CN = bar, C = CZ" in inter_ca_printed
51

  
52
    # some basic incorrect passphrase combinations
53
    passphrases = [
54
        (inter_key, None),
55
        (inter_key, "foofoobarbar"),
56
        (None, root_key),
57
        ("foofoobarbar", root_key),
58
        ("foofoobarbar", "foofoobarbar"),
59
        (None, None)
60
    ]
61

  
62
    for (key_pass, issuer_key_pass) in passphrases:
63
        # try to create it using a wrong issuer passphrase
64
        with pytest.raises(CryptographyException) as e:
65
            inter_ca = service.create_crt(Subject(common_name="bar", country="CZ"), inter_key, root_ca, root_key,
66
                                          subject_key_pass=key_pass, issuer_key_pass=issuer_key_pass)
67
        assert "bad decrypt" in e.value.message
68

  
69

  
70
def test_sign_crt_extensions(service):
71
    # create root CA and encrypt the private key of the root CA
72
    root_key_passphrase = "barbaz"
73
    root_key = service.create_private_key(passphrase=root_key_passphrase)
74
    root_ca = service.create_sscrt(Subject(common_name="foo"), root_key, key_pass=root_key_passphrase)
75

  
76
    # create a private key to be used to make a CSR for the intermediate CA
77
    inter_key_passphrase = "foofoo"
78
    inter_key = service.create_private_key()
79

  
80
    # create a CA using the root CA
81
    inter_ca = service.create_crt(Subject(common_name="bar", country="CZ"), inter_key, root_ca, root_key,
82
                                  subject_key_pass=inter_key_passphrase, issuer_key_pass=root_key_passphrase,
83
                                  extensions="authorityInfoAccess = caIssuers;URI:bar.cz/baz/cert\nbasicConstraints=critical,CA:TRUE")
84

  
85
    inter_ca_printed = export_crt(inter_ca)
86

  
87
    # assert fields
88
    assert "Issuer: CN = foo" in inter_ca_printed
89
    assert "Subject: CN = bar, C = CZ" in inter_ca_printed
90

  
91
    # assert extensions
92
    expected_extensions = """        X509v3 extensions:
93
            Authority Information Access: 
94
                CA Issuers - URI:bar.cz/baz/cert
95

  
96
            X509v3 Basic Constraints: critical
97
                CA:TRUE"""
98
    assert expected_extensions in inter_ca_printed
tests/unit_tests/services/cryptography/create_csr_test.py
1
import subprocess
2

  
3
from src.model.subject import Subject
4

  
5

  
6
def get_csr_pem(csr):
7
    return subprocess.check_output(["openssl", "req", "-noout", "-text", "-verify", "-in", "-"],
8
                                   input=bytes(csr, encoding="utf-8"), stderr=subprocess.STDOUT).decode()
9

  
10

  
11
def test_make_csr(service):
12
    private_key = service.create_private_key()
13

  
14
    subject = Subject(common_name="foo", country="CZ")
15
    csr = service._CryptographyService__create_csr(subject, private_key)
16

  
17
    assert "Subject: CN = foo, C = CZ" in get_csr_pem(csr)
18

  
19

  
20
def test_make_csr_pkey_passphrase(service):
21
    private_key = service.create_private_key(passphrase="foobar")
22

  
23
    subject = Subject(common_name="foo", country="CZ", organization_unit="Mysterious Unit")
24
    csr = service._CryptographyService__create_csr(subject, private_key, key_pass="foobar")
25

  
26
    assert "Subject: CN = foo, C = CZ, OU = Mysterious Unit" in get_csr_pem(csr)
tests/unit_tests/services/cryptography/parse_cert_pem_test.py
1
from src.model.subject import Subject
2

  
3

  
4
def test_parse_cert_pem(service):
5
    cert_pem = """
6
-----BEGIN CERTIFICATE-----
7

  
8
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
41
-----END CERTIFICATE-----
42
    """
43

  
44
    # parse a certificate supplied in a PEM format
45
    subj, n_before, n_after = service.parse_cert_pem(cert_pem)
46

  
47
    assert 3 == n_before.tm_mon
48
    assert 21 == n_before.tm_mday
49
    assert 10 == n_before.tm_hour
50
    assert 1 == n_before.tm_min
51
    assert 52 == n_before.tm_sec
52
    assert 2021 == n_before.tm_year
53

  
54
    assert 3 == n_after.tm_mon
55
    assert 21 == n_after.tm_mday
56
    assert 10 == n_after.tm_hour
57
    assert 1 == n_after.tm_min
58
    assert 52 == n_after.tm_sec
59
    assert 2026 == n_after.tm_year
60

  
61
    assert "CZ" == subj.country
62
    assert "Pilsen Region" == subj.state
63
    assert "Pilsen" == subj.locality
64
    assert "Rooting Roots" == subj.organization
65
    assert "Department of ROots" == subj.organization_unit
66
    assert "Main Rooter" == subj.common_name
67
    assert "root@root.cz" == subj.email_address
68

  
69

  
70
def test_parse_cert_pen_2(service):
71
    cert_pem = """
72
-----BEGIN CERTIFICATE-----
73
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
103
-----END CERTIFICATE-----
104
    """
105

  
106
    # parse a certificate supplied in a PEM format
107
    subj, n_before, n_after = service.parse_cert_pem(cert_pem)
108

  
109
    assert 3 == n_before.tm_mon
110
    assert 23 == n_before.tm_mday
111
    assert 21 == n_before.tm_hour
112
    assert 32 == n_before.tm_min
113
    assert 59 == n_before.tm_sec
114
    assert 2021 == n_before.tm_year
115

  
116
    assert 3 == n_after.tm_mon
117
    assert 23 == n_after.tm_mday
118
    assert 21 == n_after.tm_hour
119
    assert 32 == n_after.tm_min
120
    assert 59 == n_after.tm_sec
121
    assert 2024 == n_after.tm_year
122

  
123
    assert "AU" == subj.country
124
    assert "Some-State" == subj.state
125
    assert "Internet Widgits Pty Ltd" == subj.organization
126
    assert "NCHILD_2" == subj.common_name
127
    assert None is subj.locality
128
    assert None is subj.organization_unit
129
    assert None is subj.email_address
130

  
131

  
132
def test_parse_cert_pen_empty(service):
133
    cert_pem = """
134
-----BEGIN CERTIFICATE-----
135
MIIDczCCAlugAwIBAgIUPM++Jj33iag4uaOMIzED4/rMTB4wDQYJKoZIhvcNAQEL
136
BQAwSTELMAkGA1UEBhMCICAxCzAJBgNVBAgMAiAgMQowCAYDVQQKDAEgMQswCQYD
137
VQQDDAIgIDEUMBIGCSqGSIb3DQEJARYFIGZvbyAwHhcNMjEwNDAzMjMzMDEwWhcN
138
MjEwNTAzMjMzMDEwWjBJMQswCQYDVQQGEwIgIDELMAkGA1UECAwCICAxCjAIBgNV
139
BAoMASAxCzAJBgNVBAMMAiAgMRQwEgYJKoZIhvcNAQkBFgUgZm9vIDCCASIwDQYJ
140
KoZIhvcNAQEBBQADggEPADCCAQoCggEBALI9Ksw85aFLBw2wAeRUoxMQarXkWWbw
141
FyvGCb426EcdKYEiax4BYsK+VLxJpJsIo4DnSM1c0EKNJmN4w+l93CBVhHvmA+qo
142
3LYShf/DgNeKZD7KJgAWwPHBnA1eOA/8kUX0YT9Z76JpJN46KFfqaY9Scb9GBU/m
143
Kr/Lm2Rkg/LehMObPfNQm3XGOvcRjHON9VoB7hZW8zt2lvWTkhia9t46p/kY90eg
144
3iw5JRR/MeYBiYeikjT4g5pMZDkymWUp7eahOsoR4kGYGLkpdXVN66evWzTikUKV
145
QSHdzUZOiTJ7GFJ70qqh+gAEMCf/Lx8EDbDcuz7ZH40Lr6knY2+9xe8CAwEAAaNT
146
MFEwHQYDVR0OBBYEFChHMZUZ2fyOrclVGjtopKn7f/mSMB8GA1UdIwQYMBaAFChH
147
MZUZ2fyOrclVGjtopKn7f/mSMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
148
BQADggEBAETfyBYSS6drAyGY1/+z7fWKV3aS1Ocd8c/7oj1seFZ8AH+b0zktTynv
149
khprZhxRGRR6cHhyVmMexSWucWb7zlJZNcO9F0/FIgoqcKODtdNczTJyrC9raeuf
150
8pAqhaxXcNXXUSB8vNQKHLRtRnPCB3nZE7xSl5RRmSPyPGZyyAYygxRnLjMFgJEU
151
4c1FOpvRcfRS5yWviOS6dFv+cGA8hoUMXkpIW88GfwgdO6nMSQB1wUdqKoPnaIFc
152
3vjtLMWkuVZFYqvp3NN6GtyI5pw1O0FzjkLZsAeuHZyIkwpKkMsnGlGW8lz1svZ+
153
7AQMsDl5rA4ZVlnLXSQlq3YXVuXZlAI=
154
-----END CERTIFICATE-----
155
    """
156

  
157
    # parse a certificate supplied in a PEM format
158
    subj, n_before, n_after = service.parse_cert_pem(cert_pem)
159

  
160
    assert 4 == n_before.tm_mon
161
    assert 3 == n_before.tm_mday
162
    assert 23 == n_before.tm_hour
163
    assert 30 == n_before.tm_min
164
    assert 10 == n_before.tm_sec
165
    assert 2021 == n_before.tm_year
166

  
167
    assert 5 == n_after.tm_mon
168
    assert 3 == n_after.tm_mday
169
    assert 23 == n_after.tm_hour
170
    assert 30 == n_after.tm_min
171
    assert 10 == n_after.tm_sec
172
    assert 2021 == n_after.tm_year
173

  
174
    # TODO improve parsing of fields within quotes
175
    assert "\"  \"" == subj.country
176
    assert "\"  \"" == subj.state
177
    assert "\" \"" == subj.organization
178
    assert "\"  \"" == subj.common_name
179
    assert None is subj.locality
180
    assert None is subj.organization_unit
181
    assert "\" foo \"" == subj.email_address
182

  
183

  
184
def test_create_and_parse_cert(service):
185
    # create a private key
186
    key = service.create_private_key(passphrase="foobar")
187

  
188
    # create a certificate
189
    cert = service.create_sscrt(Subject(common_name="Foo CN", email_address="foo@bar.cz"), key, key_pass="foobar")
190

  
191
    # parse the subject
192
    parsed_subj, n_before, n_after = service.parse_cert_pem(cert)
193

  
194
    assert "Foo CN" == parsed_subj.common_name
195
    assert "foo@bar.cz" == parsed_subj.email_address
tests/unit_tests/services/cryptography/private_keys_test.py
1
import subprocess
2

  
3
import pytest
4

  
5

  
6
def test_private_key(service):
7
    private_key = service.create_private_key()
8

  
9
    # verify the private key
10
    subprocess.check_output(["openssl", "rsa", "-in", "-", "-check"], input=bytes(private_key, encoding="utf-8"),
11
                            stderr=subprocess.STDOUT)
12

  
13

  
14
def test_encrypted_private_key(service):
15
    private_key = service.create_private_key(passphrase="foobar")
16

  
17
    # verify the private key providing a correct passphrase
18
    subprocess.check_output(["openssl", "rsa", "-in", "-", "-passin", "pass:foobar", "-check"],
19
                            input=bytes(private_key, encoding="utf-8"), stderr=subprocess.STDOUT)
20

  
21

  
22
def test_encrypted_private_key_incorrect_pass(service):
23
    private_key = service.create_private_key(passphrase="foobar")
24

  
25
    # incorrect passphrase provided
26
    with pytest.raises(subprocess.CalledProcessError):
27
        subprocess.check_output(["openssl", "rsa", "-in", "-", "-passin", "pass:bazbaz", "-check"],
28
                                input=bytes(private_key, encoding="utf-8"), stderr=subprocess.STDOUT)
tests/unit_tests/services/cryptography/run_for_output_test.py
1
import pytest
2

  
3
from src.services.cryptography import CryptographyException
4

  
5

  
6
def test_simple_exec(service):
7
    out = service._CryptographyService__run_for_output(["version"])
8
    assert "OpenSSL" in out.decode()
9

  
10

  
11
def test_simple_exec_without_parameters(service):
12
    out = service._CryptographyService__run_for_output()
13
    assert "OpenSSL>" in out.decode()
14

  
15

  
16
def test_nonexistent_executable(service):
17
    with pytest.raises(CryptographyException) as e:
18
        service._CryptographyService__run_for_output(executable="nonexistent_executable#")
19
    assert """"nonexistent_executable#" not found in the current PATH.""" in e.value.message
20

  
21

  
22
def test_exception_str(service):
23
    with pytest.raises(CryptographyException) as e:
24
        service._CryptographyService__run_for_output(executable="nonexistent_executable")
25
    assert """EXECUTABLE: nonexistent_executable
26
        ARGS: ('nonexistent_executable',)
27
        MESSAGE: "nonexistent_executable" not found in the current PATH.""" in e.value.__str__()
... Rozdílový soubor je zkrácen, protože jeho délka přesahuje max. limit.

Také k dispozici: Unified diff