Example #1
0
 def __publish_ca_cert(self):
     ca_subject = self.cert.issuer
     certlist = x509.load_certificate_list_from_file(paths.IPA_CA_CRT)
     ca_certs = [c for c in certlist if c.subject == ca_subject]
     if not ca_certs:
         raise RuntimeError("HTTPD cert was issued by an unknown CA.")
     # at this time we can assume any CA cert will be valid since this is
     # only run during installation
     x509.write_certificate_list(certlist, paths.CA_CRT)
Example #2
0
 def __publish_ca_cert(self):
     ca_subject = self.cert.issuer
     certlist = x509.load_certificate_list_from_file(paths.IPA_CA_CRT)
     ca_certs = [c for c in certlist if c.subject == ca_subject]
     if not ca_certs:
         raise RuntimeError("HTTPD cert was issued by an unknown CA.")
     # at this time we can assume any CA cert will be valid since this is
     # only run during installation
     x509.write_certificate_list(certlist, paths.CA_CRT, mode=0o644)
    def install_kdc_cert(self):
        ca_cert_file = paths.CA_BUNDLE_PEM
        pkcs12_file, pin, ca_cert = installutils.load_pkcs12(
            cert_files=self.args,
            key_password=self.options.pin,
            key_nickname=self.options.cert_name,
            ca_cert_files=[ca_cert_file],
            realm_name=api.env.realm)

        cdb = certs.CertDB(api.env.realm, nssdir=paths.IPA_NSSDB_DIR)

        # Check that the ca_cert is known and trusted
        with tempfile.NamedTemporaryFile() as temp:
            certs.install_pem_from_p12(pkcs12_file.name, pin, temp.name)

            kdc_cert = x509.load_certificate_from_file(temp.name)
            ca_certs = x509.load_certificate_list_from_file(ca_cert_file)

            try:
                verify_kdc_cert_validity(kdc_cert, ca_certs, api.env.realm)
            except ValueError as e:
                raise admintool.ScriptError(
                    "Peer's certificate issuer is not trusted (%s). "
                    "Please run ipa-cacert-manage install and ipa-certupdate "
                    "to install the CA certificate." % str(e))

        try:
            ca_enabled = api.Command.ca_is_enabled()['result']
            if ca_enabled:
                certmonger.stop_tracking(certfile=paths.KDC_CERT)

            certs.install_pem_from_p12(pkcs12_file.name, pin, paths.KDC_CERT)
            certs.install_key_from_p12(pkcs12_file.name, pin, paths.KDC_KEY)

            if ca_enabled:
                # Start tracking only if the cert was issued by IPA CA
                # Retrieve IPA CA
                ipa_ca_cert = cdb.get_cert_from_db(
                    get_ca_nickname(api.env.realm),
                    pem=False)
                # And compare with the CA which signed this certificate
                if ca_cert == ipa_ca_cert:
                    certmonger.start_tracking(
                        (paths.KDC_CERT, paths.KDC_KEY),
                        storage='FILE',
                        profile='KDCs_PKINIT_Certs')
        except RuntimeError as e:
            raise admintool.ScriptError(str(e))

        krb = krbinstance.KrbInstance()
        krb.init_info(
            realm_name=api.env.realm,
            host_name=api.env.host,
        )
        krb.pkinit_enable()
