summaryrefslogtreecommitdiffstats
path: root/ipalib/plugins/service.py
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2010-11-05 15:16:53 -0400
committerAdam Young <ayoung@redhat.com>2010-11-19 10:31:42 -0500
commit2046eddb7ab3e56f57f9decd172f6354f0a945aa (patch)
tree5f903f77b433ac58e6c0314e3cb629285e02dd16 /ipalib/plugins/service.py
parenteead9eec998697cc8c147a47a8874ef7a801cbd1 (diff)
downloadfreeipa-2046eddb7ab3e56f57f9decd172f6354f0a945aa.tar.gz
freeipa-2046eddb7ab3e56f57f9decd172f6354f0a945aa.tar.xz
freeipa-2046eddb7ab3e56f57f9decd172f6354f0a945aa.zip
Revoke a host's certificate (if any) when it is deleted or disabled.
Disable any services when its host is disabled. This also adds displaying the certificate attributes (subject, etc) a bit more universal and centralized in a single function. ticket 297
Diffstat (limited to 'ipalib/plugins/service.py')
-rw-r--r--ipalib/plugins/service.py130
1 files changed, 89 insertions, 41 deletions
diff --git a/ipalib/plugins/service.py b/ipalib/plugins/service.py
index 8ccdaeac7..c65a7a4ac 100644
--- a/ipalib/plugins/service.py
+++ b/ipalib/plugins/service.py
@@ -87,6 +87,30 @@ output_params = (
Str('managedby_host',
label='Managed by',
),
+ Str('subject',
+ label=_('Subject'),
+ ),
+ Str('serial_number',
+ label=_('Serial Number'),
+ ),
+ Str('issuer',
+ label=_('Issuer'),
+ ),
+ Str('valid_not_before',
+ label=_('Not Before'),
+ ),
+ Str('valid_not_after',
+ label=_('Not After'),
+ ),
+ Str('md5_fingerprint',
+ label=_('Fingerprint (MD5)'),
+ ),
+ Str('sha1_fingerprint',
+ label=_('Fingerprint (SHA1)'),
+ ),
+ Str('revocation_reason?',
+ label=_('Revocation reason'),
+ )
)
def split_principal(principal):
@@ -171,6 +195,30 @@ def normalize_certificate(cert):
return cert
+def set_certificate_attrs(entry_attrs):
+ """
+ Set individual attributes from some values from a certificate.
+
+ entry_attrs is a dict of an entry
+
+ returns nothing
+ """
+ if not 'usercertificate' in entry_attrs:
+ return
+ if type(entry_attrs['usercertificate']) in (list, tuple):
+ cert = entry_attrs['usercertificate'][0]
+ else:
+ cert = entry_attrs['usercertificate']
+ cert = normalize_certificate(cert)
+ cert = x509.load_certificate(cert, datatype=x509.DER)
+ entry_attrs['subject'] = unicode(cert.subject)
+ entry_attrs['serial_number'] = unicode(cert.serial_number)
+ entry_attrs['issuer'] = unicode(cert.issuer)
+ entry_attrs['valid_not_before'] = unicode(cert.valid_not_before_str)
+ entry_attrs['valid_not_after'] = unicode(cert.valid_not_after_str)
+ entry_attrs['md5_fingerprint'] = unicode(nss.data_to_hex(nss.md5_digest(cert.der_data), 64)[0])
+ entry_attrs['sha1_fingerprint'] = unicode(nss.data_to_hex(nss.sha1_digest(cert.der_data), 64)[0])
+
class service(LDAPObject):
"""
@@ -313,6 +361,9 @@ class service_mod(LDAPUpdate):
entry_attrs['usercertificate'] = None
return dn
+ def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
+ set_certificate_attrs(entry_attrs)
+
api.register(service_mod)
@@ -348,6 +399,7 @@ class service_find(LDAPSearch):
del entry_attrs['krblastpwdchange']
else:
entry_attrs['has_keytab'] = False
+ set_certificate_attrs(entry_attrs)
api.register(service_find)
@@ -359,33 +411,6 @@ class service_show(LDAPRetrieve):
member_attributes = ['managedby']
takes_options = LDAPRetrieve.takes_options
- has_output_params = LDAPRetrieve.has_output_params + output_params + (
- Str('subject',
- label=_('Subject'),
- ),
- Str('serial_number',
- label=_('Serial Number'),
- ),
- Str('issuer',
- label=_('Issuer'),
- ),
- Str('valid_not_before',
- label=_('Not Before'),
- ),
- Str('valid_not_after',
- label=_('Not After'),
- ),
- Str('md5_fingerprint',
- label=_('Fingerprint (MD5)'),
- ),
- Str('sha1_fingerprint',
- label=_('Fingerprint (SHA1)'),
- ),
- Str('revocation_reason?',
- label=_('Revocation reason'),
- )
- )
-
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
if 'krblastpwdchange' in entry_attrs:
entry_attrs['has_keytab'] = True
@@ -394,15 +419,7 @@ class service_show(LDAPRetrieve):
else:
entry_attrs['has_keytab'] = False
- if 'usercertificate' in entry_attrs:
- cert = x509.load_certificate(entry_attrs['usercertificate'][0], datatype=x509.DER)
- entry_attrs['subject'] = unicode(cert.subject)
- entry_attrs['serial_number'] = unicode(cert.serial_number)
- entry_attrs['issuer'] = unicode(cert.issuer)
- entry_attrs['valid_not_before'] = unicode(cert.valid_not_before_str)
- entry_attrs['valid_not_after'] = unicode(cert.valid_not_after_str)
- entry_attrs['md5_fingerprint'] = unicode(nss.data_to_hex(nss.md5_digest(cert.der_data), 64)[0])
- entry_attrs['sha1_fingerprint'] = unicode(nss.data_to_hex(nss.sha1_digest(cert.der_data), 64)[0])
+ set_certificate_attrs(entry_attrs)
return dn
@@ -440,13 +457,44 @@ class service_disable(LDAPQuery):
ldap = self.obj.backend
dn = self.obj.get_dn(*keys, **options)
- (dn, entry_attrs) = ldap.get_entry(dn, ['krblastpwdchange'])
+ (dn, entry_attrs) = ldap.get_entry(dn, ['krblastpwdchange', 'usercertificate'])
+
+ # See if we do any work at all here and if not raise an exception
+ done_work = False
- if 'krblastpwdchange' not in entry_attrs:
- error_msg = _('Service principal has no kerberos key')
- raise errors.NotFound(reason=error_msg)
+ if 'usercertificate' in entry_attrs:
+ cert = normalize_certificate(entry_attrs.get('usercertificate')[0])
+ try:
+ serial = unicode(x509.get_serial_number(cert, x509.DER))
+ try:
+ result = api.Command['cert_show'](unicode(serial))['result']
+ if 'revocation_reason' not in result:
+ try:
+ api.Command['cert_revoke'](unicode(serial), revocation_reason=4)
+ except errors.NotImplementedError:
+ # some CA's might not implement revoke
+ pass
+ except errors.NotImplementedError:
+ # some CA's might not implement revoke
+ pass
+ except NSPRError, nsprerr:
+ if nsprerr.errno == -8183:
+ # If we can't decode the cert them proceed with
+ # disabling the service
+ self.log.info("Problem decoding certificate %s" % nsprerr.args[1])
+ else:
+ raise nsprerr
+
+ # Remove the usercertificate altogether
+ ldap.update_entry(dn, {'usercertificate': None})
+ done_work = True
+
+ if 'krblastpwdchange' in entry_attrs:
+ ldap.remove_principal_key(dn)
+ done_work = True
- ldap.remove_principal_key(dn)
+ if not done_work:
+ raise errors.AlreadyInactive()
return dict(
result=True,