summaryrefslogtreecommitdiffstats
path: root/ipaserver/install/certs.py
diff options
context:
space:
mode:
authorPetr Viktorin <pviktori@redhat.com>2013-03-27 14:25:18 +0100
committerRob Crittenden <rcritten@redhat.com>2013-04-15 16:56:12 -0400
commite736e75ce9724ae8298a5b69d093313cd6e62b60 (patch)
treec50816419b158762d6173c51dc2d74942a64cec3 /ipaserver/install/certs.py
parent006ab23c6d404fd3ee1a33ac339c77789254860e (diff)
downloadfreeipa-e736e75ce9724ae8298a5b69d093313cd6e62b60.tar.gz
freeipa-e736e75ce9724ae8298a5b69d093313cd6e62b60.tar.xz
freeipa-e736e75ce9724ae8298a5b69d093313cd6e62b60.zip
Drop --selfsign server functionality
Design: http://freeipa.org/page/V3/Drop_selfsign_functionality Ticket: https://fedorahosted.org/freeipa/ticket/3494
Diffstat (limited to 'ipaserver/install/certs.py')
-rw-r--r--ipaserver/install/certs.py583
1 files changed, 102 insertions, 481 deletions
diff --git a/ipaserver/install/certs.py b/ipaserver/install/certs.py
index 4f16e4d0f..b170c7cbf 100644
--- a/ipaserver/install/certs.py
+++ b/ipaserver/install/certs.py
@@ -17,20 +17,20 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-import os, stat, subprocess, re
+import os
+import stat
+import re
import sys
import tempfile
import shutil
-from ipapython.ipa_log_manager import *
import xml.dom.minidom
import pwd
-import fcntl
import base64
from hashlib import sha1
-from ConfigParser import RawConfigParser, MissingSectionHeaderError
from nss import nss
+from ipapython.ipa_log_manager import root_logger
from ipapython import dogtag
from ipapython import sysrestore
from ipapython import ipautil
@@ -46,32 +46,6 @@ from ipalib.text import _
# where apache can reach
NSS_DIR = "/etc/httpd/alias"
-CA_SERIALNO="/var/lib/ipa/ca_serialno"
-
-def ipa_self_signed():
- """
- Determine if the current IPA CA is self-signed or using another CA
-
- We do this based on the CA plugin that is currently in use.
- """
- if api.env.ra_plugin == 'selfsign':
- return True
- else:
- return False
-
-def ipa_self_signed_master():
- """
- The selfsign backend is enabled only one a single master.
-
- Return True/False whether this is that master.
-
- Returns None if not a self-signed server.
- """
- if ipa_self_signed():
- return api.env.enable_ra
- else:
- return None
-
def find_cert_from_txt(cert, start=0):
"""
Given a cert blob (str) which may or may not contian leading and
@@ -106,90 +80,6 @@ def get_cert_nickname(cert):
return (str(dn[0]), dn)
-def next_serial(serial_file=CA_SERIALNO):
- """
- Get the next serial number if we're using an NSS-based self-signed CA.
-
- The file is an ini-like file with following properties:
- lastvalue = the last serial number handed out
- nextreplica = the serial number the next replica should start with
- replicainterval = the number to add to nextreplica the next time a
- replica is created
-
- File locking is attempted so we have unique serial numbers.
- """
- fp = None
- parser = RawConfigParser()
- if ipautil.file_exists(serial_file):
- try:
- fp = open(serial_file, "r+")
- fcntl.flock(fp.fileno(), fcntl.LOCK_EX)
- parser.readfp(fp)
- serial = parser.getint('selfsign', 'lastvalue')
- cur_serial = serial + 1
- except IOError, e:
- raise RuntimeError("Unable to determine serial number: %s" % str(e))
- except MissingSectionHeaderError:
- fcntl.flock(fp.fileno(), fcntl.LOCK_UN)
- fp.close()
- f=open(serial_file,"r")
- r = f.readline()
- f.close()
- cur_serial = int(r) + 1
- fp = open(serial_file, "w")
- fcntl.flock(fp.fileno(), fcntl.LOCK_EX)
- parser.add_section('selfsign')
- parser.set('selfsign', 'nextreplica', 500000)
- parser.set('selfsign', 'replicainterval', 500000)
- else:
- fp = open(serial_file, "w")
- fcntl.flock(fp.fileno(), fcntl.LOCK_EX)
- parser.add_section('selfsign')
- parser.set('selfsign', 'nextreplica', 500000)
- parser.set('selfsign', 'replicainterval', 500000)
- cur_serial = 1000
-
- try:
- fp.seek(0)
- parser.set('selfsign', 'lastvalue', cur_serial)
- parser.write(fp)
- fp.flush()
- fcntl.flock(fp.fileno(), fcntl.LOCK_UN)
- fp.close()
- except IOError, e:
- raise RuntimeError("Unable to increment serial number: %s" % str(e))
-
- return str(cur_serial)
-
-def next_replica(serial_file=CA_SERIALNO):
- """
- Return the starting serial number for a new self-signed replica
- """
- fp = None
- parser = RawConfigParser()
- if ipautil.file_exists(serial_file):
- try:
- fp = open(serial_file, "r+")
- fcntl.flock(fp.fileno(), fcntl.LOCK_EX)
- parser.readfp(fp)
- serial = parser.getint('selfsign', 'nextreplica')
- nextreplica = serial + parser.getint('selfsign', 'replicainterval')
- except IOError, e:
- raise RuntimeError("Unable to determine serial number: %s" % str(e))
- else:
- raise RuntimeError("%s does not exist, cannot create replica" % serial_file)
- try:
- fp.seek(0)
- parser.set('selfsign', 'nextreplica', nextreplica)
- parser.write(fp)
- fp.flush()
- fcntl.flock(fp.fileno(), fcntl.LOCK_UN)
- fp.close()
- except IOError, e:
- raise RuntimeError("Unable to increment serial number: %s" % str(e))
-
- return str(serial)
-
class NSSDatabase(object):
"""A general-purpose wrapper around a NSS cert database
@@ -440,15 +330,10 @@ class CertDB(object):
except OSError, e:
raise RuntimeError("Unable to determine the current directory: %s" % str(e))
- self.self_signed_ca = ipa_self_signed()
-
if not subject_base:
self.subject_base = DN(('O', 'IPA'))
- if self.self_signed_ca:
- self.cacert_name = get_ca_nickname(self.realm, 'CN=%s Certificate Authority')
- else:
- self.cacert_name = get_ca_nickname(self.realm)
+ self.cacert_name = get_ca_nickname(self.realm)
self.valid_months = "120"
self.keysize = "1024"
@@ -495,22 +380,6 @@ class CertDB(object):
# sure we are in a unique place when this happens
os.chdir(self.reqdir)
- def set_serial_from_pkcs12(self):
- """A CA cert was loaded from a PKCS#12 file. Set up our serial file"""
-
- cur_serial = self.find_cacert_serial()
- try:
- fp = open(CA_SERIALNO, "w")
- parser = RawConfigParser()
- parser.add_section('selfsign')
- parser.set('selfsign', 'lastvalue', cur_serial)
- parser.set('selfsign', 'nextreplica', 500000)
- parser.set('selfsign', 'replicainterval', 500000)
- parser.write(fp)
- fp.close()
- except IOError, e:
- raise RuntimeError("Unable to increment serial number: %s" % str(e))
-
def set_perms(self, fname, write=False, uid=None):
if uid:
pent = pwd.getpwnam(uid)
@@ -529,13 +398,10 @@ class CertDB(object):
return self.nssdb.run_certutil(args, stdin)
def run_signtool(self, args, stdin=None):
- if not self.self_signed_ca:
- f = open(self.passwd_fname, "r")
+ with open(self.passwd_fname, "r") as f:
password = f.readline()
- f.close()
- new_args = ["/usr/bin/signtool", "-d", self.secdir, "-p", password]
- else:
- new_args = ["/usr/bin/signtool", "-d", self.secdir]
+ new_args = ["/usr/bin/signtool", "-d", self.secdir, "-p", password]
+
new_args = new_args + args
ipautil.run(new_args, stdin)
@@ -585,41 +451,6 @@ class CertDB(object):
return False
- def create_ca_cert(self):
- os.chdir(self.secdir)
- subject = DN(('cn', '%s Certificate Authority' % self.realm))
- p = subprocess.Popen(["/usr/bin/certutil",
- "-d", self.secdir,
- "-S", "-n", self.cacert_name,
- "-s", str(subject),
- "-x",
- "-t", "CT,,C",
- "-1",
- "-2",
- "-5",
- "-m", next_serial(),
- "-v", self.valid_months,
- "-z", self.noise_fname,
- "-f", self.passwd_fname],
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- # Create key usage extension
- # 0 - Digital Signature
- # 1 - Non-repudiation
- # 5 - Cert signing key
- # Is this a critical extension [y/N]? y
- p.stdin.write("0\n1\n5\n9\ny\n")
- # Create basic constraint extension
- # Is this a CA certificate [y/N]? y
- # Enter the path length constraint, enter to skip [<0 for unlimited pat
- # Is this a critical extension [y/N]? y
- # 5 6 7 9 n -> SSL, S/MIME, Object signing CA
- p.stdin.write("y\n\ny\n")
- p.stdin.write("5\n6\n7\n9\nn\n")
- p.wait()
- os.chdir(self.cwd)
-
def export_ca_cert(self, nickname, create_pkcs12=False):
"""create_pkcs12 tells us whether we should create a PKCS#12 file
of the CA or not. If we are running on a replica then we won't
@@ -686,16 +517,6 @@ class CertDB(object):
except ipautil.CalledProcessError:
return ''
- def find_cacert_serial(self):
- (out, err, returncode) = self.run_certutil(["-L", "-n", self.cacert_name])
- data = out.split('\n')
- for line in data:
- x = re.match(r'\s+Serial Number: (\d+) .*', line)
- if x is not None:
- return x.group(1)
-
- raise RuntimeError("Unable to find serial number")
-
def track_server_cert(self, nickname, principal, password_file=None, command=None):
"""
Tell certmonger to track the given certificate nickname.
@@ -752,12 +573,7 @@ class CertDB(object):
def create_server_cert(self, nickname, hostname, other_certdb=None, subject=None):
"""
- other_certdb can mean one of two things, depending on the context.
-
- If we are using a self-signed CA then other_certdb contains the
- CA that will be signing our CSR.
-
- If we are using a dogtag CA then it contains the RA agent key
+ If we are using a dogtag CA then other_certdb contains the RA agent key
that will issue our cert.
You can override the certificate Subject by specifying a subject.
@@ -802,179 +618,117 @@ class CertDB(object):
"-k", certtype,
"-g", keysize,
"-z", self.noise_fname,
- "-f", self.passwd_fname]
- if not self.self_signed_ca:
- args.append("-a")
+ "-f", self.passwd_fname,
+ "-a"]
(stdout, stderr, returncode) = self.run_certutil(args)
os.remove(self.noise_fname)
return (stdout, stderr)
def issue_server_cert(self, certreq_fname, cert_fname):
self.setup_cert_request()
- if self.self_signed_ca:
- p = subprocess.Popen(["/usr/bin/certutil",
- "-d", self.secdir,
- "-C", "-c", self.cacert_name,
- "-i", certreq_fname,
- "-o", cert_fname,
- "-m", next_serial(),
- "-v", self.valid_months,
- "-f", self.passwd_fname,
- "-1", "-5"],
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE)
-
- # Bah - this sucks, but I guess it isn't possible to fully
- # control this with command line arguments.
- #
- # What this is requesting is:
- # -1 (Create key usage extension)
- # 2 - Key encipherment
- # 9 - done
- # n - not critical
- #
- # -5 (Create netscape cert type extension)
- # 1 - SSL Server
- # 9 - done
- # n - not critical
- p.stdin.write("2\n9\nn\n1\n9\nn\n")
- p.wait()
- else:
- if self.host_name is None:
- raise RuntimeError("CA Host is not set.")
- f = open(certreq_fname, "r")
- csr = f.readlines()
- f.close()
- csr = "".join(csr)
+ if self.host_name is None:
+ raise RuntimeError("CA Host is not set.")
- # We just want the CSR bits, make sure there is nothing else
- csr = pkcs10.strip_header(csr)
+ f = open(certreq_fname, "r")
+ csr = f.readlines()
+ f.close()
+ csr = "".join(csr)
- params = {'profileId': 'caIPAserviceCert',
- 'cert_request_type': 'pkcs10',
- 'requestor_name': 'IPA Installer',
- 'cert_request': csr,
- 'xmlOutput': 'true'}
+ # We just want the CSR bits, make sure there is nothing else
+ csr = pkcs10.strip_header(csr)
- # Send the request to the CA
- f = open(self.passwd_fname, "r")
- password = f.readline()
- f.close()
- result = dogtag.https_request(
- self.host_name,
- api.env.ca_ee_install_port or
- dogtag.configured_constants().EE_SECURE_PORT,
- "/ca/ee/ca/profileSubmitSSLClient",
- self.secdir, password, "ipaCert", **params)
- http_status, http_reason_phrase, http_headers, http_body = result
-
- if http_status != 200:
- raise CertificateOperationError(
- error=_('Unable to communicate with CMS (%s)') %
- http_reason_phrase)
-
- # The result is an XML blob. Pull the certificate out of that
- doc = xml.dom.minidom.parseString(http_body)
- item_node = doc.getElementsByTagName("b64")
+ params = {'profileId': 'caIPAserviceCert',
+ 'cert_request_type': 'pkcs10',
+ 'requestor_name': 'IPA Installer',
+ 'cert_request': csr,
+ 'xmlOutput': 'true'}
+
+ # Send the request to the CA
+ f = open(self.passwd_fname, "r")
+ password = f.readline()
+ f.close()
+ result = dogtag.https_request(
+ self.host_name,
+ api.env.ca_ee_install_port or
+ dogtag.configured_constants().EE_SECURE_PORT,
+ "/ca/ee/ca/profileSubmitSSLClient",
+ self.secdir, password, "ipaCert", **params)
+ http_status, http_reason_phrase, http_headers, http_body = result
+
+ if http_status != 200:
+ raise CertificateOperationError(
+ error=_('Unable to communicate with CMS (%s)') %
+ http_reason_phrase)
+
+ # The result is an XML blob. Pull the certificate out of that
+ doc = xml.dom.minidom.parseString(http_body)
+ item_node = doc.getElementsByTagName("b64")
+ try:
try:
- try:
- cert = item_node[0].childNodes[0].data
- except IndexError:
- raise RuntimeError("Certificate issuance failed")
- finally:
- doc.unlink()
-
- # base64-decode the result for uniformity
- cert = base64.b64decode(cert)
-
- # Write the certificate to a file. It will be imported in a later
- # step. This file will be read later to be imported.
- f = open(cert_fname, "w")
- f.write(cert)
- f.close()
+ cert = item_node[0].childNodes[0].data
+ except IndexError:
+ raise RuntimeError("Certificate issuance failed")
+ finally:
+ doc.unlink()
- return
+ # base64-decode the result for uniformity
+ cert = base64.b64decode(cert)
+
+ # Write the certificate to a file. It will be imported in a later
+ # step. This file will be read later to be imported.
+ f = open(cert_fname, "w")
+ f.write(cert)
+ f.close()
def issue_signing_cert(self, certreq_fname, cert_fname):
self.setup_cert_request()
- if self.self_signed_ca:
- p = subprocess.Popen(["/usr/bin/certutil",
- "-d", self.secdir,
- "-C", "-c", self.cacert_name,
- "-i", certreq_fname,
- "-o", cert_fname,
- "-m", next_serial(),
- "-v", self.valid_months,
- "-f", self.passwd_fname,
- "-1", "-5"],
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE)
-
- # Bah - this sucks, but I guess it isn't possible to fully
- # control this with command line arguments.
- #
- # What this is requesting is:
- # -1 (Create key usage extension)
- # 0 - Digital Signature
- # 5 - Cert signing key
- # 9 - done
- # n - not critical
- #
- # -5 (Create netscape cert type extension)
- # 3 - Object Signing
- # 9 - done
- # n - not critical
- p.stdin.write("0\n5\n9\nn\n3\n9\nn\n")
- p.wait()
- else:
- if self.host_name is None:
- raise RuntimeError("CA Host is not set.")
-
- f = open(certreq_fname, "r")
- csr = f.readlines()
- f.close()
- csr = "".join(csr)
-
- # We just want the CSR bits, make sure there is no thing else
- csr = pkcs10.strip_header(csr)
- params = {'profileId': 'caJarSigningCert',
- 'cert_request_type': 'pkcs10',
- 'requestor_name': 'IPA Installer',
- 'cert_request': csr,
- 'xmlOutput': 'true'}
+ if self.host_name is None:
+ raise RuntimeError("CA Host is not set.")
- # Send the request to the CA
- f = open(self.passwd_fname, "r")
- password = f.readline()
- f.close()
- result = dogtag.https_request(
- self.host_name,
- api.env.ca_ee_install_port or
- dogtag.configured_constants().EE_SECURE_PORT,
- "/ca/ee/ca/profileSubmitSSLClient",
- self.secdir, password, "ipaCert", **params)
- http_status, http_reason_phrase, http_headers, http_body = result
- if http_status != 200:
- raise RuntimeError("Unable to submit cert request")
-
- # The result is an XML blob. Pull the certificate out of that
- doc = xml.dom.minidom.parseString(http_body)
- item_node = doc.getElementsByTagName("b64")
- cert = item_node[0].childNodes[0].data
- doc.unlink()
+ f = open(certreq_fname, "r")
+ csr = f.readlines()
+ f.close()
+ csr = "".join(csr)
- # base64-decode the cert for uniformity
- cert = base64.b64decode(cert)
+ # We just want the CSR bits, make sure there is no thing else
+ csr = pkcs10.strip_header(csr)
- # Write the certificate to a file. It will be imported in a later
- # step. This file will be read later to be imported.
- f = open(cert_fname, "w")
- f.write(cert)
- f.close()
+ params = {'profileId': 'caJarSigningCert',
+ 'cert_request_type': 'pkcs10',
+ 'requestor_name': 'IPA Installer',
+ 'cert_request': csr,
+ 'xmlOutput': 'true'}
- return
+ # Send the request to the CA
+ f = open(self.passwd_fname, "r")
+ password = f.readline()
+ f.close()
+ result = dogtag.https_request(
+ self.host_name,
+ api.env.ca_ee_install_port or
+ dogtag.configured_constants().EE_SECURE_PORT,
+ "/ca/ee/ca/profileSubmitSSLClient",
+ self.secdir, password, "ipaCert", **params)
+ http_status, http_reason_phrase, http_headers, http_body = result
+ if http_status != 200:
+ raise RuntimeError("Unable to submit cert request")
+
+ # The result is an XML blob. Pull the certificate out of that
+ doc = xml.dom.minidom.parseString(http_body)
+ item_node = doc.getElementsByTagName("b64")
+ cert = item_node[0].childNodes[0].data
+ doc.unlink()
+
+ # base64-decode the cert for uniformity
+ cert = base64.b64decode(cert)
+
+ # Write the certificate to a file. It will be imported in a later
+ # step. This file will be read later to be imported.
+ f = open(cert_fname, "w")
+ f.write(cert)
+ f.close()
def add_cert(self, cert_fname, nickname):
"""
@@ -1020,48 +774,11 @@ class CertDB(object):
"""
root_nicknames = self.nssdb.get_trust_chain(nickname)
- # Try to work around a change in the F-11 certutil where untrusted
- # CA's are not shown in the chain. This will make a default IPA
- # server installable.
- if len(root_nicknames) == 0 and self.self_signed_ca:
- return [self.cacert_name]
-
return root_nicknames
def find_root_cert_from_pkcs12(self, pkcs12_fname, passwd_fname=None):
- """Given a PKCS#12 file, try to find any certificates that do
- not have a key. The assumption is that these are the root CAs.
- """
- args = ["/usr/bin/pk12util", "-d", self.secdir,
- "-l", pkcs12_fname,
- "-k", passwd_fname]
- if passwd_fname:
- args = args + ["-w", passwd_fname]
- try:
- (stdout, stderr, returncode) = ipautil.run(args)
- except ipautil.CalledProcessError, e:
- if e.returncode == 17:
- raise RuntimeError("incorrect password")
- else:
- raise RuntimeError("unknown error using pkcs#12 file")
-
- lines = stdout.split('\n')
-
- # A simple state machine.
- # 1 = looking for "Certificate:"
- # 2 = looking for the Friendly name (nickname)
- nicknames = []
- state = 1
- for line in lines:
- if state == 2:
- m = re.match("\W+Friendly Name: (.*)", line)
- if m:
- nicknames.append( m.groups(0)[0])
- state = 1
- if line == "Certificate:":
- state = 2
-
- return nicknames
+ return self.nssdb.find_root_cert_from_pkcs12(pkcs12_fname,
+ passwd_fname=passwd_fname)
def trust_root_cert(self, root_nickname):
if root_nickname is None:
@@ -1097,14 +814,6 @@ class CertDB(object):
"-in", pem_fname, "-out", pkcs12_fname,
"-passout", "file:" + pkcs12_pwd_fname])
- def create_self_signed(self, passwd=None):
- self.create_noise_file()
- self.create_passwd_file(passwd)
- self.create_certdbs()
- self.create_ca_cert()
- self.export_ca_cert(self.cacert_name, True)
- self.create_pin_file()
-
def create_from_cacert(self, cacert_fname, passwd=None):
if ipautil.file_exists(self.certdb_fname):
# We already have a cert db, see if it is for the same CA.
@@ -1167,94 +876,6 @@ class CertDB(object):
self.create_pin_file()
self.export_ca_cert(nickname, False)
- self.self_signed_ca=False
-
- # This file implies that we have our own self-signed CA. Ensure
- # that it no longer exists (from previous installs, for example).
- try:
- os.remove(CA_SERIALNO)
- except:
- pass
-
- def create_kdc_cert(self, nickname, hostname, destdir):
- """Create a new certificate with the spcial othername encoding needed
- by a KDC certificate.
-
- nickname: the CN name set in the certificate
- destdir: the location where cert and key are to be installed
-
- destdir will contain kdc.pem if the operation is successful
- """
-
- reqcfg = "kdc_req.conf"
- extcfg = ipautil.SHARE_DIR + "kdc_extensions.template"
- key_fname = destdir + "/kdckey.pem"
- cert_fname = destdir + "/kdccert.pem"
- key_cert_fname = destdir + "/kdc.pem"
-
- # Setup the temp dir
- self.setup_cert_request()
-
- # Copy the CA password file because openssl apparently can't use
- # the same file twice within the same command and throws an error
- ca_pwd_file = self.reqdir + "pwdfile.txt"
- shutil.copyfile(self.passwd_fname, ca_pwd_file)
-
- # Extract the cacert.pem file used by openssl to sign the certs
- ipautil.run(["/usr/bin/openssl", "pkcs12",
- "-in", self.pk12_fname,
- "-passin", "file:" + self.passwd_fname,
- "-passout", "file:" + ca_pwd_file,
- "-out", "cacert.pem"])
-
- # Create the kdc key
- ipautil.run(["/usr/bin/openssl", "genrsa",
- "-out", key_fname, "2048"])
-
- # Prepare a simple cert request
- req_dict = dict(PASSWORD=self.gen_password(),
- SUBJBASE=self.subject_base,
- CERTNAME=DN(('CN', nickname)))
- req_template = ipautil.SHARE_DIR + reqcfg + ".template"
- conf = ipautil.template_file(req_template, req_dict)
- fd = open(reqcfg, "w+")
- fd.write(conf)
- fd.close()
-
- base = str(self.subject_base).replace(",", "/")
- esc_subject = DN(('CN', '%s/%s' % (nickname, base)))
-
- ipautil.run(["/usr/bin/openssl", "req", "-new",
- "-config", reqcfg,
- "-subj", str(esc_subject),
- "-key", key_fname,
- "-out", "kdc.req"])
-
- # Finally, sign the cert using the extensions file to set the
- # special name
- ipautil.run(["/usr/bin/openssl", "x509", "-req",
- "-CA", "cacert.pem",
- "-extfile", extcfg,
- "-extensions", "kdc_cert",
- "-passin", "file:" + ca_pwd_file,
- "-set_serial", next_serial(),
- "-in", "kdc.req",
- "-out", cert_fname],
- env = { 'REALM':self.realm, 'HOST_FQDN':hostname })
-
- # Merge key and cert in a single file
- fd = open(key_fname, "r")
- key = fd.read()
- fd.close()
- fd = open(cert_fname, "r")
- cert = fd.read()
- fd.close()
- fd = open(key_cert_fname, "w")
- fd.write(key)
- fd.write(cert)
- fd.close()
- os.unlink(key_fname)
- os.unlink(cert_fname)
def install_pem_from_p12(self, p12_fname, p12_pwd_fname, pem_fname):
ipautil.run(["/usr/bin/openssl", "pkcs12", "-nodes",