mirror of
https://github.com/certbot/certbot.git
synced 2026-06-06 15:22:38 -04:00
implement locking for issuing certs with openssl ca
This commit is contained in:
parent
97caf0f61a
commit
88c5b270ef
2 changed files with 16 additions and 23 deletions
|
|
@ -207,12 +207,9 @@ def encrypt(key, data):
|
|||
|
||||
def issue(csr, subjects):
|
||||
"""Issue a certificate requested by CSR, specifying the subject names
|
||||
indicated in subjects, and return the certificate."""
|
||||
# TODO: The caller should have to acquire a lock in the database to
|
||||
# prevent two certs from being issued at exactly the same time,
|
||||
# because openssl ca doesn't handle this case safely. There
|
||||
# is a longer comment in daemon.py describing how to implement
|
||||
# this lock with Redis setnx.
|
||||
indicated in subjects, and return the certificate. Calls to this
|
||||
function should be guarded with a lock to ensure that the calls never
|
||||
overlapping calls."""
|
||||
if not subjects:
|
||||
return None
|
||||
csr = str(csr)
|
||||
|
|
|
|||
|
|
@ -38,20 +38,8 @@
|
|||
# request, period, while still allowing clients to look
|
||||
# up successfully issued certs.
|
||||
# TODO: implement multithreading to allow several parallel
|
||||
# worker processes. But note:
|
||||
|
||||
# The ca command is effectively a single user command: no locking
|
||||
# is done on the various files and attempts to run more than one
|
||||
# ca command on the same database can have unpredictable results.
|
||||
# worker processes.
|
||||
#
|
||||
# -- ca(1SSL)
|
||||
|
||||
# So we need to implement our own locking mechanism. This
|
||||
# can be done easily in Redis with "setnx":
|
||||
# http://redis.io/commands/setnx
|
||||
# However apparently the proper recovery after crashes can
|
||||
# be complicated.
|
||||
|
||||
# NOTE: The daemon enforces its own timeouts, which are
|
||||
# defined in the ancient() function. These timeouts apply
|
||||
# to any session that has been placed in a queue and can
|
||||
|
|
@ -60,12 +48,19 @@
|
|||
# the server or the daemon (due to timeout or error) causes
|
||||
# a session to be treated as dead by both.
|
||||
|
||||
import redis, time, CSR, sys, signal, hashlib
|
||||
r = redis.Redis()
|
||||
|
||||
import redis, redis_lock, time, CSR, sys, signal, hashlib
|
||||
from sni_challenge.verify import verify_challenge
|
||||
from Crypto import Random
|
||||
|
||||
r = redis.Redis()
|
||||
issue_lock = redis_lock(r, "issue_lock")
|
||||
# This lock guards the ability to issue certificates with "openssl ca",
|
||||
# which has no locking of its own. We don't need locking for the updates
|
||||
# that the daemon performs on the sessions in the database because the
|
||||
# queues pending-makechallenge, pending-testchallenge, and pending-issue
|
||||
# are updated atomically and the daemon only ever acts on sessions that it
|
||||
# has removed from a queue.
|
||||
|
||||
debug = "debug" in sys.argv
|
||||
clean_shutdown = False
|
||||
|
||||
|
|
@ -232,7 +227,8 @@ def issue(session):
|
|||
return
|
||||
csr = r.hget(session, "csr")
|
||||
names = r.lrange("%s:names" % session, 0, -1)
|
||||
cert = CSR.issue(csr, names)
|
||||
with issue_lock:
|
||||
cert = CSR.issue(csr, names)
|
||||
r.hset(session, "cert", cert)
|
||||
if cert: # once issuing cert succeeded
|
||||
if debug: print "issued for", session
|
||||
|
|
|
|||
Loading…
Reference in a new issue