Example #4
0
    def install_kdc_cert(self):
        ca_cert_file = paths.CA_BUNDLE_PEM
        pkcs12_file, pin, ca_cert = installutils.load_pkcs12(
            cert_files=self.args,
            key_password=self.options.pin,
            key_nickname=self.options.cert_name,
            ca_cert_files=[ca_cert_file],
            realm_name=api.env.realm)

        cdb = certs.CertDB(api.env.realm, nssdir=paths.IPA_NSSDB_DIR)

        # Check that the ca_cert is known and trusted
        with tempfile.NamedTemporaryFile() as temp:
            certs.install_pem_from_p12(pkcs12_file.name, pin, temp.name)

            kdc_cert = x509.load_certificate_from_file(temp.name)
            ca_certs = x509.load_certificate_list_from_file(ca_cert_file)

            try:
                verify_kdc_cert_validity(kdc_cert, ca_certs, api.env.realm)
            except ValueError as e:
                raise admintool.ScriptError(
                    "Peer's certificate issuer is not trusted (%s). "
                    "Please run ipa-cacert-manage install and ipa-certupdate "
                    "to install the CA certificate." % str(e))

        try:
            ca_enabled = api.Command.ca_is_enabled()['result']
            if ca_enabled:
                certmonger.stop_tracking(certfile=paths.KDC_CERT)

            certs.install_pem_from_p12(pkcs12_file.name, pin, paths.KDC_CERT)
            certs.install_key_from_p12(pkcs12_file.name, pin, paths.KDC_KEY)

            if ca_enabled:
                # Start tracking only if the cert was issued by IPA CA
                # Retrieve IPA CA
                ipa_ca_cert = cdb.get_cert_from_db(get_ca_nickname(
                    api.env.realm),
                                                   pem=False)
                # And compare with the CA which signed this certificate
                if ca_cert == ipa_ca_cert:
                    certmonger.start_tracking((paths.KDC_CERT, paths.KDC_KEY),
                                              storage='FILE',
                                              profile='KDCs_PKINIT_Certs')
        except RuntimeError as e:
            raise admintool.ScriptError(str(e))

        krb = krbinstance.KrbInstance()
        krb.init_info(
            realm_name=api.env.realm,
            host_name=api.env.host,
        )
        krb.pkinit_enable()
    def check(self):
        try:
            ca_certs = x509.load_certificate_list_from_file(paths.IPA_CA_CRT)
        except IOError as e:
            logger.debug("Could not open %s: %s", paths.IPA_CA_CRT, e)
            yield Result(self,
                         constants.ERROR,
                         key=paths.IPA_CA_CRT,
                         error=str(e),
                         msg='Error opening IPA CA chain at {key}: {error}')
            return
        except ValueError as e:
            logger.debug("% contains an invalid certificate" %
                         paths.IPA_CA_CRT)
            yield Result(self,
                         constants.ERROR,
                         key=paths.IPA_CA_CRT,
                         error=str(e),
                         msg='IPA CA chain {key} contains an invalid '
                         'certificate: {error}')
            return

        now = datetime.now(timezone.utc)
        soon = now + timedelta(days=self.config.cert_expiration_days)
        for cert in ca_certs:
            subject = DN(cert.subject)
            subject = str(subject).replace('\\;', '\\3b')
            dt = cert.not_valid_after.replace(tzinfo=timezone.utc)
            if dt < now:
                logger.debug("%s is expired" % subject)
                yield Result(self,
                             constants.CRITICAL,
                             path=paths.IPA_CA_CRT,
                             key=subject,
                             msg='CA \'{key}\' in {path} is expired.')
            elif dt <= soon:
                logger.debug("%s is expiring soon" % subject)
                yield Result(self,
                             constants.WARNING,
                             path=paths.IPA_CA_CRT,
                             key=subject,
                             days=(dt - now).days,
                             msg='CA \'{key}\' in {path} is expiring in '
                             '{days} days.')
            else:
                yield Result(self,
                             constants.SUCCESS,
                             path=paths.IPA_CA_CRT,
                             key=subject,
                             days=(dt - now).days)
Example #6
0
    def renew_external_step_2(self, ca, old_cert_der):
        print("Importing the renewed CA certificate, please wait")

        options = self.options
        conn = api.Backend.ldap2

        old_cert_obj = x509.load_certificate(old_cert_der, x509.DER)
        old_der_subject = x509.get_der_subject(old_cert_der, x509.DER)
        old_spki = old_cert_obj.public_key().public_bytes(
            serialization.Encoding.DER,
            serialization.PublicFormat.SubjectPublicKeyInfo
        )

        cert_file, ca_file = installutils.load_external_cert(
            options.external_cert_files, DN(old_cert_obj.subject))

        with open(cert_file.name) as f:
            new_cert_data = f.read()
        new_cert_der = x509.normalize_certificate(new_cert_data)
        new_cert_obj = x509.load_certificate(new_cert_der, x509.DER)
        new_der_subject = x509.get_der_subject(new_cert_der, x509.DER)
        new_spki = new_cert_obj.public_key().public_bytes(
            serialization.Encoding.DER,
            serialization.PublicFormat.SubjectPublicKeyInfo
        )

        if new_cert_obj.subject != old_cert_obj.subject:
            raise admintool.ScriptError(
                "Subject name mismatch (visit "
                "http://www.freeipa.org/page/Troubleshooting for "
                "troubleshooting guide)")
        if new_der_subject != old_der_subject:
            raise admintool.ScriptError(
                "Subject name encoding mismatch (visit "
                "http://www.freeipa.org/page/Troubleshooting for "
                "troubleshooting guide)")
        if new_spki != old_spki:
            raise admintool.ScriptError(
                "Subject public key info mismatch (visit "
                "http://www.freeipa.org/page/Troubleshooting for "
                "troubleshooting guide)")

        with certs.NSSDatabase() as tmpdb:
            tmpdb.create_db()
            tmpdb.add_cert(old_cert_der, 'IPA CA', EXTERNAL_CA_TRUST_FLAGS)

            try:
                tmpdb.add_cert(new_cert_der, 'IPA CA', EXTERNAL_CA_TRUST_FLAGS)
            except ipautil.CalledProcessError as e:
                raise admintool.ScriptError(
                    "Not compatible with the current CA certificate: %s" % e)

            ca_certs = x509.load_certificate_list_from_file(ca_file.name)
            for ca_cert in ca_certs:
                data = ca_cert.public_bytes(serialization.Encoding.DER)
                tmpdb.add_cert(
                    data, str(DN(ca_cert.subject)), EXTERNAL_CA_TRUST_FLAGS)

            try:
                tmpdb.verify_ca_cert_validity('IPA CA')
            except ValueError as e:
                raise admintool.ScriptError(
                    "Not a valid CA certificate: %s (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)" % e)

            trust_chain = tmpdb.get_trust_chain('IPA CA')[:-1]
            for nickname in trust_chain:
                try:
                    ca_cert = tmpdb.get_cert(nickname)
                except RuntimeError:
                    break
                certstore.put_ca_cert_nss(
                    conn,
                    api.env.basedn,
                    ca_cert,
                    nickname,
                    EMPTY_TRUST_FLAGS)

        dn = DN(('cn', self.cert_nickname), ('cn', 'ca_renewal'),
                ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn)
        try:
            entry = conn.get_entry(dn, ['usercertificate'])
            entry['usercertificate'] = [new_cert_der]
            conn.update_entry(entry)
        except errors.NotFound:
            entry = conn.make_entry(
                dn,
                objectclass=['top', 'pkiuser', 'nscontainer'],
                cn=[self.cert_nickname],
                usercertificate=[new_cert_der])
            conn.add_entry(entry)
        except errors.EmptyModlist:
            pass

        try:
            ca.set_renewal_master()
        except errors.NotFound:
            raise admintool.ScriptError("CA renewal master not found")

        self.resubmit_request('dogtag-ipa-ca-renew-agent-reuse')

        print("CA certificate successfully renewed")
