freeipa/ipaclient/plugins/ca.py
Fraser Tweedale a2ad417490 Fix writing certificate chain to file
An client-side error occurs when cert commands are instructed to
write the certificate chain (--chain option) to a file
(--certificate-out option).  This regression was introduced in the
'cert' plugin in commit 5a44ca6383,
and reflected in the 'ca' plugin in commit
c7064494e5.

The server behaviour did not change; rather the client did not
correctly handle the DER-encoded certificates in the
'certificate_chain' response field.  Fix the issue by treating the
'certificate' field as base-64 encoded DER, and the
'certificate_chain' field as an array of raw DER certificates.

Add tests for checking that the relevant commands succeed and write
PEM data to the file (both with and without --chain).

Fixes: https://pagure.io/freeipa/issue/7700
Reviewed-By: Christian Heimes <cheimes@redhat.com>
2018-10-02 10:18:32 +02:00

55 lines
1.5 KiB
Python

#
# Copyright (C) 2016 FreeIPA Contributors see COPYING for license
#
import base64
from ipaclient.frontend import MethodOverride
from ipalib import errors, 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')
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
@register(override=True, no_fail=True)
class ca_add(WithCertOutArgs):
pass
@register(override=True, no_fail=True)
class ca_show(WithCertOutArgs):
pass