[Freeipa-devel] [PATCH] 352 Fixed KRA backend.

Endi Sukma Dewata edewata at redhat.com
Thu Oct 16 03:59:16 UTC 2014


The KRA backend has been simplified since most of the tasks have
been moved somewhere else. The transport certificate will be
installed on the client, and it is not needed by KRA backend. The
KRA agent's PEM certificate is now generated during installation
due to permission issue. The kra_host() for now is removed since
the current ldap_enable() cannot register the KRA service, so it
is using the kra_host environment variable.

The KRA installer has been modified to use Dogtag's CLI go create
KRA agent and setup the client authentication.

The proxy settings have been updated to include KRA's URLs.

The certs.install_pem_from_p12() has been updated to generate the
proper client certificate using the -clcerts option and also take
a password file.

Some constants have been renamed for clarity. The DOGTAG_AGENT_P12
has been renamed to DOGTAG_ADMIN_P12 since file actually contains
the Dogtag admin's certificate and private key and it can be used
to access both CA and KRA. The DOGTAG_AGENT_PEM has been renamed
to KRA_AGENT_PEM since it can only be used for KRA.

Ticket #3872

-- 
Endi S. Dewata
-------------- next part --------------
From 018d849db0f08285aeeb26e3fc886c8c161b3f33 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata at redhat.com>
Date: Wed, 1 Oct 2014 14:59:46 -0400
Subject: [PATCH] Fixed KRA backend.

The KRA backend has been simplified since most of the tasks have
been moved somewhere else. The transport certificate will be
installed on the client, and it is not needed by KRA backend. The
KRA agent's PEM certificate is now generated during installation
due to permission issue. The kra_host() for now is removed since
the current ldap_enable() cannot register the KRA service, so it
is using the kra_host environment variable.

The KRA installer has been modified to use Dogtag's CLI go create
KRA agent and setup the client authentication.

The proxy settings have been updated to include KRA's URLs.

The certs.install_pem_from_p12() has been updated to generate the
proper client certificate using the -clcerts option and also take
a password file.

Some constants have been renamed for clarity. The DOGTAG_AGENT_P12
has been renamed to DOGTAG_ADMIN_P12 since file actually contains
the Dogtag admin's certificate and private key and it can be used
to access both CA and KRA. The DOGTAG_AGENT_PEM has been renamed
to KRA_AGENT_PEM since it can only be used for KRA.

Ticket #3872
---
 install/conf/ipa-pki-proxy.conf  |   2 +-
 ipaplatform/base/paths.py        |   4 +-
 ipaserver/install/cainstance.py  |   4 +-
 ipaserver/install/certs.py       |  10 ++--
 ipaserver/install/ipa_backup.py  |   3 +-
 ipaserver/install/krainstance.py |  83 ++++++++++++++++++++++++---
 ipaserver/plugins/dogtag.py      | 120 +++++----------------------------------
 7 files changed, 100 insertions(+), 126 deletions(-)

diff --git a/install/conf/ipa-pki-proxy.conf b/install/conf/ipa-pki-proxy.conf
index 2370b4d7a7467a7e47c0d223915e018c9a009e83..5d21156848f3b5ddf14c42d92a26a30a9f94af36 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 0ba6b46c562a3d3f97e3631fd9dc0f27536bc6bc..3652a3213d2d116b34d7c4239964c511f572ed6b 100644
--- a/ipaplatform/base/paths.py
+++ b/ipaplatform/base/paths.py
@@ -127,8 +127,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 2c912206a37accfdf217c955755b82ed0d2056af..aa6de498726e779e62cd96ec13d9e52cd1262714 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/certs.py b/ipaserver/install/certs.py
index 5399a0fa566c6f7df81a9d1e347f6ac99e5188c9..d1e58da722126d0381787e13b9112d595dfc2cc7 100644
--- a/ipaserver/install/certs.py
+++ b/ipaserver/install/certs.py
@@ -637,11 +637,13 @@ class CertDB(object):
         self.create_pin_file()
         self.export_ca_cert(nickname, False)
 
-    def install_pem_from_p12(self, p12_fname, p12_passwd, pem_fname):
-        pwd = ipautil.write_tmp_file(p12_passwd)
-        ipautil.run([paths.OPENSSL, "pkcs12", "-nodes",
+    def install_pem_from_p12(self, p12_fname, p12_passwd, pem_fname, pwd_fname=None):
+        if p12_passwd:
+            pwd = ipautil.write_tmp_file(p12_passwd)
+            pwd_fname = pwd.name
+        ipautil.run([paths.OPENSSL, "pkcs12", "-clcerts", "-nodes",
                      "-in", p12_fname, "-out", pem_fname,
-                     "-passin", "file:" + pwd.name])
+                     "-passin", "file:" + pwd_fname])
 
     def publish_ca_cert(self, location):
         shutil.copy(self.cacert_fname, location)
diff --git a/ipaserver/install/ipa_backup.py b/ipaserver/install/ipa_backup.py
index ded02171cbf62687620666d55c9802f9670b1942..7e0b40caee7d15e49f474d33a390fc792c3c196c 100644
--- a/ipaserver/install/ipa_backup.py
+++ b/ipaserver/install/ipa_backup.py
@@ -153,7 +153,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 1af1c0f721cd9b0df7c6134798494d507e2ba07c..7c1bded4173420a7e8f0ebfe40fe7e12ba0476c4 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)
 
-        conn.unbind()
+        # 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)
+
+        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 0e141a45c290b84d65b15b8c2c638577a3a39363..b6d216e6626ef3e62c7d4f6227b76213ae9d85c3 100644
--- a/ipaserver/plugins/dogtag.py
+++ b/ipaserver/plugins/dogtag.py
@@ -1890,122 +1890,28 @@ 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.
+    def get_client(self):
 
-        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.
+        if not api.env.enable_kra:
+            return None
 
-        :return: None
-        """
-        (p12_pwd_fd, p12_pwd_fname) = tempfile.mkstemp()
-        (p12_fd, p12_fname) = tempfile.mkstemp()
+        crypto = cryptoutil.NSSCryptoProvider(
+            paths.HTTPD_ALIAS_DIR,
+            password_file=paths.ALIAS_PWDFILE_TXT)
 
-        try:
-            os.write(p12_pwd_fd, self.password)
-            os.close(p12_pwd_fd)
-            os.close(p12_fd)
+        connection = PKIConnection(
+            'https',
+            api.env.kra_host,
+            str(self.kra_port),
+            'kra')
 
-            certdb = CertDB(api.env.realm)
-            certdb.export_pkcs12(p12_fname, p12_pwd_fname, "ipaCert")
+        connection.set_authentication_cert(paths.KRA_AGENT_PEM)
 
-            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.
-        """
-        #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)
-
-        #create kraclient
-        kraclient = KRAClient(connection, crypto)
-
-        # 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")
-
-        crypto.initialize()
-
-        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)
-- 
1.9.0



More information about the Freeipa-devel mailing list