Example #7
0
    def renew_external_step_2(self, ca, old_cert_der):
        print("Importing the renewed CA certificate, please wait")

        options = self.options
        conn = api.Backend.ldap2

        old_cert_obj = x509.load_certificate(old_cert_der, x509.DER)
        old_der_subject = x509.get_der_subject(old_cert_der, x509.DER)
        old_spki = old_cert_obj.public_key().public_bytes(
            serialization.Encoding.DER,
            serialization.PublicFormat.SubjectPublicKeyInfo
        )

        cert_file, ca_file = installutils.load_external_cert(
            options.external_cert_files, DN(old_cert_obj.subject))

        with open(cert_file.name) as f:
            new_cert_data = f.read()
        new_cert_der = x509.normalize_certificate(new_cert_data)
        new_cert_obj = x509.load_certificate(new_cert_der, x509.DER)
        new_der_subject = x509.get_der_subject(new_cert_der, x509.DER)
        new_spki = new_cert_obj.public_key().public_bytes(
            serialization.Encoding.DER,
            serialization.PublicFormat.SubjectPublicKeyInfo
        )

        if new_cert_obj.subject != old_cert_obj.subject:
            raise admintool.ScriptError(
                "Subject name mismatch (visit "
                "http://www.freeipa.org/page/Troubleshooting for "
                "troubleshooting guide)")
        if new_der_subject != old_der_subject:
            raise admintool.ScriptError(
                "Subject name encoding mismatch (visit "
                "http://www.freeipa.org/page/Troubleshooting for "
                "troubleshooting guide)")
        if new_spki != old_spki:
            raise admintool.ScriptError(
                "Subject public key info mismatch (visit "
                "http://www.freeipa.org/page/Troubleshooting for "
                "troubleshooting guide)")

        with certs.NSSDatabase() as tmpdb:
            tmpdb.create_db()
            tmpdb.add_cert(old_cert_der, 'IPA CA', 'C,,')

            try:
                tmpdb.add_cert(new_cert_der, 'IPA CA', 'C,,')
            except ipautil.CalledProcessError as e:
                raise admintool.ScriptError(
                    "Not compatible with the current CA certificate: %s" % e)

            ca_certs = x509.load_certificate_list_from_file(ca_file.name)
            for ca_cert in ca_certs:
                data = ca_cert.public_bytes(serialization.Encoding.DER)
                tmpdb.add_cert(data, str(DN(ca_cert.subject)), 'C,,')

            try:
                tmpdb.verify_ca_cert_validity('IPA CA')
            except ValueError as e:
                raise admintool.ScriptError(
                    "Not a valid CA certificate: %s (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)" % e)

            trust_chain = tmpdb.get_trust_chain('IPA CA')[:-1]
            for nickname in trust_chain:
                try:
                    ca_cert = tmpdb.get_cert(nickname)
                except RuntimeError:
                    break
                certstore.put_ca_cert_nss(
                    conn, api.env.basedn, ca_cert, nickname, ',,')

        dn = DN(('cn', self.cert_nickname), ('cn', 'ca_renewal'),
                ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn)
        try:
            entry = conn.get_entry(dn, ['usercertificate'])
            entry['usercertificate'] = [new_cert_der]
            conn.update_entry(entry)
        except errors.NotFound:
            entry = conn.make_entry(
                dn,
                objectclass=['top', 'pkiuser', 'nscontainer'],
                cn=[self.cert_nickname],
                usercertificate=[new_cert_der])
            conn.add_entry(entry)
        except errors.EmptyModlist:
            pass

        try:
            ca.set_renewal_master()
        except errors.NotFound:
            raise admintool.ScriptError("CA renewal master not found")

        self.resubmit_request(ca, 'ipaRetrieval')

        print("CA certificate successfully renewed")
