summaryrefslogtreecommitdiffstats
path: root/ipalib/plugins/service.py
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2010-08-05 22:41:32 -0400
committerRob Crittenden <rcritten@redhat.com>2010-08-16 17:13:56 -0400
commit2f4f9054aac8bef83272d690a4868653a3a5bd0d (patch)
treeaa1ef1ff947f002337e32dda202c8135c1eeaad9 /ipalib/plugins/service.py
parent81ae7c3a605ba13c6479c7bccc44190228f8ed07 (diff)
downloadfreeipa-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/plugins/service.py')
-rw-r--r--ipalib/plugins/service.py70
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