Get CA certs for system-wide store from cert store in ipa-client-install.

All of the certificates and associated key policy are now stored in
/etc/pki/ca-trust/source/ipa.p11-kit.

Part of https://fedorahosted.org/freeipa/ticket/3259
Part of https://fedorahosted.org/freeipa/ticket/3520

Reviewed-By: Rob Crittenden <rcritten@redhat.com>
This commit is contained in:
Jan Cholasta
2014-06-12 17:20:19 +02:00
committed by Petr Viktorin
parent 24932b2d91
commit 55d3bab57b
4 changed files with 100 additions and 26 deletions

View File

@@ -771,7 +771,7 @@ def uninstall(options, env):
'as it can cause subsequent installation to fail.')
# Remove the CA cert from the systemwide certificate store
tasks.remove_ca_cert_from_systemwide_ca_store(CACERT)
tasks.remove_ca_certs_from_systemwide_ca_store()
# Remove the CA cert
try:
@@ -2545,9 +2545,6 @@ def install(options, env, fstore, statestore):
return CLIENT_INSTALL_ERROR
root_logger.info("Configured /etc/sssd/sssd.conf")
# Add the CA to the platform-dependant systemwide CA store
tasks.insert_ca_cert_into_systemwide_ca_store(CACERT)
host_principal = 'host/%s@%s' % (hostname, cli_realm)
if options.on_master:
# If on master assume kerberos is already configured properly.
@@ -2649,6 +2646,13 @@ def install(options, env, fstore, statestore):
if not remote_env['enable_ra']:
disable_ra()
# Get CA certificates from the certificate store
ca_certs = get_certs_from_ldap(cli_server[0], cli_basedn, cli_realm,
remote_env['enable_ra'])
# Add the CA to the platform-dependant systemwide CA store
tasks.insert_ca_certs_into_systemwide_ca_store(ca_certs)
# Add the CA to the default NSS database and trust it
if not purge_ipa_certs():
root_logger.info(
@@ -2662,8 +2666,6 @@ def install(options, env, fstore, statestore):
root_logger.error("Failed to open /etc/pki/nssdb/ipa.txt: %s", e)
return CLIENT_INSTALL_ERROR
ca_certs = get_certs_from_ldap(cli_server[0], cli_basedn, cli_realm,
remote_env['enable_ra'])
for cert, nickname, trusted, ext_key_usage in ca_certs:
try:
root_logger.debug("Attempting to add CA directly to the "

View File

@@ -80,7 +80,7 @@ class BasePathNamespace(object):
PAM_LDAP_CONF = "/etc/pam_ldap.conf"
PASSWD = "/etc/passwd"
ETC_PKI_CA_DIR = "/etc/pki-ca"
SYSTEMWIDE_CA_STORE = "/etc/pki/ca-trust/source/anchors/"
IPA_P11_KIT = "/etc/pki/ca-trust/source/ipa.p11-kit"
NSS_DB_DIR = "/etc/pki/nssdb"
NSSDB_CERT8_DB = "/etc/pki/nssdb/cert8.db"
NSSDB_KEY3_DB = "/etc/pki/nssdb/key3.db"

View File

@@ -49,9 +49,9 @@ class BaseTaskNamespace(object):
return
def insert_ca_cert_into_systemwide_ca_store(self, path):
def insert_ca_certs_into_systemwide_ca_store(self, ca_certs):
"""
Adds the CA certificate located at 'path' to the systemwide CA store
Adds CA certificates from 'ca_certs' to the systemwide CA store
(if available on the platform).
Returns True if the operation succeeded, False otherwise.
@@ -59,10 +59,10 @@ class BaseTaskNamespace(object):
return True
def remove_ca_cert_from_systemwide_ca_store(self, path):
def remove_ca_certs_from_systemwide_ca_store(self):
"""
Removes the CA certificate located at 'path' from the systemwide CA
store (if available on the platform).
Removes IPA CA certificates from the systemwide CA store
(if available on the platform).
Returns True if the operation succeeded, False otherwise.
"""

View File

@@ -28,12 +28,18 @@ import shutil
import stat
import socket
import sys
import urllib
import base64
from subprocess import CalledProcessError
from nss.error import NSPRError
from pyasn1.error import PyAsn1Error
from ipapython.ipa_log_manager import root_logger
from ipapython import ipautil
from ipalib import x509 # FIXME: do not import from ipalib
from ipaplatform.paths import paths
from ipaplatform.fedora.authconfig import FedoraAuthConfig
from ipaplatform.base.tasks import BaseTaskNamespace
@@ -148,19 +154,88 @@ class FedoraTaskNamespace(BaseTaskNamespace):
auth_config.add_option("nostart")
auth_config.execute()
def insert_ca_cert_into_systemwide_ca_store(self, cacert_path):
# Add the 'ipa-' prefix to cert name to avoid name collisions
cacert_name = os.path.basename(cacert_path)
new_cacert_path = os.path.join(paths.SYSTEMWIDE_CA_STORE,
'ipa-%s' % cacert_name)
def insert_ca_certs_into_systemwide_ca_store(self, ca_certs):
new_cacert_path = paths.IPA_P11_KIT
try:
f = open(new_cacert_path, 'w')
except IOError, e:
root_logger.info("Failed to open %s: %s" % (new_cacert_path, e))
return False
f.write("# This file was created by IPA. Do not edit.\n"
"\n")
has_eku = set()
for cert, nickname, trusted, ext_key_usage in ca_certs:
try:
subject = x509.get_der_subject(cert, x509.DER)
issuer = x509.get_der_issuer(cert, x509.DER)
serial_number = x509.get_der_serial_number(cert, x509.DER)
public_key_info = x509.get_der_public_key_info(cert, x509.DER)
except (NSPRError, PyAsn1Error), e:
root_logger.warning(
"Failed to decode certificate \"%s\": %s", nickname, e)
continue
label = urllib.quote(nickname)
subject = urllib.quote(subject)
issuer = urllib.quote(issuer)
serial_number = urllib.quote(serial_number)
public_key_info = urllib.quote(public_key_info)
cert = base64.b64encode(cert)
cert = x509.make_pem(cert)
obj = ("[p11-kit-object-v1]\n"
"class: certificate\n"
"certificate-type: x-509\n"
"certificate-category: authority\n"
"label: \"%(label)s\"\n"
"subject: \"%(subject)s\"\n"
"issuer: \"%(issuer)s\"\n"
"serial-number: \"%(serial_number)s\"\n"
"x-public-key-info: \"%(public_key_info)s\"\n" %
dict(label=label,
subject=subject,
issuer=issuer,
serial_number=serial_number,
public_key_info=public_key_info))
if trusted is True:
obj += "trusted: true\n"
elif trusted is False:
obj += "x-distrusted: true\n"
obj += "%s\n\n" % cert
f.write(obj)
if ext_key_usage is not None and public_key_info not in has_eku:
if not ext_key_usage:
ext_key_usage = {x509.EKU_PLACEHOLDER}
try:
ext_key_usage = x509.encode_ext_key_usage(ext_key_usage)
except PyAsn1Error, e:
root_logger.warning(
"Failed to encode extended key usage for \"%s\": %s",
nickname, e)
continue
value = urllib.quote(ext_key_usage)
obj = ("[p11-kit-object-v1]\n"
"class: x-certificate-extension\n"
"label: \"ExtendedKeyUsage for %(label)s\"\n"
"x-public-key-info: \"%(public_key_info)s\"\n"
"object-id: 2.5.29.37\n"
"value: \"%(value)s\"\n\n" %
dict(label=label,
public_key_info=public_key_info,
value=value))
f.write(obj)
has_eku.add(public_key_info)
f.close()
# Add the CA to the systemwide CA trust database
try:
shutil.copy(cacert_path, new_cacert_path)
ipautil.run([paths.UPDATE_CA_TRUST])
except OSError, e:
root_logger.info("Failed to copy %s to %s" % (cacert_path,
new_cacert_path))
except CalledProcessError, e:
root_logger.info("Failed to add CA to the systemwide "
"CA trust database: %s" % str(e))
@@ -171,11 +246,8 @@ class FedoraTaskNamespace(BaseTaskNamespace):
return False
def remove_ca_cert_from_systemwide_ca_store(self, cacert_path):
# Derive the certificate name in the store
cacert_name = os.path.basename(cacert_path)
new_cacert_path = os.path.join(paths.SYSTEMWIDE_CA_STORE,
'ipa-%s' % cacert_name)
def remove_ca_certs_from_systemwide_ca_store(self):
new_cacert_path = paths.IPA_P11_KIT
# Remove CA cert from systemwide store
if os.path.exists(new_cacert_path):