Example #8
0
    def renew_external_step_2(self, ca, old_cert):
        print("Importing the renewed CA certificate, please wait")

        options = self.options
        conn = api.Backend.ldap2
        cert_file, ca_file = installutils.load_external_cert(
            options.external_cert_files, x509.subject_base())

        nss_cert = None
        nss.nss_init(paths.PKI_TOMCAT_ALIAS_DIR)
        try:
            nss_cert = x509.load_certificate(old_cert, x509.DER)
            subject = nss_cert.subject
            der_subject = x509.get_der_subject(old_cert, x509.DER)
            #pylint: disable=E1101
            pkinfo = nss_cert.subject_public_key_info.format()
            #pylint: enable=E1101

            nss_cert = x509.load_certificate_from_file(cert_file.name)
            cert = nss_cert.der_data
            if nss_cert.subject != subject:
                raise admintool.ScriptError(
                    "Subject name mismatch (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)")
            if x509.get_der_subject(cert, x509.DER) != der_subject:
                raise admintool.ScriptError(
                    "Subject name encoding mismatch (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)")
            #pylint: disable=E1101
            if nss_cert.subject_public_key_info.format() != pkinfo:
                raise admintool.ScriptError(
                    "Subject public key info mismatch (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)")
            #pylint: enable=E1101
        finally:
            del nss_cert
            nss.nss_shutdown()

        with certs.NSSDatabase() as tmpdb:
            pw = ipautil.write_tmp_file(ipautil.ipa_generate_password())
            tmpdb.create_db(pw.name)
            tmpdb.add_cert(old_cert, 'IPA CA', 'C,,')

            try:
                tmpdb.add_cert(cert, 'IPA CA', 'C,,')
            except ipautil.CalledProcessError as e:
                raise admintool.ScriptError(
                    "Not compatible with the current CA certificate: %s" % e)

            ca_certs = x509.load_certificate_list_from_file(ca_file.name)
            for ca_cert in ca_certs:
                tmpdb.add_cert(ca_cert.der_data, str(ca_cert.subject), 'C,,')
            del ca_certs
            del ca_cert

            try:
                tmpdb.verify_ca_cert_validity('IPA CA')
            except ValueError as e:
                raise admintool.ScriptError(
                    "Not a valid CA certificate: %s (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)" % e)

            trust_chain = tmpdb.get_trust_chain('IPA CA')[:-1]
            for nickname in trust_chain:
                try:
                    ca_cert = tmpdb.get_cert(nickname)
                except RuntimeError:
                    break
                certstore.put_ca_cert_nss(
                    conn, api.env.basedn, ca_cert, nickname, ',,')

        dn = DN(('cn', self.cert_nickname), ('cn', 'ca_renewal'),
                ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn)
        try:
            entry = conn.get_entry(dn, ['usercertificate'])
            entry['usercertificate'] = [cert]
            conn.update_entry(entry)
        except errors.NotFound:
            entry = conn.make_entry(
                dn,
                objectclass=['top', 'pkiuser', 'nscontainer'],
                cn=[self.cert_nickname],
                usercertificate=[cert])
            conn.add_entry(entry)
        except errors.EmptyModlist:
            pass

        try:
            ca.set_renewal_master()
        except errors.NotFound:
            raise admintool.ScriptError("CA renewal master not found")

        self.resubmit_request(ca, 'ipaRetrieval')

        print("CA certificate successfully renewed")
