summaryrefslogtreecommitdiffstats
path: root/ipa-server/xmlrpc-server
diff options
context:
space:
mode:
authorrcritten@redhat.com <rcritten@redhat.com>2007-08-06 10:05:53 -0400
committerrcritten@redhat.com <rcritten@redhat.com>2007-08-06 10:05:53 -0400
commit993f76fe6035cf59cceb88f3611fc53680738007 (patch)
tree17bb5afed002709bd322f5fe7e99e473adc1d018 /ipa-server/xmlrpc-server
parent66ab69d0b23da46b21dbb4bf165011f318ec2da8 (diff)
downloadfreeipa-993f76fe6035cf59cceb88f3611fc53680738007.tar.gz
freeipa-993f76fe6035cf59cceb88f3611fc53680738007.tar.xz
freeipa-993f76fe6035cf59cceb88f3611fc53680738007.zip
- Abstracted client class to work directly or over RPC
- Add mod_auth_kerb and cyrus-sasl-gssapi to Requires - Remove references to admin server in ipa-server-setupssl - Generate a client certificate for the XML-RPC server to connect to LDAP with - Create a keytab for Apache - Create an ldif with a test user - Provide a certmap.conf for doing SSL client authentication - Update tools to use kerberos - Add User class
Diffstat (limited to 'ipa-server/xmlrpc-server')
-rw-r--r--ipa-server/xmlrpc-server/funcs.py339
-rw-r--r--ipa-server/xmlrpc-server/ipa.conf18
-rw-r--r--ipa-server/xmlrpc-server/ipaxmlrpc.py17
3 files changed, 217 insertions, 157 deletions
diff --git a/ipa-server/xmlrpc-server/funcs.py b/ipa-server/xmlrpc-server/funcs.py
index be95d4fab..9545ad892 100644
--- a/ipa-server/xmlrpc-server/funcs.py
+++ b/ipa-server/xmlrpc-server/funcs.py
@@ -24,152 +24,205 @@ import ldap
import ipaserver.dsinstance
import ipaserver.ipaldap
import ipaserver.util
-import pdb
import string
from types import *
import xmlrpclib
import ipa.config
-# FIXME, this needs to be auto-discovered
-host = 'localhost'
-port = 389
-binddn = "cn=directory manager"
-bindpw = "freeipa"
-
-ipa.config.init_config()
-basedn = ipaserver.util.realm_to_suffix(ipa.config.config.get_realm())
-import sys
-sys.stderr.write(basedn)
-scope = ldap.SCOPE_SUBTREE
-
-def get_user (username):
- """Get a specific user's entry. Return as a dict of values.
- Multi-valued fields are represented as lists.
- """
- ent=""
-
- # FIXME: Is this the filter we want or should it be more specific?
- filter = "(uid=" + username + ")"
- try:
- m1 = ipaserver.ipaldap.IPAdmin(host,port,binddn,bindpw)
- ent = m1.getEntry(basedn, scope, filter, None)
- except ldap.LDAPError, e:
- raise xmlrpclib.Fault(1, e)
- except ipaserver.ipaldap.NoSuchEntryError:
- raise xmlrpclib.Fault(2, "No such user")
-
- # Convert to LDIF
- entry = str(ent)
-
- # Strip off any junk
- entry = entry.strip()
-
- # Don't need to identify binary fields and this breaks the parser so
- # remove double colons
- entry = entry.replace('::', ':')
- specs = [spec.split(':') for spec in entry.split('\n')]
-
- # Convert into a dict. We need to handle multi-valued attributes as well
- # so we'll convert those into lists.
- user={}
- for (k,v) in specs:
- k = k.lower()
- if user.get(k) is not None:
- if isinstance(user[k],list):
- user[k].append(v.strip())
+class IPAServer:
+
+ def __init__(self):
+ # FIXME, this needs to be auto-discovered
+ self.host = 'localhost'
+ self.port = 636
+ self.bindcert = "/usr/share/ipa/cert.pem"
+ self.bindkey = "/usr/share/ipa/key.pem"
+ self.bindca = "/usr/share/ipa/cacert.asc"
+
+ ipa.config.init_config()
+ self.basedn = ipaserver.util.realm_to_suffix(ipa.config.config.get_realm())
+ self.scope = ldap.SCOPE_SUBTREE
+ self.princ = None
+
+ def set_principal(self, princ):
+ self.princ = princ
+
+ def get_dn_from_principal(self, princ):
+ """Given a kerberls principal get the LDAP uid"""
+ filter = "(krbPrincipalName=" + princ + ")"
+ try:
+ m1 = ipaserver.ipaldap.IPAdmin(self.host,self.port,self.bindca,self.bindcert,self.bindkey)
+ ent = m1.getEntry(self.basedn, self.scope, filter, None)
+ except ldap.LDAPError, e:
+ raise xmlrpclib.Fault(1, e)
+ except ipaserver.ipaldap.NoSuchEntryError:
+ raise xmlrpclib.Fault(2, "No such user")
+
+ return "dn:" + ent.dn
+
+ def convert_entry(self, ent):
+
+ # Convert to LDIF
+ entry = str(ent)
+
+ # Strip off any junk
+ entry = entry.strip()
+
+ # Don't need to identify binary fields and this breaks the parser so
+ # remove double colons
+ entry = entry.replace('::', ':')
+ specs = [spec.split(':') for spec in entry.split('\n')]
+
+ # Convert into a dict. We need to handle multi-valued attributes as well
+ # so we'll convert those into lists.
+ user={}
+ for (k,v) in specs:
+ k = k.lower()
+ if user.get(k) is not None:
+ if isinstance(user[k],list):
+ user[k].append(v.strip())
+ else:
+ first = user[k]
+ user[k] = []
+ user[k].append(first)
+ user[k].append(v.strip())
else:
- first = user[k]
- user[k] = []
- user[k].append(first)
- user[k].append(v.strip())
- else:
- user[k] = v.strip()
-
- return user
-# return str(ent) # return as LDIF
-
-def add_user (user):
- """Add a user in LDAP"""
- dn="uid=%s,ou=users,ou=default,%s" % (user['uid'], basedn)
- entry = ipaserver.ipaldap.Entry(dn)
-
- # some required objectclasses
- entry.setValues('objectClass', 'top', 'posixAccount', 'shadowAccount', 'account', 'person', 'inetOrgPerson', 'organizationalPerson', 'krbPrincipalAux', 'krbTicketPolicyAux')
-
- # Fill in shadow fields
- entry.setValue('shadowMin', '0')
- entry.setValue('shadowMax', '99999')
- entry.setValue('shadowWarning', '7')
- entry.setValue('shadowExpire', '-1')
- entry.setValue('shadowInactive', '-1')
- entry.setValue('shadowFlag', '-1')
-
- # FIXME: calculate shadowLastChange
-
- # fill in our new entry with everything sent by the user
- for u in user:
- entry.setValues(u, user[u])
-
- try:
- m1 = ipaserver.ipaldap.IPAdmin(host,port,binddn,bindpw)
- res = m1.addEntry(entry)
- return res
- except ldap.ALREADY_EXISTS:
- raise xmlrpclib.Fault(3, "User already exists")
- return None
- except ldap.LDAPError, e:
- raise xmlrpclib.Fault(1, str(e))
- return None
-
-def get_add_schema ():
- """Get the list of fields to be used when adding users in the GUI."""
-
- # FIXME: this needs to be pulled from LDAP
- fields = []
-
- field1 = {
- "name": "uid" ,
- "label": "Login:",
- "type": "text",
- "validator": "text",
- "required": "true"
- }
- fields.append(field1)
-
- field1 = {
- "name": "userPassword" ,
- "label": "Password:",
- "type": "password",
- "validator": "String",
- "required": "true"
- }
- fields.append(field1)
-
- field1 = {
- "name": "givenName" ,
- "label": "First name:",
- "type": "text",
- "validator": "string",
- "required": "true"
- }
- fields.append(field1)
-
- field1 = {
- "name": "sn" ,
- "label": "Last name:",
- "type": "text",
- "validator": "string",
- "required": "true"
- }
- fields.append(field1)
-
- field1 = {
- "name": "mail" ,
- "label": "E-mail address:",
- "type": "text",
- "validator": "email",
- "required": "true"
- }
- fields.append(field1)
-
- return fields
+ user[k] = v.strip()
+
+ return user
+
+ def get_user (self, username, opts=None):
+ """Get a specific user's entry. Return as a dict of values.
+ Multi-valued fields are represented as lists.
+ """
+ ent=""
+ if opts:
+ self.set_principal(opts['remoteuser'])
+ if (isinstance(username, tuple)):
+ username = username[0]
+
+ try:
+ dn = self.get_dn_from_principal(self.princ)
+ except ldap.LDAPError, e:
+ raise xmlrpclib.Fault(1, e)
+ except ipaserver.ipaldap.NoSuchEntryError:
+ raise xmlrpclib.Fault(2, "No such user")
+
+ filter = "(uid=" + username + ")"
+ try:
+ m1 = ipaserver.ipaldap.IPAdmin(self.host,self.port,self.bindca,self.bindcert,self.bindkey,dn)
+ ent = m1.getEntry(self.basedn, self.scope, filter, None)
+ except ldap.LDAPError, e:
+ raise xmlrpclib.Fault(1, e)
+ except ipaserver.ipaldap.NoSuchEntryError:
+ raise xmlrpclib.Fault(2, "No such user")
+
+ return self.convert_entry(ent)
+
+ def add_user (self, user, opts=None):
+ """Add a user in LDAP"""
+ if (isinstance(user, tuple)):
+ user = user[0]
+ dn="uid=%s,ou=users,ou=default,%s" % (user['uid'], self.basedn)
+ entry = ipaserver.ipaldap.Entry(str(dn))
+
+ # some required objectclasses
+ entry.setValues('objectClass', 'top', 'posixAccount', 'shadowAccount', 'account', 'person', 'inetOrgPerson', 'organizationalPerson', 'krbPrincipalAux', 'krbTicketPolicyAux')
+
+ # Fill in shadow fields
+ entry.setValue('shadowMin', '0')
+ entry.setValue('shadowMax', '99999')
+ entry.setValue('shadowWarning', '7')
+ entry.setValue('shadowExpire', '-1')
+ entry.setValue('shadowInactive', '-1')
+ entry.setValue('shadowFlag', '-1')
+
+ # FIXME: calculate shadowLastChange
+
+ # fill in our new entry with everything sent by the user
+ for u in user:
+ entry.setValues(str(u), str(user[u]))
+
+ if opts:
+ self.set_principal(opts['remoteuser'])
+
+ try:
+ dn = self.get_dn_from_principal(self.princ)
+ except ldap.LDAPError, e:
+ raise xmlrpclib.Fault(1, e)
+ except ipaserver.ipaldap.NoSuchEntryError:
+ raise xmlrpclib.Fault(2, "No such user")
+
+ try:
+ m1 = ipaserver.ipaldap.IPAdmin(self.host,self.port,self.bindca,self.bindcert,self.bindkey,dn)
+ res = m1.addEntry(entry)
+ return res
+ except ldap.ALREADY_EXISTS:
+ raise xmlrpclib.Fault(3, "User already exists")
+ except ldap.LDAPError, e:
+ raise xmlrpclib.Fault(1, str(e))
+
+ def get_add_schema (self):
+ """Get the list of fields to be used when adding users in the GUI."""
+
+ # FIXME: this needs to be pulled from LDAP
+ fields = []
+
+ field1 = {
+ "name": "uid" ,
+ "label": "Login:",
+ "type": "text",
+ "validator": "text",
+ "required": "true"
+ }
+ fields.append(field1)
+
+ field1 = {
+ "name": "givenName" ,
+ "label": "First name:",
+ "type": "text",
+ "validator": "string",
+ "required": "true"
+ }
+ fields.append(field1)
+
+ field1 = {
+ "name": "sn" ,
+ "label": "Last name:",
+ "type": "text",
+ "validator": "string",
+ "required": "true"
+ }
+ fields.append(field1)
+
+ field1 = {
+ "name": "mail" ,
+ "label": "E-mail address:",
+ "type": "text",
+ "validator": "email",
+ "required": "true"
+ }
+ fields.append(field1)
+
+ return fields
+
+ def get_all_users (self):
+ """Return a list containing a User object for each
+ existing user.
+ """
+
+ # FIXME: Is this the filter we want or should it be more specific?
+ filter = "(objectclass=posixAccount)"
+ try:
+ m1 = ipaserver.ipaldap.IPAdmin(self.host,self.port,self.bindca,self.bindcert,self.bindkey)
+ all_users = m1.getList(self.basedn, self.scope, filter, None)
+ except ldap.LDAPError, e:
+ raise xmlrpclib.Fault(1, e)
+ except ipaserver.ipaldap.NoSuchEntryError:
+ raise xmlrpclib.Fault(2, "No such user")
+
+ users = []
+ for u in all_users:
+ users.append(self.convert_entry(u))
+
+ return users
diff --git a/ipa-server/xmlrpc-server/ipa.conf b/ipa-server/xmlrpc-server/ipa.conf
index 1880268cf..dbe6b99fd 100644
--- a/ipa-server/xmlrpc-server/ipa.conf
+++ b/ipa-server/xmlrpc-server/ipa.conf
@@ -3,15 +3,15 @@
Alias /ipa "/usr/share/ipa/ipaserver/XMLRPC"
<Directory "/usr/share/ipa/ipaserver">
-# AuthType Kerberos
-# AuthName "Kerberos Login"
-# KrbMethodNegotiate on
-# KrbMethodK5Passwd off
-# KrbServiceName HTTP
-# KrbAuthRealms GREYOAK.COM
-# Krb5KeyTab /etc/httpd/conf/ipa.keytab
-# KrbSaveCredentials on
-# Require valid-user
+ AuthType Kerberos
+ AuthName "Kerberos Login"
+ KrbMethodNegotiate on
+ KrbMethodK5Passwd off
+ KrbServiceName HTTP
+ KrbAuthRealms GREYOAK.COM
+ Krb5KeyTab /etc/httpd/conf/ipa.keytab
+ KrbSaveCredentials on
+ Require valid-user
ErrorDocument 401 /errors/unauthorized.html
SetHandler mod_python
diff --git a/ipa-server/xmlrpc-server/ipaxmlrpc.py b/ipa-server/xmlrpc-server/ipaxmlrpc.py
index ad5e30683..7bad9ab5e 100644
--- a/ipa-server/xmlrpc-server/ipaxmlrpc.py
+++ b/ipa-server/xmlrpc-server/ipaxmlrpc.py
@@ -123,11 +123,16 @@ class ModXMLRPCRequestHandler(object):
def register_instance(self,instance):
self.register_module(instance)
- def _marshaled_dispatch(self, data):
+ def _marshaled_dispatch(self, data, remoteuser):
"""Dispatches an XML-RPC method from marshalled (XML) data."""
params, method = loads(data)
+ opts={}
+ opts['remoteuser'] = remoteuser
+
+ params = ipaserver.encode_args(params, opts)
+
# special case
# if method == "get_user":
# Marshaller._Marshaller__dump = xmlrpclib_dump
@@ -239,7 +244,7 @@ class ModXMLRPCRequestHandler(object):
req.allow_methods(['POST'],1)
raise apache.SERVER_RETURN, apache.HTTP_METHOD_NOT_ALLOWED
- response = self._marshaled_dispatch(req.read())
+ response = self._marshaled_dispatch(req.read(), req.user)
req.content_type = "text/xml"
req.set_content_length(len(response))
@@ -267,10 +272,12 @@ def handler(req, profiling=False):
else:
opts = req.get_options()
try:
+ f = funcs.IPAServer()
h = ModXMLRPCRequestHandler()
- h.register_function(funcs.get_user)
- h.register_function(funcs.add_user)
- h.register_function(funcs.get_add_schema)
+ h.register_function(f.get_user)
+ h.register_function(f.add_user)
+ h.register_function(f.get_add_schema)
+ h.register_function(f.get_all_users)
h.handle_request(req)
finally:
pass