summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFraser Tweedale <ftweedal@redhat.com>2016-06-29 13:57:53 +1000
committerJan Cholasta <jcholast@redhat.com>2016-07-01 05:54:56 +0200
commitffb1f5b1f24f0de30529d50f8c8dfb9a896c149e (patch)
treec726f9f3a4fefc9e5fa87fd83f14f9295a732d66
parent235b19ba7f9807ecf10436d1a5b28518b4475a70 (diff)
downloadfreeipa-ffb1f5b1f24f0de30529d50f8c8dfb9a896c149e.zip
freeipa-ffb1f5b1f24f0de30529d50f8c8dfb9a896c149e.tar.gz
freeipa-ffb1f5b1f24f0de30529d50f8c8dfb9a896c149e.tar.xz
Add --ca option to cert-revoke and cert-remove-hold
Implement the --ca option for cert-revoke and cert-remove-hold. Defaults to the IPA CA. Raise NotFound if the cert with the given serial was not issued by the nominated CA. Also default the --ca option of cert-show to the IPA CA. Add commentary to cert-status to explain why it does not use the --ca option. Fixes: https://fedorahosted.org/freeipa/ticket/5999 Reviewed-By: Jan Cholasta <jcholast@redhat.com>
-rw-r--r--API.txt10
-rw-r--r--VERSION4
-rw-r--r--ipaserver/plugins/cert.py47
3 files changed, 40 insertions, 21 deletions
diff --git a/API.txt b/API.txt
index 085a7e0..c01692e 100644
--- a/API.txt
+++ b/API.txt
@@ -760,8 +760,9 @@ output: ListOfEntries('result')
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
output: Output('truncated', type=[<type 'bool'>])
command: cert_remove_hold/1
-args: 1,1,1
+args: 1,2,1
arg: Int('serial_number')
+option: Str('cacn?', autofill=True, cli_name='ca', default=u'ipa')
option: Str('version?')
output: Output('result')
command: cert_request/1
@@ -769,7 +770,7 @@ args: 1,8,3
arg: Str('csr', cli_name='csr_file')
option: Flag('add', autofill=True, default=False)
option: Flag('all', autofill=True, cli_name='all', default=False)
-option: Str('cacn?', cli_name='ca')
+option: Str('cacn?', autofill=True, cli_name='ca', default=u'ipa')
option: Str('principal')
option: Str('profile_id?')
option: Flag('raw', autofill=True, cli_name='raw', default=False)
@@ -779,8 +780,9 @@ output: Entry('result')
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
output: PrimaryKey('value')
command: cert_revoke/1
-args: 1,2,1
+args: 1,3,1
arg: Int('serial_number')
+option: Str('cacn?', autofill=True, cli_name='ca', default=u'ipa')
option: Int('revocation_reason', autofill=True, default=0)
option: Str('version?')
output: Output('result')
@@ -788,7 +790,7 @@ command: cert_show/1
args: 1,6,3
arg: Int('serial_number')
option: Flag('all', autofill=True, cli_name='all', default=False)
-option: Str('cacn?', cli_name='ca')
+option: Str('cacn?', autofill=True, cli_name='ca', default=u'ipa')
option: Flag('no_members', autofill=True, default=False)
option: Str('out?')
option: Flag('raw', autofill=True, cli_name='raw', default=False)
diff --git a/VERSION b/VERSION
index 656e472..23ceecc 100644
--- a/VERSION
+++ b/VERSION
@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000
# #
########################################################
IPA_API_VERSION_MAJOR=2
-IPA_API_VERSION_MINOR=204
-# Last change: user: add object plugin for user_status
+IPA_API_VERSION_MINOR=205
+# Last change: Add --ca option to cert-revoke and cert-remove-hold
diff --git a/ipaserver/plugins/cert.py b/ipaserver/plugins/cert.py
index 1007408..817bdc2 100644
--- a/ipaserver/plugins/cert.py
+++ b/ipaserver/plugins/cert.py
@@ -327,6 +327,8 @@ class BaseCertMethod(Method):
def get_options(self):
yield Str('cacn?',
cli_name='ca',
+ default=IPA_CA_CN,
+ autofill=True,
query=True,
label=_('Issuing CA'),
doc=_('Name of issuing CA'),
@@ -416,7 +418,7 @@ class cert_request(Create, BaseCertMethod, VirtualCommand):
# enforcement so that user gets better error message if
# referencing nonexistant CA) and look up authority ID.
#
- ca = kw.get('cacn', IPA_CA_CN)
+ ca = kw['cacn']
ca_id = api.Command.ca_show(ca)['result']['ipacaid'][0]
"""
@@ -639,6 +641,8 @@ class cert_status(Retrieve, BaseCertMethod, VirtualCommand):
def get_options(self):
for option in super(cert_status, self).get_options():
if option.name == 'cacn':
+ # Dogtag requests are uniquely identified by their
+ # number; there is no need to distinguish by CA.
continue
yield option
@@ -749,10 +753,8 @@ class cert_show(Retrieve, CertMethod, VirtualCommand):
raise acierr
hostname = get_host_from_principal(bind_principal)
- issuer_dn = None
- if 'cacn' in options:
- ca_obj = api.Command.ca_show(options['cacn'])['result']
- issuer_dn = ca_obj['ipacasubjectdn'][0]
+ ca_obj = api.Command.ca_show(options['cacn'])['result']
+ issuer_dn = ca_obj['ipacasubjectdn'][0]
# Dogtag lightweight CAs have shared serial number domain, so
# we don't tell Dogtag the issuer (but we check the cert after).
@@ -760,7 +762,7 @@ class cert_show(Retrieve, CertMethod, VirtualCommand):
result = self.Backend.ra.get_certificate(str(serial_number))
cert = x509.load_certificate(result['certificate'])
- if issuer_dn is not None and DN(unicode(cert.issuer)) != DN(issuer_dn):
+ if DN(unicode(cert.issuer)) != DN(issuer_dn):
# DN of cert differs from what we requested
raise errors.NotFound(
reason=_("Certificate with serial number %(serial)s "
@@ -811,12 +813,16 @@ class cert_revoke(PKQuery, CertMethod, VirtualCommand):
)
for option in super(cert_revoke, self).get_options():
- if option.name == 'cacn':
- continue
yield option
def execute(self, serial_number, **kw):
ca_enabled_check()
+
+ # Make sure that the cert specified by issuer+serial exists.
+ # Will raise NotFound if it does not.
+ cert_show_options = dict(cacn=kw['cacn'])
+ api.Command.cert_show(unicode(serial_number), **cert_show_options)
+
hostname = None
try:
self.check_access()
@@ -825,13 +831,18 @@ class cert_revoke(PKQuery, CertMethod, VirtualCommand):
try:
# Let cert_show() handle verifying that the subject of the
# cert we're dealing with matches the hostname in the principal
- result = api.Command['cert_show'](unicode(serial_number))['result']
+ result = api.Command['cert_show'](
+ unicode(serial_number), **cert_show_options
+ )['result']
except errors.NotImplementedError:
pass
revocation_reason = kw['revocation_reason']
if revocation_reason == 7:
raise errors.CertificateOperationError(error=_('7 is not a valid revocation reason'))
return dict(
+ # Dogtag lightweight CAs have shared serial number domain, so
+ # we don't tell Dogtag the issuer (but we already checked that
+ # the given serial was issued by the named ca).
result=self.Backend.ra.revoke_certificate(
str(serial_number), revocation_reason=revocation_reason)
)
@@ -844,16 +855,18 @@ class cert_remove_hold(PKQuery, CertMethod, VirtualCommand):
operation = "certificate remove hold"
- def get_options(self):
- for option in super(cert_remove_hold, self).get_options():
- if option.name == 'cacn':
- continue
- yield option
-
def execute(self, serial_number, **kw):
ca_enabled_check()
+
+ # Make sure that the cert specified by issuer+serial exists.
+ # Will raise NotFound if it does not.
+ api.Command.cert_show(serial_number, cacn=kw['cacn'])
+
self.check_access()
return dict(
+ # Dogtag lightweight CAs have shared serial number domain, so
+ # we don't tell Dogtag the issuer (but we already checked that
+ # the given serial was issued by the named ca).
result=self.Backend.ra.take_certificate_off_hold(
str(serial_number))
)
@@ -951,6 +964,10 @@ class cert_find(Search, CertMethod):
if option.name == 'no_members':
option = option.clone(default=True,
flags=set(option.flags) | {'no_option'})
+ elif option.name == 'cacn':
+ # make CA optional, so that user may directly
+ # specify Issuer DN instead
+ option = option.clone(default=None, autofill=None)
yield option
for owner in self.obj._owners():