Example #9
0
    def renew_external_step_2(self, ca, old_cert):
        print("Importing the renewed CA certificate, please wait")

        options = self.options
        conn = api.Backend.ldap2
        cert_file, ca_file = installutils.load_external_cert(
            options.external_cert_files, x509.subject_base())

        nss_cert = None
        nss.nss_init(paths.PKI_TOMCAT_ALIAS_DIR)
        try:
            nss_cert = x509.load_certificate(old_cert, x509.DER)
            subject = nss_cert.subject
            der_subject = x509.get_der_subject(old_cert, x509.DER)
            #pylint: disable=E1101
            pkinfo = nss_cert.subject_public_key_info.format()
            #pylint: enable=E1101

            nss_cert = x509.load_certificate_from_file(cert_file.name)
            cert = nss_cert.der_data
            if nss_cert.subject != subject:
                raise admintool.ScriptError(
                    "Subject name mismatch (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)")
            if x509.get_der_subject(cert, x509.DER) != der_subject:
                raise admintool.ScriptError(
                    "Subject name encoding mismatch (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)")
            #pylint: disable=E1101
            if nss_cert.subject_public_key_info.format() != pkinfo:
                raise admintool.ScriptError(
                    "Subject public key info mismatch (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)")
            #pylint: enable=E1101
        finally:
            del nss_cert
            nss.nss_shutdown()

        with certs.NSSDatabase() as tmpdb:
            pw = ipautil.write_tmp_file(ipautil.ipa_generate_password())
            tmpdb.create_db(pw.name)
            tmpdb.add_cert(old_cert, 'IPA CA', 'C,,')

            try:
                tmpdb.add_cert(cert, 'IPA CA', 'C,,')
            except ipautil.CalledProcessError as e:
                raise admintool.ScriptError(
                    "Not compatible with the current CA certificate: %s" % e)

            ca_certs = x509.load_certificate_list_from_file(ca_file.name)
            for ca_cert in ca_certs:
                tmpdb.add_cert(ca_cert.der_data, str(ca_cert.subject), 'C,,')
            del ca_certs
            del ca_cert

            try:
                tmpdb.verify_ca_cert_validity('IPA CA')
            except ValueError as e:
                raise admintool.ScriptError(
                    "Not a valid CA certificate: %s (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)" % e)

            trust_chain = tmpdb.get_trust_chain('IPA CA')[:-1]
            for nickname in trust_chain:
                try:
                    ca_cert = tmpdb.get_cert(nickname)
                except RuntimeError:
                    break
                certstore.put_ca_cert_nss(conn, api.env.basedn, ca_cert,
                                          nickname, ',,')

        dn = DN(('cn', self.cert_nickname), ('cn', 'ca_renewal'),
                ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn)
        try:
            entry = conn.get_entry(dn, ['usercertificate'])
            entry['usercertificate'] = [cert]
            conn.update_entry(entry)
        except errors.NotFound:
            entry = conn.make_entry(
                dn,
                objectclass=['top', 'pkiuser', 'nscontainer'],
                cn=[self.cert_nickname],
                usercertificate=[cert])
            conn.add_entry(entry)
        except errors.EmptyModlist:
            pass

        try:
            ca.set_renewal_master()
        except errors.NotFound:
            raise admintool.ScriptError("CA renewal master not found")

        self.resubmit_request(ca, 'ipaRetrieval')

        print("CA certificate successfully renewed")
