diff options
24 files changed, 347 insertions, 431 deletions
diff --git a/install/certmonger/dogtag-ipa-ca-renew-agent-submit b/install/certmonger/dogtag-ipa-ca-renew-agent-submit index 2e67c7e5a..cc690b8fa 100755 --- a/install/certmonger/dogtag-ipa-ca-renew-agent-submit +++ b/install/certmonger/dogtag-ipa-ca-renew-agent-submit @@ -217,10 +217,12 @@ def request_cert(): syslog.syslog(syslog.LOG_NOTICE, "Forwarding request to dogtag-ipa-renew-agent") - path = paths.DOGTAG_IPA_RENEW_AGENT_SUBMIT - args = [path, '--dbdir', paths.IPA_RADB_DIR] - args.extend(sys.argv[1:]) - args.extend(['--submit-option', "requestor_name=IPA"]) + args = ([paths.DOGTAG_IPA_RENEW_AGENT_SUBMIT, + "--cafile", paths.IPA_CA_CRT, + "--certfile", paths.RA_AGENT_PEM, + "--keyfile", paths.RA_AGENT_KEY] + + sys.argv[1:] + + ['--submit-option', "requestor_name=IPA"]) if os.environ.get('CERTMONGER_CA_PROFILE') == 'caCACert': args += ['-N', '-O', 'bypassCAnotafter=true'] result = ipautil.run(args, raiseonerr=False, env=os.environ, diff --git a/install/restart_scripts/renew_ra_cert b/install/restart_scripts/renew_ra_cert index 4dc6c2e4f..5c71d5791 100644 --- a/install/restart_scripts/renew_ra_cert +++ b/install/restart_scripts/renew_ra_cert @@ -27,15 +27,15 @@ import tempfile import shutil import traceback +from cryptography.hazmat.primitives import serialization + from ipalib.install.kinit import kinit_keytab -from ipalib import api -from ipaserver.install import certs, cainstance, dogtaginstance +from ipalib import api, x509 +from ipaserver.install import certs, cainstance from ipaplatform.paths import paths def _main(): - nickname = 'ipaCert' - api.bootstrap(in_server=True, context='restart', confdir=paths.ETC_IPA) api.finalize() api.Backend.ldap2.connect() @@ -48,20 +48,28 @@ def _main(): os.environ['KRB5CCNAME'] = ccache_filename ca = cainstance.CAInstance(host_name=api.env.host) + ra_certpath = paths.RA_AGENT_PEM if ca.is_renewal_master(): # Fetch the new certificate - db = certs.CertDB(api.env.realm) - dercert = db.get_cert_from_db(nickname, pem=False) - if not dercert: + try: + cert = x509.load_certificate_from_file(ra_certpath) + except IOError as e: + syslog.syslog( + syslog.LOG_ERR, "Can't open '{certpath}': {err}" + .format(certpath=ra_certpath, err=e) + ) + sys.exit(1) + except (TypeError, ValueError): syslog.syslog( - syslog.LOG_ERR, "No certificate %s found." % nickname) + syslog.LOG_ERR, "'{certpath}' is not a valid certificate " + "file".format(certpath=ra_certpath) + ) sys.exit(1) + dercert = cert.public_bytes(serialization.Encoding.DER) + # Load it into dogtag cainstance.update_people_entry(dercert) - - if api.Command.kra_is_enabled()['result']: - dogtaginstance.export_ra_agent_pem() finally: shutil.rmtree(tmpdir) api.Backend.ldap2.disconnect() diff --git a/ipaclient/install/ipa_certupdate.py b/ipaclient/install/ipa_certupdate.py index ec22594f8..75c5d97df 100644 --- a/ipaclient/install/ipa_certupdate.py +++ b/ipaclient/install/ipa_certupdate.py @@ -139,7 +139,6 @@ class CertUpdate(admintool.AdminTool): services.knownservices.dirsrv.restart(instance) self.update_db(paths.HTTPD_ALIAS_DIR, certs) - self.update_db(paths.IPA_RADB_DIR, certs) if services.knownservices.httpd.is_running(): services.knownservices.httpd.restart() diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py index d89f1a7f1..e4d4f2edc 100644 --- a/ipaplatform/base/paths.py +++ b/ipaplatform/base/paths.py @@ -40,7 +40,6 @@ class BasePathNamespace(object): ETC_HTTPD_DIR = "/etc/httpd" HTTPD_ALIAS_DIR = "/etc/httpd/alias" OLD_KRA_AGENT_PEM = "/etc/httpd/alias/kra-agent.pem" - IPA_RADB_DIR = "/var/lib/ipa/radb" HTTPD_CONF_D_DIR = "/etc/httpd/conf.d/" HTTPD_IPA_KDCPROXY_CONF = "/etc/ipa/kdcproxy/ipa-kdc-proxy.conf" HTTPD_IPA_KDCPROXY_CONF_SYMLINK = "/etc/httpd/conf.d/ipa-kdc-proxy.conf" @@ -140,6 +139,7 @@ class BasePathNamespace(object): ROOT_PKI = "/root/.pki" DOGTAG_ADMIN_P12 = "/root/ca-agent.p12" RA_AGENT_PEM = "/var/lib/ipa/ra-agent.pem" + RA_AGENT_KEY = "/var/lib/ipa/ra-agent.key" CACERT_P12 = "/root/cacert.p12" ROOT_IPA_CSR = "/root/ipa.csr" NAMED_PID = "/run/named/named.pid" @@ -195,6 +195,7 @@ class BasePathNamespace(object): PAM_KRB5_SO_64 = "/usr/lib64/security/pam_krb5.so" DOGTAG_IPA_CA_RENEW_AGENT_SUBMIT = "/usr/libexec/certmonger/dogtag-ipa-ca-renew-agent-submit" DOGTAG_IPA_RENEW_AGENT_SUBMIT = "/usr/libexec/certmonger/dogtag-ipa-renew-agent-submit" + CERTMONGER_DOGTAG_SUBMIT = "/usr/libexec/certmonger/dogtag-submit" IPA_SERVER_GUARD = "/usr/libexec/certmonger/ipa-server-guard" GENERATE_RNDC_KEY = "/usr/libexec/generate-rndc-key.sh" IPA_DNSKEYSYNCD_REPLICA = "/usr/libexec/ipa/ipa-dnskeysync-replica" diff --git a/ipapython/dogtag.py b/ipapython/dogtag.py index 4aeb897fd..ff7dc4464 100644 --- a/ipapython/dogtag.py +++ b/ipapython/dogtag.py @@ -131,8 +131,9 @@ def ca_status(ca_host=None): return _parse_ca_status(body) -def https_request(host, port, url, cafile, client_certfile, - method='POST', headers=None, body=None, **kw): +def https_request( + host, port, url, cafile, client_certfile, client_keyfile, + method='POST', headers=None, body=None, **kw): """ :param method: HTTP request method (defalut: 'POST') :param url: The path (not complete URL!) to post to. @@ -149,6 +150,7 @@ def https_request(host, port, url, cafile, client_certfile, host, port, cafile=cafile, client_certfile=client_certfile, + client_keyfile=client_keyfile, tls_version_min=api.env.tls_version_min, tls_version_max=api.env.tls_version_max) diff --git a/ipaserver/install/ca.py b/ipaserver/install/ca.py index e346a2b92..649c15293 100644 --- a/ipaserver/install/ca.py +++ b/ipaserver/install/ca.py @@ -177,14 +177,14 @@ def install_check(standalone, replica_config, options): if standalone: dirname = dsinstance.config_dirname( installutils.realm_to_serverid(realm_name)) - cadb = certs.CertDB(realm_name, subject_base=options._subject_base) + cadb = certs.CertDB(realm_name, nssdir=paths.PKI_TOMCAT_ALIAS_DIR, + subject_base=options._subject_base) dsdb = certs.CertDB( realm_name, nssdir=dirname, subject_base=options._subject_base) for db in (cadb, dsdb): for nickname, _trust_flags in db.list_certs(): - if nickname in (certdb.get_ca_nickname(realm_name), - 'ipaCert'): + if nickname == certdb.get_ca_nickname(realm_name): raise ScriptError( "Certificate with nickname %s is present in %s, " "cannot continue." % (nickname, db.secdir)) @@ -193,8 +193,7 @@ def install_check(standalone, replica_config, options): if not cert: continue subject = DN(x509.load_certificate(cert).subject) - if subject in (DN(options._ca_subject), - DN('CN=IPA RA', options._subject_base)): + if subject == DN(options._ca_subject): raise ScriptError( "Certificate with subject %s is present in %s, " "cannot continue." % (subject, db.secdir)) @@ -312,31 +311,26 @@ def install_step_1(standalone, replica_config, options): dirname = dsinstance.config_dirname(serverid) # Store the new IPA CA cert chain in DS NSS database and LDAP - cadb = certs.CertDB(realm_name, subject_base=subject_base) - dsdb = certs.CertDB(realm_name, nssdir=dirname, subject_base=subject_base) - trust_flags = dict(reversed(cadb.list_certs())) - trust_chain = cadb.find_root_cert('ipaCert')[:-1] - for nickname in trust_chain[:-1]: - cert = cadb.get_cert_from_db(nickname, pem=False) - dsdb.add_cert(cert, nickname, trust_flags[nickname]) - certstore.put_ca_cert_nss(api.Backend.ldap2, api.env.basedn, - cert, nickname, trust_flags[nickname]) - - nickname = trust_chain[-1] - cert = cadb.get_cert_from_db(nickname, pem=False) - dsdb.add_cert(cert, nickname, trust_flags[nickname]) + cadb = certs.CertDB( + realm_name, nssdir=paths.PKI_TOMCAT_ALIAS_DIR, + subject_base=subject_base) + dsdb = certs.CertDB( + realm_name, nssdir=dirname, subject_base=subject_base) + cacert = cadb.get_cert_from_db('caSigningCert cert-pki-ca', pem=False) + nickname = certdb.get_ca_nickname(realm_name) + trust_flags = 'CT,C,C' + dsdb.add_cert(cacert, nickname, trust_flags) certstore.put_ca_cert_nss(api.Backend.ldap2, api.env.basedn, - cert, nickname, trust_flags[nickname], + cacert, nickname, trust_flags, config_ipa=True, config_compat=True) # Store DS CA cert in Dogtag NSS database - dogtagdb = certs.CertDB(realm_name, nssdir=paths.PKI_TOMCAT_ALIAS_DIR) trust_flags = dict(reversed(dsdb.list_certs())) server_certs = dsdb.find_server_certs() trust_chain = dsdb.find_root_cert(server_certs[0][0])[:-1] nickname = trust_chain[-1] cert = dsdb.get_cert_from_db(nickname) - dogtagdb.add_cert(cert, nickname, trust_flags[nickname]) + cadb.add_cert(cert, nickname, trust_flags[nickname]) installutils.restart_dirsrv() @@ -356,6 +350,8 @@ def install_step_1(standalone, replica_config, options): def uninstall(): ca_instance = cainstance.CAInstance(api.env.realm) ca_instance.stop_tracking_certificates() + installutils.remove_file(paths.RA_AGENT_PEM) + installutils.remove_file(paths.RA_AGENT_KEY) if ca_instance.is_configured(): ca_instance.uninstall() diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py index a4f470cf7..0991883ab 100644 --- a/ipaserver/install/cainstance.py +++ b/ipaserver/install/cainstance.py @@ -26,6 +26,7 @@ import dbus import ldap import os import pwd +import grp import re import shutil import sys @@ -37,6 +38,7 @@ import six # pylint: disable=import-error from six.moves.configparser import ConfigParser, RawConfigParser # pylint: enable=import-error +from cryptography.hazmat.primitives import serialization from ipalib import api from ipalib import x509 @@ -64,8 +66,7 @@ from ipaserver.install import installutils from ipaserver.install import ldapupdate from ipaserver.install import replication from ipaserver.install import sysupgrade -from ipaserver.install.dogtaginstance import ( - DogtagInstance, export_ra_agent_pem) +from ipaserver.install.dogtaginstance import DogtagInstance from ipaserver.plugins import ldap2 # We need to reset the template because the CA uses the regular boot @@ -314,8 +315,6 @@ class CAInstance(DogtagInstance): self.canickname = get_ca_nickname(realm) else: self.canickname = None - self.ra_agent_db = paths.IPA_RADB_DIR - self.ra_agent_pwd = os.path.join(self.ra_agent_db, "pwdfile.txt") self.ra_cert = None self.requestId = None self.log = log_mgr.get_logger(self) @@ -378,8 +377,7 @@ class CAInstance(DogtagInstance): self.external = 2 if self.clone: - cert_db = certs.CertDB(self.realm) - has_ra_cert = (cert_db.get_cert_from_db('ipaCert') != '') + has_ra_cert = os.path.exists(paths.RA_AGENT_PEM) else: has_ra_cert = False @@ -415,16 +413,14 @@ class CAInstance(DogtagInstance): else: self.step("importing RA certificate from PKCS #12 file", lambda: self.import_ra_cert(ra_p12)) - self.step("exporting RA agent cert", export_ra_agent_pem) if not ra_only: - self.step("importing CA chain to RA certificate database", self.__import_ca_chain) self.step("setting up signing cert profile", self.__setup_sign_profile) self.step("setting audit signing renewal to 2 years", self.set_audit_renewal) self.step("restarting certificate server", self.restart_instance) if not self.clone: self.step("publishing the CA certificate", - self.__publish_ca_cert) + self.__export_ca_chain) self.step("adding RA agent as a trusted user", self.__create_ca_agent) self.step("authorizing RA to modify profiles", configure_profiles_acl) self.step("authorizing RA to manage lightweight CAs", @@ -683,13 +679,22 @@ class CAInstance(DogtagInstance): Used when setting up replication """ - # Add the new RA cert into the RA database - with tempfile.NamedTemporaryFile(mode="w") as agent_file: - agent_file.write(self.dm_password) - agent_file.flush() - - import_pkcs12( - rafile, agent_file.name, self.ra_agent_db, self.ra_agent_pwd) + # get the private key from the file + ipautil.run([paths.OPENSSL, + "pkcs12", + "-in", rafile, + "-nocerts", "-nodes", + "-out", paths.RA_AGENT_KEY, + "-passin", "pass:"]) + + # get the certificate from the pkcs12 file + ipautil.run([paths.OPENSSL, + "pkcs12", + "-in", rafile, + "-clcerts", "-nokeys", + "-out", paths.RA_AGENT_PEM, + "-passin", "pass:"]) + self.__set_ra_cert_perms() self.configure_agent_renewal() @@ -697,18 +702,28 @@ class CAInstance(DogtagInstance): custodia = custodiainstance.CustodiaInstance(host_name=self.fqdn, realm=self.realm) custodia.import_ra_key(self.master_host) + self.__set_ra_cert_perms() self.configure_agent_renewal() + def __set_ra_cert_perms(self): + """ + Sets the correct permissions for the RA_AGENT_PEM, RA_AGENT_KEY files + """ + ipaapi_gid = grp.getgrnam(ipalib.constants.IPAAPI_GROUP).gr_gid + for fname in (paths.RA_AGENT_PEM, paths.RA_AGENT_KEY): + os.chown(fname, -1, ipaapi_gid) + os.chmod(fname, 0o440) + tasks.restore_context(fname) + def __create_ca_agent(self): """ Create CA agent, assign a certificate, and add the user to the appropriate groups for accessing CA services. """ - # get ipaCert certificate - cert_data = base64.b64decode(self.ra_cert) - cert = x509.load_certificate(cert_data, x509.DER) + # get RA certificate + cert_data = self.ra_cert.public_bytes(serialization.Encoding.DER) # connect to CA database server_id = installutils.realm_to_serverid(api.env.realm) @@ -716,7 +731,7 @@ class CAInstance(DogtagInstance): conn = ldap2.ldap2(api, ldap_uri=dogtag_uri) conn.connect(autobind=True) - # create ipara user with ipaCert certificate + # create ipara user with RA certificate user_dn = DN(('uid', "ipara"), ('ou', 'People'), self.basedn) entry = conn.make_entry( user_dn, @@ -729,7 +744,7 @@ class CAInstance(DogtagInstance): userstate=["1"], userCertificate=[cert_data], description=['2;%s;%s;%s' % ( - cert.serial_number, + self.ra_cert.serial_number, DN(self.ca_subject), DN(('CN', 'IPA RA'), self.subject_base))]) conn.add_entry(entry) @@ -746,57 +761,30 @@ class CAInstance(DogtagInstance): conn.disconnect() - def __publish_ca_cert(self): - db = certs.CertDB(self.realm) - db.publish_ca_cert(paths.IPA_CA_CRT) - def __get_ca_chain(self): try: return dogtag.get_ca_certchain(ca_host=self.fqdn) except Exception as e: raise RuntimeError("Unable to retrieve CA chain: %s" % str(e)) - def __import_ca_chain(self): - # Backup NSS trust flags of all already existing certificates - certdb = certs.CertDB(self.realm) - cert_backup_list = certdb.list_certs() - + def __export_ca_chain(self): + """ + Get the CA chain from Dogtag NSS DB and write it to paths.IPA_CA_CRT + """ + # Getting Dogtag CA chain chain = self.__get_ca_chain() - # If this chain contains multiple certs then certutil will only import - # the first one. So we have to pull them all out and import them - # separately. Unfortunately no NSS tool can do this so we have to - # use openssl. - # Convert to DER because the chain comes back as one long string which # makes openssl throw up. data = base64.b64decode(chain) + # Get list of PEM certificates certlist = x509.pkcs7_to_pems(data, x509.DER) - # Ok, now we have all the certificates in certs, walk through it - # and pull out each certificate and add it to our database - - ca_dn = DN(self.ca_subject) + # We have all the certificates in certlist, write them to a PEM file for cert in certlist: - with tempfile.NamedTemporaryFile(mode="w") as chain_file: - chain_file.write(cert) - chain_file.flush() - (_rdn, subject_dn) = certs.get_cert_nickname(cert) - if subject_dn == ca_dn: - nick = get_ca_nickname(self.realm) - trust_flags = 'CT,C,C' - else: - nick = str(subject_dn) - trust_flags = ',,' - certdb.run_certutil( - ['-A', '-t', trust_flags, '-n', nick, '-a', - '-i', chain_file.name] - ) - - # Restore NSS trust flags of all previously existing certificates - for nick, trust_flags in cert_backup_list: - certdb.trust_root_cert(nick, trust_flags) + with open(paths.IPA_CA_CRT, 'w') as ipaca_pem: + ipaca_pem.write(cert) def __request_ra_certificate(self): # create a temp file storing the pwd @@ -812,7 +800,7 @@ class CAInstance(DogtagInstance): chain = self.__get_ca_chain() data = base64.b64decode(chain) - result = ipautil.run( + ipautil.run( [paths.OPENSSL, "pkcs7", "-inform", @@ -839,24 +827,19 @@ class CAInstance(DogtagInstance): # The certificate must be requested using caServerCert profile # because this profile does not require agent authentication reqId = certmonger.request_and_wait_for_cert( - certpath=self.ra_agent_db, - nickname='ipaCert', + certpath=(paths.RA_AGENT_PEM, paths.RA_AGENT_KEY), principal='host/%s' % self.fqdn, - passwd_fname=self.ra_agent_pwd, subject=str(DN(('CN', 'IPA RA'), self.subject_base)), ca=ipalib.constants.RENEWAL_CA_NAME, profile='caServerCert', pre_command='renew_ra_cert_pre', - post_command='renew_ra_cert') + post_command='renew_ra_cert', + storage="FILE") + self.__set_ra_cert_perms() self.requestId = str(reqId) - certdb = certs.CertDB(self.realm) - result = certdb.run_certutil( - ['-L', '-n', 'ipaCert', '-a'], capture_output=True) - self.ra_cert = x509.strip_header(result.output) - self.ra_cert = "\n".join( - line.strip() for line - in self.ra_cert.splitlines() if line.strip()) + self.ra_cert = x509.load_certificate_from_file( + paths.RA_AGENT_PEM) finally: # we can restore the helper parameters certmonger.modify_ca_helper( @@ -1013,12 +996,11 @@ class CAInstance(DogtagInstance): def configure_agent_renewal(self): try: certmonger.start_tracking( - certpath=self.ra_agent_db, + certpath=(paths.RA_AGENT_PEM, paths.RA_AGENT_KEY), ca='dogtag-ipa-ca-renew-agent', - nickname='ipaCert', - pinfile=self.ra_agent_pwd, pre_command='renew_ra_cert_pre', - post_command='renew_ra_cert') + post_command='renew_ra_cert', + storage='FILE') except RuntimeError as e: self.log.error( "certmonger failed to start tracking certificate: %s", e) @@ -1035,7 +1017,7 @@ class CAInstance(DogtagInstance): certmonger.stop_tracking(self.nss_db, nickname=nickname) try: - certmonger.stop_tracking(self.ra_agent_db, nickname='ipaCert') + certmonger.stop_tracking(certfile=paths.RA_AGENT_PEM) except RuntimeError as e: root_logger.error( "certmonger failed to stop tracking certificate: %s", e) diff --git a/ipaserver/install/certs.py b/ipaserver/install/certs.py index c55f3c599..4f978012f 100644 --- a/ipaserver/install/certs.py +++ b/ipaserver/install/certs.py @@ -97,7 +97,7 @@ class CertDB(object): """ # TODO: Remove all selfsign code - def __init__(self, realm, nssdir=paths.IPA_RADB_DIR, fstore=None, + def __init__(self, realm, nssdir, fstore=None, host_name=None, subject_base=None, ca_subject=None, user=None, group=None, mode=None, truncate=False): self.nssdb = NSSDatabase(nssdir) @@ -417,6 +417,7 @@ class CertDB(object): url="/ca/ee/ca/profileSubmitSSLClient", cafile=api.env.tls_ca_cert, client_certfile=paths.RA_AGENT_PEM, + client_keyfile=paths.RA_AGENT_KEY, **params) http_status, _http_headers, http_body = result root_logger.debug("CA answer: %s", http_body) @@ -471,6 +472,7 @@ class CertDB(object): url="/ca/ee/ca/profileSubmitSSLClient", cafile=api.env.tls_ca_cert, client_certfile=paths.RA_AGENT_PEM, + client_keyfile=paths.RA_AGENT_KEY, **params) http_status, _http_headers, http_body = result if http_status != 200: diff --git a/ipaserver/install/custodiainstance.py b/ipaserver/install/custodiainstance.py index 1be53994a..6a6139231 100644 --- a/ipaserver/install/custodiainstance.py +++ b/ipaserver/install/custodiainstance.py @@ -112,6 +112,10 @@ class CustodiaInstance(SimpleServiceInstance): def import_ra_key(self, master_host_name): cli = self.__CustodiaClient(server=master_host_name) + # please note that ipaCert part has to stay here for historical + # reasons (old servers expect you to ask for ra/ipaCert during + # replication as they store the RA agent cert in an NSS database + # with this nickname) cli.fetch_key('ra/ipaCert') def import_dm_password(self, master_host_name): diff --git a/ipaserver/install/dogtaginstance.py b/ipaserver/install/dogtaginstance.py index 9fa61761a..9cbd34942 100644 --- a/ipaserver/install/dogtaginstance.py +++ b/ipaserver/install/dogtaginstance.py @@ -21,17 +21,13 @@ import base64 import ldap import os import shutil -import tempfile import traceback import dbus -import pwd from pki.client import PKIConnection import pki.system from ipalib import api, errors - -from ipalib.constants import IPAAPI_USER from ipalib.install import certmonger from ipaplatform import services from ipaplatform.constants import constants @@ -72,27 +68,6 @@ def is_installing_replica(sys_type): return False -def export_ra_agent_pem(): - """ - Export ipaCert with private key for client authentication. - """ - fd, filename = tempfile.mkstemp(dir=paths.IPA_RADB_DIR) - os.close(fd) - - args = ["/usr/bin/pki", - "-d", paths.IPA_RADB_DIR, - "-C", os.path.join(paths.IPA_RADB_DIR, 'pwdfile.txt'), - "client-cert-show", "ipaCert", - "--client-cert", filename] - ipautil.run(args) - - pent = pwd.getpwnam(IPAAPI_USER) - os.chown(filename, 0, pent.pw_gid) - os.chmod(filename, 0o440) - - os.rename(filename, paths.RA_AGENT_PEM) - - class DogtagInstance(service.Service): """ This is the base class for a Dogtag 10+ instance, which uses a diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py index bf80ae089..99e61903d 100644 --- a/ipaserver/install/dsinstance.py +++ b/ipaserver/install/dsinstance.py @@ -811,13 +811,14 @@ class DsInstance(service.Service): 'restart_dirsrv %s' % self.serverid) else: dsdb.create_from_cacert() - ca_args = ['/usr/libexec/certmonger/dogtag-submit', - '--ee-url', 'https://%s:8443/ca/ee/ca' % self.fqdn, - '--dbdir', paths.IPA_RADB_DIR, - '--nickname', 'ipaCert', - '--sslpinfile', os.path.join(paths.IPA_RADB_DIR, - 'pwdfile.txt'), - '--agent-submit'] + ca_args = [ + paths.CERTMONGER_DOGTAG_SUBMIT, + '--ee-url', 'https://%s:8443/ca/ee/ca' % self.fqdn, + '--certfile', paths.RA_AGENT_PEM, + '--keyfile', paths.RA_AGENT_KEY, + '--cafile', paths.IPA_CA_CRT, + '--agent-submit' + ] helper = " ".join(ca_args) prev_helper = certmonger.modify_ca_helper('IPA', helper) try: diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py index 7979ca116..0c2216eb3 100644 --- a/ipaserver/install/httpinstance.py +++ b/ipaserver/install/httpinstance.py @@ -384,14 +384,13 @@ class HTTPInstance(service.Service): if not self.promote: self.create_password_conf() ca_args = [ - '/usr/libexec/certmonger/dogtag-submit', + paths.CERTMONGER_DOGTAG_SUBMIT, '--ee-url', 'https://%s:8443/ca/ee/ca' % self.fqdn, - '--dbdir', paths.IPA_RADB_DIR, - '--nickname', 'ipaCert', - '--sslpinfile', os.path.join(paths.IPA_RADB_DIR, - 'pwdfile.txt'), + '--certfile', paths.RA_AGENT_PEM, + '--keyfile', paths.RA_AGENT_KEY, + '--cafile', paths.IPA_CA_CRT, '--agent-submit' - ] + ] helper = " ".join(ca_args) prev_helper = certmonger.modify_ca_helper('IPA', helper) @@ -419,10 +418,6 @@ class HTTPInstance(service.Service): raise RuntimeError("Could not find a suitable server cert.") def __import_ca_certs(self): - # first for the RA DB - db = certs.CertDB(self.realm, subject_base=self.subject_base) - self.import_ca_certs(db, self.ca_is_configured) - # and then also for the HTTPD DB db = certs.CertDB(self.realm, nssdir=paths.HTTPD_ALIAS_DIR, subject_base=self.subject_base) self.import_ca_certs(db, self.ca_is_configured) diff --git a/ipaserver/install/ipa_backup.py b/ipaserver/install/ipa_backup.py index 9f35bf6ac..d722e48e1 100644 --- a/ipaserver/install/ipa_backup.py +++ b/ipaserver/install/ipa_backup.py @@ -107,7 +107,6 @@ class Backup(admintool.AdminTool): paths.PKI_TOMCAT, paths.SYSCONFIG_PKI, paths.HTTPD_ALIAS_DIR, - paths.IPA_RADB_DIR, paths.VAR_LIB_PKI_DIR, paths.SYSRESTORE, paths.IPA_CLIENT_SYSRESTORE, @@ -159,6 +158,7 @@ class Backup(admintool.AdminTool): paths.SAMBA_KEYTAB, paths.DOGTAG_ADMIN_P12, paths.RA_AGENT_PEM, + paths.RA_AGENT_KEY, paths.CACERT_P12, paths.KRACERT_P12, paths.KRB5KDC_KDC_CONF, diff --git a/ipaserver/install/ipa_replica_prepare.py b/ipaserver/install/ipa_replica_prepare.py index 6fa4b4a42..5f6b6e957 100644 --- a/ipaserver/install/ipa_replica_prepare.py +++ b/ipaserver/install/ipa_replica_prepare.py @@ -631,18 +631,16 @@ class ReplicaPrepare(admintool.AdminTool): raise admintool.ScriptError(str(e)) def export_ra_pkcs12(self): - agent_fd, agent_name = tempfile.mkstemp() - os.write(agent_fd, self.dirman_password) - os.close(agent_fd) - - try: - db = certs.CertDB(api.env.realm, host_name=api.env.host) - - if db.has_nickname("ipaCert"): - pkcs12_fname = os.path.join(self.dir, "ra.p12") - db.export_pkcs12(pkcs12_fname, agent_name, "ipaCert") - finally: - os.remove(agent_name) + if (os.path.exists(paths.RA_AGENT_PEM) and + os.path.exists(paths.RA_AGENT_KEY)): + ipautil.run([ + paths.OPENSSL, + "pkcs12", "-export", + "-inkey", paths.RA_AGENT_KEY, + "-in", paths.RA_AGENT_PEM, + "-out", os.path.join(self.dir, "ra.p12"), + "-passout", "pass:" + ]) def update_pki_admin_password(self): dn = DN('uid=admin', 'ou=people', 'o=ipaca') diff --git a/ipaserver/install/krainstance.py b/ipaserver/install/krainstance.py index 1fc69bd68..5ee08dc32 100644 --- a/ipaserver/install/krainstance.py +++ b/ipaserver/install/krainstance.py @@ -26,11 +26,11 @@ import six # pylint: disable=import-error from six.moves.configparser import ConfigParser # pylint: enable=import-error +from cryptography.hazmat.primitives import serialization from ipalib import api from ipalib import x509 from ipaplatform.paths import paths -from ipapython import certdb from ipapython import ipautil from ipapython.dn import DN from ipaserver.install import cainstance @@ -290,10 +290,9 @@ class KRAInstance(DogtagInstance): the appropriate groups for accessing KRA services. """ - # get ipaCert certificate - with certdb.NSSDatabase(paths.IPA_RADB_DIR) as ipa_nssdb: - cert_data = ipa_nssdb.get_cert("ipaCert") - cert = x509.load_certificate(cert_data, x509.DER) + # get RA agent certificate + cert = x509.load_certificate_from_file(paths.RA_AGENT_PEM) + cert_data = cert.public_bytes(serialization.Encoding.DER) # connect to KRA database server_id = installutils.realm_to_serverid(api.env.realm) @@ -301,7 +300,7 @@ class KRAInstance(DogtagInstance): conn = ldap2.ldap2(api, ldap_uri=dogtag_uri) conn.connect(autobind=True) - # create ipakra user with ipaCert certificate + # create ipakra user with RA agent certificate user_dn = DN(('uid', "ipakra"), ('ou', 'people'), self.basedn) entry = conn.make_entry( user_dn, diff --git a/ipaserver/install/plugins/ca_renewal_master.py b/ipaserver/install/plugins/ca_renewal_master.py index 2447a3406..99503adfe 100644 --- a/ipaserver/install/plugins/ca_renewal_master.py +++ b/ipaserver/install/plugins/ca_renewal_master.py @@ -74,17 +74,16 @@ class update_ca_renewal_master(Updater): return False, [] criteria = { - 'cert-database': paths.HTTPD_ALIAS_DIR, - 'cert-nickname': 'ipaCert', + 'cert-file': paths.RA_AGENT_PEM, } request_id = certmonger.get_request_id(criteria) if request_id is not None: - self.debug("found certmonger request for ipaCert") + self.debug("found certmonger request for RA cert") ca_name = certmonger.get_request_value(request_id, 'ca-name') if ca_name is None: self.warning( - "certmonger request for ipaCert is missing ca_name, " + "certmonger request for RA cert is missing ca_name, " "assuming local CA is renewal slave") return False, [] ca_name = ca_name.strip() @@ -97,11 +96,11 @@ class update_ca_renewal_master(Updater): return False, [] else: self.warning( - "certmonger request for ipaCert has unknown ca_name '%s', " + "certmonger request for RA cert has unknown ca_name '%s', " "assuming local CA is renewal slave", ca_name) return False, [] else: - self.debug("certmonger request for ipaCert not found") + self.debug("certmonger request for RA cert not found") config = installutils.get_directive( paths.CA_CS_CFG_PATH, 'subsystem.select', '=') diff --git a/ipaserver/install/plugins/update_ra_cert_store.py b/ipaserver/install/plugins/update_ra_cert_store.py index e4c0ac528..937f9c59f 100644 --- a/ipaserver/install/plugins/update_ra_cert_store.py +++ b/ipaserver/install/plugins/update_ra_cert_store.py @@ -2,15 +2,15 @@ # Copyright (C) 2016 FreeIPA Contributors see COPYING for license # -import binascii import os +import tempfile from ipalib import Registry from ipalib import Updater -from ipalib.constants import IPAAPI_USER, IPAAPI_GROUP from ipalib.install import certmonger from ipaplatform.paths import paths -from ipapython import certdb +from ipapython.certdb import NSSDatabase +from ipaserver.install import cainstance register = Registry() @@ -18,58 +18,44 @@ register = Registry() @register() class update_ra_cert_store(Updater): """ - Moves the cert store from /etc/httpd/alias to /var/lib/ipa/radb + Moves the ipaCert store from /etc/httpd/alias RA_AGENT_PEM, RA_AGENT_KEY + files """ def execute(self, **options): + ra_nick = 'ipaCert' ca_enabled = self.api.Command.ca_is_enabled()['result'] if not ca_enabled: return False, [] - olddb = certdb.NSSDatabase(nssdir=paths.HTTPD_ALIAS_DIR) - if not olddb.has_nickname('ipaCert'): + certdb = NSSDatabase(nssdir=paths.HTTPD_ALIAS_DIR) + if not certdb.has_nickname(ra_nick): # Nothign to do return False, [] - - newdb = certdb.NSSDatabase(nssdir=paths.IPA_RADB_DIR) - if os.path.exists(paths.IPA_RADB_DIR): - if newdb.has_nickname('ipaCert'): - self.log.warning( - "An 'ipaCert' nickname exists in both the old {} and the " - "new {} NSS Databases!".format(paths.HTTPD_ALIAS_DIR, - paths.IPA_RADB_DIR)) - return False, [] - else: - # Create the DB - newdb.create_db(user=IPAAPI_USER, group=IPAAPI_GROUP, backup=True) - - # Import cert chain (ignore errors, as certs may already be imported) - certlist = olddb.list_certs() - certflags = {} - for name, flags in certlist: - certflags[name] = flags - for name in olddb.get_trust_chain('ipaCert'): - if name == 'ipaCert': - continue - try: - cert = olddb.get_cert(name, pem=True) - newdb.add_cert(cert, name, certflags[name], pem=True) - except Exception as e: # pylint disable=broad-except - self.log.warning("Failed to import '{}' from trust " - "chain: {}".format(name, str(e))) - - # As the last step export/import/delete the RA Cert - pw = binascii.hexlify(os.urandom(10)) - p12file = os.path.join(paths.IPA_RADB_DIR, 'ipaCert.p12') - olddb.export_pkcs12('ipaCert', p12file, pw) - newdb.import_pkcs12(p12file, pw) - - certmonger.stop_tracking(secdir=olddb.secdir, - nickname='ipaCert') - certmonger.start_tracking(certpath=newdb.secdir, - nickname='ipaCert', - pinfile=newdb.pwd_file) - - olddb.delete_cert('ipaCert') + elif os.path.exists(paths.RA_AGENT_PEM): + # even though the certificate file exists, we will overwrite it + # as it's probabably something wrong anyway + self.log.warning( + "A certificate with the nickname 'ipaCert' exists in " + "the old '{}' NSS database as well as in the new " + "PEM file '{}'" + .format(paths.HTTPD_ALIAS_DIR, paths.RA_AGENT_PEM)) + + _fd, p12file = tempfile.mkstemp(dir=certdb.secdir) + # no password is necessary as we will be saving it in clear anyway + certdb.export_pkcs12(ra_nick, p12file, pkcs12_passwd='') + + # stop tracking the old cert and remove it + certmonger.stop_tracking(paths.HTTPD_ALIAS_DIR, nickname=ra_nick) + certdb.delete_cert(ra_nick) + if os.path.exists(paths.OLD_KRA_AGENT_PEM): + os.remove(paths.OLD_KRA_AGENT_PEM) + + # get the private key and certificate from the file and start + # tracking it in certmonger + ca = cainstance.CAInstance() + ca.import_ra_cert(p12file) + + os.remove(p12file) return False, [] diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py index 813329372..be398bce7 100644 --- a/ipaserver/install/server/install.py +++ b/ipaserver/install/server/install.py @@ -14,7 +14,6 @@ import textwrap import six -from ipalib.constants import IPAAPI_USER, IPAAPI_GROUP from ipalib.install import certmonger, sysrestore from ipapython import ipautil from ipapython.ipa_log_manager import root_logger @@ -24,7 +23,8 @@ from ipapython.admintool import ScriptError from ipaplatform import services from ipaplatform.paths import paths from ipaplatform.tasks import tasks -from ipalib import api, constants, errors, x509 +from ipalib import api, errors, x509 +from ipalib.constants import DOMAIN_LEVEL_0 from ipalib.util import ( validate_domain_name, network_ip_address_warning, @@ -32,7 +32,7 @@ from ipalib.util import ( ) import ipaclient.install.ntpconf from ipaserver.install import ( - bindinstance, ca, certs, dns, dsinstance, + bindinstance, ca, dns, dsinstance, httpinstance, installutils, kra, krbinstance, ntpinstance, otpdinstance, custodiainstance, replication, service, sysupgrade) @@ -774,11 +774,6 @@ def install(installer): if n in options.__dict__} write_cache(cache_vars) - # Create RA DB - certs.CertDB(realm_name, nssdir=paths.IPA_RADB_DIR, - user=IPAAPI_USER, group=IPAAPI_GROUP, - truncate=True) - ca.install_step_0(False, None, options) else: # Put the CA cert where other instances expect it @@ -987,7 +982,7 @@ def uninstall_check(installer): else: dns.uninstall_check(options) - if domain_level == constants.DOMAIN_LEVEL_0: + if domain_level == DOMAIN_LEVEL_0: rm = replication.ReplicationManager( realm=api.env.realm, hostname=api.env.host, @@ -1102,8 +1097,7 @@ def uninstall(installer): # Note that this name will be wrong after the first uninstall. dirname = dsinstance.config_dirname( installutils.realm_to_serverid(api.env.realm)) - dirs = [dirname, paths.PKI_TOMCAT_ALIAS_DIR, paths.HTTPD_ALIAS_DIR, - paths.IPA_RADB_DIR] + dirs = [dirname, paths.PKI_TOMCAT_ALIAS_DIR, paths.HTTPD_ALIAS_DIR] ids = certmonger.check_state(dirs) if ids: root_logger.error('Some certificates may still be tracked by ' @@ -1116,11 +1110,6 @@ def uninstall(installer): ' # getcert stop-tracking -i <request_id>\n' 'for each id in: %s' % ', '.join(ids)) - try: - shutil.rmtree(paths.IPA_RADB_DIR) - except Exception: - pass - # Remove the cert renewal lock file try: os.remove(paths.IPA_RENEWAL_LOCK) diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py index c7965c7c3..eef675577 100644 --- a/ipaserver/install/server/upgrade.py +++ b/ipaserver/install/server/upgrade.py @@ -900,77 +900,72 @@ def certificate_renewal_update(ca, ds, http): template = paths.CERTMONGER_COMMAND_TEMPLATE serverid = installutils.realm_to_serverid(api.env.realm) - dirsrv_dir = dsinstance.config_dirname(serverid) # bump version when requests is changed version = 6 - requests = ( - ( - paths.PKI_TOMCAT_ALIAS_DIR, - 'auditSigningCert cert-pki-ca', - 'dogtag-ipa-ca-renew-agent', - template % 'stop_pkicad', - '%s "auditSigningCert cert-pki-ca"' % (template % 'renew_ca_cert'), - None, - ), - ( - paths.PKI_TOMCAT_ALIAS_DIR, - 'ocspSigningCert cert-pki-ca', - 'dogtag-ipa-ca-renew-agent', - template % 'stop_pkicad', - '%s "ocspSigningCert cert-pki-ca"' % (template % 'renew_ca_cert'), - None, - ), - ( - paths.PKI_TOMCAT_ALIAS_DIR, - 'subsystemCert cert-pki-ca', - 'dogtag-ipa-ca-renew-agent', - template % 'stop_pkicad', - '%s "subsystemCert cert-pki-ca"' % (template % 'renew_ca_cert'), - None, - ), - ( - paths.PKI_TOMCAT_ALIAS_DIR, - 'caSigningCert cert-pki-ca', - 'dogtag-ipa-ca-renew-agent', - template % 'stop_pkicad', - '%s "caSigningCert cert-pki-ca"' % (template % 'renew_ca_cert'), - 'ipaCACertRenewal', - ), - ( - paths.IPA_RADB_DIR, - 'ipaCert', - 'dogtag-ipa-ca-renew-agent', - template % 'renew_ra_cert_pre', - template % 'renew_ra_cert', - None, - ), - ( - paths.PKI_TOMCAT_ALIAS_DIR, - 'Server-Cert cert-pki-ca', - 'dogtag-ipa-ca-renew-agent', - template % 'stop_pkicad', - '%s "Server-Cert cert-pki-ca"' % (template % 'renew_ca_cert'), - None, - ), - ( - paths.HTTPD_ALIAS_DIR, - 'Server-Cert', - 'IPA', - None, - template % 'restart_httpd', - None, - ), - ( - dirsrv_dir, - 'Server-Cert', - 'IPA', - None, - '%s %s' % (template % 'restart_dirsrv', serverid), - None, - ), - - ) + requests = [ + { + 'cert-database': paths.PKI_TOMCAT_ALIAS_DIR, + 'cert-nickname': 'auditSigningCert cert-pki-ca', + 'ca': 'dogtag-ipa-ca-renew-agent', + 'cert-presave-command': template % 'stop_pkicad', + 'cert-postsave-command': + (template % 'renew_ca_cert "auditSigningCert cert-pki-ca"'), + }, + { + 'cert-database': paths.PKI_TOMCAT_ALIAS_DIR, + 'cert-nickname': 'ocspSigningCert cert-pki-ca', + 'ca': 'dogtag-ipa-ca-renew-agent', + 'cert-presave-command': template % 'stop_pkicad', + 'cert-postsave-command': + (template % 'renew_ca_cert "ocspSigningCert cert-pki-ca"'), + }, + { + 'cert-database': paths.PKI_TOMCAT_ALIAS_DIR, + 'cert-nickname': 'subsystemCert cert-pki-ca', + 'ca': 'dogtag-ipa-ca-renew-agent', + 'cert-presave-command': template % 'stop_pkicad', + 'cert-postsave-command': + (template % 'renew_ca_cert "subsystemCert cert-pki-ca"'), + }, + { + 'cert-database': paths.PKI_TOMCAT_ALIAS_DIR, + 'cert-nickname': 'caSigningCert cert-pki-ca', + 'ca': 'dogtag-ipa-ca-renew-agent', + 'cert-presave-command': template % 'stop_pkicad', + 'cert-postsave-command': + (template % 'renew_ca_cert "caSigningCert cert-pki-ca"'), + 'template-profile': 'ipaCACertRenewal', + }, + { + 'cert-database': paths.PKI_TOMCAT_ALIAS_DIR, + 'cert-nickname': 'Server-Cert cert-pki-ca', + 'ca': 'dogtag-ipa-ca-renew-agent', + 'cert-presave-command': template % 'stop_pkicad', + 'cert-postsave-command': + (template % 'renew_ca_cert "Server-Cert cert-pki-ca"'), + }, + { + 'cert-file': paths.RA_AGENT_PEM, + 'key-file': paths.RA_AGENT_KEY, + 'ca': 'dogtag-ipa-ca-renew-agent', + 'cert-presave-command': template % 'renew_ra_cert_pre', + 'cert-postsave-command': template % 'renew_ra_cert', + }, + { + 'cert-database': paths.HTTPD_ALIAS_DIR, + 'cert-nickname': 'Server-Cert', + 'ca': 'IPA', + 'cert-postsave-command': template % 'restart_httpd', + }, + { + 'cert-database': dsinstance.config_dirname(serverid), + 'cert-nickname': 'Server-Cert', + 'ca': 'IPA', + 'cert-postsave-command': + '%s %s' % (template % 'restart_dirsrv', serverid), + } + ] root_logger.info("[Update certmonger certificate renewal configuration to " "version %d]" % version) @@ -984,16 +979,7 @@ def certificate_renewal_update(ca, ds, http): # State not set, lets see if we are already configured for request in requests: - nss_dir, nickname, ca_name, pre_command, post_command, profile = request - criteria = { - 'cert-database': nss_dir, - 'cert-nickname': nickname, - 'ca-name': ca_name, - 'template-profile': profile, - 'cert-presave-command': pre_command, - 'cert-postsave-command': post_command, - } - request_id = certmonger.get_request_id(criteria) + request_id = certmonger.get_request_id(request) if request_id is None: break else: @@ -1402,24 +1388,6 @@ def fix_trust_flags(): sysupgrade.set_upgrade_state('http', 'fix_trust_flags', True) -def export_ra_agent_pem(): - root_logger.info('[Exporting KRA agent PEM file]') - - # export_kra_agent_pem is the original name of this function - sysupgrade.remove_upgrade_state('http', 'export_kra_agent_pem') - - if os.path.exists(paths.RA_AGENT_PEM): - root_logger.info("KRA agent PEM file already exported") - return - - if not api.Command.kra_is_enabled()['result']: - root_logger.info("KRA is not enabled") - return - - dogtaginstance.export_ra_agent_pem() - installutils.remove_file(paths.OLD_KRA_AGENT_PEM) - - def update_mod_nss_protocol(http): root_logger.info('[Updating mod_nss protocol versions]') @@ -1663,7 +1631,6 @@ def upgrade_configuration(): update_mod_nss_protocol(http) update_mod_nss_cipher_suite(http) fix_trust_flags() - export_ra_agent_pem() update_http_keytab(http) http.configure_gssproxy() http.start() diff --git a/ipaserver/plugins/dogtag.py b/ipaserver/plugins/dogtag.py index 4ae10b9fe..ca25352eb 100644 --- a/ipaserver/plugins/dogtag.py +++ b/ipaserver/plugins/dogtag.py @@ -243,6 +243,7 @@ import datetime import json from lxml import etree import time +import contextlib import six from six.moves import urllib @@ -250,8 +251,7 @@ from six.moves import urllib from ipalib import Backend, api from ipapython.dn import DN import ipapython.cookie -from ipapython import dogtag -from ipapython import ipautil +from ipapython import dogtag, ipautil, certdb if api.env.in_server: import pki @@ -1242,8 +1242,12 @@ class RestClient(Backend): if api.env.in_tree: self.client_certfile = os.path.join( api.env.dot_ipa, 'ra-agent.pem') + + self.client_keyfile = os.path.join( + api.env.dot_ipa, 'ra-agent.key') else: self.client_certfile = paths.RA_AGENT_PEM + self.client_keyfile = paths.RA_AGENT_KEY super(RestClient, self).__init__(api) # session cookie @@ -1279,6 +1283,7 @@ class RestClient(Backend): url='/ca/rest/account/login', cafile=self.ca_cert, client_certfile=self.client_certfile, + client_keyfile=self.client_keyfile, method='GET' ) cookies = ipapython.cookie.Cookie.parse(resp_headers.get('set-cookie', '')) @@ -1294,6 +1299,7 @@ class RestClient(Backend): url='/ca/rest/account/logout', cafile=self.ca_cert, client_certfile=self.client_certfile, + client_keyfile=self.client_keyfile, method='GET' ) self.cookie = None @@ -1337,6 +1343,7 @@ class RestClient(Backend): url=resource, cafile=self.ca_cert, client_certfile=self.client_certfile, + client_keyfile=self.client_keyfile, method=method, headers=headers, body=body ) if status < 200 or status >= 300: @@ -1421,6 +1428,7 @@ class ra(rabase.rabase, RestClient): self.ca_host, port, url, cafile=self.ca_cert, client_certfile=self.client_certfile, + client_keyfile=self.client_keyfile, **kw) def get_parse_result_xml(self, xml_text, parse_func): @@ -1998,6 +2006,7 @@ class kra(Backend): else: return api.env.ca_host + @contextlib.contextmanager def get_client(self): """ Returns an authenticated KRA client to access KRA services. @@ -2009,9 +2018,11 @@ class kra(Backend): # TODO: replace this with a more specific exception raise RuntimeError('KRA service is not enabled') + tempdb = certdb.NSSDatabase() + tempdb.create_db() crypto = cryptoutil.NSSCryptoProvider( - paths.IPA_RADB_DIR, - password_file=os.path.join(paths.IPA_RADB_DIR, 'pwdfile.txt')) + tempdb.secdir, + password_file=tempdb.pwd_file) # TODO: obtain KRA host & port from IPA service list or point to KRA load balancer # https://fedorahosted.org/freeipa/ticket/4557 @@ -2021,9 +2032,16 @@ class kra(Backend): str(self.kra_port), 'kra') - connection.set_authentication_cert(paths.RA_AGENT_PEM) + connection.session.cert = (paths.RA_AGENT_PEM, paths.RA_AGENT_KEY) + # uncomment the following when this commit makes it to release + # https://git.fedorahosted.org/cgit/pki.git/commit/?id=71ae20c + # connection.set_authentication_cert(paths.RA_AGENT_PEM, + # paths.RA_AGENT_KEY) - return KRAClient(connection, crypto) + try: + yield KRAClient(connection, crypto) + finally: + tempdb.close() @register() diff --git a/ipaserver/plugins/rabase.py b/ipaserver/plugins/rabase.py index 8f2c8c388..49a3f8baf 100644 --- a/ipaserver/plugins/rabase.py +++ b/ipaserver/plugins/rabase.py @@ -35,20 +35,22 @@ from ipalib import errors import os from ipaplatform.paths import paths + class rabase(Backend): """ Request Authority backend plugin. """ def __init__(self, api): + self.ca_cert = api.env.tls_ca_cert if api.env.in_tree: - self.sec_dir = api.env.dot_ipa + os.sep + 'alias' - self.pwd_file = self.sec_dir + os.sep + '.pwd' + self.client_certfile = os.path.join( + api.env.dot_ipa, 'ra-agent.pem') + self.client_keyfile = os.path.join(api.env.dot_ipa, 'ra-agent.key') else: - self.sec_dir = paths.IPA_RADB_DIR - self.pwd_file = os.path.join(paths.IPA_RADB_DIR, 'pwdfile.txt') + self.client_certfile = paths.RA_AGENT_PEM + self.client_keyfile = paths.RA_AGENT_KEY super(rabase, self).__init__(api) - def check_request_status(self, request_id): """ Check status of a certificate signing request. diff --git a/ipaserver/plugins/vault.py b/ipaserver/plugins/vault.py index 5c4c09685..57e1ed780 100644 --- a/ipaserver/plugins/vault.py +++ b/ipaserver/plugins/vault.py @@ -816,23 +816,22 @@ class vault_del(LDAPDelete): def post_callback(self, ldap, dn, *args, **options): assert isinstance(dn, DN) - kra_client = self.api.Backend.kra.get_client() + with self.api.Backend.kra.get_client() as kra_client: + kra_account = pki.account.AccountClient(kra_client.connection) + kra_account.login() - kra_account = pki.account.AccountClient(kra_client.connection) - kra_account.login() + client_key_id = self.obj.get_key_id(dn) - client_key_id = self.obj.get_key_id(dn) + # deactivate vault record in KRA + response = kra_client.keys.list_keys( + client_key_id, pki.key.KeyClient.KEY_STATUS_ACTIVE) - # deactivate vault record in KRA - response = kra_client.keys.list_keys( - client_key_id, pki.key.KeyClient.KEY_STATUS_ACTIVE) + for key_info in response.key_infos: + kra_client.keys.modify_key_status( + key_info.get_key_id(), + pki.key.KeyClient.KEY_STATUS_INACTIVE) - for key_info in response.key_infos: - kra_client.keys.modify_key_status( - key_info.get_key_id(), - pki.key.KeyClient.KEY_STATUS_INACTIVE) - - kra_account.logout() + kra_account.logout() return True @@ -987,12 +986,12 @@ class vaultconfig_show(Retrieve): raise errors.InvocationError( format=_('KRA service is not enabled')) - kra_client = self.api.Backend.kra.get_client() - transport_cert = kra_client.system_certs.get_transport_cert() - config = {'transport_cert': transport_cert.binary} - config.update( - self.api.Backend.serverroles.config_retrieve("KRA server") - ) + with self.api.Backend.kra.get_client() as kra_client: + transport_cert = kra_client.system_certs.get_transport_cert() + config = {'transport_cert': transport_cert.binary} + config.update( + self.api.Backend.serverroles.config_retrieve("KRA server") + ) return { 'result': config, @@ -1038,34 +1037,33 @@ class vault_archive_internal(PKQuery): vault = self.api.Command.vault_show(*args, **options)['result'] # connect to KRA - kra_client = self.api.Backend.kra.get_client() - - kra_account = pki.account.AccountClient(kra_client.connection) - kra_account.login() - - client_key_id = self.obj.get_key_id(vault['dn']) - - # deactivate existing vault record in KRA - response = kra_client.keys.list_keys( - client_key_id, - pki.key.KeyClient.KEY_STATUS_ACTIVE) - - for key_info in response.key_infos: - kra_client.keys.modify_key_status( - key_info.get_key_id(), - pki.key.KeyClient.KEY_STATUS_INACTIVE) - - # forward wrapped data to KRA - kra_client.keys.archive_encrypted_data( - client_key_id, - pki.key.KeyClient.PASS_PHRASE_TYPE, - wrapped_vault_data, - wrapped_session_key, - None, - nonce, - ) - - kra_account.logout() + with self.api.Backend.kra.get_client() as kra_client: + kra_account = pki.account.AccountClient(kra_client.connection) + kra_account.login() + + client_key_id = self.obj.get_key_id(vault['dn']) + + # deactivate existing vault record in KRA + response = kra_client.keys.list_keys( + client_key_id, + pki.key.KeyClient.KEY_STATUS_ACTIVE) + + for key_info in response.key_infos: + kra_client.keys.modify_key_status( + key_info.get_key_id(), + pki.key.KeyClient.KEY_STATUS_INACTIVE) + + # forward wrapped data to KRA + kra_client.keys.archive_encrypted_data( + client_key_id, + pki.key.KeyClient.PASS_PHRASE_TYPE, + wrapped_vault_data, + wrapped_session_key, + None, + nonce, + ) + + kra_account.logout() response = { 'value': args[-1], @@ -1105,29 +1103,28 @@ class vault_retrieve_internal(PKQuery): vault = self.api.Command.vault_show(*args, **options)['result'] # connect to KRA - kra_client = self.api.Backend.kra.get_client() - - kra_account = pki.account.AccountClient(kra_client.connection) - kra_account.login() + with self.api.Backend.kra.get_client() as kra_client: + kra_account = pki.account.AccountClient(kra_client.connection) + kra_account.login() - client_key_id = self.obj.get_key_id(vault['dn']) + client_key_id = self.obj.get_key_id(vault['dn']) - # find vault record in KRA - response = kra_client.keys.list_keys( - client_key_id, - pki.key.KeyClient.KEY_STATUS_ACTIVE) + # find vault record in KRA + response = kra_client.keys.list_keys( + client_key_id, + pki.key.KeyClient.KEY_STATUS_ACTIVE) - if not len(response.key_infos): - raise errors.NotFound(reason=_('No archived data.')) + if not len(response.key_infos): + raise errors.NotFound(reason=_('No archived data.')) - key_info = response.key_infos[0] + key_info = response.key_infos[0] - # retrieve encrypted data from KRA - key = kra_client.keys.retrieve_key( - key_info.get_key_id(), - wrapped_session_key) + # retrieve encrypted data from KRA + key = kra_client.keys.retrieve_key( + key_info.get_key_id(), + wrapped_session_key) - kra_account.logout() + kra_account.logout() response = { 'value': args[-1], diff --git a/ipaserver/secrets/store.py b/ipaserver/secrets/store.py index a499aef13..6a448a348 100644 --- a/ipaserver/secrets/store.py +++ b/ipaserver/secrets/store.py @@ -45,12 +45,6 @@ def PKI_TOMCAT_password_callback(): return password -def HTTPD_password_callback(): - with open(os.path.join(paths.IPA_RADB_DIR, 'pwdfile.txt')) as f: - password = f.read() - return password - - class NSSWrappedCertDB(DBMAPHandler): ''' Store that extracts private keys from an NSSDB, wrapped with the @@ -193,11 +187,11 @@ class DMLDAP(DBMAPHandler): class PEMFileHandler(DBMAPHandler): def __init__(self, config, dbmap, nickname=None): - if 'type' not in dbmap or dbmap['type'] != 'OPENSSL': - raise ValueError('Invalid type "{t}", expected OPENSSL' + if 'type' not in dbmap or dbmap['type'] != 'PEM': + raise ValueError('Invalid type "{t}", expected PEM' .format(t=dbmap['type'])) self.certfile = dbmap['certfile'] - self.keyfile = dbmap.get(['keyfile']) + self.keyfile = dbmap.get('keyfile') def export_key(self): _fd, tmpfile = tempfile.mkstemp(dir=paths.TMP) @@ -266,10 +260,10 @@ NAME_DB_MAP = { 'wrap_nick': 'caSigningCert cert-pki-ca', }, 'ra': { - 'type': 'NSSDB', - 'path': paths.IPA_RADB_DIR, - 'handler': NSSCertDB, - 'pwcallback': HTTPD_password_callback, + 'type': 'PEM', + 'handler': PEMFileHandler, + 'certfile': paths.RA_AGENT_PEM, + 'keyfile': paths.RA_AGENT_KEY, }, 'dm': { 'type': 'DMLDAP', diff --git a/ipatests/test_xmlrpc/testcert.py b/ipatests/test_xmlrpc/testcert.py index def820f16..c27ea95b0 100644 --- a/ipatests/test_xmlrpc/testcert.py +++ b/ipatests/test_xmlrpc/testcert.py @@ -79,7 +79,7 @@ def makecert(reqdir, subject, principal): """ ra = rabase.rabase(api) - if (not os.path.exists(ra.sec_dir) and + if (not os.path.exists(ra.client_certfile) and api.env.xmlrpc_uri == 'http://localhost:8888/ipa/xml'): raise AssertionError('The self-signed CA is not configured, ' 'see ipatests/test_xmlrpc/test_cert.py') |