def new_lineage(cls, lineagename, cert, privkey, chain, renewalparams=None, config=None, cli_config=None): # pylint: disable=too-many-locals,too-many-arguments """Create a new certificate lineage. Attempts to create a certificate lineage -- enrolled for potential future renewal -- with the (suggested) lineage name lineagename, and the associated cert, privkey, and chain (the associated fullchain will be created automatically). Optional configurator and renewalparams record the configuration that was originally used to obtain this cert, so that it can be reused later during automated renewal. Returns a new RenewableCert object referring to the created lineage. (The actual lineage name, as well as all the relevant file paths, will be available within this object.) :param str lineagename: the suggested name for this lineage (normally the current cert's first subject DNS name) :param str cert: the initial certificate version in PEM format :param str privkey: the private key in PEM format :param str chain: the certificate chain in PEM format :param configobj.ConfigObj renewalparams: parameters that should be used when instantiating authenticator and installer objects in the future to attempt to renew this cert or deploy new versions of it :param configobj.ConfigObj config: renewal configuration defaults, affecting, for example, the locations of the directories where the associated files will be saved :returns: the newly-created RenewalCert object :rtype: :class:`storage.renewableCert`""" config = config_with_defaults(config) # This attempts to read the renewer config file and augment or replace # the renewer defaults with any options contained in that file. If # renewer_config_file is undefined or if the file is nonexistent or # empty, this .merge() will have no effect. config.merge(configobj.ConfigObj(cli_config.renewer_config_file)) # Examine the configuration and find the new lineage's name for i in (cli_config.renewal_configs_dir, cli_config.archive_dir, cli_config.live_dir): if not os.path.exists(i): os.makedirs(i, 0700) config_file, config_filename = le_util.unique_lineage_name( cli_config.renewal_configs_dir, lineagename) if not config_filename.endswith(".conf"): raise errors.CertStorageError( "renewal config file name must end in .conf") # Determine where on disk everything will go # lineagename will now potentially be modified based on which # renewal configuration file could actually be created lineagename = os.path.basename(config_filename)[:-len(".conf")] archive = os.path.join(cli_config.archive_dir, lineagename) live_dir = os.path.join(cli_config.live_dir, lineagename) if os.path.exists(archive): raise errors.CertStorageError( "archive directory exists for " + lineagename) if os.path.exists(live_dir): raise errors.CertStorageError( "live directory exists for " + lineagename) os.mkdir(archive) os.mkdir(live_dir) relative_archive = os.path.join("..", "..", "archive", lineagename) # Put the data into the appropriate files on disk target = dict([(kind, os.path.join(live_dir, kind + ".pem")) for kind in ALL_FOUR]) for kind in ALL_FOUR: os.symlink(os.path.join(relative_archive, kind + "1.pem"), target[kind]) with open(target["cert"], "w") as f: f.write(cert) with open(target["privkey"], "w") as f: f.write(privkey) # XXX: Let's make sure to get the file permissions right here with open(target["chain"], "w") as f: f.write(chain) with open(target["fullchain"], "w") as f: # assumes that OpenSSL.crypto.dump_certificate includes # ending newline character f.write(cert + chain) # Document what we've done in a new renewal config file config_file.close() new_config = configobj.ConfigObj(config_filename, create_empty=True) for kind in ALL_FOUR: new_config[kind] = target[kind] if renewalparams: new_config["renewalparams"] = renewalparams new_config.comments["renewalparams"] = ["", "Options and defaults used" " in the renewal process"] # TODO: add human-readable comments explaining other available # parameters new_config.write() return cls(new_config, config, cli_config)
def _call(self, filename, mode=0o777): from letsencrypt.le_util import unique_lineage_name return unique_lineage_name(self.root_path, filename, mode)
def new_lineage(cls, lineagename, cert, privkey, chain, cli_config): # pylint: disable=too-many-locals """Create a new certificate lineage. Attempts to create a certificate lineage -- enrolled for potential future renewal -- with the (suggested) lineage name lineagename, and the associated cert, privkey, and chain (the associated fullchain will be created automatically). Optional configurator and renewalparams record the configuration that was originally used to obtain this cert, so that it can be reused later during automated renewal. Returns a new RenewableCert object referring to the created lineage. (The actual lineage name, as well as all the relevant file paths, will be available within this object.) :param str lineagename: the suggested name for this lineage (normally the current cert's first subject DNS name) :param str cert: the initial certificate version in PEM format :param str privkey: the private key in PEM format :param str chain: the certificate chain in PEM format :param .RenewerConfiguration cli_config: parsed command line arguments :returns: the newly-created RenewalCert object :rtype: :class:`storage.renewableCert` """ # Examine the configuration and find the new lineage's name for i in (cli_config.renewal_configs_dir, cli_config.archive_dir, cli_config.live_dir): if not os.path.exists(i): os.makedirs(i, 0o700) logger.debug("Creating directory %s.", i) config_file, config_filename = le_util.unique_lineage_name( cli_config.renewal_configs_dir, lineagename) if not config_filename.endswith(".conf"): raise errors.CertStorageError( "renewal config file name must end in .conf") # Determine where on disk everything will go # lineagename will now potentially be modified based on which # renewal configuration file could actually be created lineagename = os.path.basename(config_filename)[:-len(".conf")] archive = os.path.join(cli_config.archive_dir, lineagename) live_dir = os.path.join(cli_config.live_dir, lineagename) if os.path.exists(archive): raise errors.CertStorageError( "archive directory exists for " + lineagename) if os.path.exists(live_dir): raise errors.CertStorageError( "live directory exists for " + lineagename) os.mkdir(archive) os.mkdir(live_dir) logger.debug("Archive directory %s and live " "directory %s created.", archive, live_dir) relative_archive = os.path.join("..", "..", "archive", lineagename) # Put the data into the appropriate files on disk target = dict([(kind, os.path.join(live_dir, kind + ".pem")) for kind in ALL_FOUR]) for kind in ALL_FOUR: os.symlink(os.path.join(relative_archive, kind + "1.pem"), target[kind]) with open(target["cert"], "w") as f: logger.debug("Writing certificate to %s.", target["cert"]) f.write(cert) with open(target["privkey"], "w") as f: logger.debug("Writing private key to %s.", target["privkey"]) f.write(privkey) # XXX: Let's make sure to get the file permissions right here with open(target["chain"], "w") as f: logger.debug("Writing chain to %s.", target["chain"]) f.write(chain) with open(target["fullchain"], "w") as f: # assumes that OpenSSL.crypto.dump_certificate includes # ending newline character logger.debug("Writing full chain to %s.", target["fullchain"]) f.write(cert + chain) # Document what we've done in a new renewal config file config_file.close() # Save only the config items that are relevant to renewal values = relevant_values(vars(cli_config.namespace)) new_config = write_renewal_config(config_filename, target, values) return cls(new_config.filename, cli_config)
def new_lineage(cls, lineagename, cert, privkey, chain, cli_config): # pylint: disable=too-many-locals """Create a new certificate lineage. Attempts to create a certificate lineage -- enrolled for potential future renewal -- with the (suggested) lineage name lineagename, and the associated cert, privkey, and chain (the associated fullchain will be created automatically). Optional configurator and renewalparams record the configuration that was originally used to obtain this cert, so that it can be reused later during automated renewal. Returns a new RenewableCert object referring to the created lineage. (The actual lineage name, as well as all the relevant file paths, will be available within this object.) :param str lineagename: the suggested name for this lineage (normally the current cert's first subject DNS name) :param str cert: the initial certificate version in PEM format :param str privkey: the private key in PEM format :param str chain: the certificate chain in PEM format :param .RenewerConfiguration cli_config: parsed command line arguments :returns: the newly-created RenewalCert object :rtype: :class:`storage.renewableCert` """ # Examine the configuration and find the new lineage's name for i in (cli_config.renewal_configs_dir, cli_config.archive_dir, cli_config.live_dir): if not os.path.exists(i): os.makedirs(i, 0700) logger.debug("Creating directory %s.", i) config_file, config_filename = le_util.unique_lineage_name( cli_config.renewal_configs_dir, lineagename) if not config_filename.endswith(".conf"): raise errors.CertStorageError( "renewal config file name must end in .conf") # Determine where on disk everything will go # lineagename will now potentially be modified based on which # renewal configuration file could actually be created lineagename = os.path.basename(config_filename)[:-len(".conf")] archive = os.path.join(cli_config.archive_dir, lineagename) live_dir = os.path.join(cli_config.live_dir, lineagename) if os.path.exists(archive): raise errors.CertStorageError( "archive directory exists for " + lineagename) if os.path.exists(live_dir): raise errors.CertStorageError( "live directory exists for " + lineagename) os.mkdir(archive) os.mkdir(live_dir) logger.debug("Archive directory %s and live " "directory %s created.", archive, live_dir) relative_archive = os.path.join("..", "..", "archive", lineagename) # Put the data into the appropriate files on disk target = dict([(kind, os.path.join(live_dir, kind + ".pem")) for kind in ALL_FOUR]) for kind in ALL_FOUR: os.symlink(os.path.join(relative_archive, kind + "1.pem"), target[kind]) with open(target["cert"], "w") as f: logger.debug("Writing certificate to %s.", target["cert"]) f.write(cert) with open(target["privkey"], "w") as f: logger.debug("Writing private key to %s.", target["privkey"]) f.write(privkey) # XXX: Let's make sure to get the file permissions right here with open(target["chain"], "w") as f: logger.debug("Writing chain to %s.", target["chain"]) f.write(chain) with open(target["fullchain"], "w") as f: # assumes that OpenSSL.crypto.dump_certificate includes # ending newline character logger.debug("Writing full chain to %s.", target["fullchain"]) f.write(cert + chain) # Document what we've done in a new renewal config file config_file.close() new_config = write_renewal_config(config_filename, target, cli_config) return cls(new_config.filename, cli_config)
def new_lineage(cls, lineagename, cert, privkey, chain, renewalparams=None, config=None, cli_config=None): # pylint: disable=too-many-locals,too-many-arguments """Create a new certificate lineage. Attempts to create a certificate lineage -- enrolled for potential future renewal -- with the (suggested) lineage name lineagename, and the associated cert, privkey, and chain (the associated fullchain will be created automatically). Optional configurator and renewalparams record the configuration that was originally used to obtain this cert, so that it can be reused later during automated renewal. Returns a new RenewableCert object referring to the created lineage. (The actual lineage name, as well as all the relevant file paths, will be available within this object.) :param str lineagename: the suggested name for this lineage (normally the current cert's first subject DNS name) :param str cert: the initial certificate version in PEM format :param str privkey: the private key in PEM format :param str chain: the certificate chain in PEM format :param configobj.ConfigObj renewalparams: parameters that should be used when instantiating authenticator and installer objects in the future to attempt to renew this cert or deploy new versions of it :param configobj.ConfigObj config: renewal configuration defaults, affecting, for example, the locations of the directories where the associated files will be saved :param .RenewerConfiguration cli_config: parsed command line arguments :returns: the newly-created RenewalCert object :rtype: :class:`storage.renewableCert`""" config = config_with_defaults(config) # This attempts to read the renewer config file and augment or replace # the renewer defaults with any options contained in that file. If # renewer_config_file is undefined or if the file is nonexistent or # empty, this .merge() will have no effect. config.merge(configobj.ConfigObj(cli_config.renewer_config_file)) # Examine the configuration and find the new lineage's name for i in (cli_config.renewal_configs_dir, cli_config.archive_dir, cli_config.live_dir): if not os.path.exists(i): os.makedirs(i, 0700) config_file, config_filename = le_util.unique_lineage_name( cli_config.renewal_configs_dir, lineagename) if not config_filename.endswith(".conf"): raise errors.CertStorageError( "renewal config file name must end in .conf") # Determine where on disk everything will go # lineagename will now potentially be modified based on which # renewal configuration file could actually be created lineagename = os.path.basename(config_filename)[:-len(".conf")] archive = os.path.join(cli_config.archive_dir, lineagename) live_dir = os.path.join(cli_config.live_dir, lineagename) if os.path.exists(archive): raise errors.CertStorageError("archive directory exists for " + lineagename) if os.path.exists(live_dir): raise errors.CertStorageError("live directory exists for " + lineagename) os.mkdir(archive) os.mkdir(live_dir) relative_archive = os.path.join("..", "..", "archive", lineagename) # Put the data into the appropriate files on disk target = dict([(kind, os.path.join(live_dir, kind + ".pem")) for kind in ALL_FOUR]) for kind in ALL_FOUR: os.symlink(os.path.join(relative_archive, kind + "1.pem"), target[kind]) with open(target["cert"], "w") as f: f.write(cert) with open(target["privkey"], "w") as f: f.write(privkey) # XXX: Let's make sure to get the file permissions right here with open(target["chain"], "w") as f: f.write(chain) with open(target["fullchain"], "w") as f: # assumes that OpenSSL.crypto.dump_certificate includes # ending newline character f.write(cert + chain) # Document what we've done in a new renewal config file config_file.close() new_config = configobj.ConfigObj(config_filename, create_empty=True) for kind in ALL_FOUR: new_config[kind] = target[kind] if renewalparams: new_config["renewalparams"] = renewalparams new_config.comments["renewalparams"] = [ "", "Options and defaults used" " in the renewal process" ] # TODO: add human-readable comments explaining other available # parameters new_config.write() return cls(new_config.filename, cli_config)
def new_lineage(cls, lineagename, cert, privkey, chain, renewalparams=None, config=None, cli_config=None): # pylint: disable=too-many-locals,too-many-arguments """Create a new certificate lineage. Attempts to create a certificate lineage -- enrolled for potential future renewal -- with the (suggested) lineage name lineagename, and the associated cert, privkey, and chain (the associated fullchain will be created automatically). Optional configurator and renewalparams record the configuration that was originally used to obtain this cert, so that it can be reused later during automated renewal. Returns a new RenewableCert object referring to the created lineage. (The actual lineage name, as well as all the relevant file paths, will be available within this object.) :param str lineagename: the suggested name for this lineage (normally the current cert's first subject DNS name) :param str cert: the initial certificate version in PEM format :param str privkey: the private key in PEM format :param str chain: the certificate chain in PEM format :param configobj.ConfigObj renewalparams: parameters that should be used when instantiating authenticator and installer objects in the future to attempt to renew this cert or deploy new versions of it :param configobj.ConfigObj config: renewal configuration defaults, affecting, for example, the locations of the directories where the associated files will be saved :param .RenewerConfiguration cli_config: parsed command line arguments :returns: the newly-created RenewalCert object :rtype: :class:`storage.renewableCert`""" config = config_with_defaults(config) # This attempts to read the renewer config file and augment or replace # the renewer defaults with any options contained in that file. If # renewer_config_file is undefined or if the file is nonexistent or # empty, this .merge() will have no effect. config.merge(configobj.ConfigObj(cli_config.renewer_config_file)) # Examine the configuration and find the new lineage's name for i in (cli_config.renewal_configs_dir, cli_config.archive_dir, cli_config.live_dir): if not os.path.exists(i): os.makedirs(i, 0700) logger.debug("Creating directory %s.", i) config_file, config_filename = le_util.unique_lineage_name(cli_config.renewal_configs_dir, lineagename) if not config_filename.endswith(".conf"): raise errors.CertStorageError("renewal config file name must end in .conf") # Determine where on disk everything will go # lineagename will now potentially be modified based on which # renewal configuration file could actually be created lineagename = os.path.basename(config_filename)[: -len(".conf")] archive = os.path.join(cli_config.archive_dir, lineagename) live_dir = os.path.join(cli_config.live_dir, lineagename) if os.path.exists(archive): raise errors.CertStorageError("archive directory exists for " + lineagename) if os.path.exists(live_dir): raise errors.CertStorageError("live directory exists for " + lineagename) os.mkdir(archive) os.mkdir(live_dir) logger.debug("Archive directory %s and live " "directory %s created.", archive, live_dir) relative_archive = os.path.join("..", "..", "archive", lineagename) # Put the data into the appropriate files on disk target = dict([(kind, os.path.join(live_dir, kind + ".pem")) for kind in ALL_FOUR]) for kind in ALL_FOUR: os.symlink(os.path.join(relative_archive, kind + "1.pem"), target[kind]) with open(target["cert"], "w") as f: logger.debug("Writing certificate to %s.", target["cert"]) f.write(cert) with os.fdopen(os.open(target["privkey"], os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0600), "w") as f: logger.debug("Writing private key to %s.", target["privkey"]) f.write(privkey)