Example #10
0
    def renew_external_step_2(self, ca, old_cert):
        print("Importing the renewed CA certificate, please wait")

        options = self.options
        conn = api.Backend.ldap2

        old_spki = old_cert.public_key_info_bytes

        cert_file, ca_file = installutils.load_external_cert(
            options.external_cert_files, DN(old_cert.subject))

        with open(cert_file.name, 'rb') as f:
            new_cert_data = f.read()
        new_cert = x509.load_pem_x509_certificate(new_cert_data)
        new_spki = new_cert.public_key_info_bytes

        if new_cert.subject != old_cert.subject:
            raise admintool.ScriptError(
                "Subject name mismatch (visit "
                "http://www.freeipa.org/page/Troubleshooting for "
                "troubleshooting guide)")
        if new_cert.subject_bytes != old_cert.subject_bytes:
            raise admintool.ScriptError(
                "Subject name encoding mismatch (visit "
                "http://www.freeipa.org/page/Troubleshooting for "
                "troubleshooting guide)")
        if new_spki != old_spki:
            raise admintool.ScriptError(
                "Subject public key info mismatch (visit "
                "http://www.freeipa.org/page/Troubleshooting for "
                "troubleshooting guide)")

        with certs.NSSDatabase() as tmpdb:
            tmpdb.create_db()
            tmpdb.add_cert(old_cert, 'IPA CA', EXTERNAL_CA_TRUST_FLAGS)

            try:
                tmpdb.add_cert(new_cert, 'IPA CA', EXTERNAL_CA_TRUST_FLAGS)
            except ipautil.CalledProcessError as e:
                raise admintool.ScriptError(
                    "Not compatible with the current CA certificate: %s" % e)

            ca_certs = x509.load_certificate_list_from_file(ca_file.name)
            for ca_cert in ca_certs:
                tmpdb.add_cert(ca_cert, str(DN(ca_cert.subject)),
                               EXTERNAL_CA_TRUST_FLAGS)

            try:
                tmpdb.verify_ca_cert_validity('IPA CA')
            except ValueError as e:
                raise admintool.ScriptError(
                    "Not a valid CA certificate: %s (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)" % e)

            trust_chain = tmpdb.get_trust_chain('IPA CA')[:-1]
            for nickname in trust_chain:
                try:
                    ca_cert = tmpdb.get_cert(nickname)
                except RuntimeError:
                    break
                certstore.put_ca_cert_nss(conn, api.env.basedn, ca_cert,
                                          nickname, EMPTY_TRUST_FLAGS)

        dn = DN(('cn', self.cert_nickname), ('cn', 'ca_renewal'),
                ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn)

        try:
            entry = conn.get_entry(dn, ['usercertificate'])
            entry['usercertificate'] = [new_cert]
            conn.update_entry(entry)
        except errors.NotFound:
            entry = conn.make_entry(
                dn,
                objectclass=['top', 'pkiuser', 'nscontainer'],
                cn=[self.cert_nickname],
                usercertificate=[new_cert])
            conn.add_entry(entry)
        except errors.EmptyModlist:
            pass

        update_ipa_ca_entry(api, new_cert)

        try:
            ca.set_renewal_master()
        except errors.NotFound:
            raise admintool.ScriptError("CA renewal master not found")

        self.resubmit_request(RENEWAL_REUSE_CA_NAME)

        print("CA certificate successfully renewed")
Example #11
0
    def check(self):
        if not self.ca.is_configured():
            logger.debug("No CA configured, skipping certificate match check")
            return

        # Ensure /etc/ipa/ca.crt matches the NSS DB CA certificates
        def match_cacert_and_db(plugin, cacerts, dbpath):
            db = certs.CertDB(api.env.realm, dbpath)
            nickname = '%s IPA CA' % api.env.realm
            try:
                dbcacerts = self.get_cert_list_from_db(db, nickname)
            except Exception as e:
                yield Result(plugin,
                             constants.ERROR,
                             error=str(e),
                             msg='Unable to load CA cert: {error}')
                return False

            ok = True
            for cert in dbcacerts:
                if cert not in cacerts:
                    ok = False
                    yield Result(plugin,
                                 constants.ERROR,
                                 nickname=nickname,
                                 serial_number=cert.serial_number,
                                 dbdir=dbpath,
                                 certdir=paths.IPA_CA_CRT,
                                 msg=('CA Certificate nickname {nickname} '
                                      'with serial number {serial} '
                                      'is in {dbdir} but is not in'
                                      '%s' % paths.IPA_CA_CRT))
            return ok

        try:
            cacerts = x509.load_certificate_list_from_file(paths.IPA_CA_CRT)
        except Exception:
            yield Result(self,
                         constants.ERROR,
                         path=paths.IPA_CA_CRT,
                         msg='Unable to load CA cert file {path}: {error}')
            return

        # Ensure CA cert entry from LDAP matches /etc/ipa/ca.crt
        dn = DN('cn=%s IPA CA' % api.env.realm,
                'cn=certificates,cn=ipa,cn=etc', api.env.basedn)
        try:
            entry = self.conn.get_entry(dn)
        except errors.NotFound:
            yield Result(self,
                         constants.ERROR,
                         dn=str(dn),
                         msg='CA Certificate entry \'{dn}\' '
                         'not found in LDAP')
            return

        cacerts_ok = True
        # Are all the certs in LDAP for the IPA CA in /etc/ipa/ca.crt
        for cert in entry['CACertificate']:
            if cert not in cacerts:
                cacerts_ok = False
                yield Result(self,
                             constants.ERROR,
                             dn=str(dn),
                             serial_number=cert.serial_number,
                             msg=('CA Certificate serial number {serial} is '
                                  'in LDAP \'{dn}\' but is not in '
                                  '%s' % paths.IPA_CA_CRT))

        # Ensure NSS DBs have matching CA certs for /etc/ipa/ca.crt
        serverid = realm_to_serverid(api.env.realm)
        dspath = paths.ETC_DIRSRV_SLAPD_INSTANCE_TEMPLATE % serverid

        cacertds_ok = yield from match_cacert_and_db(self, cacerts, dspath)
        cacertnss_ok = yield from match_cacert_and_db(self, cacerts,
                                                      paths.IPA_NSSDB_DIR)
        if cacerts_ok:
            yield Result(self, constants.SUCCESS, key=paths.IPA_CA_CRT)
        if cacertds_ok:
            yield Result(self, constants.SUCCESS, key=dspath)
        if cacertnss_ok:
            yield Result(self, constants.SUCCESS, key=paths.IPA_NSSDB_DIR)
