Moving ipaCert from HTTPD_ALIAS_DIR

The "ipaCert" nicknamed certificate is not required to be
in /var/lib/ipa/radb NSSDB anymore as we were keeping a copy
of this file in a separate file anyway. Remove it from there
and track only the file. Remove the IPA_RADB_DIR as well as
it is not required anymore.

https://fedorahosted.org/freeipa/ticket/5695
https://fedorahosted.org/freeipa/ticket/6680

Reviewed-By: Jan Cholasta <jcholast@redhat.com>
This commit is contained in:
Stanislav Laznicka
2017-01-13 09:08:42 +01:00
committed by Jan Cholasta
parent 24b134c633
commit 5ab85b365a
24 changed files with 337 additions and 421 deletions

View File

@@ -217,10 +217,12 @@ def request_cert():
syslog.syslog(syslog.LOG_NOTICE, syslog.syslog(syslog.LOG_NOTICE,
"Forwarding request to dogtag-ipa-renew-agent") "Forwarding request to dogtag-ipa-renew-agent")
path = paths.DOGTAG_IPA_RENEW_AGENT_SUBMIT args = ([paths.DOGTAG_IPA_RENEW_AGENT_SUBMIT,
args = [path, '--dbdir', paths.IPA_RADB_DIR] "--cafile", paths.IPA_CA_CRT,
args.extend(sys.argv[1:]) "--certfile", paths.RA_AGENT_PEM,
args.extend(['--submit-option', "requestor_name=IPA"]) "--keyfile", paths.RA_AGENT_KEY] +
sys.argv[1:] +
['--submit-option', "requestor_name=IPA"])
if os.environ.get('CERTMONGER_CA_PROFILE') == 'caCACert': if os.environ.get('CERTMONGER_CA_PROFILE') == 'caCACert':
args += ['-N', '-O', 'bypassCAnotafter=true'] args += ['-N', '-O', 'bypassCAnotafter=true']
result = ipautil.run(args, raiseonerr=False, env=os.environ, result = ipautil.run(args, raiseonerr=False, env=os.environ,

View File

@@ -27,15 +27,15 @@ import tempfile
import shutil import shutil
import traceback import traceback
from cryptography.hazmat.primitives import serialization
from ipalib.install.kinit import kinit_keytab from ipalib.install.kinit import kinit_keytab
from ipalib import api from ipalib import api, x509
from ipaserver.install import certs, cainstance, dogtaginstance from ipaserver.install import certs, cainstance
from ipaplatform.paths import paths from ipaplatform.paths import paths
def _main(): def _main():
nickname = 'ipaCert'
api.bootstrap(in_server=True, context='restart', confdir=paths.ETC_IPA) api.bootstrap(in_server=True, context='restart', confdir=paths.ETC_IPA)
api.finalize() api.finalize()
api.Backend.ldap2.connect() api.Backend.ldap2.connect()
@@ -48,20 +48,28 @@ def _main():
os.environ['KRB5CCNAME'] = ccache_filename os.environ['KRB5CCNAME'] = ccache_filename
ca = cainstance.CAInstance(host_name=api.env.host) ca = cainstance.CAInstance(host_name=api.env.host)
ra_certpath = paths.RA_AGENT_PEM
if ca.is_renewal_master(): if ca.is_renewal_master():
# Fetch the new certificate # Fetch the new certificate
db = certs.CertDB(api.env.realm) try:
dercert = db.get_cert_from_db(nickname, pem=False) cert = x509.load_certificate_from_file(ra_certpath)
if not dercert: except IOError as e:
syslog.syslog( syslog.syslog(
syslog.LOG_ERR, "No certificate %s found." % nickname) syslog.LOG_ERR, "Can't open '{certpath}': {err}"
.format(certpath=ra_certpath, err=e)
)
sys.exit(1) sys.exit(1)
except (TypeError, ValueError):
syslog.syslog(
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 # Load it into dogtag
cainstance.update_people_entry(dercert) cainstance.update_people_entry(dercert)
if api.Command.kra_is_enabled()['result']:
dogtaginstance.export_ra_agent_pem()
finally: finally:
shutil.rmtree(tmpdir) shutil.rmtree(tmpdir)
api.Backend.ldap2.disconnect() api.Backend.ldap2.disconnect()

View File

@@ -139,7 +139,6 @@ class CertUpdate(admintool.AdminTool):
services.knownservices.dirsrv.restart(instance) services.knownservices.dirsrv.restart(instance)
self.update_db(paths.HTTPD_ALIAS_DIR, certs) self.update_db(paths.HTTPD_ALIAS_DIR, certs)
self.update_db(paths.IPA_RADB_DIR, certs)
if services.knownservices.httpd.is_running(): if services.knownservices.httpd.is_running():
services.knownservices.httpd.restart() services.knownservices.httpd.restart()

View File

@@ -40,7 +40,6 @@ class BasePathNamespace(object):
ETC_HTTPD_DIR = "/etc/httpd" ETC_HTTPD_DIR = "/etc/httpd"
HTTPD_ALIAS_DIR = "/etc/httpd/alias" HTTPD_ALIAS_DIR = "/etc/httpd/alias"
OLD_KRA_AGENT_PEM = "/etc/httpd/alias/kra-agent.pem" 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_CONF_D_DIR = "/etc/httpd/conf.d/"
HTTPD_IPA_KDCPROXY_CONF = "/etc/ipa/kdcproxy/ipa-kdc-proxy.conf" HTTPD_IPA_KDCPROXY_CONF = "/etc/ipa/kdcproxy/ipa-kdc-proxy.conf"
HTTPD_IPA_KDCPROXY_CONF_SYMLINK = "/etc/httpd/conf.d/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" ROOT_PKI = "/root/.pki"
DOGTAG_ADMIN_P12 = "/root/ca-agent.p12" DOGTAG_ADMIN_P12 = "/root/ca-agent.p12"
RA_AGENT_PEM = "/var/lib/ipa/ra-agent.pem" RA_AGENT_PEM = "/var/lib/ipa/ra-agent.pem"
RA_AGENT_KEY = "/var/lib/ipa/ra-agent.key"
CACERT_P12 = "/root/cacert.p12" CACERT_P12 = "/root/cacert.p12"
ROOT_IPA_CSR = "/root/ipa.csr" ROOT_IPA_CSR = "/root/ipa.csr"
NAMED_PID = "/run/named/named.pid" NAMED_PID = "/run/named/named.pid"
@@ -195,6 +195,7 @@ class BasePathNamespace(object):
PAM_KRB5_SO_64 = "/usr/lib64/security/pam_krb5.so" 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_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" 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" IPA_SERVER_GUARD = "/usr/libexec/certmonger/ipa-server-guard"
GENERATE_RNDC_KEY = "/usr/libexec/generate-rndc-key.sh" GENERATE_RNDC_KEY = "/usr/libexec/generate-rndc-key.sh"
IPA_DNSKEYSYNCD_REPLICA = "/usr/libexec/ipa/ipa-dnskeysync-replica" IPA_DNSKEYSYNCD_REPLICA = "/usr/libexec/ipa/ipa-dnskeysync-replica"

View File

@@ -131,8 +131,9 @@ def ca_status(ca_host=None):
return _parse_ca_status(body) return _parse_ca_status(body)
def https_request(host, port, url, cafile, client_certfile, def https_request(
method='POST', headers=None, body=None, **kw): host, port, url, cafile, client_certfile, client_keyfile,
method='POST', headers=None, body=None, **kw):
""" """
:param method: HTTP request method (defalut: 'POST') :param method: HTTP request method (defalut: 'POST')
:param url: The path (not complete URL!) to post to. :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, host, port,
cafile=cafile, cafile=cafile,
client_certfile=client_certfile, client_certfile=client_certfile,
client_keyfile=client_keyfile,
tls_version_min=api.env.tls_version_min, tls_version_min=api.env.tls_version_min,
tls_version_max=api.env.tls_version_max) tls_version_max=api.env.tls_version_max)

View File

@@ -177,14 +177,14 @@ def install_check(standalone, replica_config, options):
if standalone: if standalone:
dirname = dsinstance.config_dirname( dirname = dsinstance.config_dirname(
installutils.realm_to_serverid(realm_name)) 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( dsdb = certs.CertDB(
realm_name, nssdir=dirname, subject_base=options._subject_base) realm_name, nssdir=dirname, subject_base=options._subject_base)
for db in (cadb, dsdb): for db in (cadb, dsdb):
for nickname, _trust_flags in db.list_certs(): for nickname, _trust_flags in db.list_certs():
if nickname in (certdb.get_ca_nickname(realm_name), if nickname == certdb.get_ca_nickname(realm_name):
'ipaCert'):
raise ScriptError( raise ScriptError(
"Certificate with nickname %s is present in %s, " "Certificate with nickname %s is present in %s, "
"cannot continue." % (nickname, db.secdir)) "cannot continue." % (nickname, db.secdir))
@@ -193,8 +193,7 @@ def install_check(standalone, replica_config, options):
if not cert: if not cert:
continue continue
subject = DN(x509.load_certificate(cert).subject) subject = DN(x509.load_certificate(cert).subject)
if subject in (DN(options._ca_subject), if subject == DN(options._ca_subject):
DN('CN=IPA RA', options._subject_base)):
raise ScriptError( raise ScriptError(
"Certificate with subject %s is present in %s, " "Certificate with subject %s is present in %s, "
"cannot continue." % (subject, db.secdir)) "cannot continue." % (subject, db.secdir))
@@ -312,31 +311,26 @@ def install_step_1(standalone, replica_config, options):
dirname = dsinstance.config_dirname(serverid) dirname = dsinstance.config_dirname(serverid)
# Store the new IPA CA cert chain in DS NSS database and LDAP # Store the new IPA CA cert chain in DS NSS database and LDAP
cadb = certs.CertDB(realm_name, subject_base=subject_base) cadb = certs.CertDB(
dsdb = certs.CertDB(realm_name, nssdir=dirname, subject_base=subject_base) realm_name, nssdir=paths.PKI_TOMCAT_ALIAS_DIR,
trust_flags = dict(reversed(cadb.list_certs())) subject_base=subject_base)
trust_chain = cadb.find_root_cert('ipaCert')[:-1] dsdb = certs.CertDB(
for nickname in trust_chain[:-1]: realm_name, nssdir=dirname, subject_base=subject_base)
cert = cadb.get_cert_from_db(nickname, pem=False) cacert = cadb.get_cert_from_db('caSigningCert cert-pki-ca', pem=False)
dsdb.add_cert(cert, nickname, trust_flags[nickname]) nickname = certdb.get_ca_nickname(realm_name)
certstore.put_ca_cert_nss(api.Backend.ldap2, api.env.basedn, trust_flags = 'CT,C,C'
cert, nickname, trust_flags[nickname]) dsdb.add_cert(cacert, nickname, trust_flags)
nickname = 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, 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) config_ipa=True, config_compat=True)
# Store DS CA cert in Dogtag NSS database # 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())) trust_flags = dict(reversed(dsdb.list_certs()))
server_certs = dsdb.find_server_certs() server_certs = dsdb.find_server_certs()
trust_chain = dsdb.find_root_cert(server_certs[0][0])[:-1] trust_chain = dsdb.find_root_cert(server_certs[0][0])[:-1]
nickname = trust_chain[-1] nickname = trust_chain[-1]
cert = dsdb.get_cert_from_db(nickname) 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() installutils.restart_dirsrv()
@@ -356,6 +350,8 @@ def install_step_1(standalone, replica_config, options):
def uninstall(): def uninstall():
ca_instance = cainstance.CAInstance(api.env.realm) ca_instance = cainstance.CAInstance(api.env.realm)
ca_instance.stop_tracking_certificates() ca_instance.stop_tracking_certificates()
installutils.remove_file(paths.RA_AGENT_PEM)
installutils.remove_file(paths.RA_AGENT_KEY)
if ca_instance.is_configured(): if ca_instance.is_configured():
ca_instance.uninstall() ca_instance.uninstall()

