summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--freeipa.spec.in1
-rw-r--r--install/share/Makefile.am1
-rwxr-xr-xinstall/share/copy-schema-to-ca.py84
-rwxr-xr-xinstall/tools/ipa-ca-install7
-rwxr-xr-xinstall/tools/ipa-replica-install7
-rw-r--r--install/tools/man/ipa-ca-install.13
-rw-r--r--install/tools/man/ipa-replica-install.13
-rw-r--r--ipaserver/install/cainstance.py55
8 files changed, 161 insertions, 0 deletions
diff --git a/freeipa.spec.in b/freeipa.spec.in
index ab6c5c65e..870aaa62c 100644
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -554,6 +554,7 @@ fi
%attr(755,root,root) %{_libdir}/ipa/certmonger/*
%dir %{_usr}/share/ipa
%{_usr}/share/ipa/wsgi.py*
+%{_usr}/share/ipa/copy-schema-to-ca.py*
%{_usr}/share/ipa/*.ldif
%{_usr}/share/ipa/*.uldif
%{_usr}/share/ipa/*.template
diff --git a/install/share/Makefile.am b/install/share/Makefile.am
index 7f953bc42..4a5f81a67 100644
--- a/install/share/Makefile.am
+++ b/install/share/Makefile.am
@@ -60,6 +60,7 @@ app_DATA = \
automember.ldif \
replica-automember.ldif \
replica-s4u2proxy.ldif \
+ copy-schema-to-ca.py \
$(NULL)
EXTRA_DIST = \
diff --git a/install/share/copy-schema-to-ca.py b/install/share/copy-schema-to-ca.py
new file mode 100755
index 000000000..4e2054eac
--- /dev/null
+++ b/install/share/copy-schema-to-ca.py
@@ -0,0 +1,84 @@
+#! /usr/bin/python
+
+"""Copy the IPA schema to the CA directory server instance
+
+You need to run this script to prepare a 2.2 or 3.0 IPA master for
+installation of a 3.1 replica.
+
+Once a 3.1 replica is in the domain, every older CA master will emit schema
+replication errors until this script is run on it.
+
+"""
+
+import os
+import sys
+import pwd
+import shutil
+
+from ipapython import services, ipautil, dogtag
+from ipapython.ipa_log_manager import root_logger, standard_logging_setup
+from ipaserver.install.dsinstance import DS_USER, schema_dirname
+from ipaserver.install.cainstance import PKI_USER
+from ipalib import api
+
+SERVERID = "PKI-IPA"
+SCHEMA_FILENAMES = (
+ "60kerberos.ldif",
+ "60samba.ldif",
+ "60ipaconfig.ldif",
+ "60basev2.ldif",
+ "60basev3.ldif",
+ "60ipadns.ldif",
+ "61kerberos-ipav3.ldif",
+ "65ipasudo.ldif",
+ "05rfc2247.ldif",
+)
+
+
+def add_ca_schema():
+ """Copy IPA schema files into the CA DS instance
+ """
+ pki_pent = pwd.getpwnam(PKI_USER)
+ ds_pent = pwd.getpwnam(DS_USER)
+ for schema_fname in SCHEMA_FILENAMES:
+ source_fname = os.path.join(ipautil.SHARE_DIR, schema_fname)
+ target_fname = os.path.join(schema_dirname(SERVERID), schema_fname)
+ if not os.path.exists(source_fname):
+ root_logger.debug('File does not exist: %s', source_fname)
+ continue
+ if os.path.exists(target_fname):
+ root_logger.info(
+ 'Target exists, not overwriting: %s', target_fname)
+ continue
+ try:
+ shutil.copyfile(source_fname, target_fname)
+ except IOError, e:
+ root_logger.warning('Could not install %s: %s', target_fname, e)
+ else:
+ root_logger.info('Installed %s', target_fname)
+ os.chmod(target_fname, 0440) # read access for dirsrv user/group
+ os.chown(target_fname, pki_pent.pw_uid, ds_pent.pw_gid)
+
+
+def restart_pki_ds():
+ """Restart the CA DS instance to pick up schema changes
+ """
+ root_logger.info('Restarting CA DS')
+ services.service('dirsrv').restart(SERVERID)
+
+
+def main():
+ if os.getegid() != 0:
+ sys.exit("Must be root to run this script")
+ standard_logging_setup(verbose=True)
+
+ # In 3.0, restarting needs access to api.env
+ (options, argv) = api.bootstrap_with_global_options(context='server')
+
+ add_ca_schema()
+ restart_pki_ds()
+
+ root_logger.info('Schema updated successfully')
+
+
+main()
diff --git a/install/tools/ipa-ca-install b/install/tools/ipa-ca-install
index 05dce8ae5..aefcee8e5 100755
--- a/install/tools/ipa-ca-install
+++ b/install/tools/ipa-ca-install
@@ -58,6 +58,8 @@ def parse_options():
help="Do not use DNS for hostname lookup during installation")
parser.add_option("--skip-conncheck", dest="skip_conncheck", action="store_true",
default=False, help="skip connection check to remote master")
+ parser.add_option("--skip-schema-check", dest="skip_schema_check", action="store_true",
+ default=False, help="skip check for updated CA DS schema on the remote master")
parser.add_option("-U", "--unattended", dest="unattended", action="store_true",
default=False, help="unattended installation never prompts the user")
@@ -154,6 +156,11 @@ def main():
config.master_host_name, config.host_name, config.realm_name, True,
dogtag_master_ds_port, options.admin_password)
+ if options.skip_schema_check:
+ root_logger.info("Skipping CA DS schema check")
+ else:
+ cainstance.replica_ca_install_check(config, dogtag_master_ds_port)
+
# Configure the CA if necessary
(CA, cs) = cainstance.install_replica_ca(
config, dogtag_master_ds_port, postinstall=True)
diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install
index b7870fbe8..f041c58a8 100755
--- a/install/tools/ipa-replica-install
+++ b/install/tools/ipa-replica-install
@@ -90,6 +90,8 @@ def parse_options():
cert_group = OptionGroup(parser, "certificate system options")
cert_group.add_option("--no-pkinit", dest="setup_pkinit", action="store_false",
default=True, help="disables pkinit setup steps")
+ cert_group.add_option("--skip-schema-check", dest="skip_schema_check", action="store_true",
+ default=False, help="skip check for updated CA DS schema on the remote master")
parser.add_option_group(cert_group)
dns_group = OptionGroup(parser, "DNS options")
@@ -602,6 +604,11 @@ def main():
if replman and replman.conn:
replman.conn.unbind_s()
+ if options.skip_schema_check:
+ root_logger.info("Skipping CA DS schema check")
+ else:
+ cainstance.replica_ca_install_check(config, dogtag_master_ds_port)
+
# Configure ntpd
if options.conf_ntp:
ntp = ntpinstance.NTPInstance()
diff --git a/install/tools/man/ipa-ca-install.1 b/install/tools/man/ipa-ca-install.1
index b70dfbd7f..13ef43a80 100644
--- a/install/tools/man/ipa-ca-install.1
+++ b/install/tools/man/ipa-ca-install.1
@@ -41,6 +41,9 @@ Do not use DNS for hostname lookup during installation
\fB\-\-skip\-conncheck\fR
Skip connection check to remote master
.TP
+\fB\-\-skip\-schema\-check\fR
+Skip check for updated CA DS schema on the remote master
+.TP
\fB\-U\fR, \fB\-\-unattended\fR
An unattended installation that will never prompt for user input
.SH "EXIT STATUS"
diff --git a/install/tools/man/ipa-replica-install.1 b/install/tools/man/ipa-replica-install.1
index 084b45436..43d284f57 100644
--- a/install/tools/man/ipa-replica-install.1
+++ b/install/tools/man/ipa-replica-install.1
@@ -75,6 +75,9 @@ An unattended installation that will never prompt for user input
.TP
\fB\-\-no\-pkinit\fR
Disables pkinit setup steps
+.TP
+\fB\-\-skip\-schema\-check\fR
+Skip check for updated CA DS schema on the remote master
.SS "DNS OPTIONS"
.TP
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index 68e1485cd..9b32623c2 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -56,6 +56,7 @@ from ipaserver.install import installutils
from ipaserver.install import dsinstance
from ipaserver.install import certs
from ipaserver.install.installutils import ReplicaConfig
+from ipaserver.plugins import ldap2
from ipalib import util
from ipapython.ipa_log_manager import *
@@ -673,6 +674,7 @@ class CAInstance(service.Service):
str(self.master_replication_port),
"pki_clone_replication_clone_port":
dogtag.install_constants.DS_PORT,
+ "pki_clone_replicate_schema": "False",
"pki_clone_uri":
"https://%s" % ipautil.format_netloc(self.master_host, 443)
}
@@ -1557,6 +1559,59 @@ class CAInstance(service.Service):
return master == 'New'
+
+def replica_ca_install_check(config, master_ds_port):
+ if not config.setup_ca:
+ return
+
+ cafile = config.dir + "/cacert.p12"
+ if not ipautil.file_exists(cafile):
+ # self-signed replica
+ return
+
+ master_ds_port = int(master_ds_port)
+
+ # Exit if we have an old-style (Dogtag 9) CA already installed
+ ca = CAInstance(config.realm_name, certs.NSS_DIR,
+ dogtag_constants=dogtag.Dogtag9Constants)
+ if ca.is_installed():
+ root_logger.info('Dogtag 9 style CA instance found')
+ sys.exit("A CA is already configured on this system.")
+
+ if master_ds_port != dogtag.Dogtag9Constants.DS_PORT:
+ root_logger.debug(
+ 'Installing CA Replica from master with a merged database')
+ return
+
+ # Check if the master has the necessary schema in its CA instance
+ ca_ldap_url = 'ldap://%s:%s' % (config.master_host_name, master_ds_port)
+ objectclass = 'ipaObject'
+ root_logger.debug('Checking if IPA schema is present in %s', ca_ldap_url)
+ try:
+ connection = ldap2.IPASimpleLDAPObject(ca_ldap_url)
+ connection.start_tls_s()
+ connection.simple_bind_s(DN(('cn', 'Directory Manager')),
+ config.dirman_password)
+ rschema = connection.schema
+ result = rschema.get_obj(ldap.schema.models.ObjectClass, objectclass)
+ except Exception:
+ root_logger.critical(
+ 'CA DS schema check failed. Make sure the PKI service on the '
+ 'remote master is operational.')
+ raise
+ if result:
+ root_logger.debug('Check OK')
+ else:
+ root_logger.critical(
+ 'The master CA directory server does not have necessary schema. '
+ 'Please copy the following script to all CA masters and run it '
+ 'on them: %s\n'
+ 'If you are certain that this is a false positive, use '
+ '--skip-schema-check.',
+ os.path.join(ipautil.SHARE_DIR, 'copy-schema-to-ca.py'))
+ exit('IPA schema missing on master CA directory server')
+
+
def install_replica_ca(config, master_ds_port, postinstall=False):
"""
Install a CA on a replica.