From dbe49423ab16ed9ad01166feee22b68b7b05c725 Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Fri, 10 Oct 2008 03:36:39 -0400 Subject: Start service principal plugin --- ipalib/plugins/f_service.py | 155 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 ipalib/plugins/f_service.py (limited to 'ipalib/plugins/f_service.py') diff --git a/ipalib/plugins/f_service.py b/ipalib/plugins/f_service.py new file mode 100644 index 00000000..0db1171c --- /dev/null +++ b/ipalib/plugins/f_service.py @@ -0,0 +1,155 @@ +# Authors: +# Jason Gerard DeRose +# +# Copyright (C) 2008 Red Hat +# see file 'COPYING' for use and warranty information +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; version 2 only +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +""" +Frontend plugins for service (Identity). +""" + +from ipalib import frontend +from ipalib import crud +from ipalib.frontend import Param +from ipalib import api +from ipalib import errors +from ipalib import ipa_types +from ipa_server import servercore +from ipa_server import ipaldap +import ldap + +class service(frontend.Object): + """ + Service object. + """ + takes_params = ( + Param('principal', primary_key=True), + ) +api.register(service) + + +class service_add(crud.Add): + 'Add a new service.' + """ + my_params = ( + Param('force', type=ipa_types.Bool(), default=False), + ) + def get_options(self): + for param in self.my_params: + yield param + """ + def execute(self, *args, **kw): + """args[0] = service principal to add + kw{force} determines whether we continue on errors + """ + force = kw.get('force', False) + + principal = args[0] + + # Break down the principal into its component parts, which may or + # may not include the realm. + sp = principal.split('/') + if len(sp) != 2: + raise errors.MalformedServicePrincipal + service = sp[0] + + sr = sp[1].split('@') + if len(sr) == 1: + hostname = sr[0].lower() + realm = servercore.realm + elif len(sr) == 2: + hostname = sr[0].lower() + realm = sr[1] + else: + raise MalformedServicePrincipal + + """ + FIXME once DNS client is done + if not force: + fqdn = hostname + "." + rs = dnsclient.query(fqdn, dnsclient.DNS_C_IN, dnsclient.DNS_T_A) + if len(rs) == 0: + logging.debug("IPA: DNS A record lookup failed for '%s'" % hostname) + raise ipaerror.gen_exception(ipaerror.INPUT_NOT_DNS_A_RECORD) + else: + logging.debug("IPA: found %d records for '%s'" % (len(rs), hostname)) + """ + + service_container = servercore.DefaultServiceContainer + + # At some point we'll support multiple realms + if (realm != servercore.realm): + raise errors.RealmMismatch + + # Put the principal back together again + princ_name = service + "/" + hostname + "@" + realm + + dn = "krbprincipalname=%s,%s,%s" % (ldap.dn.escape_dn_chars(princ_name), + service_container,servercore.basedn) + entry = ipaldap.Entry(dn) + + entry.setValues('objectClass', 'krbPrincipal', 'krbPrincipalAux', 'krbTicketPolicyAux') + entry.setValues('krbprincipalname', princ_name) + + result = servercore.add_entry(entry) + return result + def forward(self, *args, **kw): + result = super(crud.Add, self).forward(*args, **kw) + if result: + print "Service %s added" % args[0] +api.register(service_add) + + +class service_del(crud.Del): + 'Delete an existing service.' + def execute(self, *args, **kw): + """args[0] = princial to remove + + Delete a service principal. + + principal is the full DN of the entry to delete. + + This should be called with much care. + """ + principal = args[0] + return False + def forward(self, *args, **kw): + result = super(crud.Del, self).forward(*args, **kw) + if result: + print "Service %s removed" % args[0] +api.register(service_del) + + +class service_mod(crud.Mod): + 'Edit an existing service.' +api.register(service_mod) + + +class service_find(crud.Find): + 'Search the existing services.' +api.register(service_find) + + +class service_show(crud.Get): + 'Examine an existing service.' + def execute(self, *args, **kw): + filter = "(&(objectclass=krbPrincipalAux)(!(objectClass=person))(!(|(krbprincipalname=kadmin/*)(krbprincipalname=K/M@*)(krbprincipalname=krbtgt/*)))(&(|(krbprincipalname=%s))))" % args[0] + result = servercore.get_sub_entry(servercore.basedn, filter, ["*"]) + return result + def forward(self, *args, **kw): + result = super(crud.Get, self).forward(*args, **kw) + return result +api.register(service_show) -- cgit From 42cdca3e8340c9aae721d582a522b7991ea38050 Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Fri, 10 Oct 2008 03:40:52 -0400 Subject: Use new options handler --- ipalib/plugins/f_service.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'ipalib/plugins/f_service.py') diff --git a/ipalib/plugins/f_service.py b/ipalib/plugins/f_service.py index 0db1171c..baed5233 100644 --- a/ipalib/plugins/f_service.py +++ b/ipalib/plugins/f_service.py @@ -43,14 +43,9 @@ api.register(service) class service_add(crud.Add): 'Add a new service.' - """ - my_params = ( - Param('force', type=ipa_types.Bool(), default=False), + takes_options = ( + Param('force?', type=ipa_types.Bool(), default=False, doc='Force a service principal name'), ) - def get_options(self): - for param in self.my_params: - yield param - """ def execute(self, *args, **kw): """args[0] = service principal to add kw{force} determines whether we continue on errors -- cgit From ae8370be44d95b9f6793ded46ef81126aebef3e0 Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Fri, 17 Oct 2008 19:20:23 -0400 Subject: Port f_service to LDAP backend Add new keyword, 'filter', that can be passed to the search function. This is globbed onto the filter that is auto-created. --- ipalib/plugins/f_service.py | 137 +++++++++++++++++++++++++++++--------------- 1 file changed, 92 insertions(+), 45 deletions(-) (limited to 'ipalib/plugins/f_service.py') diff --git a/ipalib/plugins/f_service.py b/ipalib/plugins/f_service.py index baed5233..38c80ad2 100644 --- a/ipalib/plugins/f_service.py +++ b/ipalib/plugins/f_service.py @@ -1,5 +1,6 @@ # Authors: # Jason Gerard DeRose +# Rob Crittenden # # Copyright (C) 2008 Red Hat # see file 'COPYING' for use and warranty information @@ -27,9 +28,6 @@ from ipalib.frontend import Param from ipalib import api from ipalib import errors from ipalib import ipa_types -from ipa_server import servercore -from ipa_server import ipaldap -import ldap class service(frontend.Object): """ @@ -46,13 +44,26 @@ class service_add(crud.Add): takes_options = ( Param('force?', type=ipa_types.Bool(), default=False, doc='Force a service principal name'), ) - def execute(self, *args, **kw): - """args[0] = service principal to add - kw{force} determines whether we continue on errors + def execute(self, principal, **kw): """ - force = kw.get('force', False) + Execute the service-add operation. + + The dn should not be passed as a keyword argument as it is constructed + by this method. - principal = args[0] + Returns the entry as it will be created in LDAP. + + :param principal: The service to be added in the form: service/hostname + :param kw: Keyword arguments for the other LDAP attributes. + """ + assert 'krbprincipalname' not in kw + ldap = self.api.Backend.ldap + + force = kw.get('force', False) + try: + del kw['force'] + except: + pass # Break down the principal into its component parts, which may or # may not include the realm. @@ -64,7 +75,7 @@ class service_add(crud.Add): sr = sp[1].split('@') if len(sr) == 1: hostname = sr[0].lower() - realm = servercore.realm + realm = self.api.env.realm elif len(sr) == 2: hostname = sr[0].lower() realm = sr[1] @@ -83,68 +94,104 @@ class service_add(crud.Add): logging.debug("IPA: found %d records for '%s'" % (len(rs), hostname)) """ - service_container = servercore.DefaultServiceContainer - # At some point we'll support multiple realms - if (realm != servercore.realm): + if (realm != self.api.env.realm): raise errors.RealmMismatch # Put the principal back together again princ_name = service + "/" + hostname + "@" + realm - dn = "krbprincipalname=%s,%s,%s" % (ldap.dn.escape_dn_chars(princ_name), - service_container,servercore.basedn) - entry = ipaldap.Entry(dn) + dn = ldap.make_service_dn(princ_name) - entry.setValues('objectClass', 'krbPrincipal', 'krbPrincipalAux', 'krbTicketPolicyAux') - entry.setValues('krbprincipalname', princ_name) + kw['dn'] = dn + kw['objectClass'] = ['krbPrincipal', 'krbPrincipalAux', 'krbTicketPolicyAux'] + + return ldap.create(**kw) + + def output_to_cli(self, ret): + if ret: + print "Service added" - result = servercore.add_entry(entry) - return result - def forward(self, *args, **kw): - result = super(crud.Add, self).forward(*args, **kw) - if result: - print "Service %s added" % args[0] api.register(service_add) class service_del(crud.Del): 'Delete an existing service.' - def execute(self, *args, **kw): - """args[0] = princial to remove + def execute(self, principal, **kw): + """ + Delete a service principal. - Delete a service principal. + principal is the krbprincipalname of the entry to delete. - principal is the full DN of the entry to delete. + This should be called with much care. - This should be called with much care. + :param principal: The service to be added in the form: service/hostname + :param kw: not used """ - principal = args[0] - return False - def forward(self, *args, **kw): - result = super(crud.Del, self).forward(*args, **kw) - if result: - print "Service %s removed" % args[0] -api.register(service_del) + ldap = self.api.Backend.ldap + dn = ldap.find_entry_dn("krbprincipalname", principal) + return ldap.delete(dn) + def output_to_cli(self, ret): + if ret: + print "Service removed" -class service_mod(crud.Mod): - 'Edit an existing service.' -api.register(service_mod) +api.register(service_del) +# There is no service-mod. The principal itself contains nothing that +# is user-changeable class service_find(crud.Find): 'Search the existing services.' + def execute(self, principal, **kw): + ldap = self.api.Backend.ldap + + kw['filter'] = "&(objectclass=krbPrincipalAux)(!(objectClass=person))(!(|(krbprincipalname=kadmin/*)(krbprincipalname=K/M@*)(krbprincipalname=krbtgt/*)))" + kw['krbprincipalname'] = principal + + object_type = ldap.get_object_type("krbprincipalname") + if object_type and not kw.get('objectclass'): + kw['objectclass'] = object_type + + return ldap.search(**kw) + + def output_for_cli(self, services): + if not services: + return + + counter = services[0] + services = services[1:] + if counter == 0: + print "No entries found" + return + elif counter == -1: + print "These results are truncated." + print "Please refine your search and try again." + + for s in services: + for a in s.keys(): + print "%s: %s" % (a, s[a]) + api.register(service_find) class service_show(crud.Get): 'Examine an existing service.' - def execute(self, *args, **kw): - filter = "(&(objectclass=krbPrincipalAux)(!(objectClass=person))(!(|(krbprincipalname=kadmin/*)(krbprincipalname=K/M@*)(krbprincipalname=krbtgt/*)))(&(|(krbprincipalname=%s))))" % args[0] - result = servercore.get_sub_entry(servercore.basedn, filter, ["*"]) - return result - def forward(self, *args, **kw): - result = super(crud.Get, self).forward(*args, **kw) - return result + def execute(self, principal, **kw): + """ + Execute the service-show operation. + + The dn should not be passed as a keyword argument as it is constructed + by this method. + + Returns the entry + + :param principal: The service principal to retrieve + :param kw: Not used. + """ + ldap = self.api.Backend.ldap + dn = ldap.find_entry_dn("krbprincipalname", principal) + # FIXME: should kw contain the list of attributes to display? + return ldap.retrieve(dn) + api.register(service_show) -- cgit From 8788afe18403e7585e4fc2b6a52a352a035fee0b Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Fri, 24 Oct 2008 11:40:47 -0400 Subject: Use posixAccount instead of person to identify users Add output_for_cli to service-find --- ipalib/plugins/f_service.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'ipalib/plugins/f_service.py') diff --git a/ipalib/plugins/f_service.py b/ipalib/plugins/f_service.py index 38c80ad2..9e9cec53 100644 --- a/ipalib/plugins/f_service.py +++ b/ipalib/plugins/f_service.py @@ -110,7 +110,7 @@ class service_add(crud.Add): def output_to_cli(self, ret): if ret: - print "Service added" + print "Service added" api.register(service_add) @@ -146,7 +146,7 @@ class service_find(crud.Find): def execute(self, principal, **kw): ldap = self.api.Backend.ldap - kw['filter'] = "&(objectclass=krbPrincipalAux)(!(objectClass=person))(!(|(krbprincipalname=kadmin/*)(krbprincipalname=K/M@*)(krbprincipalname=krbtgt/*)))" + kw['filter'] = "&(objectclass=krbPrincipalAux)(!(objectClass=posixAccount))(!(|(krbprincipalname=kadmin/*)(krbprincipalname=K/M@*)(krbprincipalname=krbtgt/*)))" kw['krbprincipalname'] = principal object_type = ldap.get_object_type("krbprincipalname") @@ -193,5 +193,11 @@ class service_show(crud.Get): dn = ldap.find_entry_dn("krbprincipalname", principal) # FIXME: should kw contain the list of attributes to display? return ldap.retrieve(dn) + def output_for_cli(self, service): + if not service: + return + + for a in service.keys(): + print "%s: %s" % (a, service[a]) api.register(service_show) -- cgit From 34520981eeaac5d4f37915509a9e26428e26f5c0 Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Fri, 24 Oct 2008 14:17:20 -0400 Subject: Don't allow service-add to create host/ principals --- ipalib/plugins/f_service.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'ipalib/plugins/f_service.py') diff --git a/ipalib/plugins/f_service.py b/ipalib/plugins/f_service.py index 9e9cec53..f02176ff 100644 --- a/ipalib/plugins/f_service.py +++ b/ipalib/plugins/f_service.py @@ -72,6 +72,9 @@ class service_add(crud.Add): raise errors.MalformedServicePrincipal service = sp[0] + if service.lower() == "host": + raise errors.HostService + sr = sp[1].split('@') if len(sr) == 1: hostname = sr[0].lower() -- cgit From dd9206deb62c1c96344d2280f672353a53a7fd11 Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Fri, 31 Oct 2008 17:03:10 -0400 Subject: Uncomment some logging statements ported over from v1. --- ipalib/plugins/f_service.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ipalib/plugins/f_service.py') diff --git a/ipalib/plugins/f_service.py b/ipalib/plugins/f_service.py index f02176ff..04187a86 100644 --- a/ipalib/plugins/f_service.py +++ b/ipalib/plugins/f_service.py @@ -91,10 +91,10 @@ class service_add(crud.Add): fqdn = hostname + "." rs = dnsclient.query(fqdn, dnsclient.DNS_C_IN, dnsclient.DNS_T_A) if len(rs) == 0: - logging.debug("IPA: DNS A record lookup failed for '%s'" % hostname) + self.log.debug("IPA: DNS A record lookup failed for '%s'" % hostname) raise ipaerror.gen_exception(ipaerror.INPUT_NOT_DNS_A_RECORD) else: - logging.debug("IPA: found %d records for '%s'" % (len(rs), hostname)) + self.log.debug("IPA: found %d records for '%s'" % (len(rs), hostname)) """ # At some point we'll support multiple realms -- cgit From af7b5645af001352aff626f46ec39031b2e9b10a Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Wed, 10 Dec 2008 16:42:45 -0500 Subject: Convert to new output_for_cli() function --- ipalib/plugins/f_service.py | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) (limited to 'ipalib/plugins/f_service.py') diff --git a/ipalib/plugins/f_service.py b/ipalib/plugins/f_service.py index 04187a86..fc0ae65e 100644 --- a/ipalib/plugins/f_service.py +++ b/ipalib/plugins/f_service.py @@ -158,22 +158,20 @@ class service_find(crud.Find): return ldap.search(**kw) - def output_for_cli(self, services): - if not services: - return - - counter = services[0] - services = services[1:] + def output_for_cli(self, textui, result, *args, **options): + counter = result[0] + services = result[1:] if counter == 0: - print "No entries found" + textui.print_plain("No entries found") return - elif counter == -1: - print "These results are truncated." - print "Please refine your search and try again." for s in services: - for a in s.keys(): - print "%s: %s" % (a, s[a]) + textui.print_entry(s) + + if counter == -1: + textui.print_plain("These results are truncated.") + textui.print_plain("Please refine your search and try again.") + textui.print_count(services, '%d services matched') api.register(service_find) @@ -196,11 +194,7 @@ class service_show(crud.Get): dn = ldap.find_entry_dn("krbprincipalname", principal) # FIXME: should kw contain the list of attributes to display? return ldap.retrieve(dn) - def output_for_cli(self, service): - if not service: - return - - for a in service.keys(): - print "%s: %s" % (a, service[a]) + def output_for_cli(self, textui, result, *args, **options): + textui.print_entry(result) api.register(service_show) -- cgit From 46bd3974af5ce312cb1dd3ca12e6184d78dc470e Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Wed, 10 Dec 2008 16:45:07 -0500 Subject: Don't pass along the kw dictionary we were passed by XML-RPC. We generally want to just search indexed attributes. We get this list of attributes from the configuration, use it. --- ipalib/plugins/f_service.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'ipalib/plugins/f_service.py') diff --git a/ipalib/plugins/f_service.py b/ipalib/plugins/f_service.py index fc0ae65e..a353d52e 100644 --- a/ipalib/plugins/f_service.py +++ b/ipalib/plugins/f_service.py @@ -149,14 +149,15 @@ class service_find(crud.Find): def execute(self, principal, **kw): ldap = self.api.Backend.ldap - kw['filter'] = "&(objectclass=krbPrincipalAux)(!(objectClass=posixAccount))(!(|(krbprincipalname=kadmin/*)(krbprincipalname=K/M@*)(krbprincipalname=krbtgt/*)))" - kw['krbprincipalname'] = principal + search_kw = {} + search_kw['filter'] = "&(objectclass=krbPrincipalAux)(!(objectClass=posixAccount))(!(|(krbprincipalname=kadmin/*)(krbprincipalname=K/M@*)(krbprincipalname=krbtgt/*)))" + search_kw['krbprincipalname'] = principal object_type = ldap.get_object_type("krbprincipalname") if object_type and not kw.get('objectclass'): - kw['objectclass'] = object_type + search_kw['objectclass'] = object_type - return ldap.search(**kw) + return ldap.search(**search_kw) def output_for_cli(self, textui, result, *args, **options): counter = result[0] -- cgit From a10144be247d109e0bcfb4d5b7812bef508ab8d6 Mon Sep 17 00:00:00 2001 From: Jason Gerard DeRose Date: Wed, 14 Jan 2009 22:35:13 -0700 Subject: Updated service plugins module to where it can at least be imported --- ipalib/plugins/f_service.py | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'ipalib/plugins/f_service.py') diff --git a/ipalib/plugins/f_service.py b/ipalib/plugins/f_service.py index a353d52e..06d6a5d0 100644 --- a/ipalib/plugins/f_service.py +++ b/ipalib/plugins/f_service.py @@ -22,27 +22,30 @@ Frontend plugins for service (Identity). """ -from ipalib import frontend -from ipalib import crud -from ipalib.frontend import Param -from ipalib import api -from ipalib import errors -from ipalib import ipa_types - -class service(frontend.Object): +from ipalib import api, crud, errors +from ipalib import Object # Plugin base classes +from ipalib import Str, Flag # Parameter types + + +class service(Object): """ Service object. """ takes_params = ( - Param('principal', primary_key=True), + Str('principal', primary_key=True), ) api.register(service) class service_add(crud.Add): - 'Add a new service.' + """ + Add a new service. + """ + takes_options = ( - Param('force?', type=ipa_types.Bool(), default=False, doc='Force a service principal name'), + Flag('force', + doc='Force a service principal name', + ), ) def execute(self, principal, **kw): """ -- cgit