Revize bbcb7c89
Přidáno uživatelem Stanislav Král před asi 4 roky(ů)
src/services/certificate_service.py | ||
---|---|---|
1 |
from src.constants import ROOT_CA_ID |
|
1 |
from src.constants import ROOT_CA_ID, INTERMEDIATE_CA_ID
|
|
2 | 2 |
from src.dao.certificate_repository import CertificateRepository |
3 | 3 |
from src.model.certificate import Certificate |
4 | 4 |
from src.model.private_key import PrivateKey |
... | ... | |
8 | 8 |
import time |
9 | 9 |
|
10 | 10 |
DATE_FORMAT = "%d.%m.%Y %H:%M:%S" |
11 |
CA_EXTENSIONS = "basicConstraints=critical,CA:TRUE" |
|
11 | 12 |
|
12 | 13 |
|
13 | 14 |
class CertificateService: |
... | ... | |
16 | 17 |
self.cryptography_service = cryptography_service |
17 | 18 |
self.certificate_repository = certificate_repository |
18 | 19 |
|
20 |
# TODO usages present in method parameters but not in class diagram |
|
19 | 21 |
def create_root_ca(self, key: PrivateKey, subject: Subject, extensions: str = "", config: str = ""): |
20 | 22 |
# create a new self signed certificate |
21 | 23 |
cert_pem = self.cryptography_service.create_sscrt(subject, key.private_key, key_pass=key.password, |
... | ... | |
40 | 42 |
|
41 | 43 |
return certificate |
42 | 44 |
|
45 |
# TODO config parameter present in class diagram but not here (unused) |
|
46 |
def create_ca(self, subject_key: PrivateKey, subject: Subject, issuer_cert: Certificate, issuer_key: PrivateKey, |
|
47 |
extensions: str = "", days: int = 30): |
|
48 |
extensions = extensions + "\n" + CA_EXTENSIONS |
|
49 |
# TODO implement AIA URI via extensions |
|
50 |
cert_pem = self.cryptography_service.create_crt(subject, subject_key.private_key, issuer_cert.pem_data, |
|
51 |
issuer_key.private_key, |
|
52 |
subject_key_pass=subject_key.password, |
|
53 |
issuer_key_pass=issuer_key.password, extensions=extensions, |
|
54 |
days=days) |
|
55 |
|
|
56 |
# parse the generated pem for subject and notBefore/notAfter fields |
|
57 |
subj, not_before, not_after = self.cryptography_service.parse_cert_pem(cert_pem) |
|
58 |
|
|
59 |
# format the parsed date |
|
60 |
not_before_formatted = time.strftime(DATE_FORMAT, not_before) |
|
61 |
not_after_formatted = time.strftime(DATE_FORMAT, not_after) |
|
62 |
|
|
63 |
# create a certificate wrapper |
|
64 |
certificate = Certificate(-1, subject.common_name, not_before_formatted, not_after_formatted, cert_pem, |
|
65 |
subject_key.private_key_id, INTERMEDIATE_CA_ID, 0, {}) |
|
66 |
|
|
67 |
# store the wrapper into the repository |
|
68 |
created_id = self.certificate_repository.create(certificate) |
|
69 |
|
|
70 |
# assign the generated ID to the inserted certificate |
|
71 |
certificate.certificate_id = created_id |
|
72 |
|
|
73 |
return certificate |
|
74 |
|
|
43 | 75 |
def get_certificate(self, unique_id: int) -> Certificate: |
44 | 76 |
return self.certificate_repository.read(unique_id) |
tests/integration_tests/services/certificate_key_service_test.py | ||
---|---|---|
1 |
import subprocess |
|
2 |
|
|
1 | 3 |
from src.model.subject import Subject |
2 | 4 |
|
3 | 5 |
|
6 |
def export_crt(crt): |
|
7 |
return subprocess.check_output(["openssl", "x509", "-noout", "-text", "-in", "-"], |
|
8 |
input=bytes(crt, encoding="utf-8"), stderr=subprocess.STDOUT).decode() |
|
9 |
|
|
10 |
|
|
4 | 11 |
def test_create_and_get_pk(private_key_service, certificate_service): |
5 | 12 |
private_key = private_key_service.create_new_key(passphrase="foobar") |
6 | 13 |
private_key_loaded = private_key_service.get_key(private_key.private_key_id) |
... | ... | |
10 | 17 |
assert private_key.password == private_key_loaded.password |
11 | 18 |
|
12 | 19 |
|
13 |
def test_create_and_get_cert(private_key_service, certificate_service):
|
|
20 |
def test_create_and_get_root_ca(private_key_service, certificate_service):
|
|
14 | 21 |
private_key = private_key_service.create_new_key(passphrase="foobar") |
15 | 22 |
|
16 | 23 |
cert = certificate_service.create_root_ca(private_key, |
... | ... | |
18 | 25 |
|
19 | 26 |
cert_loaded = certificate_service.get_certificate(cert.certificate_id) |
20 | 27 |
|
28 |
# verify that the loaded certificate is a CA |
|
29 |
cert_loaded_printed = export_crt(cert_loaded.pem_data) |
|
30 |
assert """ X509v3 Basic Constraints: critical |
|
31 |
CA:TRUE""" in cert_loaded_printed |
|
32 |
|
|
21 | 33 |
assert cert.certificate_id == cert_loaded.certificate_id |
22 | 34 |
assert cert.common_name == cert_loaded.common_name |
23 | 35 |
assert cert.valid_from == cert_loaded.valid_from |
... | ... | |
27 | 39 |
assert cert.type_id == cert_loaded.type_id |
28 | 40 |
assert cert.parent_id == cert_loaded.parent_id |
29 | 41 |
assert cert.usages == cert_loaded.usages |
42 |
|
|
43 |
|
|
44 |
def test_create_and_get_cert(private_key_service, certificate_service): |
|
45 |
root_ca_private_key = private_key_service.create_new_key(passphrase="foobar") |
|
46 |
inter_ca_private_key = private_key_service.create_new_key() |
|
47 |
|
|
48 |
root_ca = certificate_service.create_root_ca(root_ca_private_key, |
|
49 |
Subject(common_name="RootFoo", organization_unit="Department of Foo")) |
|
50 |
|
|
51 |
inter_cert = certificate_service.create_ca(inter_ca_private_key, Subject(common_name="Intermediate CA"), root_ca, |
|
52 |
root_ca_private_key) |
|
53 |
|
|
54 |
inter_cert_loaded = certificate_service.get_certificate(inter_cert.certificate_id) |
|
55 |
|
|
56 |
# verify that the loaded certificate is a CA |
|
57 |
cert_loaded_printed = export_crt(inter_cert_loaded.pem_data) |
|
58 |
assert """ X509v3 Basic Constraints: critical |
|
59 |
CA:TRUE""" in cert_loaded_printed |
|
60 |
|
|
61 |
assert inter_cert_loaded.certificate_id == inter_cert_loaded.certificate_id |
|
62 |
assert inter_cert.common_name == inter_cert_loaded.common_name |
|
63 |
assert inter_cert.valid_from == inter_cert_loaded.valid_from |
|
64 |
assert inter_cert.valid_to == inter_cert_loaded.valid_to |
|
65 |
assert inter_cert.pem_data == inter_cert_loaded.pem_data |
|
66 |
assert inter_cert.private_key_id == inter_cert_loaded.private_key_id |
|
67 |
assert inter_cert.type_id == inter_cert_loaded.type_id |
|
68 |
assert inter_cert.parent_id == root_ca.certificate_id |
|
69 |
assert inter_cert.usages == inter_cert_loaded.usages |
Také k dispozici: Unified diff
Re #8472 - Implemented create_ca method in CertificateService and added test verifying this method's validity