Revize 94f8d5cf
Přidáno uživatelem Jan Pašek před téměř 4 roky(ů)
src/constants.py | ||
---|---|---|
59 | 59 |
"CACompromise", "affiliationChanged", |
60 | 60 |
"superseded", "cessationOfOperation", |
61 | 61 |
"certificateHold", "removeFromCRL"} |
62 |
CERTIFICATE_REVOCATION_REASON_HOLD = "certificateHold" |
|
62 | 63 |
|
63 | 64 |
|
64 | 65 |
# Insert values into the template using % (index_file, serial_file) |
src/controllers/certificates_controller.py | ||
---|---|---|
14 | 14 |
from src.exceptions.unknown_exception import UnknownException |
15 | 15 |
from src.model.subject import Subject |
16 | 16 |
from src.services.certificate_service import CertificateService, RevocationReasonInvalidException, \ |
17 |
CertificateStatusInvalidException, CertificateNotFoundException, CertificateAlreadyRevokedException |
|
17 |
CertificateStatusInvalidException, CertificateNotFoundException, CertificateAlreadyRevokedException, \ |
|
18 |
CertificateCannotBeSetToValid |
|
18 | 19 |
# responsibility. |
19 | 20 |
from src.services.key_service import KeyService |
20 | 21 |
|
... | ... | |
357 | 358 |
return E_NO_CERTIFICATE_ALREADY_REVOKED, C_BAD_REQUEST |
358 | 359 |
except CertificateNotFoundException: |
359 | 360 |
return E_NO_CERTIFICATES_FOUND, C_NOT_FOUND |
361 |
except CertificateCannotBeSetToValid as e: |
|
362 |
return {"success": False, "data": str(e)}, C_BAD_REQUEST |
|
360 | 363 |
return {"success": True, |
361 | 364 |
"data": "Certificate status updated successfully."}, C_SUCCESS |
362 | 365 |
# throw an error in case the request does not contain a json body |
src/services/certificate_service.py | ||
---|---|---|
4 | 4 |
|
5 | 5 |
from src.config.configuration import Configuration |
6 | 6 |
from src.constants import ROOT_CA_ID, INTERMEDIATE_CA_ID, CA_ID, CERTIFICATE_ID, CERTIFICATE_STATES, \ |
7 |
CERTIFICATE_REVOCATION_REASONS, SSL_ID, SIGNATURE_ID, AUTHENTICATION_ID |
|
7 |
CERTIFICATE_REVOCATION_REASONS, SSL_ID, SIGNATURE_ID, AUTHENTICATION_ID, CERTIFICATE_REVOCATION_REASON_HOLD
|
|
8 | 8 |
from src.dao.certificate_repository import CertificateRepository |
9 | 9 |
from src.exceptions.certificate_not_found_exception import CertificateNotFoundException |
10 | 10 |
from src.exceptions.database_exception import DatabaseException |
... | ... | |
326 | 326 |
:param reason: reason for revocation |
327 | 327 |
:param id: identifier of the certificate whose status is to be changed |
328 | 328 |
:param status: new status of the certificate |
329 |
:raises CertificateStatusInvalidException: if status is not valid |
|
330 |
:raises RevocationReasonInvalidException: if reason is not valid |
|
331 |
:raises CertificateNotFoundException: if certificate with given id cannot be found |
|
332 |
:raises CertificateCannotBeSetToValid: if certificate was already revoked and not on hold, |
|
333 |
it cannot be set revalidated |
|
334 |
:raises CertificateAlreadyRevokedException: if caller tries to revoke a certificate that is already revoked |
|
335 |
:raises UnknownException: if the database is corrupted |
|
329 | 336 |
""" |
330 | 337 |
if status not in CERTIFICATE_STATES: |
331 | 338 |
raise CertificateStatusInvalidException(status) |
... | ... | |
339 | 346 |
|
340 | 347 |
updated = False |
341 | 348 |
if status == STATUS_VALID: |
349 |
# if the certificate is revoked but the reason is not certificateHold, it cannot be re-validated |
|
350 |
# -> throw an exception |
|
351 |
if certificate.revocation_reason != "" and \ |
|
352 |
certificate.revocation_reason != CERTIFICATE_REVOCATION_REASON_HOLD: |
|
353 |
raise CertificateCannotBeSetToValid(certificate.revocation_reason) |
|
342 | 354 |
updated = self.certificate_repository.clear_certificate_revocation(id) |
343 | 355 |
elif status == STATUS_REVOKED: |
344 | 356 |
# check if the certificate is not revoked already |
... | ... | |
430 | 442 |
|
431 | 443 |
def __str__(self): |
432 | 444 |
return f"Certificate id '{self.id}' is already revoked." |
445 |
|
|
446 |
|
|
447 |
class CertificateCannotBeSetToValid(Exception): |
|
448 |
""" |
|
449 |
Exception that denotes that the caller was trying to |
|
450 |
set certificate to valid if the certificate was already |
|
451 |
revoked but not certificateHold. |
|
452 |
""" |
|
453 |
|
|
454 |
def __init__(self, old_reason): |
|
455 |
self.old_state = old_reason |
|
456 |
|
|
457 |
def __str__(self): |
|
458 |
return "Cannot set revoked certificate back to valid when the certificate revocation reason is not " \ |
|
459 |
"certificateHold. " \ |
|
460 |
f"The revocation reason of the certificate is {self.old_state}" |
tests/integration_tests/rest_api/certificates_test.py | ||
---|---|---|
639 | 639 |
d = created_ret.json |
640 | 640 |
cert_id = d["data"] |
641 | 641 |
|
642 |
# hold certificate |
|
643 |
revocation_body = { |
|
644 |
"status": "revoked", |
|
645 |
"reason": "certificateHold" |
|
646 |
} |
|
647 |
revoke_ret = server.patch(f"/api/certificates/{cert_id}", content_type="application/json", json=revocation_body) |
|
648 |
|
|
649 |
assert revoke_ret.status_code == 200 |
|
650 |
assert "data" in revoke_ret.json |
|
651 |
assert "success" in revoke_ret.json |
|
652 |
assert revoke_ret.json["success"] |
|
653 |
|
|
654 |
# set back to valid again |
|
655 |
valid_body = { |
|
656 |
"status": "valid" |
|
657 |
} |
|
658 |
valid_ret = server.patch(f"/api/certificates/{cert_id}", content_type="application/json", json=valid_body) |
|
659 |
|
|
660 |
assert valid_ret.status_code == 200 |
|
661 |
assert "data" in valid_ret.json |
|
662 |
assert "success" in valid_ret.json |
|
663 |
assert valid_ret.json["success"] |
|
664 |
|
|
642 | 665 |
# revoke the certificate |
643 | 666 |
revocation_body = { |
644 | 667 |
"status": "revoked", |
... | ... | |
664 | 687 |
} |
665 | 688 |
valid_ret = server.patch(f"/api/certificates/{cert_id}", content_type="application/json", json=valid_body) |
666 | 689 |
|
667 |
assert valid_ret.status_code == 200
|
|
690 |
assert valid_ret.status_code == 400
|
|
668 | 691 |
assert "data" in valid_ret.json |
669 | 692 |
assert "success" in valid_ret.json |
670 |
assert valid_ret.json["success"] |
|
693 |
assert not valid_ret.json["success"]
|
|
671 | 694 |
|
672 | 695 |
# wrong status |
673 | 696 |
revocation_body = { |
tests/integration_tests/services/certificate_service_test.py | ||
---|---|---|
5 | 5 |
from src.constants import SSL_ID, CA_ID, AUTHENTICATION_ID, INTERMEDIATE_CA_ID, ROOT_CA_ID, CERTIFICATE_ID, SIGNATURE_ID |
6 | 6 |
from src.model.subject import Subject |
7 | 7 |
from src.services.certificate_service import RevocationReasonInvalidException, CertificateStatusInvalidException, \ |
8 |
CertificateNotFoundException, CertificateAlreadyRevokedException |
|
8 |
CertificateNotFoundException, CertificateAlreadyRevokedException, CertificateCannotBeSetToValid
|
|
9 | 9 |
|
10 | 10 |
|
11 | 11 |
def export_crt(crt): |
... | ... | |
318 | 318 |
root_ca_cert, |
319 | 319 |
root_ca_private_key, usages={SSL_ID: True}) |
320 | 320 |
|
321 |
certificate_service_unique.set_certificate_revocation_status(inter_ca_cert.certificate_id, "revoked", "unspecified")
|
|
321 |
certificate_service_unique.set_certificate_revocation_status(inter_ca_cert.certificate_id, "revoked", "certificateHold")
|
|
322 | 322 |
all_revoked = certificate_repository_unique.get_all_revoked_by(root_ca_cert.certificate_id) |
323 | 323 |
|
324 | 324 |
assert len(all_revoked) == 1 |
... | ... | |
353 | 353 |
with pytest.raises(CertificateAlreadyRevokedException) as e: |
354 | 354 |
certificate_service_unique.set_certificate_revocation_status(root_ca_cert.certificate_id, "revoked", |
355 | 355 |
"unspecified") |
356 |
|
|
357 |
with pytest.raises(CertificateCannotBeSetToValid) as e: |
|
358 |
certificate_service_unique.set_certificate_revocation_status(root_ca_cert.certificate_id, "valid") |
Také k dispozici: Unified diff
Re #8700 - Implemented certificate revalidation check and fixed affected tests