Setup lightweight CA key retrieval on install/upgrade

Add the ipa-pki-retrieve-key helper program and configure
lightweight CA key replication on installation and upgrade.  The
specific configuration steps are:

- Add the 'dogtag/$HOSTNAME' service principal
- Create the pricipal's Custodia keys
- Retrieve the principal's keytab
- Configure Dogtag's CS.cfg to use ExternalProcessKeyRetriever
  to invoke ipa-pki-retrieve-key for key retrieval

Also bump the minimum version of Dogtag to 10.3.2.

Part of: https://fedorahosted.org/freeipa/ticket/4559

Reviewed-By: Jan Cholasta <jcholast@redhat.com>
This commit is contained in:
Fraser Tweedale 2016-06-01 08:07:33 +10:00 committed by Jan Cholasta
parent 0d37d230c0
commit b0d9a4728f
10 changed files with 119 additions and 8 deletions

View File

@ -94,7 +94,7 @@ BuildRequires: libunistring-devel
BuildRequires: python-lesscpy
BuildRequires: python-yubico >= 1.2.3
BuildRequires: openssl-devel
BuildRequires: pki-base >= 10.2.6
BuildRequires: pki-base >= 10.3.2
BuildRequires: python-pytest-multihost >= 0.5
BuildRequires: python-pytest-sourceorder
BuildRequires: python-kdcproxy >= 0.3
@ -155,8 +155,8 @@ Requires(post): systemd-units
Requires: selinux-policy >= %{selinux_policy_version}
Requires(post): selinux-policy-base >= %{selinux_policy_version}
Requires: slapi-nis >= 0.55-1
Requires: pki-ca >= 10.2.6-19
Requires: pki-kra >= 10.2.6-19
Requires: pki-ca >= 10.3.2
Requires: pki-kra >= 10.3.2
Requires(preun): python systemd-units
Requires(postun): python systemd-units
Requires: zip
@ -1074,6 +1074,7 @@ fi
%{_libexecdir}/ipa/ipa-dnskeysync-replica
%{_libexecdir}/ipa/ipa-ods-exporter
%{_libexecdir}/ipa/ipa-httpd-kdcproxy
%{_libexecdir}/ipa/ipa-pki-retrieve-key
%dir %{_libexecdir}/ipa/oddjob
%attr(0755,root,root) %{_libexecdir}/ipa/oddjob/org.freeipa.server.conncheck
%config(noreplace) %{_sysconfdir}/dbus-1/system.d/org.freeipa.server.conf

View File

@ -179,6 +179,12 @@ objectClass: nsContainer
objectClass: top
cn: custodia
dn: cn=dogtag,cn=custodia,cn=ipa,cn=etc,$SUFFIX
changetype: add
objectClass: nsContainer
objectClass: top
cn: dogtag
dn: cn=s4u2proxy,cn=etc,$SUFFIX
changetype: add
objectClass: nsContainer

View File

@ -39,6 +39,7 @@ EXTRA_DIST = \
appdir = $(libexecdir)/ipa/
app_SCRIPTS = \
ipa-httpd-kdcproxy \
ipa-pki-retrieve-key \
$(NULL)
MAINTAINERCLEANFILES = \

View File

@ -0,0 +1,32 @@
#!/usr/bin/python2
from __future__ import print_function
import os
import sys
from ipalib import constants
from ipalib.config import Env
from ipaplatform.paths import paths
from ipapython.secrets.client import CustodiaClient
env = Env()
env._finalize()
keyname = "ca_wrapped/" + sys.argv[1]
servername = sys.argv[2]
service = constants.PKI_GSSAPI_SERVICE_NAME
client_keyfile = os.path.join(paths.PKI_TOMCAT, service + '.keys')
client_keytab = os.path.join(paths.PKI_TOMCAT, service + '.keytab')
# pylint: disable=no-member
client = CustodiaClient(
client_service='%s@%s' % (service, env.host), server=servername,
realm=env.realm, ldap_uri="ldaps://" + env.host,
keyfile=client_keyfile, keytab=client_keytab,
)
# Print the response JSON to stdout; it is already in the format
# that Dogtag's ExternalProcessKeyRetriever expects
print(client.fetch_key(keyname, store=False))

View File

@ -2,3 +2,8 @@ dn: cn=custodia,cn=ipa,cn=etc,$SUFFIX
default: objectClass: top
default: objectClass: nsContainer
default: cn: custodia
dn: cn=dogtag,cn=custodia,cn=ipa,cn=etc,$SUFFIX
default: objectClass: top
default: objectClass: nsContainer
default: cn: dogtag

View File

