diff --git a/ipa-python/ipaclient.py b/ipa-python/ipaclient.py
index c5377f3af..c05abd510 100644
--- a/ipa-python/ipaclient.py
+++ b/ipa-python/ipaclient.py
@@ -386,6 +386,9 @@ class IPAClient:
def add_service_principal(self, princ_name):
return self.transport.add_service_principal(princ_name)
+ def delete_service_principal(self, principal_dn):
+ return self.transport.delete_service_principal(principal_dn)
+
def find_service_principal(self, criteria, sattrs=None, searchlimit=0, timelimit=-1):
"""Return a list: counter followed by a Entity object for each host that
matches the criteria. If the results are truncated, counter will
diff --git a/ipa-python/rpcclient.py b/ipa-python/rpcclient.py
index 32249fd3c..4d6b3a701 100644
--- a/ipa-python/rpcclient.py
+++ b/ipa-python/rpcclient.py
@@ -699,6 +699,18 @@ class RPCClient:
return ipautil.unwrap_binary_data(result)
+ def delete_service_principal(self, principal_dn):
+ server = self.setup_server()
+
+ try:
+ result = server.delete_service_principal(principal_dn)
+ except xmlrpclib.Fault, fault:
+ raise ipaerror.gen_exception(fault.faultCode, fault.faultString)
+ except socket.error, (value, msg):
+ raise xmlrpclib.Fault(value, msg)
+
+ return ipautil.unwrap_binary_data(result)
+
def find_service_principal (self, criteria, sattrs=None, searchlimit=0, timelimit=-1):
"""Return a list: counter followed by a Entity object for each host that
matches the criteria. If the results are truncated, counter will
diff --git a/ipa-server/ipa-gui/ipagui/subcontrollers/principal.py b/ipa-server/ipa-gui/ipagui/subcontrollers/principal.py
index 27c4f9d63..47deb8879 100644
--- a/ipa-server/ipa-gui/ipagui/subcontrollers/principal.py
+++ b/ipa-server/ipa-gui/ipagui/subcontrollers/principal.py
@@ -125,6 +125,51 @@ class PrincipalController(IPAController):
return dict(principals=principals, hostname=hostname, fields=ipagui.forms.principal.PrincipalFields())
+ @expose("ipagui.templates.principalshow")
+ @identity.require(identity.not_anonymous())
+ def show(self, **kw):
+ """Display a single service principal"""
+
+ try:
+ princ = kw['principal']
+ princ_dn = kw['principal_dn']
+ except KeyError, e:
+ turbogears.flash("Principal show failed. Unable to find key %s" % e)
+ raise turbogears.redirect("/principal/list")
+
+ principal = {}
+
+ try:
+ # The principal info is passed in. Not going to both to re-query this.
+ (service,host) = princ.split('/')
+ h = host.split('@')
+ principal['service'] = service
+ principal['hostname'] = h[0]
+ principal['principal_dn'] = princ_dn
+
+ return dict(principal=principal)
+ except:
+ turbogears.flash("Principal show failed %s" % princ)
+ raise turbogears.redirect("/")
+
+ @expose()
+ @identity.require(identity.in_group("admins"))
+ def delete(self, principal):
+ """Delete a service principal"""
+ self.restrict_post()
+ client = self.get_ipaclient()
+
+ print "Deleting %s" % principal
+
+ try:
+ client.delete_service_principal(principal)
+
+ turbogears.flash("Service principal deleted")
+ raise turbogears.redirect('/principal/list')
+ except (SyntaxError, ipaerror.IPAError), e:
+ turbogears.flash("Service principal deletion failed: " + str(e) + "
" + e.detail[0]['desc'])
+ raise turbogears.redirect('/principal/list')
+
@validate(form=principal_new_form)
@identity.require(identity.not_anonymous())
def principalcreatevalidate(self, tg_errors=None, **kw):
diff --git a/ipa-server/ipa-gui/ipagui/templates/principallist.kid b/ipa-server/ipa-gui/ipagui/templates/principallist.kid
index ae8bdda46..8da9c15e3 100644
--- a/ipa-server/ipa-gui/ipagui/templates/principallist.kid
+++ b/ipa-server/ipa-gui/ipagui/templates/principallist.kid
@@ -33,10 +33,12 @@