mirror of
https://github.com/certbot/certbot.git
synced 2026-07-27 16:30:31 +02:00
Refactor for revocation
This commit is contained in:
@@ -481,7 +481,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
||||
|
||||
# Add directives
|
||||
vh_p = self.aug.match("/files%s//* [label()=~regexp('%s')]" %
|
||||
(ssl_fp, parser.case_i('VirtualHost')))
|
||||
(ssl_fp, parser.case_i('VirtualHost')))
|
||||
if len(vh_p) != 1:
|
||||
logging.error("Error: should only be one vhost in %s", avail_fp)
|
||||
sys.exit(1)
|
||||
|
||||
+17
-230
@@ -1,18 +1,14 @@
|
||||
"""ACME protocol client class and helper functions."""
|
||||
import collections
|
||||
import csv
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import socket
|
||||
import string
|
||||
import sys
|
||||
import time
|
||||
|
||||
import jsonschema
|
||||
import M2Crypto
|
||||
import requests
|
||||
|
||||
from letsencrypt.client import acme
|
||||
from letsencrypt.client import challenge
|
||||
@@ -21,6 +17,7 @@ from letsencrypt.client import crypto_util
|
||||
from letsencrypt.client import display
|
||||
from letsencrypt.client import errors
|
||||
from letsencrypt.client import le_util
|
||||
from letsencrypt.client import network
|
||||
|
||||
|
||||
# it's weird to point to chocolate servers via raw IPv6 addresses, and
|
||||
@@ -33,8 +30,9 @@ ALLOW_RAW_IPV6_SERVER = False
|
||||
class Client(object):
|
||||
"""ACME protocol client.
|
||||
|
||||
:ivar str server: Certificate authority server
|
||||
:ivar str server_url: Full URL of the CSR server
|
||||
:ivar network: Network object for sending and receiving messages
|
||||
:type network: :class:`letsencrypt.client.network.Network`
|
||||
|
||||
:ivar list names: Domain names (:class:`list` of :class:`str`).
|
||||
|
||||
:ivar auth: Object that supports the IAuthenticator interface.
|
||||
@@ -49,8 +47,7 @@ class Client(object):
|
||||
|
||||
def __init__(self, server, names, authkey, auth, installer):
|
||||
"""Initialize a client."""
|
||||
self.server = server
|
||||
self.server_url = "https://%s/acme/" % self.server
|
||||
self.network = network.Network(server)
|
||||
self.names = names
|
||||
self.authkey = authkey
|
||||
|
||||
@@ -104,7 +101,7 @@ class Client(object):
|
||||
:rtype: dict
|
||||
|
||||
"""
|
||||
return self.send_and_receive_expected(
|
||||
return self.network.send_and_receive_expected(
|
||||
acme.challenge_request(self.names[0]), "challenge")
|
||||
|
||||
def acme_authorization(self, challenge_msg, chal_objs, responses):
|
||||
@@ -119,13 +116,14 @@ class Client(object):
|
||||
:rtype: dict
|
||||
|
||||
"""
|
||||
auth_dict = self.send(acme.authorization_request(
|
||||
challenge_msg["sessionID"], self.names[0],
|
||||
challenge_msg["nonce"], responses, self.authkey.pem))
|
||||
|
||||
try:
|
||||
return self.is_expected_msg(auth_dict, "authorization")
|
||||
except:
|
||||
return self.network.send_and_receive_expected(
|
||||
acme.authorization_request(
|
||||
challenge_msg["sessionID"], self.names[0],
|
||||
challenge_msg["nonce"], responses, self.authkey.pem),
|
||||
"authorization")
|
||||
except errors.LetsEncryptClientError as err:
|
||||
logging.fatal(str(err))
|
||||
logging.fatal(
|
||||
"Failed Authorization procedure - cleaning up challenges")
|
||||
sys.exit(1)
|
||||
@@ -142,195 +140,10 @@ class Client(object):
|
||||
|
||||
"""
|
||||
logging.info("Preparing and sending CSR...")
|
||||
return self.send_and_receive_expected(
|
||||
return self.network.send_and_receive_expected(
|
||||
acme.certificate_request(csr_der, self.authkey.pem), "certificate")
|
||||
|
||||
def acme_revocation(self, cert):
|
||||
"""Handle ACME "revocation" phase.
|
||||
|
||||
:param dict cert: TODO
|
||||
|
||||
:returns: ACME "revocation" message.
|
||||
:rtype: dict
|
||||
|
||||
"""
|
||||
cert_der = M2Crypto.X509.load_cert(cert["backup_cert_file"]).as_der()
|
||||
with open(cert["backup_key_file"], 'rU') as backup_key_file:
|
||||
key = backup_key_file.read()
|
||||
|
||||
revocation = self.send_and_receive_expected(
|
||||
acme.revocation_request(cert_der, key), "revocation")
|
||||
|
||||
display.generic_notification(
|
||||
"You have successfully revoked the certificate for "
|
||||
"%s" % cert["cn"], width=70, height=9)
|
||||
|
||||
remove_cert_key(cert)
|
||||
self.list_certs_keys()
|
||||
|
||||
return revocation
|
||||
|
||||
def send(self, msg):
|
||||
"""Send ACME message to server.
|
||||
|
||||
:param dict msg: ACME message (JSON serializable).
|
||||
|
||||
:returns: Server response message.
|
||||
:rtype: dict
|
||||
|
||||
:raises TypeError: if `msg` is not JSON serializable
|
||||
:raises jsonschema.ValidationError: if not valid ACME message
|
||||
:raises errors.LetsEncryptClientError: in case of connection error
|
||||
or if response from server is not a valid ACME message.
|
||||
|
||||
"""
|
||||
json_encoded = json.dumps(msg)
|
||||
acme.acme_object_validate(json_encoded)
|
||||
|
||||
try:
|
||||
response = requests.post(
|
||||
self.server_url,
|
||||
data=json_encoded,
|
||||
headers={"Content-Type": "application/json"},
|
||||
)
|
||||
except requests.exceptions.RequestException as error:
|
||||
raise errors.LetsEncryptClientError(
|
||||
'Sending ACME message to server has failed: %s' % error)
|
||||
|
||||
try:
|
||||
acme.acme_object_validate(response.content)
|
||||
except ValueError:
|
||||
raise errors.LetsEncryptClientError(
|
||||
'Server did not send JSON serializable message')
|
||||
except jsonschema.ValidationError as error:
|
||||
raise errors.LetsEncryptClientError(
|
||||
'Response from server is not a valid ACME message')
|
||||
|
||||
return response.json()
|
||||
|
||||
def send_and_receive_expected(self, msg, expected):
|
||||
"""Send ACME message to server and return expected message.
|
||||
|
||||
:param dict msg: ACME message (JSON serializable).
|
||||
:param str expected: Name of the expected response ACME message type.
|
||||
|
||||
:returns: ACME response message of expected type.
|
||||
:rtype: dict
|
||||
|
||||
:raises errors.LetsEncryptClientError: An exception is thrown
|
||||
|
||||
"""
|
||||
response = self.send(msg)
|
||||
try:
|
||||
return self.is_expected_msg(response, expected)
|
||||
except: # TODO: too generic exception
|
||||
raise errors.LetsEncryptClientError(
|
||||
'Expected message (%s) not received' % expected)
|
||||
|
||||
def is_expected_msg(self, response, expected, delay=3, rounds=20):
|
||||
"""Is reponse expected ACME message?
|
||||
|
||||
:param dict response: ACME response message from server.
|
||||
:param str expected: Name of the expected response ACME message type.
|
||||
:param int delay: Number of seconds to delay before next round
|
||||
in case of ACME "defer" response message.
|
||||
:param int rounds: Number of resend attempts in case of ACME "defer"
|
||||
reponse message.
|
||||
|
||||
:returns: ACME response message from server.
|
||||
:rtype: dict
|
||||
|
||||
:raises LetsEncryptClientError: if server sent ACME "error" message
|
||||
|
||||
"""
|
||||
for _ in xrange(rounds):
|
||||
if response["type"] == expected:
|
||||
return response
|
||||
|
||||
elif response["type"] == "error":
|
||||
logging.error(
|
||||
"%s: %s - More Info: %s", response["error"],
|
||||
response.get("message", ""), response.get("moreInfo", ""))
|
||||
raise errors.LetsEncryptClientError(response["error"])
|
||||
|
||||
elif response["type"] == "defer":
|
||||
logging.info("Waiting for %d seconds...", delay)
|
||||
time.sleep(delay)
|
||||
response = self.send(acme.status_request(response["token"]))
|
||||
else:
|
||||
logging.fatal("Received unexpected message")
|
||||
logging.fatal("Expected: %s" % expected)
|
||||
logging.fatal("Received: %s" % response)
|
||||
sys.exit(33)
|
||||
|
||||
logging.error(
|
||||
"Server has deferred past the max of %d seconds", rounds * delay)
|
||||
|
||||
def list_certs_keys(self):
|
||||
"""List trusted Let's Encrypt certificates."""
|
||||
list_file = os.path.join(CONFIG.CERT_KEY_BACKUP, "LIST")
|
||||
certs = []
|
||||
|
||||
if not os.path.isfile(list_file):
|
||||
logging.info(
|
||||
"You don't have any certificates saved from letsencrypt")
|
||||
return
|
||||
|
||||
c_sha1_vh = {}
|
||||
for (cert, _, path) in self.installer.get_all_certs_keys():
|
||||
try:
|
||||
c_sha1_vh[M2Crypto.X509.load_cert(
|
||||
cert).get_fingerprint(md='sha1')] = path
|
||||
except:
|
||||
continue
|
||||
|
||||
with open(list_file, 'rb') as csvfile:
|
||||
csvreader = csv.reader(csvfile)
|
||||
for row in csvreader:
|
||||
cert = crypto_util.get_cert_info(row[1])
|
||||
|
||||
b_k = os.path.join(CONFIG.CERT_KEY_BACKUP,
|
||||
os.path.basename(row[2]) + "_" + row[0])
|
||||
b_c = os.path.join(CONFIG.CERT_KEY_BACKUP,
|
||||
os.path.basename(row[1]) + "_" + row[0])
|
||||
|
||||
cert.update({
|
||||
"orig_key_file": row[2],
|
||||
"orig_cert_file": row[1],
|
||||
"idx": int(row[0]),
|
||||
"backup_key_file": b_k,
|
||||
"backup_cert_file": b_c,
|
||||
"installed": c_sha1_vh.get(cert["fingerprint"], ""),
|
||||
})
|
||||
certs.append(cert)
|
||||
if certs:
|
||||
self.choose_certs(certs)
|
||||
else:
|
||||
display.generic_notification(
|
||||
"There are not any trusted Let's Encrypt "
|
||||
"certificates for this server.")
|
||||
|
||||
def choose_certs(self, certs):
|
||||
"""Display choose certificates menu.
|
||||
|
||||
:param list certs: List of cert dicts.
|
||||
|
||||
"""
|
||||
code, tag = display.display_certs(certs)
|
||||
|
||||
if code == display.OK:
|
||||
cert = certs[tag]
|
||||
if display.confirm_revocation(cert):
|
||||
self.acme_revocation(cert)
|
||||
else:
|
||||
self.choose_certs(certs)
|
||||
elif code == display.HELP:
|
||||
cert = certs[tag]
|
||||
display.more_info_cert(cert)
|
||||
self.choose_certs(certs)
|
||||
else:
|
||||
exit(0)
|
||||
|
||||
# pylint: disable=no-self-use
|
||||
def save_certificate(self, certificate_dict, cert_path, chain_path):
|
||||
"""Saves the certificate received from the ACME server.
|
||||
|
||||
@@ -477,6 +290,7 @@ class Client(object):
|
||||
|
||||
return responses, challenge_objs
|
||||
|
||||
# pylint: disable=no-self-use
|
||||
def _assign_responses(self, resp, index_list, responses):
|
||||
"""Assign chall_response to appropriate places in response list.
|
||||
|
||||
@@ -715,33 +529,6 @@ def csr_pem_to_der(csr):
|
||||
return Client.CSR(csr.file, csr_obj.as_der(), "der")
|
||||
|
||||
|
||||
def remove_cert_key(cert):
|
||||
"""Remove certificate and key.
|
||||
|
||||
:param dict cert: Cert dict used throughout revocation
|
||||
|
||||
"""
|
||||
list_file = os.path.join(CONFIG.CERT_KEY_BACKUP, "LIST")
|
||||
list_file2 = os.path.join(CONFIG.CERT_KEY_BACKUP, "LIST.tmp")
|
||||
|
||||
with open(list_file, 'rb') as orgfile:
|
||||
csvreader = csv.reader(orgfile)
|
||||
|
||||
with open(list_file2, 'wb') as newfile:
|
||||
csvwriter = csv.writer(newfile)
|
||||
|
||||
for row in csvreader:
|
||||
if not (row[0] == str(cert["idx"]) and
|
||||
row[1] == cert["orig_cert_file"] and
|
||||
row[2] == cert["orig_key_file"]):
|
||||
csvwriter.writerow(row)
|
||||
|
||||
shutil.copy2(list_file2, list_file)
|
||||
os.remove(list_file2)
|
||||
os.remove(cert["backup_cert_file"])
|
||||
os.remove(cert["backup_key_file"])
|
||||
|
||||
|
||||
def sanity_check_names(names):
|
||||
"""Make sure host names are valid.
|
||||
|
||||
@@ -779,5 +566,5 @@ def is_hostname_sane(hostname):
|
||||
# is this a valid IPv6 address?
|
||||
socket.getaddrinfo(hostname, 443, socket.AF_INET6)
|
||||
return True
|
||||
except:
|
||||
except socket.error:
|
||||
return False
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
"""Network Module."""
|
||||
import json
|
||||
import logging
|
||||
import sys
|
||||
import time
|
||||
|
||||
import jsonschema
|
||||
import requests
|
||||
|
||||
from letsencrypt.client import acme
|
||||
from letsencrypt.client import errors
|
||||
|
||||
|
||||
class Network(object):
|
||||
"""Class for communicating with ACME servers.
|
||||
|
||||
:ivar str server: Certificate authority server
|
||||
:ivar str server_url: Full URL of the CSR server
|
||||
|
||||
"""
|
||||
def __init__(self, server):
|
||||
self.server = server
|
||||
self.server_url = "https://%s/acme/" % self.server
|
||||
|
||||
def send(self, msg):
|
||||
"""Send ACME message to server.
|
||||
|
||||
:param dict msg: ACME message (JSON serializable).
|
||||
|
||||
:returns: Server response message.
|
||||
:rtype: dict
|
||||
|
||||
:raises TypeError: if `msg` is not JSON serializable
|
||||
:raises jsonschema.ValidationError: if not valid ACME message
|
||||
:raises errors.LetsEncryptClientError: in case of connection error
|
||||
or if response from server is not a valid ACME message.
|
||||
|
||||
"""
|
||||
json_encoded = json.dumps(msg)
|
||||
acme.acme_object_validate(json_encoded)
|
||||
|
||||
try:
|
||||
response = requests.post(
|
||||
self.server_url,
|
||||
data=json_encoded,
|
||||
headers={"Content-Type": "application/json"},
|
||||
)
|
||||
except requests.exceptions.RequestException as error:
|
||||
raise errors.LetsEncryptClientError(
|
||||
'Sending ACME message to server has failed: %s' % error)
|
||||
|
||||
try:
|
||||
acme.acme_object_validate(response.content)
|
||||
except ValueError:
|
||||
raise errors.LetsEncryptClientError(
|
||||
'Server did not send JSON serializable message')
|
||||
except jsonschema.ValidationError as error:
|
||||
raise errors.LetsEncryptClientError(
|
||||
'Response from server is not a valid ACME message')
|
||||
|
||||
return response.json()
|
||||
|
||||
def send_and_receive_expected(self, msg, expected):
|
||||
"""Send ACME message to server and return expected message.
|
||||
|
||||
:param dict msg: ACME message (JSON serializable).
|
||||
:param str expected: Name of the expected response ACME message type.
|
||||
|
||||
:returns: ACME response message of expected type.
|
||||
:rtype: dict
|
||||
|
||||
:raises errors.LetsEncryptClientError: An exception is thrown
|
||||
|
||||
"""
|
||||
response = self.send(msg)
|
||||
try:
|
||||
return self.is_expected_msg(response, expected)
|
||||
except: # TODO: too generic exception
|
||||
raise errors.LetsEncryptClientError(
|
||||
'Expected message (%s) not received' % expected)
|
||||
|
||||
def is_expected_msg(self, response, expected, delay=3, rounds=20):
|
||||
"""Is reponse expected ACME message?
|
||||
|
||||
:param dict response: ACME response message from server.
|
||||
:param str expected: Name of the expected response ACME message type.
|
||||
:param int delay: Number of seconds to delay before next round
|
||||
in case of ACME "defer" response message.
|
||||
:param int rounds: Number of resend attempts in case of ACME "defer"
|
||||
reponse message.
|
||||
|
||||
:returns: ACME response message from server.
|
||||
:rtype: dict
|
||||
|
||||
:raises LetsEncryptClientError: if server sent ACME "error" message
|
||||
|
||||
"""
|
||||
for _ in xrange(rounds):
|
||||
if response["type"] == expected:
|
||||
return response
|
||||
|
||||
elif response["type"] == "error":
|
||||
logging.error(
|
||||
"%s: %s - More Info: %s", response["error"],
|
||||
response.get("message", ""), response.get("moreInfo", ""))
|
||||
raise errors.LetsEncryptClientError(response["error"])
|
||||
|
||||
elif response["type"] == "defer":
|
||||
logging.info("Waiting for %d seconds...", delay)
|
||||
time.sleep(delay)
|
||||
response = self.send(acme.status_request(response["token"]))
|
||||
else:
|
||||
logging.fatal("Received unexpected message")
|
||||
logging.fatal("Expected: %s", expected)
|
||||
logging.fatal("Received: %s", response)
|
||||
sys.exit(33)
|
||||
|
||||
logging.error(
|
||||
"Server has deferred past the max of %d seconds", rounds * delay)
|
||||
@@ -0,0 +1,137 @@
|
||||
"""Revoker module to enable LE revocations."""
|
||||
import csv
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
|
||||
import M2Crypto
|
||||
|
||||
from letsencrypt.client import acme
|
||||
from letsencrypt.client import CONFIG
|
||||
from letsencrypt.client import crypto_util
|
||||
from letsencrypt.client import display
|
||||
from letsencrypt.client import network
|
||||
|
||||
|
||||
class Revoker(object):
|
||||
"""A revocation class for LE."""
|
||||
def __init__(self, server, installer):
|
||||
self.network = network.Network(server)
|
||||
self.installer = installer
|
||||
|
||||
def acme_revocation(self, cert):
|
||||
"""Handle ACME "revocation" phase.
|
||||
|
||||
:param dict cert: TODO
|
||||
|
||||
:returns: ACME "revocation" message.
|
||||
:rtype: dict
|
||||
|
||||
"""
|
||||
cert_der = M2Crypto.X509.load_cert(cert["backup_cert_file"]).as_der()
|
||||
with open(cert["backup_key_file"], 'rU') as backup_key_file:
|
||||
key = backup_key_file.read()
|
||||
|
||||
revocation = self.network.send_and_receive_expected(
|
||||
acme.revocation_request(cert_der, key), "revocation")
|
||||
|
||||
display.generic_notification(
|
||||
"You have successfully revoked the certificate for "
|
||||
"%s" % cert["cn"], width=70, height=9)
|
||||
|
||||
self.remove_cert_key(cert)
|
||||
self.list_certs_keys()
|
||||
|
||||
return revocation
|
||||
|
||||
def list_certs_keys(self):
|
||||
"""List trusted Let's Encrypt certificates."""
|
||||
list_file = os.path.join(CONFIG.CERT_KEY_BACKUP, "LIST")
|
||||
certs = []
|
||||
|
||||
if not os.path.isfile(list_file):
|
||||
logging.info(
|
||||
"You don't have any certificates saved from letsencrypt")
|
||||
return
|
||||
|
||||
c_sha1_vh = {}
|
||||
for (cert, _, path) in self.installer.get_all_certs_keys():
|
||||
try:
|
||||
c_sha1_vh[M2Crypto.X509.load_cert(
|
||||
cert).get_fingerprint(md='sha1')] = path
|
||||
except:
|
||||
continue
|
||||
|
||||
with open(list_file, 'rb') as csvfile:
|
||||
csvreader = csv.reader(csvfile)
|
||||
for row in csvreader:
|
||||
cert = crypto_util.get_cert_info(row[1])
|
||||
|
||||
b_k = os.path.join(CONFIG.CERT_KEY_BACKUP,
|
||||
os.path.basename(row[2]) + "_" + row[0])
|
||||
b_c = os.path.join(CONFIG.CERT_KEY_BACKUP,
|
||||
os.path.basename(row[1]) + "_" + row[0])
|
||||
|
||||
cert.update({
|
||||
"orig_key_file": row[2],
|
||||
"orig_cert_file": row[1],
|
||||
"idx": int(row[0]),
|
||||
"backup_key_file": b_k,
|
||||
"backup_cert_file": b_c,
|
||||
"installed": c_sha1_vh.get(cert["fingerprint"], ""),
|
||||
})
|
||||
certs.append(cert)
|
||||
if certs:
|
||||
self.choose_certs(certs)
|
||||
else:
|
||||
display.generic_notification(
|
||||
"There are not any trusted Let's Encrypt "
|
||||
"certificates for this server.")
|
||||
|
||||
def choose_certs(self, certs):
|
||||
"""Display choose certificates menu.
|
||||
|
||||
:param list certs: List of cert dicts.
|
||||
|
||||
"""
|
||||
code, tag = display.display_certs(certs)
|
||||
|
||||
if code == display.OK:
|
||||
cert = certs[tag]
|
||||
if display.confirm_revocation(cert):
|
||||
self.acme_revocation(cert)
|
||||
else:
|
||||
self.choose_certs(certs)
|
||||
elif code == display.HELP:
|
||||
cert = certs[tag]
|
||||
display.more_info_cert(cert)
|
||||
self.choose_certs(certs)
|
||||
else:
|
||||
exit(0)
|
||||
|
||||
# pylint: disable=no-self-use
|
||||
def remove_cert_key(self, cert):
|
||||
"""Remove certificate and key.
|
||||
|
||||
:param dict cert: Cert dict used throughout revocation
|
||||
|
||||
"""
|
||||
list_file = os.path.join(CONFIG.CERT_KEY_BACKUP, "LIST")
|
||||
list_file2 = os.path.join(CONFIG.CERT_KEY_BACKUP, "LIST.tmp")
|
||||
|
||||
with open(list_file, 'rb') as orgfile:
|
||||
csvreader = csv.reader(orgfile)
|
||||
|
||||
with open(list_file2, 'wb') as newfile:
|
||||
csvwriter = csv.writer(newfile)
|
||||
|
||||
for row in csvreader:
|
||||
if not (row[0] == str(cert["idx"]) and
|
||||
row[1] == cert["orig_cert_file"] and
|
||||
row[2] == cert["orig_key_file"]):
|
||||
csvwriter.writerow(row)
|
||||
|
||||
shutil.copy2(list_file2, list_file)
|
||||
os.remove(list_file2)
|
||||
os.remove(cert["backup_cert_file"])
|
||||
os.remove(cert["backup_key_file"])
|
||||
+38
-38
@@ -11,7 +11,7 @@ from letsencrypt.client import display
|
||||
from letsencrypt.client import interfaces
|
||||
from letsencrypt.client import errors
|
||||
from letsencrypt.client import log
|
||||
|
||||
from letsencrypt.client import revoker
|
||||
from letsencrypt.client.apache import configurator
|
||||
|
||||
|
||||
@@ -65,9 +65,39 @@ def main():
|
||||
|
||||
# Set up logging
|
||||
logger = logging.getLogger()
|
||||
logger.setLevel(logging.INFO) # TODO: --log
|
||||
logger.setLevel(logging.INFO)
|
||||
if args.use_curses:
|
||||
logger.addHandler(log.DialogHandler())
|
||||
display.set_display(display.NcursesDisplay())
|
||||
else:
|
||||
display.set_display(display.FileDisplay(sys.stdout))
|
||||
|
||||
installer = determine_installer()
|
||||
server = args.server is None and CONFIG.ACME_SERVER or args.server
|
||||
|
||||
if args.revoke:
|
||||
revoc = revoker.Revoker(server, installer)
|
||||
revoc.list_certs_keys()
|
||||
sys.exit()
|
||||
|
||||
if args.rollback > 0:
|
||||
rollback(installer, args.rollback)
|
||||
sys.exit()
|
||||
|
||||
if args.view_checkpoints:
|
||||
view_checkpoints(installer)
|
||||
sys.exit()
|
||||
|
||||
# Use the same object if possible
|
||||
if interfaces.IAuthenticator.providedBy(installer):
|
||||
auth = installer
|
||||
else:
|
||||
auth = determine_authenticator()
|
||||
|
||||
if not args.eula:
|
||||
display_eula()
|
||||
|
||||
domains = choose_names(installer) if args.domains is None else args.domains
|
||||
|
||||
# Enforce '--privkey' is set along with '--csr'.
|
||||
if args.csr and not args.privkey:
|
||||
@@ -75,34 +105,6 @@ def main():
|
||||
"with the certificate signing request file (--csr)"
|
||||
.format(os.linesep))
|
||||
|
||||
if args.use_curses:
|
||||
display.set_display(display.NcursesDisplay())
|
||||
else:
|
||||
display.set_display(display.FileDisplay(sys.stdout))
|
||||
|
||||
if args.rollback > 0:
|
||||
rollback(configurator.ApacheConfigurator(), args.rollback)
|
||||
sys.exit()
|
||||
|
||||
if args.view_checkpoints:
|
||||
view_checkpoints(configurator.ApacheConfigurator())
|
||||
sys.exit()
|
||||
|
||||
server = args.server is None and CONFIG.ACME_SERVER or args.server
|
||||
|
||||
if not args.eula:
|
||||
display_eula()
|
||||
|
||||
auth = determine_authenticator()
|
||||
|
||||
# Use the same object if possible
|
||||
if interfaces.IInstaller.providedBy(auth):
|
||||
installer = auth
|
||||
else:
|
||||
installer = determine_installer()
|
||||
|
||||
domains = choose_names(installer) if args.domains is None else args.domains
|
||||
|
||||
# Prepare for init of Client
|
||||
if args.privkey is None:
|
||||
privkey = client.init_key()
|
||||
@@ -115,15 +117,13 @@ def main():
|
||||
client.Client.CSR(args.csr[0], args.csr[1], "pem"))
|
||||
|
||||
acme = client.Client(server, domains, privkey, auth, installer)
|
||||
if args.revoke:
|
||||
acme.list_certs_keys()
|
||||
else:
|
||||
# Validate the key and csr
|
||||
client.validate_key_csr(privkey, csr, domains)
|
||||
|
||||
cert_file, chain_file = acme.obtain_certificate(csr)
|
||||
vhost = acme.deploy_certificate(privkey, cert_file, chain_file)
|
||||
acme.optimize_config(vhost, args.redirect)
|
||||
# Validate the key and csr
|
||||
client.validate_key_csr(privkey, csr, domains)
|
||||
|
||||
cert_file, chain_file = acme.obtain_certificate(csr)
|
||||
vhost = acme.deploy_certificate(privkey, cert_file, chain_file)
|
||||
acme.optimize_config(vhost, args.redirect)
|
||||
|
||||
|
||||
def display_eula():
|
||||
|
||||
Reference in New Issue
Block a user