From 7120ecb30f6cefa30e4e9514a789d4e64ab12b68 Mon Sep 17 00:00:00 2001 From: William Brown Date: Jan 28 2020 02:58:06 +0000 Subject: Ticket 50694 - import PEM certs on startup Bug Description: To make container setup easier, given TLS material in defined locations we should convert these into a functional nssdb Fix Description: Provided that we have: * /data/config/pwdfile.txt * /data/tls/server.key * /data/tls/server.crt * /data/tls/ca/*.crt There are imported into the nssdb as such: /data/tls/ca/ca.crt C,, Server-Cert u,u,u This works on restarts, changes of keys, etc. IE to replace these, just change out the pem files, and restart, and we "do the right thing". Importantly, this will allow a much easier deployment of containerised 389-ds with let's encrypt! https://pagure.io/389-ds-base/issue/50694 Author: William Brown Review by: mreynolds, mhonek (thanks) --- diff --git a/src/lib389/cli/dscontainer b/src/lib389/cli/dscontainer index 7bea9ba..7117637 100755 --- a/src/lib389/cli/dscontainer +++ b/src/lib389/cli/dscontainer @@ -40,8 +40,15 @@ from lib389.cli_base import setup_script_logger from lib389.instance.setup import SetupDs from lib389.instance.options import General2Base, Slapd2Base from lib389.passwd import password_generate +from lib389.nss_ssl import NssSsl, CERT_NAME from lib389.paths import Paths -from lib389._constants import DSRC_CONTAINER +from lib389._constants import ( + DSRC_CONTAINER, + CONTAINER_TLS_SERVER_KEY, + CONTAINER_TLS_SERVER_CERT, + CONTAINER_TLS_SERVER_CADIR, + CONTAINER_TLS_PWDFILE +) from lib389.idm.directorymanager import DirectoryManager @@ -77,6 +84,47 @@ def _begin_environment_config(): inst.close() +def _begin_setup_pem_tls(): + # If we have the needed files, we can use them. + # + # We need at least: + # * 1 ca in the ca's folder + # * the server.key + # * the server.crt + # + # Optional future idea: we have many ca's in ca folder + log.info("Checking for PEM TLS files ...") + have_atleast_ca = False + have_server_key = os.path.exists(CONTAINER_TLS_SERVER_KEY) + have_server_cert = os.path.exists(CONTAINER_TLS_SERVER_CERT) + have_pwdfile = os.path.exists(CONTAINER_TLS_PWDFILE) + if os.path.exists(CONTAINER_TLS_SERVER_CADIR) and os.path.isdir(CONTAINER_TLS_SERVER_CADIR): + cas = [ca for ca in os.listdir(CONTAINER_TLS_SERVER_CADIR) if ca.endswith('.crt')] + log.info("Found -> %s" % cas) + have_atleast_ca = len(cas) > 0 + log.info("Have %s -> %s" % (CONTAINER_TLS_SERVER_KEY, have_server_key)) + log.info("Have %s -> %s" % (CONTAINER_TLS_SERVER_CERT, have_server_cert)) + log.info("Have %s -> %s" % (CONTAINER_TLS_SERVER_CADIR, have_atleast_ca)) + log.info("Have %s -> %s" % (CONTAINER_TLS_PWDFILE, have_pwdfile)) + + if not (have_atleast_ca and have_server_key and have_server_cert and have_pwdfile): + log.info("Unable to configure TLS from PEM, missing a required file.") + return + log.info("TLS PEM requirements met - configuring NSSDB ...") + inst = _gen_instance() + tls = NssSsl(dirsrv=inst) + # First, remove the existing server-cert. + tls.del_cert(CERT_NAME) + # Import the ca's + for ca_path in [os.path.join(CONTAINER_TLS_SERVER_CADIR, ca) for ca in cas]: + log.info("Enrolling -> %s" % ca_path) + tls.add_cert(nickname=ca_path, input_file=ca_path) + tls.edit_cert_trust(ca_path, "C,,") + # Import the new server-cert + tls.add_server_key_and_cert(CONTAINER_TLS_SERVER_KEY, CONTAINER_TLS_SERVER_CERT) + # Done! + log.info("TLS PEM configuration complete.") + def _begin_check_reindex(): if os.getenv('DS_REINDEX', None) is not None: log.info("Reindexing database. This may take a while ...") @@ -210,6 +258,9 @@ binddn = cn=Directory Manager """) os.chmod(DSRC_CONTAINER, 0o755) + # Setup TLS from PEM files as required. + _begin_setup_pem_tls() + # If we have been requested to re-index, do so now ... _begin_check_reindex() diff --git a/src/lib389/lib389/_constants.py b/src/lib389/lib389/_constants.py index 5c9b90a..4037770 100644 --- a/src/lib389/lib389/_constants.py +++ b/src/lib389/lib389/_constants.py @@ -349,3 +349,8 @@ args_dse_keys = SER_PROPNAME_TO_ATTRNAME DSRC_HOME = '~/.dsrc' DSRC_CONTAINER = '/data/config/container.inf' + +CONTAINER_TLS_SERVER_KEY = '/data/tls/server.key' +CONTAINER_TLS_SERVER_CERT = '/data/tls/server.crt' +CONTAINER_TLS_SERVER_CADIR = '/data/tls/ca' +CONTAINER_TLS_PWDFILE = '/data/config/pwdfile.txt'