[Pki-devel] [PATCH] 529 Updated KRA Python client library.

Endi Sukma Dewata edewata at redhat.com
Wed Oct 8 18:45:10 UTC 2014


The Python client library for KRA has been modified to simplify
the usage. The NSSCryptoProvider's setup_database() and __init__()
now take a password file parameter. The import_cert() now can
take either cert binary/encoded data or CertData object. It also
provides a default value for the trust attribute. The KRAClient
now stores the crypto provider object.

The KRA test has been updated to provide options to override
the default test configuration (e.g. hostname, port). It also has
been modified to use a temporary NSS database. The setup document
has been updated to describe the process to run the test as root
and as a regular user.

-- 
Endi S. Dewata
-------------- next part --------------
From 3a7786d4693c6d1b026988177dbd6c46e5952752 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata at redhat.com>
Date: Tue, 7 Oct 2014 13:47:10 -0400
Subject: [PATCH] Updated KRA Python client library.

The Python client library for KRA has been modified to simplify
the usage. The NSSCryptoProvider's setup_database() and __init__()
now take a password file parameter. The import_cert() now can
take either cert binary/encoded data or CertData object. It also
provides a default value for the trust attribute. The KRAClient
now stores the crypto provider object.

The KRA test has been updated to provide options to override
the default test configuration (e.g. hostname, port). It also has
been modified to use a temporary NSS database. The setup document
has been updated to describe the process to run the test as root
and as a regular user.
---
 base/common/python/pki/crypto.py       | 39 +++++++++++----
 base/common/python/pki/kra.py          |  4 +-
 base/kra/functional/drmtest.py         | 87 +++++++++++++++++++++++++++++-----
 base/kra/functional/drmtest.readme.txt | 75 +++++++++++++++++++++--------
 4 files changed, 159 insertions(+), 46 deletions(-)
 mode change 100644 => 100755 base/kra/functional/drmtest.py

diff --git a/base/common/python/pki/crypto.py b/base/common/python/pki/crypto.py
index f9aed3f36c67e40877f7d017c9628dac14e2fbbd..f54386e4df4c0e1d1b04dcc916d267c30842307d 100644
--- a/base/common/python/pki/crypto.py
+++ b/base/common/python/pki/crypto.py
@@ -102,7 +102,7 @@ class NSSCryptoProvider(CryptoProvider):
     """
 
     @staticmethod
-    def setup_database(db_dir, password, over_write=False):
+    def setup_database(db_dir, password=None, over_write=False, password_file=None):
         """ Create an NSS database """
         if os.path.exists(db_dir):
             if not over_write:
@@ -113,14 +113,20 @@ class NSSCryptoProvider(CryptoProvider):
                 os.remove(db_dir)
         os.makedirs(db_dir)
 
-        home = os.path.expanduser("~")
-        with tempfile.NamedTemporaryFile(dir=home) as pwd_file:
-            pwd_file.write(password)
-            pwd_file.flush()
-            command = ['certutil', '-N', '-d', db_dir, '-f', pwd_file.name]
+        if password:
+            (f, n) = tempfile.mkstemp()
+            os.write(f, password)
+            os.close(f)
+            password_file = n
+
+        try:
+            command = ['certutil', '-N', '-d', db_dir, '-f', password_file]
             subprocess.check_call(command)
+        finally:
+            if password:
+                os.remove(password_file)
 
-    def __init__(self, certdb_dir, certdb_password):
+    def __init__(self, certdb_dir, certdb_password=None, password_file=None):
         """ Initialize nss and nss related parameters
 
             This method expects a NSS database to have already been created at
@@ -128,7 +134,14 @@ class NSSCryptoProvider(CryptoProvider):
         """
         CryptoProvider.__init__(self)
         self.certdb_dir = certdb_dir
-        self.certdb_password = certdb_password
+
+        if certdb_password:
+            self.certdb_password = certdb_password
+
+        elif password_file:
+            with open(password_file, 'r') as f:
+                self.certdb_password = f.readline().strip()
+
         self.nonce_iv = "e4:bb:3b:d3:c3:71:2e:58"
 
     def initialize(self):
@@ -137,12 +150,18 @@ class NSSCryptoProvider(CryptoProvider):
         """
         nss.nss_init(self.certdb_dir)
 
-    def import_cert(self, cert_nick, cert, trust):
+    def import_cert(self, cert_nick, cert, trust=',,'):
         """ Import a certificate into the nss database
         """
+        # accept both CertData object or cert actual data
+        if type(cert).__name__ == 'CertData':
+            content = cert.encoded
+        else:
+            content = cert
+
         # certutil -A -d db_dir -n cert_nick -t trust -i cert_file
         with tempfile.NamedTemporaryFile() as cert_file:
-            cert_file.write(cert.binary)
+            cert_file.write(content)
             cert_file.flush()
             command = ['certutil', '-A', '-d', self.certdb_dir,
                        '-n', cert_nick, '-t', trust,
diff --git a/base/common/python/pki/kra.py b/base/common/python/pki/kra.py
index 6559b986b05bc3e9049cdf7d95a8bef19a118cd8..9e46235d264a286b878005b2be49a4987e962b75 100644
--- a/base/common/python/pki/kra.py
+++ b/base/common/python/pki/kra.py
@@ -52,8 +52,6 @@ class KRAClient(object):
                         initialized beforehand.
         """
         self.connection = connection
+        self.crypto = crypto
         self.keys = key.KeyClient(connection, crypto, transport_cert_nick)
         self.system_certs = SystemCertClient(connection)
-
-
-
diff --git a/base/kra/functional/drmtest.py b/base/kra/functional/drmtest.py
old mode 100644
new mode 100755
index 8653763c11933c6d577a5c39397d59cfb8817201..0a7bbeaaef350a4027e82ab0c74407bc057e3e8f
--- a/base/kra/functional/drmtest.py
+++ b/base/kra/functional/drmtest.py
@@ -18,6 +18,7 @@
 #
 # Authors:
 #     Ade Lee <alee at redhat.com>
+#     Endi S. Dewata <edewata at redhat.com>
 
 """
 =========================================================================
@@ -32,10 +33,18 @@ See drmtest.readme.txt.
 """
 
 import base64
+import getopt
+import os
+import random
+import shutil
+import string
+import sys
+import tempfile
+import time
+
 import pki
 import pki.crypto
 import pki.key as key
-import time
 
 from pki.client import PKIConnection
 from pki.kra import KRAClient
@@ -75,18 +84,12 @@ def print_key_data(key_data):
         print "Private Data: " + base64.encodestring(key_data.data)
 
 
-def main():
+def run_test(protocol, hostname, port, client_cert, certdb_dir, certdb_password):
     """ test code execution """
 
     # set up the connection to the DRM, including authentication credentials
-    connection = PKIConnection('https', 'localhost', '8443', 'kra')
-    connection.set_authentication_cert('/tmp/auth.pem')
-
-    # create an NSS DB for crypto operations
-    certdb_dir = "/tmp/drmtest-certdb"
-    certdb_password = "redhat123"
-    pki.crypto.NSSCryptoProvider.setup_database(certdb_dir, certdb_password,
-                                                over_write=True)
+    connection = PKIConnection(protocol, hostname, port, 'kra')
+    connection.set_authentication_cert(client_cert)
 
     #create kraclient
     crypto = pki.crypto.NSSCryptoProvider(certdb_dir, certdb_password)
@@ -98,7 +101,7 @@ def main():
     transport_cert = kraclient.system_certs.get_transport_cert()
     print "Subject DN: " + transport_cert.subject_dn
     print transport_cert.encoded
-    crypto.import_cert(transport_nick, transport_cert, "u,u,u")
+    crypto.import_cert(transport_nick, transport_cert)
 
     # initialize the certdb for crypto operations
     # for NSS db, this must be done after importing the transport cert
@@ -286,5 +289,65 @@ def main():
     key_info = keyclient.get_key_info(response.request_info.get_key_id())
     print_key_info(key_info)
 
+
+def usage():
+    print 'Usage: drmtest.py [OPTIONS]'
+    print
+    print '  -P <protocol>                  KRA server protocol (default: https).'
+    print '  -h <hostname>                  KRA server hostname (default: localhost).'
+    print '  -p <port>                      KRA server port (default: 8443).'
+    print '  -n <path>                      KRA agent certificate and private key (default: kraagent.pem).'
+    print
+    print '  --help                         Show this help message.'
+
+
+def main(argv):
+    try:
+        opts, _ = getopt.getopt(argv[1:], 'h:P:p:n:d:c:', ['help'])
+
+    except getopt.GetoptError as e:
+        print 'ERROR: ' + str(e)
+        usage()
+        sys.exit(1)
+
+    protocol    = 'https'
+    hostname    = 'localhost'
+    port        = '8443'
+    client_cert = 'kraagent.pem'
+
+    for o, a in opts:
+        if o == '-P':
+            protocol = a
+
+        elif o == '-h':
+            hostname = a
+
+        elif o == '-p':
+            port = a
+
+        elif o == '-n':
+            client_cert = a
+
+        elif o == '--help':
+            usage()
+            sys.exit()
+
+        else:
+            print 'ERROR: unknown option ' + o
+            usage()
+            sys.exit(1)
+
+    certdb_dir = tempfile.mkdtemp(prefix='pki-kra-test-')
+    print "NSS database dir: %s" % certdb_dir
+
+    certdb_password = ''.join(random.choice(string.ascii_letters + string.digits) for i in range(8))
+    print "NSS database password: %s" % certdb_password
+
+    try:
+        run_test(protocol, hostname, port, client_cert, certdb_dir, certdb_password)
+    finally:
+        shutil.rmtree(certdb_dir)
+
+
 if __name__ == "__main__":
-    main()
+    main(sys.argv)
diff --git a/base/kra/functional/drmtest.readme.txt b/base/kra/functional/drmtest.readme.txt
index 46debaa2b824ef6e8561064c89238c13158e1d7e..853e97082d3f1af5a910d4e229b6ece91ee203eb 100644
--- a/base/kra/functional/drmtest.readme.txt
+++ b/base/kra/functional/drmtest.readme.txt
@@ -1,28 +1,61 @@
-You will need to set up a few things first though:
-1.  Install a CA/KRA.  If this is not on the default ports, you will
-need to modify the connection information in drmtest.__main__
+= Overview =
 
-2. The python code uses python-requests to talk to the server, and
-requests uses openssl.  That means you need to export your DRM admin
-cert to a PEM file, so that it can be used for client auth.  I did this
-as follows:
+This document describes the process to setup and run KRA
+test.
 
- openssl pkcs12 -in ~/.dogtag/pki-tomcat/ca_admin_cert.p12 -out /tmp/temp4.pem -nodes
+To reflect the real-world deployment the test should be
+run by a regular user, not the root user. However, to
+simplify the process, the test can also be run by the
+root user.
 
-Without any changes, the code in KRAClient.__main__ assumes this file
-will be in /tmp/temp4.pem.
 
-3.  We do some crypto functions using NSS commands (like generating a
-symmetric key or wrapping using the transport cert).  Therefore, we need
-to create an NSS database and populate it with the transport cert.  The
-code expects it to be at /tmp/drmtest/certdb
+= Running KRA test as a regular user =
 
-I did this as follows:
-mkdir -p /tmp/drmtest/certdb
-certutil -N -d /tmp/drmtest/certdb
-chmod +r /tmp/drmtest/certdb/*
+1. Install a CA and KRA as described in the following page:
+   http://pki.fedoraproject.org/wiki/Quick_Start
 
-certutil -L -d /var/lib/pki/pki-tomcat/alias/ -n "transportCert cert-pki-tomcat KRA" -a > transport_cert.txt
-certutil -A -d /tmp/drmtest/certdb/ -n "kra transport cert" -i ./transport_cert.txt -a -t "u,u,u"
+2. Setup CA admin as described in the following page:
+   http://pki.fedoraproject.org/wiki/CA_Admin_Setup
 
-4. Then just run drmtest.__main__ with no arguments.
\ No newline at end of file
+3. Setup KRA agent as described in the following page:
+   http://pki.fedoraproject.org/wiki/KRA_Agent_Setup
+
+4. As root, copy the KRA test into KRA agent home directory:
+
+   cd <Dogtag source tree>/base/kra/functional
+   cp drmtest.py <KRA agent home directory>
+   chown kraagent.kraagent <KRA agent home directory>/drmtest.py
+
+5. As KRA agent, export the KRA agent client certificate:
+
+   pki -c <password> client-cert-show <nickname> --client-cert kraagent.pem
+
+6. As KRA agent, execute the KRA test:
+
+   python drmtest.py
+
+
+= Running KRA test as root =
+
+1. Install a CA and KRA with the deployment configuration
+   as described in the following page:
+   http://pki.fedoraproject.org/wiki/Quick_Start
+
+   Make sure it contains pki_client_database_purge=False
+   so root can authenticate as CA admin certificate directly
+   with the certificate in ~/.dogtag/pki-tomcat/ca/alias.
+
+   Also, make sure the CA admin certificate is imported
+   during KRA installation so root can authenticate as
+   KRA admin with the same certificate.
+
+   By default the KRA admin is already in the KRA agents group
+   so root can act as a KRA agent.
+
+2. As root, export the CA admin client certificate:
+
+   pki ~/.dogtag/pki-tomcat/ca/alias -c <password> client-cert-show caadmin --client-cert kraagent.pem
+
+3. As root, execute the KRA test:
+
+   python <Dogtag source tree>/base/kra/functional/drmtest.py
-- 
1.8.4.2



More information about the Pki-devel mailing list