diff options
author | Rob Crittenden <rcritten@redhat.com> | 2010-08-05 22:41:32 -0400 |
---|---|---|
committer | Rob Crittenden <rcritten@redhat.com> | 2010-08-16 17:13:56 -0400 |
commit | 2f4f9054aac8bef83272d690a4868653a3a5bd0d (patch) | |
tree | aa1ef1ff947f002337e32dda202c8135c1eeaad9 /ipalib | |
parent | 81ae7c3a605ba13c6479c7bccc44190228f8ed07 (diff) | |
download | freeipa-2f4f9054aac8bef83272d690a4868653a3a5bd0d.tar.gz freeipa-2f4f9054aac8bef83272d690a4868653a3a5bd0d.tar.xz freeipa-2f4f9054aac8bef83272d690a4868653a3a5bd0d.zip |
Enable a host to retrieve a keytab for all its services.
Using the host service principal one should be able to retrieve a keytab
for other services for the host using ipa-getkeytab. This required a number
of changes:
- allow hosts in the service's managedby to write krbPrincipalKey
- automatically add the host to managedby when a service is created
- fix ipa-getkeytab to return the entire prinicpal and not just the
first data element. It was returning "host" from the service tgt
and not host/ipa.example.com
- fix the display of the managedby attribute in the service plugin
This led to a number of changes in the service unit tests. I took the
opportunity to switch to the Declarative scheme and tripled the number
of tests we were doing. This shed some light on a few bugs in the plugin:
- if a service had a bad usercertificate it was impossible to delete the
service. I made it a bit more flexible.
- I added a summary for the mod and find commands
- has_keytab wasn't being set in the find output
ticket 68
Diffstat (limited to 'ipalib')
-rw-r--r-- | ipalib/plugins/service.py | 70 |
1 files changed, 53 insertions, 17 deletions
diff --git a/ipalib/plugins/service.py b/ipalib/plugins/service.py index ac949b788..c9ae0b88e 100644 --- a/ipalib/plugins/service.py +++ b/ipalib/plugins/service.py @@ -65,8 +65,18 @@ from ipalib import Str, Flag, Bytes from ipalib.plugins.baseldap import * from ipalib import x509 from ipalib import _, ngettext +from nss.error import NSPRError +output_params = ( + Flag('has_keytab', + label=_('Keytab'), + ), + Str('managedby_host', + label='Managed by', + ), +) + def split_principal(principal): service = hostname = realm = None @@ -155,6 +165,7 @@ class service_add(LDAPCreate): """ msg_summary = _('Added service "%(value)s"') member_attributes = ['managedby'] + has_output_params = LDAPCreate.has_output_params + output_params takes_options = ( Flag('force', doc=_('force principal name even if not in DNS'), @@ -171,7 +182,7 @@ class service_add(LDAPCreate): raise errors.HostService() try: - api.Command['host_show'](hostname) + hostresult = api.Command['host_show'](hostname)['result'] except errors.NotFound: raise errors.NotFound(reason="The host '%s' does not exist to add a service to." % hostname) @@ -188,6 +199,8 @@ class service_add(LDAPCreate): # really want to discourage creating services for hosts that # don't exist in DNS. util.validate_host_dns(self.log, hostname) + if not 'managedby' in entry_attrs: + entry_attrs['managedby'] = hostresult['dn'] return dn @@ -206,18 +219,26 @@ class service_del(LDAPDelete): cert = entry_attrs.get('usercertificate') if cert: cert = cert[0] - 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 + 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 + # removing the service. + self.log.info("Problem decoding certificate %s" % nsprerr.args[1]) + else: + raise nsprerr return dn api.register(service_del) @@ -227,6 +248,7 @@ class service_mod(LDAPUpdate): """ Modify service. """ + msg_summary = _('Modified service "%(value)s"') takes_options = LDAPUpdate.takes_options + ( Bytes('usercertificate?', validate_certificate, cli_name='certificate', @@ -234,6 +256,7 @@ class service_mod(LDAPUpdate): doc=_('Base-64 encoded server certificate'), ), ) + has_output_params = LDAPUpdate.has_output_params + output_params member_attributes = ['managedby'] @@ -261,6 +284,9 @@ class service_find(LDAPSearch): """ Search for services. """ + msg_summary = ngettext( + '%(count)d service matched', '%(count)d services matched' + ) member_attributes = ['managedby'] takes_options = LDAPSearch.takes_options + ( Bytes('usercertificate?', validate_certificate, @@ -269,6 +295,7 @@ class service_find(LDAPSearch): doc=_('Base-64 encoded server certificate'), ), ) + has_output_params = LDAPSearch.has_output_params + output_params def pre_callback(self, ldap, filter, attrs_list, base_dn, *args, **options): # lisp style! custom_filter = '(&(objectclass=ipaService)' \ @@ -282,6 +309,16 @@ class service_find(LDAPSearch): (custom_filter, filter), rules=ldap.MATCH_ALL ) + def post_callback(self, ldap, entries, truncated, *args, **options): + for entry in entries: + entry_attrs = entry[1] + if 'krblastpwdchange' in entry_attrs: + entry_attrs['has_keytab'] = True + if not options.get('all', False): + del entry_attrs['krblastpwdchange'] + else: + entry_attrs['has_keytab'] = False + api.register(service_find) @@ -297,11 +334,7 @@ class service_show(LDAPRetrieve): doc=_('Base-64 encoded server certificate'), ), ) - has_output_params = ( - Flag('has_keytab', - label=_('Keytab'), - ) - ) + has_output_params = LDAPRetrieve.has_output_params + output_params def post_callback(self, ldap, dn, entry_attrs, *keys, **options): if 'krblastpwdchange' in entry_attrs: @@ -320,6 +353,7 @@ class service_add_host(LDAPAddMember): Add hosts that can manage this service. """ member_attributes = ['managedby'] + has_output_params = LDAPAddMember.has_output_params + output_params api.register(service_add_host) @@ -329,6 +363,7 @@ class service_remove_host(LDAPRemoveMember): Remove hosts that can manage this service. """ member_attributes = ['managedby'] + has_output_params = LDAPRemoveMember.has_output_params + output_params api.register(service_remove_host) @@ -339,6 +374,7 @@ class service_disable(LDAPQuery): """ has_output = output.standard_value msg_summary = _('Removed kerberos key from "%(value)s"') + has_output_params = LDAPQuery.has_output_params + output_params def execute(self, *keys, **options): ldap = self.obj.backend |