Commit 8984006f authored by Vincent Pelletier's avatar Vincent Pelletier

ca: Make _renewCAIfNeeded threadsafe.

This is called from many places which make sense to call independently
and should not conflict. So protect against parallel CA renewal.
Result code will never block: a single thread will process renewal,
concurrent threads will just use the still-valid latest CA.
parent 20de8d07
...@@ -23,6 +23,7 @@ import datetime ...@@ -23,6 +23,7 @@ import datetime
import json import json
import os import os
import struct import struct
import threading
from cryptography import x509 from cryptography import x509
from cryptography.hazmat.backends import default_backend from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization, hashes, hmac from cryptography.hazmat.primitives import serialization, hashes, hmac
...@@ -140,6 +141,7 @@ class CertificateAuthority(object): ...@@ -140,6 +141,7 @@ class CertificateAuthority(object):
value given on later instanciation will be ignored. value given on later instanciation will be ignored.
""" """
self._storage = storage self._storage = storage
self._ca_renewal_lock = threading.Lock()
if lock_auto_sign_csr_amount: if lock_auto_sign_csr_amount:
storage.setConfigOnce( storage.setConfigOnce(
_CONFIG_NAME_AUTO_SIGN_CSR_AMOUNT, _CONFIG_NAME_AUTO_SIGN_CSR_AMOUNT,
...@@ -521,13 +523,18 @@ class CertificateAuthority(object): ...@@ -521,13 +523,18 @@ class CertificateAuthority(object):
ca_life_periods of validity left. ca_life_periods of validity left.
Updates self._ca_key_pairs_list . Updates self._ca_key_pairs_list .
""" """
if not self._ca_key_pairs_list or ( if (
not self._ca_key_pairs_list or (
self._ca_key_pairs_list[-1]['crt'].not_valid_after - datetime.datetime.utcnow() self._ca_key_pairs_list[-1]['crt'].not_valid_after - datetime.datetime.utcnow()
).total_seconds() / self._crt_life_time.total_seconds() <= 2: ).total_seconds() / self._crt_life_time.total_seconds() <= 2
) and self._ca_renewal_lock.acquire(False):
try:
# No CA certificate at all or less than 2 certificate validity periods # No CA certificate at all or less than 2 certificate validity periods
# left with latest CA certificate. Prepare the next one so it starts # left with latest CA certificate. Prepare the next one so it starts
# getting distributed. # getting distributed.
self.createCAKeyPair() self.createCAKeyPair()
finally:
self._ca_renewal_lock.release()
def _getCurrentCAKeypair(self): def _getCurrentCAKeypair(self):
""" """
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment