diff options
-rw-r--r-- | freeipa.spec.in | 1 | ||||
-rw-r--r-- | install/share/Makefile.am | 1 | ||||
-rwxr-xr-x | install/share/copy-schema-to-ca.py | 84 | ||||
-rwxr-xr-x | install/tools/ipa-ca-install | 7 | ||||
-rwxr-xr-x | install/tools/ipa-replica-install | 7 | ||||
-rw-r--r-- | install/tools/man/ipa-ca-install.1 | 3 | ||||
-rw-r--r-- | install/tools/man/ipa-replica-install.1 | 3 | ||||
-rw-r--r-- | ipaserver/install/cainstance.py | 55 |
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. |