URL: https://github.com/freeipa/freeipa/pull/329 Author: frasertweedale Title: #329: experiment: did pull/177 break ci? Action: opened
PR body: """ This PR reverts the commits from pull/177 to test the hypothesis that something in these commits broke CI. """ To pull the PR as Git branch: git remote add ghfreeipa https://github.com/freeipa/freeipa git fetch ghfreeipa pull/329/head:pr329 git checkout pr329
From 8e13b7c01311e44eb3ec1dc16dac26b8d3287139 Mon Sep 17 00:00:00 2001 From: Fraser Tweedale <ftwee...@redhat.com> Date: Tue, 13 Dec 2016 10:50:50 +1000 Subject: [PATCH 1/3] Revert "Add options to write lightweight CA cert or chain to file" This reverts commit 32b1743e5fb318b226a602ec8d9a4b6ef2a25c9d. --- API.txt | 6 +-- VERSION.m4 | 4 +- ipaclient/plugins/ca.py | 53 ------------------------- ipaserver/plugins/ca.py | 65 +++---------------------------- ipaserver/plugins/dogtag.py | 12 ------ ipatests/test_xmlrpc/tracker/ca_plugin.py | 31 ++++----------- ipatests/test_xmlrpc/xmlrpc_test.py | 17 -------- 7 files changed, 16 insertions(+), 172 deletions(-) delete mode 100644 ipaclient/plugins/ca.py diff --git a/API.txt b/API.txt index 543cec5..bad3b92 100644 --- a/API.txt +++ b/API.txt @@ -445,11 +445,10 @@ option: Str('version?') output: Output('count', type=[<type 'int'>]) output: Output('results', type=[<type 'list'>, <type 'tuple'>]) command: ca_add/1 -args: 1,8,3 +args: 1,7,3 arg: Str('cn', cli_name='name') option: Str('addattr*', cli_name='addattr') option: Flag('all', autofill=True, cli_name='all', default=False) -option: Flag('chain', autofill=True, default=False) option: Str('description?', cli_name='desc') option: DNParam('ipacasubjectdn', cli_name='subject') option: Flag('raw', autofill=True, cli_name='raw', default=False) @@ -520,10 +519,9 @@ output: Entry('result') output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>]) output: PrimaryKey('value') command: ca_show/1 -args: 1,5,3 +args: 1,4,3 arg: Str('cn', cli_name='name') option: Flag('all', autofill=True, cli_name='all', default=False) -option: Flag('chain', autofill=True, default=False) option: Flag('raw', autofill=True, cli_name='raw', default=False) option: Flag('rights', autofill=True, default=False) option: Str('version?') diff --git a/VERSION.m4 b/VERSION.m4 index 36929ee..7d9e107 100644 --- a/VERSION.m4 +++ b/VERSION.m4 @@ -73,8 +73,8 @@ define(IPA_DATA_VERSION, 20100614120000) # # ######################################################## define(IPA_API_VERSION_MAJOR, 2) -define(IPA_API_VERSION_MINOR, 217) -# Last change: Add options to write lightweight CA cert or chain to file +define(IPA_API_VERSION_MINOR, 216) +# Last change: DNS: Support URI resource record type ######################################################## diff --git a/ipaclient/plugins/ca.py b/ipaclient/plugins/ca.py deleted file mode 100644 index fcdf484..0000000 --- a/ipaclient/plugins/ca.py +++ /dev/null @@ -1,53 +0,0 @@ -# -# Copyright (C) 2016 FreeIPA Contributors see COPYING for license -# - -import base64 -from ipaclient.frontend import MethodOverride -from ipalib import util, x509, Str -from ipalib.plugable import Registry -from ipalib.text import _ - -register = Registry() - - -class WithCertOutArgs(MethodOverride): - - takes_options = ( - Str( - 'certificate_out?', - doc=_('Write certificate (chain if --chain used) to file'), - include='cli', - cli_metavar='FILE', - ), - ) - - def forward(self, *keys, **options): - filename = None - if 'certificate_out' in options: - filename = options.pop('certificate_out') - util.check_writable_file(filename) - - result = super(WithCertOutArgs, self).forward(*keys, **options) - if filename: - def to_pem(x): - return x509.make_pem(x) - if options.get('chain', False): - ders = result['result']['certificate_chain'] - data = '\n'.join(to_pem(base64.b64encode(der)) for der in ders) - else: - data = to_pem(result['result']['certificate']) - with open(filename, 'wb') as f: - f.write(data) - - return result - - -@register(override=True, no_fail=True) -class ca_add(WithCertOutArgs): - pass - - -@register(override=True, no_fail=True) -class ca_show(WithCertOutArgs): - pass diff --git a/ipaserver/plugins/ca.py b/ipaserver/plugins/ca.py index ef1d68c..d9ae8c8 100644 --- a/ipaserver/plugins/ca.py +++ b/ipaserver/plugins/ca.py @@ -2,18 +2,14 @@ # Copyright (C) 2016 FreeIPA Contributors see COPYING for license # -import base64 - -import six - -from ipalib import api, errors, output, Bytes, DNParam, Flag, Str +from ipalib import api, errors, output, DNParam, Str from ipalib.constants import IPA_CA_CN from ipalib.plugable import Registry from ipaserver.plugins.baseldap import ( LDAPObject, LDAPSearch, LDAPCreate, LDAPDelete, LDAPUpdate, LDAPRetrieve, LDAPQuery, pkey_to_value) from ipaserver.plugins.cert import ca_enabled_check -from ipalib import _, ngettext, x509 +from ipalib import _, ngettext __doc__ = _(""" @@ -104,18 +100,6 @@ class ca(LDAPObject): doc=_('Issuer Distinguished Name'), flags=['no_create', 'no_update'], ), - Bytes( - 'certificate', - label=_("Certificate"), - doc=_("Base-64 encoded certificate."), - flags={'no_create', 'no_update', 'no_search'}, - ), - Bytes( - 'certificate_chain*', - label=_("Certificate chain"), - doc=_("X.509 certificate chain"), - flags={'no_create', 'no_update', 'no_search'}, - ), ) permission_filter_objectclasses = ['ipaca'] @@ -161,21 +145,6 @@ class ca(LDAPObject): } -def set_certificate_attrs(entry, options, always_include_cert=True): - ca_id = entry['ipacaid'][0] - full = options.get('all', False) - with api.Backend.ra_lightweight_ca as ca_api: - if always_include_cert or full: - der = ca_api.read_ca_cert(ca_id) - entry['certificate'] = six.text_type(base64.b64encode(der)) - - if options.get('chain', False) or full: - pkcs7_der = ca_api.read_ca_chain(ca_id) - pems = x509.pkcs7_to_pems(pkcs7_der, x509.DER) - ders = [x509.normalize_certificate(pem) for pem in pems] - entry['certificate_chain'] = ders - - @register() class ca_find(LDAPSearch): __doc__ = _("Search for CAs.") @@ -185,32 +154,16 @@ class ca_find(LDAPSearch): def execute(self, *keys, **options): ca_enabled_check() - result = super(ca_find, self).execute(*keys, **options) - for entry in result['result']: - set_certificate_attrs(entry, options, always_include_cert=False) - return result - - -_chain_flag = Flag( - 'chain', - default=False, - doc=_('Include certificate chain in output'), -) + return super(ca_find, self).execute(*keys, **options) @register() class ca_show(LDAPRetrieve): __doc__ = _("Display the properties of a CA.") - takes_options = LDAPRetrieve.takes_options + ( - _chain_flag, - ) - - def execute(self, *keys, **options): + def execute(self, *args, **kwargs): ca_enabled_check() - result = super(ca_show, self).execute(*keys, **options) - set_certificate_attrs(result['result'], options) - return result + return super(ca_show, self).execute(*args, **kwargs) @register() @@ -218,10 +171,6 @@ class ca_add(LDAPCreate): __doc__ = _("Create a CA.") msg_summary = _('Created CA "%(value)s"') - takes_options = LDAPCreate.takes_options + ( - _chain_flag, - ) - def pre_callback(self, ldap, dn, entry, entry_attrs, *keys, **options): ca_enabled_check() if not ldap.can_add(dn[1:]): @@ -254,10 +203,6 @@ def pre_callback(self, ldap, dn, entry, entry_attrs, *keys, **options): entry['ipacasubjectdn'] = [resp['dn']] return dn - def post_callback(self, ldap, dn, entry_attrs, *keys, **options): - set_certificate_attrs(entry_attrs, options) - return dn - @register() class ca_del(LDAPDelete): diff --git a/ipaserver/plugins/dogtag.py b/ipaserver/plugins/dogtag.py index 73c14ed..3d0838c 100644 --- a/ipaserver/plugins/dogtag.py +++ b/ipaserver/plugins/dogtag.py @@ -2127,18 +2127,6 @@ def read_ca(self, ca_id): except: raise errors.RemoteRetrieveError(reason=_("Response from CA was not valid JSON")) - def read_ca_cert(self, ca_id): - _status, _resp_headers, resp_body = self._ssldo( - 'GET', '{}/cert'.format(ca_id), - headers={'Accept': 'application/pkix-cert'}) - return resp_body - - def read_ca_chain(self, ca_id): - _status, _resp_headers, resp_body = self._ssldo( - 'GET', '{}/chain'.format(ca_id), - headers={'Accept': 'application/pkcs7-mime'}) - return resp_body - def disable_ca(self, ca_id): self._ssldo( 'POST', ca_id + '/disable', diff --git a/ipatests/test_xmlrpc/tracker/ca_plugin.py b/ipatests/test_xmlrpc/tracker/ca_plugin.py index e18b1c1..ec58c28 100644 --- a/ipatests/test_xmlrpc/tracker/ca_plugin.py +++ b/ipatests/test_xmlrpc/tracker/ca_plugin.py @@ -8,13 +8,7 @@ from ipapython.dn import DN from ipatests.test_xmlrpc.tracker.base import Tracker from ipatests.util import assert_deepequal -from ipatests.test_xmlrpc.xmlrpc_test import ( - fuzzy_issuer, - fuzzy_caid, - fuzzy_base64, - fuzzy_sequence_of, - fuzzy_bytes, -) +from ipatests.test_xmlrpc.xmlrpc_test import fuzzy_issuer, fuzzy_caid from ipatests.test_xmlrpc import objectclasses @@ -25,21 +19,12 @@ class CATracker(Tracker): """Implementation of a Tracker class for CA plugin.""" - ldap_keys = { + retrieve_keys = { 'dn', 'cn', 'ipacaid', 'ipacasubjectdn', 'ipacaissuerdn', 'description' } - cert_keys = { - 'certificate', - } - cert_all_keys = { - 'certificate_chain', - } - find_keys = ldap_keys - find_all_keys = {'objectclass'} | ldap_keys - retrieve_keys = ldap_keys | cert_keys - retrieve_all_keys = {'objectclass'} | retrieve_keys | cert_all_keys - create_keys = {'objectclass'} | retrieve_keys - update_keys = ldap_keys - {'dn'} + retrieve_all_keys = {'objectclass'} | retrieve_keys + create_keys = retrieve_all_keys + update_keys = retrieve_keys - {'dn'} def __init__(self, name, subject, desc=u"Test generated CA", default_version=None): @@ -74,8 +59,6 @@ def track_create(self): ipacasubjectdn=[self.ipasubjectdn], ipacaissuerdn=[fuzzy_issuer], ipacaid=[fuzzy_caid], - certificate=fuzzy_base64, - certificate_chain=fuzzy_sequence_of(fuzzy_bytes), objectclass=objectclasses.ca ) self.exists = True @@ -119,9 +102,9 @@ def make_find_command(self, *args, **kwargs): def check_find(self, result, all=False, raw=False): """Check the plugin's `find` command result""" if all: - expected = self.filter_attrs(self.find_all_keys) + expected = self.filter_attrs(self.retrieve_all_keys) else: - expected = self.filter_attrs(self.find_keys) + expected = self.filter_attrs(self.retrieve_keys) assert_deepequal(dict( count=1, diff --git a/ipatests/test_xmlrpc/xmlrpc_test.py b/ipatests/test_xmlrpc/xmlrpc_test.py index 67565b0..0ce1245 100644 --- a/ipatests/test_xmlrpc/xmlrpc_test.py +++ b/ipatests/test_xmlrpc/xmlrpc_test.py @@ -22,7 +22,6 @@ """ from __future__ import print_function -import collections import datetime import inspect @@ -50,20 +49,6 @@ '^cn=%s,cn=automember rebuild membership,cn=tasks,cn=config$' % uuid_re ) -# base64-encoded value -fuzzy_base64 = Fuzzy('^[0-9A-Za-z/+]+={0,2}$') - - -def fuzzy_sequence_of(fuzzy): - """Construct a Fuzzy for a Sequence of values matching the given Fuzzy.""" - def test(xs): - if not isinstance(xs, collections.Sequence): - return False - else: - return all(fuzzy == x for x in xs) - - return Fuzzy(test=test) - # Matches an automember task finish message fuzzy_automember_message = Fuzzy( '^Automember rebuild task finished\. Processed \(\d+\) entries\.$' @@ -124,8 +109,6 @@ def test(xs): # match any string fuzzy_string = Fuzzy(type=six.string_types) -fuzzy_bytes = Fuzzy(type=bytes) - # case insensitive match of sets def fuzzy_set_ci(s): return Fuzzy(test=lambda other: set(x.lower() for x in other) == set(y.lower() for y in s)) From 102efca0c53a04c071199a057c647ff923287df4 Mon Sep 17 00:00:00 2001 From: Fraser Tweedale <ftwee...@redhat.com> Date: Tue, 13 Dec 2016 10:50:53 +1000 Subject: [PATCH 2/3] Revert "certdb: accumulate extracted certs as list of PEMs" This reverts commit cc5b88e5d4ac1171374be9ae8e6e60730243dd3d. --- ipapython/certdb.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/ipapython/certdb.py b/ipapython/certdb.py index 9481326..4fbbbd9 100644 --- a/ipapython/certdb.py +++ b/ipapython/certdb.py @@ -203,7 +203,7 @@ def import_files(self, files, db_password_filename, import_keys=False, """ key_file = None extracted_key = None - extracted_certs = [] + extracted_certs = '' for filename in files: try: @@ -234,7 +234,7 @@ def import_files(self, files, db_password_filename, import_keys=False, filename, line, e) continue else: - extracted_certs.append(body) + extracted_certs += body + '\n' loaded = True continue @@ -252,7 +252,7 @@ def import_files(self, files, db_password_filename, import_keys=False, filename, line, e) continue else: - extracted_certs.extend(certs) + extracted_certs += '\n'.join(certs) + '\n' loaded = True continue @@ -302,7 +302,7 @@ def import_files(self, files, db_password_filename, import_keys=False, pass else: data = x509.make_pem(base64.b64encode(data)) - extracted_certs.append(data) + extracted_certs += data + '\n' continue # Try to import the file as PKCS#12 file @@ -343,15 +343,14 @@ def import_files(self, files, db_password_filename, import_keys=False, raise RuntimeError( "No server certificates found in %s" % (', '.join(files))) - for cert_pem in extracted_certs: - cert = x509.load_certificate(cert_pem) + certs = x509.load_certificate_list(extracted_certs) + for cert in certs: nickname = str(DN(cert.subject)) data = cert.public_bytes(serialization.Encoding.DER) self.add_cert(data, nickname, ',,') if extracted_key: - in_file = ipautil.write_tmp_file( - '\n'.join(extracted_certs) + '\n' + extracted_key) + in_file = ipautil.write_tmp_file(extracted_certs + extracted_key) out_file = tempfile.NamedTemporaryFile() out_password = ipautil.ipa_generate_password() out_pwdfile = ipautil.write_tmp_file(out_password) From 8ef08908aa6b22c7ac000037a1f3271b95313501 Mon Sep 17 00:00:00 2001 From: Fraser Tweedale <ftwee...@redhat.com> Date: Tue, 13 Dec 2016 10:50:54 +1000 Subject: [PATCH 3/3] Revert "Add function for extracting PEM certs from PKCS #7" This reverts commit c7ea56c049ec8ab1a5500852eca6faf750b1479f. --- ipalib/x509.py | 29 +---------------------- ipapython/certdb.py | 9 +++++-- ipaserver/install/cainstance.py | 52 ++++++++++++++++++++++++++--------------- 3 files changed, 41 insertions(+), 49 deletions(-) diff --git a/ipalib/x509.py b/ipalib/x509.py index 851af5a..e1c3867 100644 --- a/ipalib/x509.py +++ b/ipalib/x509.py @@ -49,14 +49,6 @@ from ipalib import util from ipalib import errors from ipapython.dn import DN -from ipapython import ipautil - -try: - from ipaplatform.paths import paths -except ImportError: - OPENSSL = '/usr/bin/openssl' -else: - OPENSSL = paths.OPENSSL if six.PY3: unicode = str @@ -64,9 +56,7 @@ PEM = 0 DER = 1 -PEM_REGEX = re.compile( - r'-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----', - re.DOTALL) +PEM_REGEX = re.compile(r'(?<=-----BEGIN CERTIFICATE-----).*?(?=-----END CERTIFICATE-----)', re.DOTALL) EKU_SERVER_AUTH = '1.3.6.1.5.5.7.3.1' EKU_CLIENT_AUTH = '1.3.6.1.5.5.7.3.2' @@ -155,23 +145,6 @@ def load_certificate_list_from_file(filename): return load_certificate_list(f.read()) -def pkcs7_to_pems(data, datatype=PEM): - """ - Extract certificates from a PKCS #7 object. - - Return a ``list`` of X.509 PEM strings. - - May throw ``ipautil.CalledProcessError`` on invalid data. - - """ - cmd = [ - OPENSSL, "pkcs7", "-print_certs", - "-inform", "PEM" if datatype == PEM else "DER", - ] - result = ipautil.run(cmd, stdin=data, capture_output=True) - return PEM_REGEX.findall(result.output) - - def is_self_signed(certificate, datatype=PEM): cert = load_certificate(certificate, datatype) return cert.issuer == cert.subject diff --git a/ipapython/certdb.py b/ipapython/certdb.py index 4fbbbd9..4e05b78 100644 --- a/ipapython/certdb.py +++ b/ipapython/certdb.py @@ -239,8 +239,13 @@ def import_files(self, files, db_password_filename, import_keys=False, continue if label in ('PKCS7', 'PKCS #7 SIGNED DATA', 'CERTIFICATE'): + args = [ + OPENSSL, 'pkcs7', + '-print_certs', + ] try: - certs = x509.pkcs7_to_pems(body) + result = ipautil.run( + args, stdin=body, capture_output=True) except ipautil.CalledProcessError as e: if label == 'CERTIFICATE': root_logger.warning( @@ -252,7 +257,7 @@ def import_files(self, files, db_password_filename, import_keys=False, filename, line, e) continue else: - extracted_certs += '\n'.join(certs) + '\n' + extracted_certs += result.output + '\n' loaded = True continue diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py index c7e81f0..dbea519 100644 --- a/ipaserver/install/cainstance.py +++ b/ipaserver/install/cainstance.py @@ -749,30 +749,44 @@ def __import_ca_chain(self): # makes openssl throw up. data = base64.b64decode(chain) - certlist = x509.pkcs7_to_pems(data, x509.DER) + result = ipautil.run( + [paths.OPENSSL, + "pkcs7", + "-inform", + "DER", + "-print_certs", + ], stdin=data, capture_output=True) + certlist = result.output # Ok, now we have all the certificates in certs, walk through it # and pull out each certificate and add it to our database + st = 1 + en = 0 + subid = 0 ca_dn = DN(('CN','Certificate Authority'), self.subject_base) - for cert in certlist: - try: - chain_fd, chain_name = tempfile.mkstemp() - os.write(chain_fd, cert) - os.close(chain_fd) - (_rdn, subject_dn) = certs.get_cert_nickname(cert) - if subject_dn == ca_dn: - nick = get_ca_nickname(self.realm) - trust_flags = 'CT,C,C' - else: - nick = str(subject_dn) - trust_flags = ',,' - self.__run_certutil( - ['-A', '-t', trust_flags, '-n', nick, '-a', - '-i', chain_name] - ) - finally: - os.remove(chain_name) + while st > 0: + st = certlist.find('-----BEGIN', en) + en = certlist.find('-----END', en+1) + if st > 0: + try: + (chain_fd, chain_name) = tempfile.mkstemp() + os.write(chain_fd, certlist[st:en+25]) + os.close(chain_fd) + (_rdn, subject_dn) = certs.get_cert_nickname(certlist[st:en+25]) + if subject_dn == ca_dn: + nick = get_ca_nickname(self.realm) + trust_flags = 'CT,C,C' + else: + nick = str(subject_dn) + trust_flags = ',,' + self.__run_certutil( + ['-A', '-t', trust_flags, '-n', nick, '-a', + '-i', chain_name] + ) + finally: + os.remove(chain_name) + subid += 1 # Restore NSS trust flags of all previously existing certificates for nick, trust_flags in cert_backup_list:
-- Manage your subscription for the Freeipa-devel mailing list: https://www.redhat.com/mailman/listinfo/freeipa-devel Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code