def forward(self, *keys, **options): filename = None if 'certificate_out' in options: filename = options.pop('certificate_out') try: util.check_writable_file(filename) except errors.FileError as e: raise errors.ValidationError(name='certificate-out', error=str(e)) result = super(WithCertOutArgs, self).forward(*keys, **options) if filename: # if result certificate / certificate_chain not present in result, # it means Dogtag did not provide it (probably due to LWCA key # replication lag or failure. The server transmits a warning # message in this case, which the client automatically prints. # So in this section we just ignore it and move on. certs = None if options.get('chain', False): if 'certificate_chain' in result['result']: certs = result['result']['certificate_chain'] else: if 'certificate' in result['result']: certs = [base64.b64decode(result['result']['certificate'])] if certs: x509.write_certificate_list( (x509.load_der_x509_certificate(cert) for cert in certs), filename) return result
def _install_pkinit_ca_bundle(self): ca_certs = certstore.get_ca_certs(self.api.Backend.ldap2, self.api.env.basedn, self.api.env.realm, False) ca_certs = [c for c, _n, t, _u in ca_certs if t is not False] x509.write_certificate_list(ca_certs, paths.CACERT_PEM)
def _install_pkinit_ca_bundle(self): ca_certs = certstore.get_ca_certs(self.api.Backend.ldap2, self.api.env.basedn, self.api.env.realm, False) ca_certs = [c for c, _n, t, _u in ca_certs if t is not False] x509.write_certificate_list(ca_certs, paths.CACERT_PEM, mode=0o644)
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)
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 forward(self, *keys, **options): if "out" in options: util.check_writable_file(options["out"]) result = super(service_show, self).forward(*keys, **options) if "usercertificate" in result["result"]: x509.write_certificate_list(result["result"]["usercertificate"], options["out"]) result["summary"] = _("Certificate(s) stored in file '%(file)s'") % dict(file=options["out"]) return result else: raise errors.NoCertificateError(entry=keys[-1]) else: return super(service_show, self).forward(*keys, **options)
def install_ca_cert(ldap, base_dn, realm, cafile): try: try: certs = certstore.get_ca_certs(ldap, base_dn, realm, False) except errors.NotFound: shutil.copy(cafile, constants.CACERT) else: certs = [c[0] for c in certs if c[2] is not False] x509.write_certificate_list(certs, constants.CACERT) os.chmod(constants.CACERT, 0444) except Exception, e: print "error copying files: " + str(e) sys.exit(1)
def forward(self, *keys, **options): if 'out' in options: util.check_writable_file(options['out']) result = super(user_show, self).forward(*keys, **options) if 'usercertificate' in result['result']: x509.write_certificate_list( result['result']['usercertificate'], options['out']) result['summary'] = ( _('Certificate(s) stored in file \'%(file)s\'') % dict(file=options['out'])) return result else: raise errors.NoCertificateError(entry=keys[-1]) else: return super(user_show, self).forward(*keys, **options)
def install_ca_cert(ldap, base_dn, realm, cafile, destfile=paths.IPA_CA_CRT): try: try: certs = certstore.get_ca_certs(ldap, base_dn, realm, False) except errors.NotFound: try: shutil.copy(cafile, destfile) except shutil.Error: # cafile == IPA_CA_CRT pass else: certs = [c[0] for c in certs if c[2] is not False] x509.write_certificate_list(certs, destfile, mode=0o644) except Exception as e: raise ScriptError("error copying files: " + str(e)) return destfile
def forward(self, *keys, **options): if 'out' in options: util.check_writable_file(options['out']) result = super(service_show, self).forward(*keys, **options) if 'usercertificate' in result['result']: certs = (x509.load_der_x509_certificate(c) for c in result['result']['usercertificate']) x509.write_certificate_list(certs, options['out']) result['summary'] = ( _('Certificate(s) stored in file \'%(file)s\'') % dict(file=options['out']) ) return result else: raise errors.NoCertificateError(entry=keys[-1]) else: return super(service_show, self).forward(*keys, **options)
def forward(self, *keys, **options): filename = None if 'certificate_out' in options: filename = options.pop('certificate_out') try: util.check_writable_file(filename) except errors.FileError as e: raise errors.ValidationError(name='certificate-out', error=str(e)) result = super(WithCertOutArgs, self).forward(*keys, **options) if filename: if options.get('chain', False): certs = result['result']['certificate_chain'] else: certs = [base64.b64decode(result['result']['certificate'])] certs = (x509.load_der_x509_certificate(cert) for cert in certs) x509.write_certificate_list(certs, filename) return result
def forward(self, *args, **options): if 'certificate_out' in options: certificate_out = options.pop('certificate_out') try: util.check_writable_file(certificate_out) except errors.FileError as e: raise errors.ValidationError(name='certificate-out', error=str(e)) else: certificate_out = None result = super(CertRetrieveOverride, self).forward(*args, **options) if certificate_out is not None: if options.get('chain', False): certs = result['result']['certificate_chain'] else: certs = [base64.b64decode(result['result']['certificate'])] certs = (x509.load_der_x509_certificate(cert) for cert in certs) x509.write_certificate_list(certs, certificate_out) return result
def forward(self, *args, **options): if 'certificate_out' in options: certificate_out = options.pop('certificate_out') try: util.check_writable_file(certificate_out) except errors.FileError as e: raise errors.ValidationError(name='certificate-out', error=str(e)) else: certificate_out = None result = super(CertRetrieveOverride, self).forward(*args, **options) if certificate_out is not None: if options.get('chain', False): certs = result['result']['certificate_chain'] else: certs = [result['result']['certificate']] certs = (x509.load_der_x509_certificate(base64.b64decode(cert)) for cert in certs) x509.write_certificate_list(certs, certificate_out) return result
def update_file(filename, certs, mode=0o644): certs = (c[0] for c in certs if c[2] is not False) try: x509.write_certificate_list(certs, filename, mode=mode) except Exception as e: logger.error("failed to update %s: %s", filename, e)
def main(): module = AnsibleModule( argument_spec = dict( servers=dict(required=True, type='list'), domain=dict(required=True), realm=dict(required=True), hostname=dict(required=True), basedn=dict(required=True), principal=dict(required=False), subject_base=dict(required=True), ca_enabled=dict(required=True, type='bool'), mkhomedir=dict(required=False, type='bool'), on_master=dict(required=False, type='bool'), ), supports_check_mode = True, ) module._ansible_debug = True servers = module.params.get('servers') realm = module.params.get('realm') hostname = module.params.get('hostname') basedn = module.params.get('basedn') domain = module.params.get('domain') principal = module.params.get('principal') subject_base = module.params.get('subject_base') ca_enabled = module.params.get('ca_enabled') mkhomedir = module.params.get('mkhomedir') on_master = module.params.get('on_master') fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) statestore = sysrestore.StateFile(paths.IPA_CLIENT_SYSRESTORE) ########################################################################### os.environ['KRB5CCNAME'] = CCACHE_FILE class Object(object): pass options = Object() options.dns_updates = False options.all_ip_addresses = False options.ip_addresses = None options.request_cert = False options.hostname = hostname options.preserve_sssd = False options.on_master = False options.conf_ssh = True options.conf_sshd = True options.conf_sudo = True options.primary = False options.permit = False options.krb5_offline_passwords = False options.create_sshfp = True ########################################################################## # Create IPA NSS database try: create_ipa_nssdb() except ipautil.CalledProcessError as e: module.fail_json(msg="Failed to create IPA NSS database: %s" % e) # Get CA certificates from the certificate store try: ca_certs = get_certs_from_ldap(servers[0], basedn, realm, ca_enabled) except errors.NoCertificateError: if ca_enabled: ca_subject = DN(('CN', 'Certificate Authority'), subject_base) else: ca_subject = None ca_certs = certstore.make_compat_ca_certs(ca_certs, realm, ca_subject) ca_certs_trust = [(c, n, certstore.key_policy_to_trust_flags(t, True, u)) for (c, n, t, u) in ca_certs] if hasattr(paths, "KDC_CA_BUNDLE_PEM"): x509.write_certificate_list( [c for c, n, t, u in ca_certs if t is not False], paths.KDC_CA_BUNDLE_PEM) if hasattr(paths, "CA_BUNDLE_PEM"): x509.write_certificate_list( [c for c, n, t, u in ca_certs if t is not False], paths.CA_BUNDLE_PEM) # Add the CA certificates to the IPA NSS database module.debug("Adding CA certificates to the IPA NSS database.") ipa_db = certdb.NSSDatabase(paths.IPA_NSSDB_DIR) for cert, nickname, trust_flags in ca_certs_trust: try: ipa_db.add_cert(cert, nickname, trust_flags) except CalledProcessError as e: module.fail_json(msg="Failed to add %s to the IPA NSS database." % nickname) # Add the CA certificates to the platform-dependant systemwide CA store tasks.insert_ca_certs_into_systemwide_ca_store(ca_certs) if not on_master: client_dns(servers[0], hostname, options) configure_certmonger(fstore, subject_base, realm, hostname, options, ca_enabled) if hasattr(paths, "SSH_CONFIG_DIR"): ssh_config_dir = paths.SSH_CONFIG_DIR else: ssh_config_dir = services.knownservices.sshd.get_config_dir() update_ssh_keys(hostname, ssh_config_dir, options.create_sshfp) try: os.remove(CCACHE_FILE) except Exception: pass ########################################################################## # Name Server Caching Daemon. Disable for SSSD, use otherwise # (if installed) nscd = services.knownservices.nscd if nscd.is_installed(): save_state(nscd, statestore) try: nscd_service_action = 'stop' nscd.stop() except Exception: module.warn("Failed to %s the %s daemon" % (nscd_service_action, nscd.service_name)) try: nscd.disable() except Exception: module.warn("Failed to disable %s daemon. Disable it manually." % nscd.service_name) nslcd = services.knownservices.nslcd if nslcd.is_installed(): save_state(nslcd, statestore) retcode, conf = (0, None) ########################################################################## # Modify nsswitch/pam stack tasks.modify_nsswitch_pam_stack(sssd=True, mkhomedir=mkhomedir, statestore=statestore) module.log("SSSD enabled") argspec = inspect.getargspec(services.service) if len(argspec.args) > 1: sssd = services.service('sssd', api) else: sssd = services.service('sssd') try: sssd.restart() except CalledProcessError: module.warn("SSSD service restart was unsuccessful.") try: sssd.enable() except CalledProcessError as e: module.warn( "Failed to enable automatic startup of the SSSD daemon: " "%s", e) if configure_openldap_conf(fstore, basedn, servers): module.log("Configured /etc/openldap/ldap.conf") else: module.log("Failed to configure /etc/openldap/ldap.conf") # Check that nss is working properly if not on_master: user = principal if user is None or user == "": user = "******" % domain module.log("Principal is not set when enrolling with OTP" "; using principal '%s' for 'getent passwd'" % user) elif '@' not in user: user = "******" % (user, domain) n = 0 found = False # Loop for up to 10 seconds to see if nss is working properly. # It can sometimes take a few seconds to connect to the remote # provider. # Particulary, SSSD might take longer than 6-8 seconds. while n < 10 and not found: try: ipautil.run(["getent", "passwd", user]) found = True except Exception as e: time.sleep(1) n = n + 1 if not found: module.fail_json(msg="Unable to find '%s' user with 'getent " "passwd %s'!" % (user.split("@")[0], user)) if conf: module.log("Recognized configuration: %s" % conf) else: module.fail_json(msg= "Unable to reliably detect " "configuration. Check NSS setup manually.") try: hardcode_ldap_server(servers) except Exception as e: module.fail_json(msg="Adding hardcoded server name to " "/etc/ldap.conf failed: %s" % str(e)) ########################################################################## module.exit_json(changed=True, ca_enabled_ra=ca_enabled)
def load_external_cert(files, ca_subject): """ Load and verify external CA certificate chain from multiple files. The files are accepted in PEM and DER certificate and PKCS#7 certificate chain formats. :param files: Names of files to import :param ca_subject: IPA CA subject DN :returns: Temporary file with the IPA CA certificate and temporary file with the external CA certificate chain """ with certs.NSSDatabase() as nssdb: nssdb.create_db() try: nssdb.import_files(files) except RuntimeError as e: raise ScriptError(str(e)) ca_subject = DN(ca_subject) ca_nickname = None cache = {} for nickname, _trust_flags in nssdb.list_certs(): cert = nssdb.get_cert(nickname) subject = DN(cert.subject) issuer = DN(cert.issuer) cache[nickname] = (cert, subject, issuer) if subject == ca_subject: ca_nickname = nickname nssdb.trust_root_cert(nickname, EXTERNAL_CA_TRUST_FLAGS) if ca_nickname is None: raise ScriptError( "IPA CA certificate with subject '%s' " "was not found in %s." % (ca_subject, (",".join(files)))) trust_chain = list(reversed(nssdb.get_trust_chain(ca_nickname))) ca_cert_chain = [] for nickname in trust_chain: cert, subject, issuer = cache[nickname] ca_cert_chain.append(cert) if subject == issuer: break else: raise ScriptError( "CA certificate chain in %s is incomplete: " "missing certificate with subject '%s'" % (", ".join(files), issuer)) for nickname in trust_chain: try: nssdb.verify_ca_cert_validity(nickname) except ValueError as e: cert, subject, issuer = cache[nickname] raise ScriptError( "CA certificate %s in %s is not valid: %s" % (subject, ", ".join(files), e)) cert_file = tempfile.NamedTemporaryFile() cert_file.write(ca_cert_chain[0].public_bytes(x509.Encoding.PEM) + b'\n') cert_file.flush() ca_file = tempfile.NamedTemporaryFile() x509.write_certificate_list( ca_cert_chain[1:], ca_file.name, mode=0o644 ) ca_file.flush() return cert_file, ca_file
def load_external_cert(files, ca_subject): """ Load and verify external CA certificate chain from multiple files. The files are accepted in PEM and DER certificate and PKCS#7 certificate chain formats. :param files: Names of files to import :param ca_subject: IPA CA subject DN :returns: Temporary file with the IPA CA certificate and temporary file with the external CA certificate chain """ with certs.NSSDatabase() as nssdb: nssdb.create_db() try: nssdb.import_files(files) except RuntimeError as e: raise ScriptError(str(e)) ca_subject = DN(ca_subject) ca_nickname = None cache = {} for nickname, _trust_flags in nssdb.list_certs(): cert = nssdb.get_cert(nickname) subject = DN(cert.subject) issuer = DN(cert.issuer) cache[nickname] = (cert, subject, issuer) if subject == ca_subject: ca_nickname = nickname nssdb.trust_root_cert(nickname, EXTERNAL_CA_TRUST_FLAGS) if ca_nickname is None: raise ScriptError( "IPA CA certificate with subject '%s' " "was not found in %s." % (ca_subject, (",".join(files)))) trust_chain = list(reversed(nssdb.get_trust_chain(ca_nickname))) ca_cert_chain = [] for nickname in trust_chain: cert, subject, issuer = cache[nickname] ca_cert_chain.append(cert) if subject == issuer: break else: raise ScriptError( "CA certificate chain in %s is incomplete: " "missing certificate with subject '%s'" % (", ".join(files), issuer)) for nickname in trust_chain: try: nssdb.verify_ca_cert_validity(nickname) except ValueError as e: raise ScriptError( "CA certificate %s in %s is not valid: %s" % (subject, ", ".join(files), e)) cert_file = tempfile.NamedTemporaryFile() cert_file.write(ca_cert_chain[0].public_bytes(x509.Encoding.PEM) + b'\n') cert_file.flush() ca_file = tempfile.NamedTemporaryFile() x509.write_certificate_list( ca_cert_chain[1:], ca_file.name, mode=0o644 ) ca_file.flush() return cert_file, ca_file
def update_file(self, filename, certs, mode=0444): certs = (c[0] for c in certs if c[2] is not False) try: x509.write_certificate_list(certs, filename) except Exception, e: self.log.error("failed to update %s: %s", filename, e)