View File

@@ -26,6 +26,7 @@ import dbus
import ldap import ldap
import os import os
import pwd import pwd
import grp
import re import re
import shutil import shutil
import sys import sys
@@ -37,6 +38,7 @@ import six
# pylint: disable=import-error # pylint: disable=import-error
from six.moves.configparser import ConfigParser, RawConfigParser from six.moves.configparser import ConfigParser, RawConfigParser
# pylint: enable=import-error # pylint: enable=import-error
from cryptography.hazmat.primitives import serialization
from ipalib import api from ipalib import api
from ipalib import x509 from ipalib import x509
@@ -64,8 +66,7 @@ from ipaserver.install import installutils
from ipaserver.install import ldapupdate from ipaserver.install import ldapupdate
from ipaserver.install import replication from ipaserver.install import replication
from ipaserver.install import sysupgrade from ipaserver.install import sysupgrade
from ipaserver.install.dogtaginstance import ( from ipaserver.install.dogtaginstance import DogtagInstance
DogtagInstance, export_ra_agent_pem)
from ipaserver.plugins import ldap2 from ipaserver.plugins import ldap2
# We need to reset the template because the CA uses the regular boot # 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) self.canickname = get_ca_nickname(realm)
else: else:
self.canickname = None 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.ra_cert = None
self.requestId = None self.requestId = None
self.log = log_mgr.get_logger(self) self.log = log_mgr.get_logger(self)
@@ -378,8 +377,7 @@ class CAInstance(DogtagInstance):
self.external = 2 self.external = 2
if self.clone: if self.clone:
cert_db = certs.CertDB(self.realm) has_ra_cert = os.path.exists(paths.RA_AGENT_PEM)
has_ra_cert = (cert_db.get_cert_from_db('ipaCert') != '')
else: else:
has_ra_cert = False has_ra_cert = False
@@ -415,16 +413,14 @@ class CAInstance(DogtagInstance):
else: else:
self.step("importing RA certificate from PKCS #12 file", self.step("importing RA certificate from PKCS #12 file",
lambda: self.import_ra_cert(ra_p12)) lambda: self.import_ra_cert(ra_p12))
self.step("exporting RA agent cert", export_ra_agent_pem)
if not ra_only: 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 up signing cert profile", self.__setup_sign_profile)
self.step("setting audit signing renewal to 2 years", self.set_audit_renewal) self.step("setting audit signing renewal to 2 years", self.set_audit_renewal)
self.step("restarting certificate server", self.restart_instance) self.step("restarting certificate server", self.restart_instance)
if not self.clone: if not self.clone:
self.step("publishing the CA certificate", 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("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 modify profiles", configure_profiles_acl)
self.step("authorizing RA to manage lightweight CAs", self.step("authorizing RA to manage lightweight CAs",
@@ -683,13 +679,22 @@ class CAInstance(DogtagInstance):
Used when setting up replication Used when setting up replication
""" """
# Add the new RA cert into the RA database # get the private key from the file
with tempfile.NamedTemporaryFile(mode="w") as agent_file: ipautil.run([paths.OPENSSL,
agent_file.write(self.dm_password) "pkcs12",
agent_file.flush() "-in", rafile,
"-nocerts", "-nodes",
"-out", paths.RA_AGENT_KEY,
"-passin", "pass:"])
import_pkcs12( # get the certificate from the pkcs12 file
rafile, agent_file.name, self.ra_agent_db, self.ra_agent_pwd) 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() self.configure_agent_renewal()
@@ -697,18 +702,28 @@ class CAInstance(DogtagInstance):
custodia = custodiainstance.CustodiaInstance(host_name=self.fqdn, custodia = custodiainstance.CustodiaInstance(host_name=self.fqdn,
realm=self.realm) realm=self.realm)
custodia.import_ra_key(self.master_host) custodia.import_ra_key(self.master_host)
self.__set_ra_cert_perms()
self.configure_agent_renewal() 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): def __create_ca_agent(self):
""" """
Create CA agent, assign a certificate, and add the user to Create CA agent, assign a certificate, and add the user to
the appropriate groups for accessing CA services. the appropriate groups for accessing CA services.
""" """
# get ipaCert certificate # get RA certificate
cert_data = base64.b64decode(self.ra_cert) cert_data = self.ra_cert.public_bytes(serialization.Encoding.DER)
cert = x509.load_certificate(cert_data, x509.DER)
# connect to CA database # connect to CA database
server_id = installutils.realm_to_serverid(api.env.realm) 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 = ldap2.ldap2(api, ldap_uri=dogtag_uri)
conn.connect(autobind=True) 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) user_dn = DN(('uid', "ipara"), ('ou', 'People'), self.basedn)
entry = conn.make_entry( entry = conn.make_entry(
user_dn, user_dn,
@@ -729,7 +744,7 @@ class CAInstance(DogtagInstance):
userstate=["1"], userstate=["1"],
userCertificate=[cert_data], userCertificate=[cert_data],
description=['2;%s;%s;%s' % ( description=['2;%s;%s;%s' % (
cert.serial_number, self.ra_cert.serial_number,
DN(self.ca_subject), DN(self.ca_subject),
DN(('CN', 'IPA RA'), self.subject_base))]) DN(('CN', 'IPA RA'), self.subject_base))])
conn.add_entry(entry) conn.add_entry(entry)
@@ -746,57 +761,30 @@ class CAInstance(DogtagInstance):
conn.disconnect() 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): def __get_ca_chain(self):
try: try:
return dogtag.get_ca_certchain(ca_host=self.fqdn) return dogtag.get_ca_certchain(ca_host=self.fqdn)
except Exception as e: except Exception as e:
raise RuntimeError("Unable to retrieve CA chain: %s" % str(e)) raise RuntimeError("Unable to retrieve CA chain: %s" % str(e))
def __import_ca_chain(self): def __export_ca_chain(self):
# Backup NSS trust flags of all already existing certificates """
certdb = certs.CertDB(self.realm) Get the CA chain from Dogtag NSS DB and write it to paths.IPA_CA_CRT
cert_backup_list = certdb.list_certs() """
# Getting Dogtag CA chain
chain = self.__get_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 # Convert to DER because the chain comes back as one long string which
# makes openssl throw up. # makes openssl throw up.
data = base64.b64decode(chain) data = base64.b64decode(chain)
# Get list of PEM certificates
certlist = x509.pkcs7_to_pems(data, x509.DER) certlist = x509.pkcs7_to_pems(data, x509.DER)
# Ok, now we have all the certificates in certs, walk through it # We have all the certificates in certlist, write them to a PEM file
# and pull out each certificate and add it to our database
ca_dn = DN(self.ca_subject)
for cert in certlist: for cert in certlist:
with tempfile.NamedTemporaryFile(mode="w") as chain_file: with open(paths.IPA_CA_CRT, 'w') as ipaca_pem:
chain_file.write(cert) ipaca_pem.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)
def __request_ra_certificate(self): def __request_ra_certificate(self):
# create a temp file storing the pwd # create a temp file storing the pwd
@@ -812,7 +800,7 @@ class CAInstance(DogtagInstance):
chain = self.__get_ca_chain() chain = self.__get_ca_chain()
data = base64.b64decode(chain) data = base64.b64decode(chain)
result = ipautil.run( ipautil.run(
[paths.OPENSSL, [paths.OPENSSL,
"pkcs7", "pkcs7",
"-inform", "-inform",
@@ -839,24 +827,19 @@ class CAInstance(DogtagInstance):
# The certificate must be requested using caServerCert profile # The certificate must be requested using caServerCert profile
# because this profile does not require agent authentication # because this profile does not require agent authentication
reqId = certmonger.request_and_wait_for_cert( reqId = certmonger.request_and_wait_for_cert(
certpath=self.ra_agent_db, certpath=(paths.RA_AGENT_PEM, paths.RA_AGENT_KEY),
nickname='ipaCert',
principal='host/%s' % self.fqdn, principal='host/%s' % self.fqdn,
passwd_fname=self.ra_agent_pwd,
subject=str(DN(('CN', 'IPA RA'), self.subject_base)), subject=str(DN(('CN', 'IPA RA'), self.subject_base)),
ca=ipalib.constants.RENEWAL_CA_NAME, ca=ipalib.constants.RENEWAL_CA_NAME,
profile='caServerCert', profile='caServerCert',
pre_command='renew_ra_cert_pre', 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) self.requestId = str(reqId)
certdb = certs.CertDB(self.realm) self.ra_cert = x509.load_certificate_from_file(
result = certdb.run_certutil( paths.RA_AGENT_PEM)
['-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())
finally: finally:
# we can restore the helper parameters # we can restore the helper parameters
certmonger.modify_ca_helper( certmonger.modify_ca_helper(
@@ -1013,12 +996,11 @@ class CAInstance(DogtagInstance):
def configure_agent_renewal(self): def configure_agent_renewal(self):
try: try:
certmonger.start_tracking( certmonger.start_tracking(
certpath=self.ra_agent_db, certpath=(paths.RA_AGENT_PEM, paths.RA_AGENT_KEY),
ca='dogtag-ipa-ca-renew-agent', ca='dogtag-ipa-ca-renew-agent',
nickname='ipaCert',
pinfile=self.ra_agent_pwd,
pre_command='renew_ra_cert_pre', pre_command='renew_ra_cert_pre',
post_command='renew_ra_cert') post_command='renew_ra_cert',
storage='FILE')
except RuntimeError as e: except RuntimeError as e:
self.log.error( self.log.error(
"certmonger failed to start tracking certificate: %s", e) "certmonger failed to start tracking certificate: %s", e)
@@ -1035,7 +1017,7 @@ class CAInstance(DogtagInstance):
certmonger.stop_tracking(self.nss_db, nickname=nickname) certmonger.stop_tracking(self.nss_db, nickname=nickname)
try: try:
certmonger.stop_tracking(self.ra_agent_db, nickname='ipaCert') certmonger.stop_tracking(certfile=paths.RA_AGENT_PEM)
except RuntimeError as e: except RuntimeError as e:
root_logger.error( root_logger.error(
"certmonger failed to stop tracking certificate: %s", e) "certmonger failed to stop tracking certificate: %s", e)

View File

@@ -97,7 +97,7 @@ class CertDB(object):
""" """
# TODO: Remove all selfsign code # 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, host_name=None, subject_base=None, ca_subject=None,
user=None, group=None, mode=None, truncate=False): user=None, group=None, mode=None, truncate=False):
self.nssdb = NSSDatabase(nssdir) self.nssdb = NSSDatabase(nssdir)
@@ -417,6 +417,7 @@ class CertDB(object):
url="/ca/ee/ca/profileSubmitSSLClient", url="/ca/ee/ca/profileSubmitSSLClient",
cafile=api.env.tls_ca_cert, cafile=api.env.tls_ca_cert,
client_certfile=paths.RA_AGENT_PEM, client_certfile=paths.RA_AGENT_PEM,
client_keyfile=paths.RA_AGENT_KEY,
**params) **params)
http_status, _http_headers, http_body = result http_status, _http_headers, http_body = result
root_logger.debug("CA answer: %s", http_body) root_logger.debug("CA answer: %s", http_body)
@@ -471,6 +472,7 @@ class CertDB(object):
url="/ca/ee/ca/profileSubmitSSLClient", url="/ca/ee/ca/profileSubmitSSLClient",
cafile=api.env.tls_ca_cert, cafile=api.env.tls_ca_cert,
client_certfile=paths.RA_AGENT_PEM, client_certfile=paths.RA_AGENT_PEM,
client_keyfile=paths.RA_AGENT_KEY,
**params) **params)
http_status, _http_headers, http_body = result http_status, _http_headers, http_body = result
if http_status != 200: if http_status != 200:

View File

@@ -112,6 +112,10 @@ class CustodiaInstance(SimpleServiceInstance):
def import_ra_key(self, master_host_name): def import_ra_key(self, master_host_name):
cli = self.__CustodiaClient(server=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') cli.fetch_key('ra/ipaCert')
def import_dm_password(self, master_host_name): def import_dm_password(self, master_host_name):

View File

@@ -21,17 +21,13 @@ import base64
import ldap import ldap
import os import os
import shutil import shutil
import tempfile
import traceback import traceback
import dbus import dbus
import pwd
from pki.client import PKIConnection from pki.client import PKIConnection
import pki.system import pki.system
from ipalib import api, errors from ipalib import api, errors
from ipalib.constants import IPAAPI_USER
from ipalib.install import certmonger from ipalib.install import certmonger
from ipaplatform import services from ipaplatform import services
from ipaplatform.constants import constants from ipaplatform.constants import constants
@@ -72,27 +68,6 @@ def is_installing_replica(sys_type):
return False 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): class DogtagInstance(service.Service):
""" """
This is the base class for a Dogtag 10+ instance, which uses a This is the base class for a Dogtag 10+ instance, which uses a

View File

@@ -811,13 +811,14 @@ class DsInstance(service.Service):
'restart_dirsrv %s' % self.serverid) 'restart_dirsrv %s' % self.serverid)
else: else:
dsdb.create_from_cacert() dsdb.create_from_cacert()
ca_args = ['/usr/libexec/certmonger/dogtag-submit', ca_args = [
'--ee-url', 'https://%s:8443/ca/ee/ca' % self.fqdn, paths.CERTMONGER_DOGTAG_SUBMIT,
'--dbdir', paths.IPA_RADB_DIR, '--ee-url', 'https://%s:8443/ca/ee/ca' % self.fqdn,
'--nickname', 'ipaCert', '--certfile', paths.RA_AGENT_PEM,
'--sslpinfile', os.path.join(paths.IPA_RADB_DIR, '--keyfile', paths.RA_AGENT_KEY,
'pwdfile.txt'), '--cafile', paths.IPA_CA_CRT,
'--agent-submit'] '--agent-submit'
]
helper = " ".join(ca_args) helper = " ".join(ca_args)
prev_helper = certmonger.modify_ca_helper('IPA', helper) prev_helper = certmonger.modify_ca_helper('IPA', helper)
try: try:

View File

@@ -384,14 +384,13 @@ class HTTPInstance(service.Service):
if not self.promote: if not self.promote:
self.create_password_conf() self.create_password_conf()
ca_args = [ ca_args = [
'/usr/libexec/certmonger/dogtag-submit', paths.CERTMONGER_DOGTAG_SUBMIT,
'--ee-url', 'https://%s:8443/ca/ee/ca' % self.fqdn, '--ee-url', 'https://%s:8443/ca/ee/ca' % self.fqdn,
'--dbdir', paths.IPA_RADB_DIR, '--certfile', paths.RA_AGENT_PEM,
'--nickname', 'ipaCert', '--keyfile', paths.RA_AGENT_KEY,
'--sslpinfile', os.path.join(paths.IPA_RADB_DIR, '--cafile', paths.IPA_CA_CRT,
'pwdfile.txt'),
'--agent-submit' '--agent-submit'
] ]
helper = " ".join(ca_args) helper = " ".join(ca_args)
prev_helper = certmonger.modify_ca_helper('IPA', helper) 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.") raise RuntimeError("Could not find a suitable server cert.")
def __import_ca_certs(self): 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, db = certs.CertDB(self.realm, nssdir=paths.HTTPD_ALIAS_DIR,
subject_base=self.subject_base) subject_base=self.subject_base)
self.import_ca_certs(db, self.ca_is_configured) self.import_ca_certs(db, self.ca_is_configured)

View File

@@ -107,7 +107,6 @@ class Backup(admintool.AdminTool):
paths.PKI_TOMCAT, paths.PKI_TOMCAT,
paths.SYSCONFIG_PKI, paths.SYSCONFIG_PKI,
paths.HTTPD_ALIAS_DIR, paths.HTTPD_ALIAS_DIR,
paths.IPA_RADB_DIR,
paths.VAR_LIB_PKI_DIR, paths.VAR_LIB_PKI_DIR,
paths.SYSRESTORE, paths.SYSRESTORE,
paths.IPA_CLIENT_SYSRESTORE, paths.IPA_CLIENT_SYSRESTORE,
@@ -159,6 +158,7 @@ class Backup(admintool.AdminTool):
paths.SAMBA_KEYTAB, paths.SAMBA_KEYTAB,
paths.DOGTAG_ADMIN_P12, paths.DOGTAG_ADMIN_P12,
paths.RA_AGENT_PEM, paths.RA_AGENT_PEM,
paths.RA_AGENT_KEY,
paths.CACERT_P12, paths.CACERT_P12,
paths.KRACERT_P12, paths.KRACERT_P12,
paths.KRB5KDC_KDC_CONF, paths.KRB5KDC_KDC_CONF,

View File

@@ -631,18 +631,16 @@ class ReplicaPrepare(admintool.AdminTool):
raise admintool.ScriptError(str(e)) raise admintool.ScriptError(str(e))
def export_ra_pkcs12(self): def export_ra_pkcs12(self):
agent_fd, agent_name = tempfile.mkstemp() if (os.path.exists(paths.RA_AGENT_PEM) and
os.write(agent_fd, self.dirman_password) os.path.exists(paths.RA_AGENT_KEY)):
os.close(agent_fd) ipautil.run([
paths.OPENSSL,
try: "pkcs12", "-export",
db = certs.CertDB(api.env.realm, host_name=api.env.host) "-inkey", paths.RA_AGENT_KEY,
"-in", paths.RA_AGENT_PEM,
if db.has_nickname("ipaCert"): "-out", os.path.join(self.dir, "ra.p12"),
pkcs12_fname = os.path.join(self.dir, "ra.p12") "-passout", "pass:"
db.export_pkcs12(pkcs12_fname, agent_name, "ipaCert") ])
finally:
os.remove(agent_name)
def update_pki_admin_password(self): def update_pki_admin_password(self):
dn = DN('uid=admin', 'ou=people', 'o=ipaca') dn = DN('uid=admin', 'ou=people', 'o=ipaca')

View File

@@ -26,11 +26,11 @@ import six
# pylint: disable=import-error # pylint: disable=import-error
from six.moves.configparser import ConfigParser from six.moves.configparser import ConfigParser
# pylint: enable=import-error # pylint: enable=import-error
from cryptography.hazmat.primitives import serialization
from ipalib import api from ipalib import api
from ipalib import x509 from ipalib import x509
from ipaplatform.paths import paths from ipaplatform.paths import paths
from ipapython import certdb
from ipapython import ipautil from ipapython import ipautil
from ipapython.dn import DN from ipapython.dn import DN
from ipaserver.install import cainstance from ipaserver.install import cainstance
@@ -290,10 +290,9 @@ class KRAInstance(DogtagInstance):
the appropriate groups for accessing KRA services. the appropriate groups for accessing KRA services.
""" """
# get ipaCert certificate # get RA agent certificate
with certdb.NSSDatabase(paths.IPA_RADB_DIR) as ipa_nssdb: cert = x509.load_certificate_from_file(paths.RA_AGENT_PEM)
cert_data = ipa_nssdb.get_cert("ipaCert") cert_data = cert.public_bytes(serialization.Encoding.DER)
cert = x509.load_certificate(cert_data, x509.DER)
# connect to KRA database # connect to KRA database
server_id = installutils.realm_to_serverid(api.env.realm) 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 = ldap2.ldap2(api, ldap_uri=dogtag_uri)
conn.connect(autobind=True) 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) user_dn = DN(('uid', "ipakra"), ('ou', 'people'), self.basedn)
entry = conn.make_entry( entry = conn.make_entry(
user_dn, user_dn,

View File

@@ -74,17 +74,16 @@ class update_ca_renewal_master(Updater):
return False, [] return False, []
criteria = { criteria = {
'cert-database': paths.HTTPD_ALIAS_DIR, 'cert-file': paths.RA_AGENT_PEM,
'cert-nickname': 'ipaCert',
} }
request_id = certmonger.get_request_id(criteria) request_id = certmonger.get_request_id(criteria)
if request_id is not None: 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') ca_name = certmonger.get_request_value(request_id, 'ca-name')
if ca_name is None: if ca_name is None:
self.warning( 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") "assuming local CA is renewal slave")
return False, [] return False, []
ca_name = ca_name.strip() ca_name = ca_name.strip()
@@ -97,11 +96,11 @@ class update_ca_renewal_master(Updater):
return False, [] return False, []
else: else:
self.warning( 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) "assuming local CA is renewal slave", ca_name)
return False, [] return False, []
else: else:
self.debug("certmonger request for ipaCert not found") self.debug("certmonger request for RA cert not found")
config = installutils.get_directive( config = installutils.get_directive(
paths.CA_CS_CFG_PATH, 'subsystem.select', '=') paths.CA_CS_CFG_PATH, 'subsystem.select', '=')

View File

@@ -2,15 +2,15 @@
# Copyright (C) 2016 FreeIPA Contributors see COPYING for license # Copyright (C) 2016 FreeIPA Contributors see COPYING for license
# #
import binascii
import os import os
import tempfile
from ipalib import Registry from ipalib import Registry
from ipalib import Updater from ipalib import Updater
from ipalib.constants import IPAAPI_USER, IPAAPI_GROUP
from ipalib.install import certmonger from ipalib.install import certmonger
from ipaplatform.paths import paths from ipaplatform.paths import paths
from ipapython import certdb from ipapython.certdb import NSSDatabase
from ipaserver.install import cainstance
register = Registry() register = Registry()
@@ -18,58 +18,44 @@ register = Registry()
@register() @register()
class update_ra_cert_store(Updater): 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): def execute(self, **options):
ra_nick = 'ipaCert'
ca_enabled = self.api.Command.ca_is_enabled()['result'] ca_enabled = self.api.Command.ca_is_enabled()['result']
if not ca_enabled: if not ca_enabled:
return False, [] return False, []
olddb = certdb.NSSDatabase(nssdir=paths.HTTPD_ALIAS_DIR) certdb = NSSDatabase(nssdir=paths.HTTPD_ALIAS_DIR)
if not olddb.has_nickname('ipaCert'): if not certdb.has_nickname(ra_nick):
# Nothign to do # Nothign to do
return False, [] return False, []
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))
newdb = certdb.NSSDatabase(nssdir=paths.IPA_RADB_DIR) _fd, p12file = tempfile.mkstemp(dir=certdb.secdir)
if os.path.exists(paths.IPA_RADB_DIR): # no password is necessary as we will be saving it in clear anyway
if newdb.has_nickname('ipaCert'): certdb.export_pkcs12(ra_nick, p12file, pkcs12_passwd='')
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) # stop tracking the old cert and remove it
certlist = olddb.list_certs() certmonger.stop_tracking(paths.HTTPD_ALIAS_DIR, nickname=ra_nick)
certflags = {} certdb.delete_cert(ra_nick)
for name, flags in certlist: if os.path.exists(paths.OLD_KRA_AGENT_PEM):
certflags[name] = flags os.remove(paths.OLD_KRA_AGENT_PEM)
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 # get the private key and certificate from the file and start
pw = binascii.hexlify(os.urandom(10)) # tracking it in certmonger
p12file = os.path.join(paths.IPA_RADB_DIR, 'ipaCert.p12') ca = cainstance.CAInstance()
olddb.export_pkcs12('ipaCert', p12file, pw) ca.import_ra_cert(p12file)
newdb.import_pkcs12(p12file, pw)
certmonger.stop_tracking(secdir=olddb.secdir, os.remove(p12file)
nickname='ipaCert')
certmonger.start_tracking(certpath=newdb.secdir,
nickname='ipaCert',
pinfile=newdb.pwd_file)
olddb.delete_cert('ipaCert')
return False, [] return False, []

View File

@@ -14,7 +14,6 @@ import textwrap
import six import six
from ipalib.constants import IPAAPI_USER, IPAAPI_GROUP
from ipalib.install import certmonger, sysrestore from ipalib.install import certmonger, sysrestore
from ipapython import ipautil from ipapython import ipautil
from ipapython.ipa_log_manager import root_logger from ipapython.ipa_log_manager import root_logger
@@ -24,7 +23,8 @@ from ipapython.admintool import ScriptError
from ipaplatform import services from ipaplatform import services
from ipaplatform.paths import paths from ipaplatform.paths import paths
from ipaplatform.tasks import tasks 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 ( from ipalib.util import (
validate_domain_name, validate_domain_name,
network_ip_address_warning, network_ip_address_warning,
@@ -32,7 +32,7 @@ from ipalib.util import (
) )
import ipaclient.install.ntpconf import ipaclient.install.ntpconf
from ipaserver.install import ( from ipaserver.install import (
bindinstance, ca, certs, dns, dsinstance, bindinstance, ca, dns, dsinstance,
httpinstance, installutils, kra, krbinstance, httpinstance, installutils, kra, krbinstance,
ntpinstance, otpdinstance, custodiainstance, replication, service, ntpinstance, otpdinstance, custodiainstance, replication, service,
sysupgrade) sysupgrade)
@@ -774,11 +774,6 @@ def install(installer):
if n in options.__dict__} if n in options.__dict__}
write_cache(cache_vars) 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) ca.install_step_0(False, None, options)
else: else:
# Put the CA cert where other instances expect it # Put the CA cert where other instances expect it
@@ -987,7 +982,7 @@ def uninstall_check(installer):
else: else:
dns.uninstall_check(options) dns.uninstall_check(options)
if domain_level == constants.DOMAIN_LEVEL_0: if domain_level == DOMAIN_LEVEL_0:
rm = replication.ReplicationManager( rm = replication.ReplicationManager(
realm=api.env.realm, realm=api.env.realm,
hostname=api.env.host, hostname=api.env.host,
@@ -1102,8 +1097,7 @@ def uninstall(installer):
# Note that this name will be wrong after the first uninstall. # Note that this name will be wrong after the first uninstall.
dirname = dsinstance.config_dirname( dirname = dsinstance.config_dirname(
installutils.realm_to_serverid(api.env.realm)) installutils.realm_to_serverid(api.env.realm))
dirs = [dirname, paths.PKI_TOMCAT_ALIAS_DIR, paths.HTTPD_ALIAS_DIR, dirs = [dirname, paths.PKI_TOMCAT_ALIAS_DIR, paths.HTTPD_ALIAS_DIR]
paths.IPA_RADB_DIR]
ids = certmonger.check_state(dirs) ids = certmonger.check_state(dirs)
if ids: if ids:
root_logger.error('Some certificates may still be tracked by ' root_logger.error('Some certificates may still be tracked by '
@@ -1116,11 +1110,6 @@ def uninstall(installer):
' # getcert stop-tracking -i <request_id>\n' ' # getcert stop-tracking -i <request_id>\n'
'for each id in: %s' % ', '.join(ids)) 'for each id in: %s' % ', '.join(ids))
try:
shutil.rmtree(paths.IPA_RADB_DIR)
except Exception:
pass
# Remove the cert renewal lock file # Remove the cert renewal lock file
try: try:
os.remove(paths.IPA_RENEWAL_LOCK) os.remove(paths.IPA_RENEWAL_LOCK)

View File

@@ -900,77 +900,72 @@ def certificate_renewal_update(ca, ds, http):
template = paths.CERTMONGER_COMMAND_TEMPLATE template = paths.CERTMONGER_COMMAND_TEMPLATE
serverid = installutils.realm_to_serverid(api.env.realm) serverid = installutils.realm_to_serverid(api.env.realm)
dirsrv_dir = dsinstance.config_dirname(serverid)
# bump version when requests is changed # bump version when requests is changed
version = 6 version = 6
requests = ( requests = [
( {
paths.PKI_TOMCAT_ALIAS_DIR, 'cert-database': paths.PKI_TOMCAT_ALIAS_DIR,
'auditSigningCert cert-pki-ca', 'cert-nickname': 'auditSigningCert cert-pki-ca',
'dogtag-ipa-ca-renew-agent', 'ca': 'dogtag-ipa-ca-renew-agent',
template % 'stop_pkicad', 'cert-presave-command': template % 'stop_pkicad',
'%s "auditSigningCert cert-pki-ca"' % (template % 'renew_ca_cert'), 'cert-postsave-command':
None, (template % 'renew_ca_cert "auditSigningCert cert-pki-ca"'),
), },
( {
paths.PKI_TOMCAT_ALIAS_DIR, 'cert-database': paths.PKI_TOMCAT_ALIAS_DIR,
'ocspSigningCert cert-pki-ca', 'cert-nickname': 'ocspSigningCert cert-pki-ca',
'dogtag-ipa-ca-renew-agent', 'ca': 'dogtag-ipa-ca-renew-agent',
template % 'stop_pkicad', 'cert-presave-command': template % 'stop_pkicad',
'%s "ocspSigningCert cert-pki-ca"' % (template % 'renew_ca_cert'), 'cert-postsave-command':
None, (template % 'renew_ca_cert "ocspSigningCert cert-pki-ca"'),
), },
( {
paths.PKI_TOMCAT_ALIAS_DIR, 'cert-database': paths.PKI_TOMCAT_ALIAS_DIR,
'subsystemCert cert-pki-ca', 'cert-nickname': 'subsystemCert cert-pki-ca',
'dogtag-ipa-ca-renew-agent', 'ca': 'dogtag-ipa-ca-renew-agent',
template % 'stop_pkicad', 'cert-presave-command': template % 'stop_pkicad',
'%s "subsystemCert cert-pki-ca"' % (template % 'renew_ca_cert'), 'cert-postsave-command':
None, (template % 'renew_ca_cert "subsystemCert cert-pki-ca"'),
), },
( {
paths.PKI_TOMCAT_ALIAS_DIR, 'cert-database': paths.PKI_TOMCAT_ALIAS_DIR,
'caSigningCert cert-pki-ca', 'cert-nickname': 'caSigningCert cert-pki-ca',
'dogtag-ipa-ca-renew-agent', 'ca': 'dogtag-ipa-ca-renew-agent',
template % 'stop_pkicad', 'cert-presave-command': template % 'stop_pkicad',
'%s "caSigningCert cert-pki-ca"' % (template % 'renew_ca_cert'), 'cert-postsave-command':
'ipaCACertRenewal', (template % 'renew_ca_cert "caSigningCert cert-pki-ca"'),
), 'template-profile': 'ipaCACertRenewal',
( },
paths.IPA_RADB_DIR, {
'ipaCert', 'cert-database': paths.PKI_TOMCAT_ALIAS_DIR,
'dogtag-ipa-ca-renew-agent', 'cert-nickname': 'Server-Cert cert-pki-ca',
template % 'renew_ra_cert_pre', 'ca': 'dogtag-ipa-ca-renew-agent',
template % 'renew_ra_cert', 'cert-presave-command': template % 'stop_pkicad',
None, 'cert-postsave-command':
), (template % 'renew_ca_cert "Server-Cert cert-pki-ca"'),
( },
paths.PKI_TOMCAT_ALIAS_DIR, {
'Server-Cert cert-pki-ca', 'cert-file': paths.RA_AGENT_PEM,
'dogtag-ipa-ca-renew-agent', 'key-file': paths.RA_AGENT_KEY,
template % 'stop_pkicad', 'ca': 'dogtag-ipa-ca-renew-agent',
'%s "Server-Cert cert-pki-ca"' % (template % 'renew_ca_cert'), 'cert-presave-command': template % 'renew_ra_cert_pre',
None, 'cert-postsave-command': template % 'renew_ra_cert',
), },
( {
paths.HTTPD_ALIAS_DIR, 'cert-database': paths.HTTPD_ALIAS_DIR,
'Server-Cert', 'cert-nickname': 'Server-Cert',
'IPA', 'ca': 'IPA',
None, 'cert-postsave-command': template % 'restart_httpd',
template % 'restart_httpd', },
None, {
), 'cert-database': dsinstance.config_dirname(serverid),
( 'cert-nickname': 'Server-Cert',
dirsrv_dir, 'ca': 'IPA',
'Server-Cert', 'cert-postsave-command':
'IPA', '%s %s' % (template % 'restart_dirsrv', serverid),
None, }
'%s %s' % (template % 'restart_dirsrv', serverid), ]
None,
),
)
root_logger.info("[Update certmonger certificate renewal configuration to " root_logger.info("[Update certmonger certificate renewal configuration to "
"version %d]" % version) "version %d]" % version)
@@ -984,16 +979,7 @@ def certificate_renewal_update(ca, ds, http):
# State not set, lets see if we are already configured # State not set, lets see if we are already configured
for request in requests: for request in requests:
nss_dir, nickname, ca_name, pre_command, post_command, profile = request request_id = certmonger.get_request_id(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)
if request_id is None: if request_id is None:
break break
else: else:
@@ -1402,24 +1388,6 @@ def fix_trust_flags():
sysupgrade.set_upgrade_state('http', 'fix_trust_flags', True) 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): def update_mod_nss_protocol(http):
root_logger.info('[Updating mod_nss protocol versions]') root_logger.info('[Updating mod_nss protocol versions]')
@@ -1663,7 +1631,6 @@ def upgrade_configuration():
update_mod_nss_protocol(http) update_mod_nss_protocol(http)
update_mod_nss_cipher_suite(http) update_mod_nss_cipher_suite(http)
fix_trust_flags() fix_trust_flags()
export_ra_agent_pem()
update_http_keytab(http) update_http_keytab(http)
http.configure_gssproxy() http.configure_gssproxy()
http.start() http.start()

View File

@@ -243,6 +243,7 @@ import datetime
import json import json
from lxml import etree from lxml import etree
import time import time
import contextlib
import six import six
from six.moves import urllib from six.moves import urllib
@@ -250,8 +251,7 @@ from six.moves import urllib
from ipalib import Backend, api from ipalib import Backend, api
from ipapython.dn import DN from ipapython.dn import DN
import ipapython.cookie import ipapython.cookie
from ipapython import dogtag from ipapython import dogtag, ipautil, certdb
from ipapython import ipautil
if api.env.in_server: if api.env.in_server:
import pki import pki
@@ -1242,8 +1242,12 @@ class RestClient(Backend):
if api.env.in_tree: if api.env.in_tree:
self.client_certfile = os.path.join( self.client_certfile = os.path.join(
api.env.dot_ipa, 'ra-agent.pem') api.env.dot_ipa, 'ra-agent.pem')
self.client_keyfile = os.path.join(
api.env.dot_ipa, 'ra-agent.key')
else: else:
self.client_certfile = paths.RA_AGENT_PEM self.client_certfile = paths.RA_AGENT_PEM
self.client_keyfile = paths.RA_AGENT_KEY
super(RestClient, self).__init__(api) super(RestClient, self).__init__(api)
# session cookie # session cookie
@@ -1279,6 +1283,7 @@ class RestClient(Backend):
url='/ca/rest/account/login', url='/ca/rest/account/login',
cafile=self.ca_cert, cafile=self.ca_cert,
client_certfile=self.client_certfile, client_certfile=self.client_certfile,
client_keyfile=self.client_keyfile,
method='GET' method='GET'
) )
cookies = ipapython.cookie.Cookie.parse(resp_headers.get('set-cookie', '')) cookies = ipapython.cookie.Cookie.parse(resp_headers.get('set-cookie', ''))
@@ -1294,6 +1299,7 @@ class RestClient(Backend):
url='/ca/rest/account/logout', url='/ca/rest/account/logout',
cafile=self.ca_cert, cafile=self.ca_cert,
client_certfile=self.client_certfile, client_certfile=self.client_certfile,
client_keyfile=self.client_keyfile,
method='GET' method='GET'
) )
self.cookie = None self.cookie = None
@@ -1337,6 +1343,7 @@ class RestClient(Backend):
url=resource, url=resource,
cafile=self.ca_cert, cafile=self.ca_cert,
client_certfile=self.client_certfile, client_certfile=self.client_certfile,
client_keyfile=self.client_keyfile,
method=method, headers=headers, body=body method=method, headers=headers, body=body
) )
if status < 200 or status >= 300: if status < 200 or status >= 300:
@@ -1421,6 +1428,7 @@ class ra(rabase.rabase, RestClient):
self.ca_host, port, url, self.ca_host, port, url,
cafile=self.ca_cert, cafile=self.ca_cert,
client_certfile=self.client_certfile, client_certfile=self.client_certfile,
client_keyfile=self.client_keyfile,
**kw) **kw)
def get_parse_result_xml(self, xml_text, parse_func): def get_parse_result_xml(self, xml_text, parse_func):
@@ -1998,6 +2006,7 @@ class kra(Backend):
else: else:
return api.env.ca_host return api.env.ca_host
@contextlib.contextmanager
def get_client(self): def get_client(self):
""" """
Returns an authenticated KRA client to access KRA services. Returns an authenticated KRA client to access KRA services.
@@ -2009,9 +2018,11 @@ class kra(Backend):
# TODO: replace this with a more specific exception # TODO: replace this with a more specific exception
raise RuntimeError('KRA service is not enabled') raise RuntimeError('KRA service is not enabled')
tempdb = certdb.NSSDatabase()
tempdb.create_db()
crypto = cryptoutil.NSSCryptoProvider( crypto = cryptoutil.NSSCryptoProvider(
paths.IPA_RADB_DIR, tempdb.secdir,
password_file=os.path.join(paths.IPA_RADB_DIR, 'pwdfile.txt')) password_file=tempdb.pwd_file)
# TODO: obtain KRA host & port from IPA service list or point to KRA load balancer # TODO: obtain KRA host & port from IPA service list or point to KRA load balancer
# https://fedorahosted.org/freeipa/ticket/4557 # https://fedorahosted.org/freeipa/ticket/4557
@@ -2021,9 +2032,16 @@ class kra(Backend):
str(self.kra_port), str(self.kra_port),
'kra') '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() @register()

View File

@@ -35,20 +35,22 @@ from ipalib import errors
import os import os
from ipaplatform.paths import paths from ipaplatform.paths import paths
class rabase(Backend): class rabase(Backend):
""" """
Request Authority backend plugin. Request Authority backend plugin.
""" """
def __init__(self, api): def __init__(self, api):
self.ca_cert = api.env.tls_ca_cert
if api.env.in_tree: if api.env.in_tree:
self.sec_dir = api.env.dot_ipa + os.sep + 'alias' self.client_certfile = os.path.join(
self.pwd_file = self.sec_dir + os.sep + '.pwd' api.env.dot_ipa, 'ra-agent.pem')
self.client_keyfile = os.path.join(api.env.dot_ipa, 'ra-agent.key')
else: else:
self.sec_dir = paths.IPA_RADB_DIR self.client_certfile = paths.RA_AGENT_PEM
self.pwd_file = os.path.join(paths.IPA_RADB_DIR, 'pwdfile.txt') self.client_keyfile = paths.RA_AGENT_KEY
super(rabase, self).__init__(api) super(rabase, self).__init__(api)
def check_request_status(self, request_id): def check_request_status(self, request_id):
""" """
Check status of a certificate signing request. Check status of a certificate signing request.

View File

@@ -816,23 +816,22 @@ class vault_del(LDAPDelete):
def post_callback(self, ldap, dn, *args, **options): def post_callback(self, ldap, dn, *args, **options):
assert isinstance(dn, DN) 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) client_key_id = self.obj.get_key_id(dn)
kra_account.login()
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 for key_info in response.key_infos:
response = kra_client.keys.list_keys( kra_client.keys.modify_key_status(
client_key_id, pki.key.KeyClient.KEY_STATUS_ACTIVE) key_info.get_key_id(),
pki.key.KeyClient.KEY_STATUS_INACTIVE)
for key_info in response.key_infos: kra_account.logout()
kra_client.keys.modify_key_status(
key_info.get_key_id(),
pki.key.KeyClient.KEY_STATUS_INACTIVE)
kra_account.logout()
return True return True
@@ -987,12 +986,12 @@ class vaultconfig_show(Retrieve):
raise errors.InvocationError( raise errors.InvocationError(
format=_('KRA service is not enabled')) format=_('KRA service is not enabled'))
kra_client = self.api.Backend.kra.get_client() with self.api.Backend.kra.get_client() as kra_client:
transport_cert = kra_client.system_certs.get_transport_cert() transport_cert = kra_client.system_certs.get_transport_cert()
config = {'transport_cert': transport_cert.binary} config = {'transport_cert': transport_cert.binary}
config.update( config.update(
self.api.Backend.serverroles.config_retrieve("KRA server") self.api.Backend.serverroles.config_retrieve("KRA server")
) )
return { return {
'result': config, 'result': config,
@@ -1038,34 +1037,33 @@ class vault_archive_internal(PKQuery):
vault = self.api.Command.vault_show(*args, **options)['result'] vault = self.api.Command.vault_show(*args, **options)['result']
# connect to KRA # connect to KRA
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) client_key_id = self.obj.get_key_id(vault['dn'])
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)
# deactivate existing vault record in KRA for key_info in response.key_infos:
response = kra_client.keys.list_keys( kra_client.keys.modify_key_status(
client_key_id, key_info.get_key_id(),
pki.key.KeyClient.KEY_STATUS_ACTIVE) pki.key.KeyClient.KEY_STATUS_INACTIVE)
for key_info in response.key_infos: # forward wrapped data to KRA
kra_client.keys.modify_key_status( kra_client.keys.archive_encrypted_data(
key_info.get_key_id(), client_key_id,
pki.key.KeyClient.KEY_STATUS_INACTIVE) pki.key.KeyClient.PASS_PHRASE_TYPE,
wrapped_vault_data,
wrapped_session_key,
None,
nonce,
)
# forward wrapped data to KRA kra_account.logout()
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 = { response = {
'value': args[-1], 'value': args[-1],
@@ -1105,29 +1103,28 @@ class vault_retrieve_internal(PKQuery):
vault = self.api.Command.vault_show(*args, **options)['result'] vault = self.api.Command.vault_show(*args, **options)['result']
# connect to KRA # connect to KRA
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) client_key_id = self.obj.get_key_id(vault['dn'])
kra_account.login()
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 if not len(response.key_infos):
response = kra_client.keys.list_keys( raise errors.NotFound(reason=_('No archived data.'))
client_key_id,
pki.key.KeyClient.KEY_STATUS_ACTIVE)
if not len(response.key_infos): key_info = response.key_infos[0]
raise errors.NotFound(reason=_('No archived data.'))
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 kra_account.logout()
key = kra_client.keys.retrieve_key(
key_info.get_key_id(),
wrapped_session_key)
kra_account.logout()
response = { response = {
'value': args[-1], 'value': args[-1],

View File

@@ -45,12 +45,6 @@ def PKI_TOMCAT_password_callback():
return password 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): class NSSWrappedCertDB(DBMAPHandler):
''' '''
Store that extracts private keys from an NSSDB, wrapped with the Store that extracts private keys from an NSSDB, wrapped with the
@@ -193,11 +187,11 @@ class DMLDAP(DBMAPHandler):
class PEMFileHandler(DBMAPHandler): class PEMFileHandler(DBMAPHandler):
def __init__(self, config, dbmap, nickname=None): def __init__(self, config, dbmap, nickname=None):
if 'type' not in dbmap or dbmap['type'] != 'OPENSSL': if 'type' not in dbmap or dbmap['type'] != 'PEM':
raise ValueError('Invalid type "{t}", expected OPENSSL' raise ValueError('Invalid type "{t}", expected PEM'
.format(t=dbmap['type'])) .format(t=dbmap['type']))
self.certfile = dbmap['certfile'] self.certfile = dbmap['certfile']
self.keyfile = dbmap.get(['keyfile']) self.keyfile = dbmap.get('keyfile')
def export_key(self): def export_key(self):
_fd, tmpfile = tempfile.mkstemp(dir=paths.TMP) _fd, tmpfile = tempfile.mkstemp(dir=paths.TMP)
@@ -266,10 +260,10 @@ NAME_DB_MAP = {
'wrap_nick': 'caSigningCert cert-pki-ca', 'wrap_nick': 'caSigningCert cert-pki-ca',
}, },
'ra': { 'ra': {
'type': 'NSSDB', 'type': 'PEM',
'path': paths.IPA_RADB_DIR, 'handler': PEMFileHandler,
'handler': NSSCertDB, 'certfile': paths.RA_AGENT_PEM,
'pwcallback': HTTPD_password_callback, 'keyfile': paths.RA_AGENT_KEY,
}, },
'dm': { 'dm': {
'type': 'DMLDAP', 'type': 'DMLDAP',

View File

@@ -79,7 +79,7 @@ def makecert(reqdir, subject, principal):
""" """
ra = rabase.rabase(api) 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'): api.env.xmlrpc_uri == 'http://localhost:8888/ipa/xml'):
raise AssertionError('The self-signed CA is not configured, ' raise AssertionError('The self-signed CA is not configured, '
'see ipatests/test_xmlrpc/test_cert.py') 'see ipatests/test_xmlrpc/test_cert.py')