Example #12
0
    def renew_external_step_2(self, ca, old_cert):
        print "Importing the renewed CA certificate, please wait"

        options = self.options
        cert_file, ca_file = installutils.load_external_cert(
            options.external_cert_files, x509.subject_base())

        nss_cert = None
        nss.nss_init(ca.dogtag_constants.ALIAS_DIR)
        try:
            nss_cert = x509.load_certificate(old_cert, x509.DER)
            subject = nss_cert.subject
            der_subject = x509.get_der_subject(old_cert, x509.DER)
            #pylint: disable=E1101
            pkinfo = nss_cert.subject_public_key_info.format()
            #pylint: enable=E1101

            nss_cert = x509.load_certificate_from_file(cert_file.name)
            cert = nss_cert.der_data
            if nss_cert.subject != subject:
                raise admintool.ScriptError(
                    "Subject name mismatch (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)")
            if x509.get_der_subject(cert, x509.DER) != der_subject:
                raise admintool.ScriptError(
                    "Subject name encoding mismatch (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)")
            #pylint: disable=E1101
            if nss_cert.subject_public_key_info.format() != pkinfo:
                raise admintool.ScriptError(
                    "Subject public key info mismatch (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)")
            #pylint: enable=E1101
        finally:
            del nss_cert
            nss.nss_shutdown()

        with certs.NSSDatabase() as tmpdb:
            pw = ipautil.write_tmp_file(ipautil.ipa_generate_password())
            tmpdb.create_db(pw.name)
            tmpdb.add_cert(old_cert, 'IPA CA', 'C,,')

            try:
                tmpdb.add_cert(cert, 'IPA CA', 'C,,')
            except ipautil.CalledProcessError, e:
                raise admintool.ScriptError(
                    "Not compatible with the current CA certificate: %s" % e)

            ca_certs = x509.load_certificate_list_from_file(ca_file.name)
            for ca_cert in ca_certs:
                tmpdb.add_cert(ca_cert.der_data, str(ca_cert.subject), 'C,,')
            del ca_certs
            del ca_cert

            try:
                tmpdb.verify_ca_cert_validity('IPA CA')
            except ValueError, e:
                raise admintool.ScriptError(
                    "Not a valid CA certificate: %s (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)" % e)
Example #13
0
    def renew_external_step_2(self, ca, old_cert):
        print "Importing the renewed CA certificate, please wait"

        options = self.options
        cert_file, ca_file = installutils.load_external_cert(
            options.external_cert_files, x509.subject_base())

        nss_cert = None
        nss.nss_init(ca.dogtag_constants.ALIAS_DIR)
        try:
            nss_cert = x509.load_certificate(old_cert, x509.DER)
            subject = nss_cert.subject
            der_subject = x509.get_der_subject(old_cert, x509.DER)
            #pylint: disable=E1101
            pkinfo = nss_cert.subject_public_key_info.format()
            #pylint: enable=E1101

            nss_cert = x509.load_certificate_from_file(cert_file.name)
            cert = nss_cert.der_data
            if nss_cert.subject != subject:
                raise admintool.ScriptError(
                    "Subject name mismatch (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)")
            if x509.get_der_subject(cert, x509.DER) != der_subject:
                raise admintool.ScriptError(
                    "Subject name encoding mismatch (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)")
            #pylint: disable=E1101
            if nss_cert.subject_public_key_info.format() != pkinfo:
                raise admintool.ScriptError(
                    "Subject public key info mismatch (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)")
            #pylint: enable=E1101
        finally:
            del nss_cert
            nss.nss_shutdown()

        with certs.NSSDatabase() as tmpdb:
            pw = ipautil.write_tmp_file(ipautil.ipa_generate_password())
            tmpdb.create_db(pw.name)
            tmpdb.add_cert(old_cert, 'IPA CA', 'C,,')

            try:
                tmpdb.add_cert(cert, 'IPA CA', 'C,,')
            except ipautil.CalledProcessError, e:
                raise admintool.ScriptError(
                    "Not compatible with the current CA certificate: %s" % e)

            ca_certs = x509.load_certificate_list_from_file(ca_file.name)
            for ca_cert in ca_certs:
                tmpdb.add_cert(ca_cert.der_data, str(ca_cert.subject), 'C,,')
            del ca_certs
            del ca_cert

            try:
                tmpdb.verify_ca_cert_validity('IPA CA')
            except ValueError, e:
                raise admintool.ScriptError(
                    "Not a valid CA certificate: %s (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)" % e)
