def load_pem_certificate(cert): """Abstract load PEM certificate by IPA version""" if version.NUM_VERSION < 40600: return x509.load_certificate(cert, x509.PEM) elif version.NUM_VERSION < 40700: return x509.load_pem_x509_certificate(cert) else: return x509.load_pem_x509_certificate(bytes(cert, 'utf-8'))
def test_cert_rsa4096(self): ca_pem = self.master.get_file_contents( paths.IPA_CA_CRT, encoding=None ) cert = load_pem_x509_certificate(ca_pem) assert cert.public_key().key_size == 4096 assert cert.signature_hash_algorithm.name == hashes.SHA512.name
def test_switch_to_external_ca(self): result = self.master.run_command( [paths.IPA_CACERT_MANAGE, 'renew', '--external-ca']) assert result.returncode == 0 # Sign CA, transport it to the host and get ipa a root ca paths. root_ca_fname, ipa_ca_fname = tasks.sign_ca_and_transport( self.master, paths.IPA_CA_CSR, ROOT_CA, IPA_CA) # renew CA with externally signed one result = self.master.run_command([ paths.IPA_CACERT_MANAGE, 'renew', '--external-cert-file={}'.format(ipa_ca_fname), '--external-cert-file={}'.format(root_ca_fname) ]) assert result.returncode == 0 # update IPA certificate databases result = self.master.run_command([paths.IPA_CERTUPDATE]) assert result.returncode == 0 # Check if external CA have "C" flag after the switch result = check_CA_flag(self.master) assert bool(result), ('External CA does not have "C" flag') # Check that ldap entries for the CA have been updated remote_cacrt = self.master.get_file_contents(ipa_ca_fname) cacrt = ipa_x509.load_pem_x509_certificate(remote_cacrt) verify_caentry(self.master, cacrt)
def _get_vaultconfig(self, force_refresh=False): config = None if not force_refresh: config = _kra_config_cache.load(self.api.env.domain) if config is None: # vaultconfig_show also caches data response = self.api.Command.vaultconfig_show() config = response['result'] transport_cert = x509.load_der_x509_certificate( config['transport_cert']) else: # cached JSON uses PEM-encoded ASCII string transport_cert = x509.load_pem_x509_certificate( config['transport_cert'].encode('ascii')) default_algo = config.get('wrapping_default_algorithm') if default_algo is None: # old server wrapping_algo = constants.VAULT_WRAPPING_AES128_CBC elif default_algo in constants.VAULT_WRAPPING_SUPPORTED_ALGOS: # try to use server default wrapping_algo = default_algo else: # prefer server's sorting order for algo in config['wrapping_supported_algorithms']: if algo in constants.VAULT_WRAPPING_SUPPORTED_ALGOS: wrapping_algo = algo break else: raise errors.ValidationError( "No overlapping wrapping algorithm between server and " "client.") return transport_cert, wrapping_algo
def test_install_master(self): result = tasks.install_master(self.master) assert result.returncode == 0 # Check the content of the ldap entries for the CA remote_cacrt = self.master.get_file_contents(paths.IPA_CA_CRT) cacrt = ipa_x509.load_pem_x509_certificate(remote_cacrt) verify_caentry(self.master, cacrt)
def get_cert_from_db(self, nickname): """ Retrieve a certificate from the current NSS database for nickname. """ try: args = ["-L", "-n", nickname, "-a"] result = self.run_certutil(args, capture_output=True) return x509.load_pem_x509_certificate(result.raw_output) except ipautil.CalledProcessError: return None
def check_pkinit_cert_issuer(host, issuer): """Ensures that the PKINIT cert is signed by the expected issuer""" data = host.get_file_contents(paths.KDC_CERT) pkinit_cert = x509.load_pem_x509_certificate(data) # Make sure that the issuer is the expected one assert DN(pkinit_cert.issuer) == DN(issuer) # KDC cert must have SAN for KDC hostname assert host.hostname in pkinit_cert.san_a_label_dns_names # at least three SANs, profile adds UPN and KRB principal name assert len(pkinit_cert.san_general_names) >= 3
def test_http_cert(self): """ Test that HTTP certificate contains ipa-ca.$DOMAIN DNS name. """ data = self.master.get_file_contents(paths.HTTPD_CERT_FILE) cert = x509.load_pem_x509_certificate(data) name = f'ipa-ca.{self.master.domain.name}' assert crypto_x509.DNSName(name) in cert.san_general_names
def load_cert_from_str(cert): cert = cert.strip() if not cert.startswith("-----BEGIN CERTIFICATE-----"): cert = "-----BEGIN CERTIFICATE-----\n" + cert if not cert.endswith("-----END CERTIFICATE-----"): cert += "\n-----END CERTIFICATE-----" if load_pem_x509_certificate is not None: cert = load_pem_x509_certificate(cert.encode('utf-8')) else: cert = load_certificate(cert.encode('utf-8')) return cert
def test_long_oid(self): """ Test cerificate with very long OID. In this case we are using a certificate from an opened case where one of X509v3 Certificate`s Policies OID is longer then 80 chars. """ cert = x509.load_pem_x509_certificate(long_oid_cert) ext = cert.extensions.get_extension_for_class( crypto_x509.CertificatePolicies) assert len(ext.value) == 1 assert ext.value[0].policy_identifier.dotted_string == ( u'1.3.6.1.4.1.311.21.8.8950086.10656446.2706058.12775672.480128.' '147.13466065.13029902')
def test_3_cert_contents(self): """ Test the contents of a certificate """ # Verify certificate contents. This exercises python-cryptography # more than anything but confirms our usage of it. not_before = datetime.datetime(2010, 6, 25, 13, 0, 42) not_after = datetime.datetime(2015, 6, 25, 13, 0, 42) cert = x509.load_pem_x509_certificate(goodcert_headers) assert DN(cert.subject) == DN(('CN', 'ipa.example.com'), ('O', 'IPA')) assert DN(cert.issuer) == DN(('CN', 'IPA Test Certificate Authority')) assert cert.serial_number == 1093 assert cert.not_valid_before == not_before assert cert.not_valid_after == not_after
def test_ipa_demo_letsencrypt(self): cert = x509.load_pem_x509_certificate(ipa_demo_crt) assert DN(cert.subject) == DN('CN=ipa.demo1.freeipa.org') assert DN(cert.issuer) == DN( "CN=Let's Encrypt Authority X3,O=Let's Encrypt,C=US") assert cert.serial_number == 0x03ad42a2a5ada59a131327cb0979623cb605 not_before = datetime.datetime(2018, 7, 25, 5, 36, 59) not_after = datetime.datetime(2018, 10, 23, 5, 36, 59) assert cert.not_valid_before == not_before assert cert.not_valid_after == not_after assert cert.san_general_names == [DNSName('ipa.demo1.freeipa.org')] assert cert.san_a_label_dns_names == ['ipa.demo1.freeipa.org'] assert cert.extended_key_usage == { '1.3.6.1.5.5.7.3.1', '1.3.6.1.5.5.7.3.2' } assert cert.extended_key_usage_bytes == ( b'0 \x06\x03U\x1d%\x01\x01\xff\x04\x160\x14\x06\x08+\x06\x01' b'\x05\x05\x07\x03\x01\x06\x08+\x06\x01\x05\x05\x07\x03\x02')
def test_1_load_base64_cert(self): """ Test loading a base64-encoded certificate. """ # Load a good cert x509.load_pem_x509_certificate(goodcert_headers) # Load a good cert with headers and leading text newcert = (b'leading text\n' + goodcert_headers) x509.load_pem_x509_certificate(newcert) # Load a good cert with bad headers newcert = b'-----BEGIN CERTIFICATE-----' + goodcert_headers with pytest.raises((TypeError, ValueError)): x509.load_pem_x509_certificate(newcert) # Load a bad cert with pytest.raises(ValueError): x509.load_pem_x509_certificate(badcert)
def test_1_load_base64_cert(self): """ Test loading a base64-encoded certificate. """ # Load a good cert x509.load_pem_x509_certificate(goodcert_headers) # Load a good cert with headers and leading text newcert = ( b'leading text\n' + goodcert_headers) x509.load_pem_x509_certificate(newcert) # Load a good cert with bad headers newcert = b'-----BEGIN CERTIFICATE-----' + goodcert_headers with pytest.raises((TypeError, ValueError)): x509.load_pem_x509_certificate(newcert) # Load a bad cert with pytest.raises(ValueError): x509.load_pem_x509_certificate(badcert)
def decode_certificate(cert): """ Decode a certificate using base64. It also takes FreeIPA versions into account and returns a IPACertificate for newer IPA versions. """ if hasattr(x509, "IPACertificate"): cert = cert.strip() if not cert.startswith("-----BEGIN CERTIFICATE-----"): cert = "-----BEGIN CERTIFICATE-----\n" + cert if not cert.endswith("-----END CERTIFICATE-----"): cert += "\n-----END CERTIFICATE-----" if load_pem_x509_certificate is not None: cert = load_pem_x509_certificate(cert.encode('utf-8')) else: cert = load_certificate(cert.encode('utf-8')) else: cert = base64.b64decode(cert) return cert
def test_3_cert_contents(self): """ Test the contents of a certificate """ # Verify certificate contents. This exercises python-cryptography # more than anything but confirms our usage of it. not_before = datetime.datetime(2010, 6, 25, 13, 0, 42) not_after = datetime.datetime(2015, 6, 25, 13, 0, 42) cert = x509.load_pem_x509_certificate(goodcert_headers) assert DN(cert.subject) == DN(('CN', 'ipa.example.com'), ('O', 'IPA')) assert DN(cert.issuer) == DN(('CN', 'IPA Test Certificate Authority')) assert cert.serial_number == 1093 assert cert.not_valid_before == not_before assert cert.not_valid_after == not_after assert cert.san_general_names == [] assert cert.san_a_label_dns_names == [] assert cert.extended_key_usage == {'1.3.6.1.5.5.7.3.1'} assert cert.extended_key_usage_bytes == ( b'0\x16\x06\x03U\x1d%\x01\x01\xff\x04\x0c0\n\x06\x08' b'+\x06\x01\x05\x05\x07\x03\x01')
def test_cert_rsa4096(self): ca_pem = self.master.get_file_contents(paths.IPA_CA_CRT, encoding=None) cert = load_pem_x509_certificate(ca_pem) assert cert.public_key().key_size == 4096
def check_pkinit_cert_issuer(host, issuer): """Ensures that the PKINIT cert is signed by the expected issuer""" data = host.get_file_contents(paths.KDC_CERT) pkinit_cert = x509.load_pem_x509_certificate(data) # Make sure that the issuer is the expected one assert DN(pkinit_cert.issuer) == DN(issuer)
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")
def test_cert_rsa4096(self): ca_pem = self.master.get_file_contents(paths.IPA_CA_CRT, encoding=None) cert = load_pem_x509_certificate(ca_pem) assert cert.public_key().key_size == 4096 assert cert.signature_hash_algorithm.name == hashes.SHA512.name
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")
def test_x509_v1_cert(self): with pytest.raises(ValueError): x509.load_pem_x509_certificate(v1_cert)