diff options
-rw-r--r-- | freeipa.spec.in | 4 | ||||
-rw-r--r-- | install/conf/ipa-pki-proxy.conf | 2 | ||||
-rw-r--r-- | ipaplatform/base/paths.py | 4 | ||||
-rw-r--r-- | ipaserver/install/cainstance.py | 4 | ||||
-rw-r--r-- | ipaserver/install/ipa_backup.py | 3 | ||||
-rw-r--r-- | ipaserver/install/krainstance.py | 83 | ||||
-rw-r--r-- | ipaserver/plugins/dogtag.py | 122 |
7 files changed, 101 insertions, 121 deletions
diff --git a/freeipa.spec.in b/freeipa.spec.in index 52c96757e..1302d850d 100644 --- a/freeipa.spec.in +++ b/freeipa.spec.in @@ -130,8 +130,8 @@ Requires(post): systemd-units Requires: selinux-policy >= %{selinux_policy_version} Requires(post): selinux-policy-base Requires: slapi-nis >= 0.54-1 -Requires: pki-ca >= 10.2.0-3 -Requires: pki-kra >= 10.2.0 +Requires: pki-ca >= 10.2.1-0.1 +Requires: pki-kra >= 10.2.1-0.1 %if 0%{?rhel} Requires: subscription-manager %endif diff --git a/install/conf/ipa-pki-proxy.conf b/install/conf/ipa-pki-proxy.conf index 2370b4d7a..5d2115684 100644 --- a/install/conf/ipa-pki-proxy.conf +++ b/install/conf/ipa-pki-proxy.conf @@ -19,7 +19,7 @@ ProxyRequests Off </LocationMatch> # matches for agent port and eeca port -<LocationMatch "^/ca/agent/ca/displayBySerial|^/ca/agent/ca/doRevoke|^/ca/agent/ca/doUnrevoke|^/ca/agent/ca/updateDomainXML|^/ca/eeca/ca/profileSubmitSSLClient|^/kra/agent/kra/connector|^/kra/rest/agent/keyrequests|^/kra/rest/agent/keys|^/ca/rest/admin/kraconnector/remove"> +<LocationMatch "^/ca/agent/ca/displayBySerial|^/ca/agent/ca/doRevoke|^/ca/agent/ca/doUnrevoke|^/ca/agent/ca/updateDomainXML|^/ca/eeca/ca/profileSubmitSSLClient|^/kra/agent/kra/connector|^/kra/rest/account|^/kra/rest/agent/keyrequests|^/kra/rest/agent/keys|^/ca/rest/admin/kraconnector/remove"> NSSOptions +StdEnvVars +ExportCertData +StrictRequire +OptRenegotiate NSSVerifyClient require ProxyPassMatch ajp://localhost:$DOGTAG_PORT diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py index bbe6eed76..01505594a 100644 --- a/ipaplatform/base/paths.py +++ b/ipaplatform/base/paths.py @@ -138,8 +138,8 @@ class BasePathNamespace(object): HOME_DIR = "/home" ROOT_IPA_CACHE = "/root/.ipa_cache" ROOT_PKI = "/root/.pki" - DOGTAG_AGENT_P12 = "/root/ca-agent.p12" - DOGTAG_AGENT_PEM = "/etc/httpd/alias/agent.pem" + DOGTAG_ADMIN_P12 = "/root/ca-agent.p12" + KRA_AGENT_PEM = "/etc/httpd/alias/kra-agent.pem" CACERT_P12 = "/root/cacert.p12" ROOT_IPA_CSR = "/root/ipa.csr" ROOT_TMP_CA_P12 = "/root/tmp-ca.p12" diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py index 1ae39639a..fe9520151 100644 --- a/ipaserver/install/cainstance.py +++ b/ipaserver/install/cainstance.py @@ -514,7 +514,7 @@ class CAInstance(DogtagInstance): config.set("CA", "pki_admin_nickname", "ipa-ca-agent") config.set("CA", "pki_admin_subject_dn", str(DN(('cn', 'ipa-ca-agent'), self.subject_base))) - config.set("CA", "pki_client_admin_cert_p12", paths.DOGTAG_AGENT_P12) + config.set("CA", "pki_client_admin_cert_p12", paths.DOGTAG_ADMIN_P12) # Directory server config.set("CA", "pki_ds_ldap_port", str(self.ds_port)) @@ -979,7 +979,7 @@ class CAInstance(DogtagInstance): try: ipautil.run([paths.PK12UTIL, "-n", "ipa-ca-agent", - "-o", paths.DOGTAG_AGENT_P12, + "-o", paths.DOGTAG_ADMIN_P12, "-d", self.agent_db, "-k", pwd_name, "-w", pwd_name]) diff --git a/ipaserver/install/ipa_backup.py b/ipaserver/install/ipa_backup.py index 4bee5d51f..34be5383d 100644 --- a/ipaserver/install/ipa_backup.py +++ b/ipaserver/install/ipa_backup.py @@ -157,7 +157,8 @@ class Backup(admintool.AdminTool): paths.NTP_CONF, paths.SMB_CONF, paths.SAMBA_KEYTAB, - paths.DOGTAG_AGENT_P12, + paths.DOGTAG_ADMIN_P12, + paths.KRA_AGENT_PEM, paths.CACERT_P12, paths.KRB5KDC_KDC_CONF, paths.SYSTEMD_IPA_SERVICE, diff --git a/ipaserver/install/krainstance.py b/ipaserver/install/krainstance.py index 1af1c0f72..7c1bded41 100644 --- a/ipaserver/install/krainstance.py +++ b/ipaserver/install/krainstance.py @@ -169,7 +169,7 @@ class KRAInstance(DogtagInstance): str(DN(('cn', 'ipa-ca-agent'), self.subject_base))) config.set("KRA", "pki_import_admin_cert", "True") config.set("KRA", "pki_admin_cert_file", paths.ADMIN_CERT_PATH) - config.set("KRA", "pki_client_admin_cert_p12", paths.DOGTAG_AGENT_P12) + config.set("KRA", "pki_client_admin_cert_p12", paths.DOGTAG_ADMIN_P12) # Directory server config.set("KRA", "pki_ds_ldap_port", str(self.ds_port)) @@ -259,16 +259,81 @@ class KRAInstance(DogtagInstance): """ Add RA agent created for CA to KRA agent group. """ - conn = ipaldap.IPAdmin(self.fqdn, self.ds_port) - conn.do_simple_bind(DN(('cn', 'Directory Manager')), self.dm_password) - entry_dn = DN(('uid', "ipara"), ('ou', 'People'), ('o', 'ipaca')) - dn = DN(('cn', 'Data Recovery Manager Agents'), ('ou', 'groups'), - self.basedn) - modlist = [(0, 'uniqueMember', '%s' % entry_dn)] - conn.modify_s(dn, modlist) + # import CA certificate into temporary security database + args = ["/usr/bin/pki", + "-d", self.agent_db, + "-c", self.admin_password, + "client-cert-import", + "--pkcs12", paths.KRACERT_P12, + "--pkcs12-password", self.admin_password] + ipautil.run(args) + + # trust CA certificate + args = ["/usr/bin/pki", + "-d", self.agent_db, + "-c", self.admin_password, + "client-cert-mod", "Certificate Authority - %s" % api.env.realm, + "--trust", "CT,c,"] + ipautil.run(args) + + # import Dogtag admin certificate into temporary security database + args = ["/usr/bin/pki", + "-d", self.agent_db, + "-c", self.admin_password, + "client-cert-import", + "--pkcs12", paths.DOGTAG_ADMIN_P12, + "--pkcs12-password", self.admin_password] + ipautil.run(args) + + # as Dogtag admin, create ipakra user in KRA + args = ["/usr/bin/pki", + "-d", self.agent_db, + "-c", self.admin_password, + "-n", "ipa-ca-agent", + "kra-user-add", "ipakra", + "--fullName", "IPA KRA User"] + ipautil.run(args) + + # as Dogtag admin, add ipakra into KRA agents group + args = ["/usr/bin/pki", + "-d", self.agent_db, + "-c", self.admin_password, + "-n", "ipa-ca-agent", + "kra-user-membership-add", "ipakra", "Data Recovery Manager Agents"] + ipautil.run(args) + + # assign ipaCert to ipakra + (file, filename) = tempfile.mkstemp() + os.close(file) + try: + # export ipaCert without private key + args = ["/usr/bin/pki", + "-d", paths.HTTPD_ALIAS_DIR, + "-C", paths.ALIAS_PWDFILE_TXT, + "client-cert-show", "ipaCert", + "--cert", filename] + ipautil.run(args) + + # as Dogtag admin, upload and assign ipaCert to ipakra + args = ["/usr/bin/pki", + "-d", self.agent_db, + "-c", self.admin_password, + "-n", "ipa-ca-agent", + "kra-user-cert-add", "ipakra", + "--input", filename] + ipautil.run(args) - conn.unbind() + finally: + os.remove(filename) + + # export ipaCert with private key for client authentication + args = ["/usr/bin/pki", + "-d", paths.HTTPD_ALIAS_DIR, + "-C", paths.ALIAS_PWDFILE_TXT, + "client-cert-show", "ipaCert", + "--client-cert", paths.KRA_AGENT_PEM] + ipautil.run(args) @staticmethod def update_cert_config(nickname, cert, dogtag_constants=None): diff --git a/ipaserver/plugins/dogtag.py b/ipaserver/plugins/dogtag.py index 0e141a45c..cd1c05cd5 100644 --- a/ipaserver/plugins/dogtag.py +++ b/ipaserver/plugins/dogtag.py @@ -1890,122 +1890,36 @@ class kra(Backend): """ def __init__(self, kra_port=443): - if api.env.in_tree: - self.sec_dir = os.path.join(api.env.dot_ipa, 'alias') - pwd_file = os.path.join(self.sec_dir, '.pwd') - self.pem_file = os.path.join(self.sec_dir, ".pemfile") - else: - self.sec_dir = paths.HTTPD_ALIAS_DIR - pwd_file = paths.ALIAS_PWDFILE_TXT - self.pem_file = paths.DOGTAG_AGENT_PEM self.kra_port = kra_port - self.transport_nick = "IPA KRA Transport Cert" - self.password = "" - with open(pwd_file, "r") as f: - self.password = f.readline().strip() - self.keyclient = None super(kra, self).__init__() - def _create_pem_file(self): - """ Create PEM file used by KRA plugin for authentication. - - This function reads the IPA HTTPD database and extracts the - Dogtag agent certificate and keys into a PKCS#12 temporary file. - The PKCS#12 file is then converted into PEM format so that it - can be used by python-requests to authenticate to the KRA. - - :return: None + def get_client(self): """ - (p12_pwd_fd, p12_pwd_fname) = tempfile.mkstemp() - (p12_fd, p12_fname) = tempfile.mkstemp() + Returns an authenticated KRA client to access KRA services. - try: - os.write(p12_pwd_fd, self.password) - os.close(p12_pwd_fd) - os.close(p12_fd) - - certdb = CertDB(api.env.realm) - certdb.export_pkcs12(p12_fname, p12_pwd_fname, "ipaCert") - - certdb.install_pem_from_p12(p12_fname, self.password, self.pem_file) - except: - self.debug("Error when creating PEM file for KRA operations") - raise - finally: - os.remove(p12_fname) - os.remove(p12_pwd_fname) - - def _transport_cert_present(self): - """ Check if the client certDB contains the KRA transport certificate - :return: True/False - """ - # certutil -L -d db_dir -n cert_nick - certdb = CertDB(api.env.realm) - return certdb.has_nickname(self.transport_nick) - - def _setup(self): - """ Do initial setup and crypto initialization of the KRA client - - Creates a PEM file containing the KRA agent cert/keys to be used for - authentication to the KRA (if it does not already exist), Sets up a - connection to the KRA and initializes an NSS certificate database to - store the transport certificate, Retrieves the transport certificate - if it is not already present. + Raises a generic exception if KRA is not enabled. """ - #set up pem file if not present - if not os.path.exists(self.pem_file): - self._create_pem_file() - - # set up connection - connection = PKIConnection('https', - self.kra_host, - str(self.kra_port), - 'kra') - connection.set_authentication_cert(self.pem_file) - crypto = cryptoutil.NSSCryptoProvider(self.sec_dir, self.password) + if not api.env.enable_kra: + # TODO: replace this with a more specific exception + raise RuntimeError('KRA service is not enabled') - #create kraclient - kraclient = KRAClient(connection, crypto) + crypto = cryptoutil.NSSCryptoProvider( + paths.HTTPD_ALIAS_DIR, + password_file=paths.ALIAS_PWDFILE_TXT) - # get transport cert if needed - if not self._transport_cert_present(): - transport_cert = kraclient.system_certs.get_transport_cert() - crypto.import_cert(self.transport_nick, transport_cert, "u,u,u") + # TODO: obtain KRA host & port from IPA service list or point to KRA load balancer + # https://fedorahosted.org/freeipa/ticket/4557 + connection = PKIConnection( + 'https', + api.env.kra_host, + str(self.kra_port), + 'kra') - crypto.initialize() + connection.set_authentication_cert(paths.KRA_AGENT_PEM) - self.keyclient = kraclient.keys - self.keyclient.set_transport_cert(self.transport_nick) - - @cachedproperty - def kra_host(self): - """ - :return: host - as str - - Select our KRA host. - """ - ldap2 = self.api.Backend.ldap2 - if host_has_service(api.env.kra_host, ldap2, "kra"): - return api.env.kra_host - if api.env.host != api.env.kra_host: - if host_has_service(api.env.host, ldap2, "kra"): - return api.env.host - host = select_any_master(ldap2, "kra") - if host: - return host - else: - return api.env.kra_host - - def get_keyclient(self): - """Return a keyclient to perform key archival and retrieval. - :return: pki.key.keyclient - """ - if self.keyclient is None: - self._setup() - return self.keyclient + return KRAClient(connection, crypto) api.register(kra) |