@ -264,3 +264,4 @@ REPL_AGMT_STRIP_ATTRS = ('modifiersName',
DOMAIN_SUFFIX_NAME = 'domain'
CA_SUFFIX_NAME = 'ca'
PKI_GSSAPI_SERVICE_NAME = 'dogtag'

View File

@ -182,7 +182,7 @@ def install_step_1(standalone, replica_config, options):
basedn = ipautil.realm_to_suffix(realm_name)
ca = cainstance.CAInstance(realm_name, certs.NSS_DIR)
ca = cainstance.CAInstance(realm_name, certs.NSS_DIR, host_name=host_name)
if standalone:
ca.stop('pki-tomcat')
@ -197,6 +197,13 @@ def install_step_1(standalone, replica_config, options):
# This is done within stopped_service context, which restarts CA
ca.enable_client_auth_to_db(paths.CA_CS_CFG_PATH)
# Lightweight CA key retrieval is configured in step 1 instead
# of CAInstance.configure_instance (which is invoked from step
# 0) because kadmin_addprinc fails until krb5.conf is installed
# by krb.create_instance.
#
ca.setup_lightweight_ca_key_retrieval()
if standalone and replica_config is None:
serverid = installutils.realm_to_serverid(realm_name)
dirname = dsinstance.config_dirname(serverid)

View File

@ -45,6 +45,7 @@ from six.moves.configparser import ConfigParser, RawConfigParser
from ipalib import api
from ipalib import pkcs10, x509
from ipalib import errors
import ipalib.constants
from ipaplatform import services
from ipaplatform.constants import constants
@ -59,6 +60,7 @@ from ipapython.certdb import get_ca_nickname
from ipapython.dn import DN
from ipapython.ipa_log_manager import log_mgr,\
standard_logging_setup, root_logger
from ipapython.secrets.kem import IPAKEMKeys
from ipaserver.install import certs
from ipaserver.install import dsinstance
@ -66,6 +68,7 @@ from ipaserver.install import installutils
from ipaserver.install import ldapupdate
from ipaserver.install import replication
from ipaserver.install import service
from ipaserver.install import sysupgrade
from ipaserver.install.dogtaginstance import (export_kra_agent_pem,
DogtagInstance)
from ipaserver.plugins import ldap2
@ -1356,11 +1359,64 @@ class CAInstance(DogtagInstance):
self.step("updating IPA configuration", update_ipa_conf)
self.step("Restart HTTP server to pick up changes",
self.__restart_http_instance)
self.step("Configure lightweight CA key retrieval",
self.setup_lightweight_ca_key_retrieval)
self.step("enabling CA instance", self.__enable_instance)
self.start_creation(runtime=210)
def setup_lightweight_ca_key_retrieval(self):
if sysupgrade.get_upgrade_state('dogtag', 'setup_lwca_key_retrieval'):
return
root_logger.info('[Set up lightweight CA key retrieval]')
self.__setup_lightweight_ca_key_retrieval_kerberos()
self.__setup_lightweight_ca_key_retrieval_custodia()
root_logger.info('Configuring key retriever')
directives = [
('features.authority.keyRetrieverClass',
'com.netscape.ca.ExternalProcessKeyRetriever'),
('features.authority.keyRetrieverConfig.executable',
'/usr/libexec/ipa/ipa-pki-retrieve-key'),
]
for k, v in directives:
installutils.set_directive(
paths.CA_CS_CFG_PATH, k, v, quotes=False, separator='=')
sysupgrade.set_upgrade_state('dogtag', 'setup_lwca_key_retieval', True)
def __setup_lightweight_ca_key_retrieval_kerberos(self):
service = ipalib.constants.PKI_GSSAPI_SERVICE_NAME
principal = '{}/{}@{}'.format(service, api.env.host, self.realm)
pent = pwd.getpwnam(constants.PKI_USER)
root_logger.info('Creating principal')
installutils.kadmin_addprinc(principal)
self.suffix = ipautil.realm_to_suffix(self.realm)
if not self.admin_conn:
self.ldap_connect()
self.move_service(principal)
root_logger.info('Retrieving keytab')
keytab = os.path.join(paths.PKI_TOMCAT, service + '.keytab')
installutils.create_keytab(keytab, principal)
os.chmod(keytab, 0o600)
os.chown(keytab, pent.pw_uid, pent.pw_gid)
def __setup_lightweight_ca_key_retrieval_custodia(self):
service = ipalib.constants.PKI_GSSAPI_SERVICE_NAME
pent = pwd.getpwnam(constants.PKI_USER)
root_logger.info('Creating Custodia keys')
keyfile = os.path.join(paths.PKI_TOMCAT, service + '.keys')
keystore = IPAKEMKeys({'server_keys': keyfile})
keystore.generate_keys(service)
os.chmod(keyfile, 0o600)
os.chown(keyfile, pent.pw_uid, pent.pw_gid)
def replica_ca_install_check(config):
if not config.setup_ca:

View File

@ -891,9 +891,6 @@ def install(installer):
# we now need to enable ssl on the ds
ds.enable_ssl()
if setup_ca:
ca.install_step_1(False, None, options)
krb = krbinstance.KrbInstance(fstore)
if options.pkinit_cert_files:
krb.create_instance(realm_name, host_name, domain_name,
@ -907,6 +904,9 @@ def install(installer):
setup_pkinit=not options.no_pkinit,
subject_base=options.subject)
if setup_ca:
ca.install_step_1(False, None, options)
# The DS instance is created before the keytab, add the SSL cert we
# generated
ds.add_cert_to_service()

View File

@ -1492,7 +1492,8 @@ def upgrade_configuration():
if subject_base:
sub_dict['SUBJECT_BASE'] = subject_base
ca = cainstance.CAInstance(api.env.realm, certs.NSS_DIR)
ca = cainstance.CAInstance(
api.env.realm, certs.NSS_DIR, host_name=api.env.host)
ca_running = ca.is_running()
with installutils.stopped_service('pki-tomcatd', 'pki-tomcat'):
@ -1697,6 +1698,7 @@ def upgrade_configuration():
if ca.is_configured():
cainstance.repair_profile_caIPAserviceCert()
ca.setup_lightweight_ca_key_retrieval()
set_sssd_domain_option('ipa_server_mode', 'True')