New patch attached.

On 10/29/2014 7:58 AM, Petr Viktorin wrote:
Dependency is bumped to 10.2.1-0.1 which is available from my
COPR repo:

   dnf copr enable edewata/pki

OK. We should get that to an IPA COPR before merging this.

How do we do that? Here is the SRPM:
https://edewata.fedorapeople.org/pki/copr/pki-core-10.2.1-0.1.fc20.src.rpm

ipaserver.plugins.dogtag.kra.get_client:
Should every caller check if this returns None?
If not, raise an exception instead.
If yes, at least mention it in a docstring.

Fixed. It's now raising a generic exception.

Is there an existing exception that is more appropriate for backend
issues like this?

I'd go for RuntimeError.

Fixed.

Don't use translatable strings (the _ function) if you're not using
ipalib.PublicError subclasses.

Fixed.

How can I do some basic smoke check on this? Is there something I still
need to to besides ipa-kra-istall? Any other patches?
I tried:

from ipalib import api
from pki.key import KeyClient
api.bootstrap(context='server')
api.finalize()
keyclient = api.Backend.kra.get_client()
keyclient.keys.archive_key('test3', KeyClient.PASS_PHRASE_TYPE, 'tkey')

which gives me:

Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
   File "/usr/lib/python2.7/site-packages/pki/__init__.py", line 295, in
handler
     return fn_call(inst, *args, **kwargs)
   File "/usr/lib/python2.7/site-packages/pki/key.py", line 687, in
archive_key
     nonce_iv = self.crypto.generate_nonce_iv()
   File "/usr/lib/python2.7/site-packages/pki/crypto.py", line 176, in
generate_nonce_iv
     iv_data = nss.generate_random(iv_length)
nss.error.NSPRError: (SEC_ERROR_NO_TOKEN) The security card or token
does not exist, needs to be initialized, or has been removed.

The simplest test is probably this:

from ipalib import api

api.bootstrap(context='server')
api.finalize()

kra_client = api.Backend.kra.get_client()
transport_cert = kra_client.system_certs.get_transport_cert()

print "Serial number: %s" % transport_cert.serial_number
print "Issuer DN: %s" % transport_cert.issuer_dn
print "Subject DN: %s" % transport_cert.subject_dn

print transport_cert.encoded

If you want to test the key archival it would require installing a transport certificate and add some authentication operations. A better way to do that is to install patch #354-1, #353-3, #355-1, and #356-1 and test the vault-archive command. It will install the transport cert automatically and perform the required authentication.

--
Endi S. Dewata
>From 7b68ff1c93554975abd75e6d672ee18a7a0bcf04 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edew...@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 to create
KRA agent and setup the client authentication.

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

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.

The Dogtag dependency has been updated to 10.2.1-0.1.

https://fedorahosted.org/freeipa/ticket/4503
---
 freeipa.spec.in                  |   4 +-
 install/conf/ipa-pki-proxy.conf  |   2 +-
 ipaplatform/base/paths.py        |   4 +-
 ipaserver/install/cainstance.py  |   4 +-
 ipaserver/install/ipa_backup.py  |   3 +-
 ipaserver/install/krainstance.py |  83 +++++++++++++++++++++++---
 ipaserver/plugins/dogtag.py      | 122 ++++++---------------------------------
 7 files changed, 101 insertions(+), 121 deletions(-)

diff --git a/freeipa.spec.in b/freeipa.spec.in
index 
8fcb535e229db4f7a8eaaee3c99b18446eef7f1e..dc04be48b2bb52ff05f9fab371c4b333a15d24ca
 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 
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 
bbe6eed76ccb3c5f325fd368694ac6a2afbb72f0..01505594a7af926c860f867b817bd397c54efff5
 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 
1ae39639ac9702651851e6c3964faa69788db31e..fe95201517a577b9f6dba7642afe09b4eef2328d
 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 
014b49bb63579227c12a8380cfb630a0bd6c677a..ed9139576f511c4c0989675d3e5b0d356584d893
 100644
--- a/ipaserver/install/ipa_backup.py
+++ b/ipaserver/install/ipa_backup.py
@@ -158,7 +158,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..cd1c05cd53429e85df39cd793e209d69e77ce643
 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
-        """
-        (p12_pwd_fd, p12_pwd_fname) = tempfile.mkstemp()
-        (p12_fd, p12_fname) = tempfile.mkstemp()
-
-        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
+    def get_client(self):
         """
-        # 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
+        Returns an authenticated KRA client to access KRA services.
 
-        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)
+        if not api.env.enable_kra:
+            # TODO: replace this with a more specific exception
+            raise RuntimeError('KRA service is not enabled')
 
-        crypto = cryptoutil.NSSCryptoProvider(self.sec_dir, self.password)
+        crypto = cryptoutil.NSSCryptoProvider(
+            paths.HTTPD_ALIAS_DIR,
+            password_file=paths.ALIAS_PWDFILE_TXT)
 
-        #create kraclient
-        kraclient = KRAClient(connection, crypto)
+        # 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')
 
-        # 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")
+        connection.set_authentication_cert(paths.KRA_AGENT_PEM)
 
-        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

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to