Example #14
0
def main():
    module = AnsibleModule(
        argument_spec = dict(
            servers=dict(required=True, type='list'),
            realm=dict(required=True),
            hostname=dict(required=True),
            debug=dict(required=False, type='bool', default="false")
        ),
        supports_check_mode = True,
    )

    module._ansible_debug = True
    realm = module.params.get('realm')
    hostname = module.params.get('hostname')
    servers = module.params.get('servers')
    debug = module.params.get('debug')

    fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
    statestore = sysrestore.StateFile(paths.IPA_CLIENT_SYSRESTORE)
    host_principal = 'host/%s@%s' % (hostname, realm)
    os.environ['KRB5CCNAME'] = paths.IPA_DNS_CCACHE
    
    ca_certs = x509.load_certificate_list_from_file(paths.IPA_CA_CRT)
    if NUM_VERSION >= 40500 and NUM_VERSION < 40590:
        ca_certs = [ cert.public_bytes(serialization.Encoding.DER)
                     for cert in ca_certs ]
    elif NUM_VERSION < 40500:
        ca_certs = [ cert.der_data for cert in ca_certs ]

    with certdb.NSSDatabase() as tmp_db:
        api.bootstrap(context='cli_installer',
                      confdir=paths.ETC_IPA,
                      debug=debug,
                      delegate=False,
                      nss_dir=tmp_db.secdir)

        if 'config_loaded' not in api.env:
            module.fail_json(msg="Failed to initialize IPA API.")

        # Clear out any current session keyring information
        try:
            delete_persistent_client_session_data(host_principal)
        except ValueError:
            pass

        # Add CA certs to a temporary NSS database
        argspec = inspect.getargspec(tmp_db.create_db)
        try:
            if NUM_VERSION > 40404:
                tmp_db.create_db()

                for i, cert in enumerate(ca_certs):
                    tmp_db.add_cert(cert,
                                    'CA certificate %d' % (i + 1),
                                    certdb.EXTERNAL_CA_TRUST_FLAGS)
            else:
                pwd_file = write_tmp_file(ipa_generate_password())
                tmp_db.create_db(pwd_file.name)

                for i, cert in enumerate(ca_certs):
                    tmp_db.add_cert(cert, 'CA certificate %d' % (i + 1), 'C,,')
        except CalledProcessError as e:
            module.fail_json(msg="Failed to add CA to temporary NSS database.")

        api.finalize()

        # Now, let's try to connect to the server's RPC interface
        connected = False
        try:
            api.Backend.rpcclient.connect()
            connected = True
            module.debug("Try RPC connection")
            api.Backend.rpcclient.forward('ping')
        except errors.KerberosError as e:
            if connected:
                api.Backend.rpcclient.disconnect()
            module.log(
                "Cannot connect to the server due to Kerberos error: %s. "
                "Trying with delegate=True" % e)
            try:
                api.Backend.rpcclient.connect(delegate=True)
                module.debug("Try RPC connection")
                api.Backend.rpcclient.forward('ping')

                module.log("Connection with delegate=True successful")

                # The remote server is not capable of Kerberos S4U2Proxy
                # delegation. This features is implemented in IPA server
                # version 2.2 and higher
                module.warn(
                    "Target IPA server has a lower version than the enrolled "
                    "client")
                module.warn(
                    "Some capabilities including the ipa command capability "
                    "may not be available")
            except errors.PublicError as e2:
                module.fail_json(
                    msg="Cannot connect to the IPA server RPC interface: %s" % e2)
        except errors.PublicError as e:
            module.fail_json(
                msg="Cannot connect to the server due to generic error: %s" % e)
    # Use the RPC directly so older servers are supported
    try:
        result = api.Backend.rpcclient.forward(
            'ca_is_enabled',
            version=u'2.107',
        )
        ca_enabled = result['result']
    except (errors.CommandError, errors.NetworkError):
        result = api.Backend.rpcclient.forward(
            'env',
            server=True,
            version=u'2.0',
        )
        ca_enabled = result['result']['enable_ra']
    if not ca_enabled:
        disable_ra()

    # Get subject base from ipa server
    try:
        config = api.Command['config_show']()['result']
        subject_base = str(DN(config['ipacertificatesubjectbase'][0]))
    except errors.PublicError as e:
        module.fail_json(msg="Cannot get subject base from server: %s" % e)

    module.exit_json(changed=True,
                     ca_enabled=ca_enabled,
                     subject_base=subject_base)