mirror of
https://github.com/certbot/certbot.git
synced 2026-08-01 02:44:21 +02:00
Readability improvements for storage.py
This commit is contained in:
+49
-37
@@ -69,10 +69,12 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes
|
|||||||
def consistent(self):
|
def consistent(self):
|
||||||
"""Is the structure of the archived files and links related to this
|
"""Is the structure of the archived files and links related to this
|
||||||
lineage correct and self-consistent?"""
|
lineage correct and self-consistent?"""
|
||||||
|
|
||||||
# Each element must be referenced with an absolute path
|
# Each element must be referenced with an absolute path
|
||||||
if any(not os.path.isabs(x) for x in
|
if any(not os.path.isabs(x) for x in
|
||||||
(self.cert, self.privkey, self.chain, self.fullchain)):
|
(self.cert, self.privkey, self.chain, self.fullchain)):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Each element must exist and be a symbolic link
|
# Each element must exist and be a symbolic link
|
||||||
if any(not os.path.islink(x) for x in
|
if any(not os.path.islink(x) for x in
|
||||||
(self.cert, self.privkey, self.chain, self.fullchain)):
|
(self.cert, self.privkey, self.chain, self.fullchain)):
|
||||||
@@ -83,6 +85,7 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes
|
|||||||
target = os.readlink(link)
|
target = os.readlink(link)
|
||||||
if not os.path.isabs(target):
|
if not os.path.isabs(target):
|
||||||
target = os.path.join(where, target)
|
target = os.path.join(where, target)
|
||||||
|
|
||||||
# Each element's link must point within the cert lineage's
|
# Each element's link must point within the cert lineage's
|
||||||
# directory within the official archive directory
|
# directory within the official archive directory
|
||||||
desired_directory = os.path.join(
|
desired_directory = os.path.join(
|
||||||
@@ -90,14 +93,17 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes
|
|||||||
if not os.path.samefile(os.path.dirname(target),
|
if not os.path.samefile(os.path.dirname(target),
|
||||||
desired_directory):
|
desired_directory):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# The link must point to a file that exists
|
# The link must point to a file that exists
|
||||||
if not os.path.exists(target):
|
if not os.path.exists(target):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# The link must point to a file that follows the archive
|
# The link must point to a file that follows the archive
|
||||||
# naming convention
|
# naming convention
|
||||||
pattern = re.compile(r"^{0}([0-9]+)\.pem$".format(kind))
|
pattern = re.compile(r"^{0}([0-9]+)\.pem$".format(kind))
|
||||||
if not pattern.match(os.path.basename(target)):
|
if not pattern.match(os.path.basename(target)):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# It is NOT required that the link's target be a regular
|
# It is NOT required that the link's target be a regular
|
||||||
# file (it may itself be a symlink). But we should probably
|
# file (it may itself be a symlink). But we should probably
|
||||||
# do a recursive check that ultimately the target does
|
# do a recursive check that ultimately the target does
|
||||||
@@ -109,8 +115,8 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes
|
|||||||
# XXX: All four of the targets are in the same directory
|
# XXX: All four of the targets are in the same directory
|
||||||
# (This check is redundant with the check that they
|
# (This check is redundant with the check that they
|
||||||
# are all in the desired directory!)
|
# are all in the desired directory!)
|
||||||
# len(set(os.path.basename(self.current_target(x)
|
# len(set(os.path.basename(self.current_target(x)
|
||||||
# for x in ALL_FOUR))) == 1
|
# for x in ALL_FOUR))) == 1
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def fix(self):
|
def fix(self):
|
||||||
@@ -299,9 +305,11 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes
|
|||||||
# XXX: both self.ocsp_revoked() and self.notafter() are bugs
|
# XXX: both self.ocsp_revoked() and self.notafter() are bugs
|
||||||
# here because we should be looking at the latest version, not
|
# here because we should be looking at the latest version, not
|
||||||
# the current version!
|
# the current version!
|
||||||
|
|
||||||
# Renewals on the basis of revocation
|
# Renewals on the basis of revocation
|
||||||
if self.ocsp_revoked():
|
if self.ocsp_revoked():
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# Renewals on the basis of expiry time
|
# Renewals on the basis of expiry time
|
||||||
interval = self.configuration.get("renew_before_expiry", "10 days")
|
interval = self.configuration.get("renew_before_expiry", "10 days")
|
||||||
autorenew_interval = parse_time_interval(interval)
|
autorenew_interval = parse_time_interval(interval)
|
||||||
@@ -326,6 +334,8 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes
|
|||||||
Returns a new RenewableCert object referring to the created
|
Returns a new RenewableCert object referring to the created
|
||||||
lineage. (The actual lineage name, as well as all the relevant
|
lineage. (The actual lineage name, as well as all the relevant
|
||||||
file paths, will be available within this object.)"""
|
file paths, will be available within this object.)"""
|
||||||
|
|
||||||
|
# Examine the configuration and find the new lineage's name
|
||||||
configs_dir = config["renewal_configs_dir"]
|
configs_dir = config["renewal_configs_dir"]
|
||||||
archive_dir = config["official_archive_dir"]
|
archive_dir = config["official_archive_dir"]
|
||||||
live_dir = config["live_dir"]
|
live_dir = config["live_dir"]
|
||||||
@@ -336,7 +346,9 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes
|
|||||||
lineagename)
|
lineagename)
|
||||||
if not config_filename.endswith(".conf"):
|
if not config_filename.endswith(".conf"):
|
||||||
raise ValueError("renewal config file name must end in .conf")
|
raise ValueError("renewal config file name must end in .conf")
|
||||||
# lineagename will now potentially be modified based on what
|
|
||||||
|
# Determine where on disk everything will go
|
||||||
|
# lineagename will now potentially be modified based on which
|
||||||
# renewal configuration file could actually be created
|
# renewal configuration file could actually be created
|
||||||
lineagename = os.path.basename(config_filename)[:-len(".conf")]
|
lineagename = os.path.basename(config_filename)[:-len(".conf")]
|
||||||
archive = os.path.join(archive_dir, lineagename)
|
archive = os.path.join(archive_dir, lineagename)
|
||||||
@@ -348,33 +360,28 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes
|
|||||||
os.mkdir(archive)
|
os.mkdir(archive)
|
||||||
os.mkdir(live_dir)
|
os.mkdir(live_dir)
|
||||||
relative_archive = os.path.join("..", "..", "archive", lineagename)
|
relative_archive = os.path.join("..", "..", "archive", lineagename)
|
||||||
cert_target = os.path.join(live_dir, "cert.pem")
|
|
||||||
privkey_target = os.path.join(live_dir, "privkey.pem")
|
# Put the data into the appropriate files on disk
|
||||||
chain_target = os.path.join(live_dir, "chain.pem")
|
target = dict([(kind, os.path.join(live_dir, kind + ".pem"))
|
||||||
fullchain_target = os.path.join(live_dir, "fullchain.pem")
|
for kind in ALL_FOUR])
|
||||||
os.symlink(os.path.join(relative_archive, "cert1.pem"),
|
for kind in ALL_FOUR:
|
||||||
cert_target)
|
os.symlink(os.path.join(relative_archive, kind + "1.pem"),
|
||||||
os.symlink(os.path.join(relative_archive, "privkey1.pem"),
|
target[kind])
|
||||||
privkey_target)
|
with open(target["cert"], "w") as f:
|
||||||
os.symlink(os.path.join(relative_archive, "chain1.pem"),
|
|
||||||
chain_target)
|
|
||||||
os.symlink(os.path.join(relative_archive, "fullchain1.pem"),
|
|
||||||
fullchain_target)
|
|
||||||
with open(cert_target, "w") as f:
|
|
||||||
f.write(cert)
|
f.write(cert)
|
||||||
with open(privkey_target, "w") as f:
|
with open(target["privkey"], "w") as f:
|
||||||
f.write(privkey)
|
f.write(privkey)
|
||||||
# XXX: Let's make sure to get the file permissions right here
|
# XXX: Let's make sure to get the file permissions right here
|
||||||
with open(chain_target, "w") as f:
|
with open(target["chain"], "w") as f:
|
||||||
f.write(chain)
|
f.write(chain)
|
||||||
with open(fullchain_target, "w") as f:
|
with open(target["fullchain"], "w") as f:
|
||||||
f.write(cert + chain)
|
f.write(cert + chain)
|
||||||
|
|
||||||
|
# Document what we've done in a new renewal config file
|
||||||
config_file.close()
|
config_file.close()
|
||||||
new_config = configobj.ConfigObj(config_filename, create_empty=True)
|
new_config = configobj.ConfigObj(config_filename, create_empty=True)
|
||||||
new_config["cert"] = cert_target
|
for kind in ALL_FOUR:
|
||||||
new_config["privkey"] = privkey_target
|
new_config[kind] = target[kind]
|
||||||
new_config["chain"] = chain_target
|
|
||||||
new_config["fullchain"] = fullchain_target
|
|
||||||
if renewalparams:
|
if renewalparams:
|
||||||
new_config["renewalparams"] = renewalparams
|
new_config["renewalparams"] = renewalparams
|
||||||
new_config.comments["renewalparams"] = ["",
|
new_config.comments["renewalparams"] = ["",
|
||||||
@@ -385,6 +392,7 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes
|
|||||||
new_config.write()
|
new_config.write()
|
||||||
return cls(new_config, config)
|
return cls(new_config, config)
|
||||||
|
|
||||||
|
|
||||||
def save_successor(self, prior_version, new_cert, new_privkey, new_chain):
|
def save_successor(self, prior_version, new_cert, new_privkey, new_chain):
|
||||||
"""Save a new cert and chain as a successor of a specific prior
|
"""Save a new cert and chain as a successor of a specific prior
|
||||||
version in this lineage. Returns the new version number that was
|
version in this lineage. Returns the new version number that was
|
||||||
@@ -393,19 +401,19 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes
|
|||||||
# XXX: consider using os.open for availablity of os.O_EXCL
|
# XXX: consider using os.open for availablity of os.O_EXCL
|
||||||
# XXX: ensure file permissions are correct; also create directories
|
# XXX: ensure file permissions are correct; also create directories
|
||||||
# if needed (ensuring their permissions are correct)
|
# if needed (ensuring their permissions are correct)
|
||||||
|
# Figure out what the new version is and hence where to save things
|
||||||
|
|
||||||
target_version = self.next_free_version()
|
target_version = self.next_free_version()
|
||||||
archive = self.configuration["official_archive_dir"]
|
archive = self.configuration["official_archive_dir"]
|
||||||
prefix = os.path.join(archive, self.lineagename)
|
prefix = os.path.join(archive, self.lineagename)
|
||||||
cert_target = os.path.join(
|
target = dict(
|
||||||
prefix, "cert{0}.pem".format(target_version))
|
[(kind,
|
||||||
privkey_target = os.path.join(
|
os.path.join(prefix, "{0}{1}.pem".format(kind, target_version)))
|
||||||
prefix, "privkey{0}.pem".format(target_version))
|
for kind in ALL_FOUR])
|
||||||
chain_target = os.path.join(
|
|
||||||
prefix, "chain{0}.pem".format(target_version))
|
# Distinguish the cases where the privkey has changed and where it
|
||||||
fullchain_target = os.path.join(
|
# has not changed (in the latter case, making an appropriate symlink
|
||||||
prefix, "fullchain{0}.pem".format(target_version))
|
# to an earlier privkey version)
|
||||||
with open(cert_target, "w") as f:
|
|
||||||
f.write(new_cert)
|
|
||||||
if new_privkey is None:
|
if new_privkey is None:
|
||||||
# The behavior below keeps the prior key by creating a new
|
# The behavior below keeps the prior key by creating a new
|
||||||
# symlink to the old key or the target of the old key symlink.
|
# symlink to the old key or the target of the old key symlink.
|
||||||
@@ -415,12 +423,16 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes
|
|||||||
old_privkey = os.readlink(old_privkey)
|
old_privkey = os.readlink(old_privkey)
|
||||||
else:
|
else:
|
||||||
old_privkey = "privkey{0}.pem".format(prior_version)
|
old_privkey = "privkey{0}.pem".format(prior_version)
|
||||||
os.symlink(old_privkey, privkey_target)
|
os.symlink(old_privkey, target["privkey"])
|
||||||
else:
|
else:
|
||||||
with open(privkey_target, "w") as f:
|
with open(target["privkey"], "w") as f:
|
||||||
f.write(new_privkey)
|
f.write(new_privkey)
|
||||||
with open(chain_target, "w") as f:
|
|
||||||
|
# Save everything else
|
||||||
|
with open(target["cert"], "w") as f:
|
||||||
|
f.write(new_cert)
|
||||||
|
with open(target["chain"], "w") as f:
|
||||||
f.write(new_chain)
|
f.write(new_chain)
|
||||||
with open(fullchain_target, "w") as f:
|
with open(target["fullchain"], "w") as f:
|
||||||
f.write(new_cert + new_chain)
|
f.write(new_cert + new_chain)
|
||||||
return target_version
|
return target_version
|
||||||
|
|||||||
Reference in New Issue
Block a user