- IdentityXmlRpcApi
- ok()
- authenticate(agent, response=None)
- enableAccount(token, account, services=None, data=dict())
- disableAccount(token, account, services=None)
- updateAccount(token, account, data)
- getAccountInformation(token, account, services, attrib='uid')
- getAccountStatus(token, account)
- getServices(token)
- getServiceMap(token)
- getConnectors(token)
- getConnectorsStatus(token)
- getResponseById(token, myId)
- provisionRequest
ok()
This method is used to see if the XML-RPC server is up and running. This method is preferred to other methods of creating dummy requests because it is designed to not create any logs on the server. If the 'ok' ping is frequent (~1 minute) then relevant log lines are lost in a see of dummy requests.
This method does not require authentication.
History
For a yet undetermined reason 'network events' corrupt the input/output buffers of the XML-RPC server and cause any XML-RPC request to fail with an IOError exception as well as crashing the
identity service.
Arguments
None
Return
Returns string 'OK'
authenticate(agent, response=None)
This method allows an agent to gain a session token to access and manipulate data in the provision systems. The authentication mechanism is a challenge/response MD5 hash. The advantage of this method is that the password is never transmitted between the client and server. The client first requests a challenge by calling authenticate with the clients agent name is the only argument. The server will return a response which is then digested with the clients password and the resultant hash is sent back to the server via the authenticate method; this time with the agent name and response as arguments.
An Example Python Client would look like this:
#hashlib is newer and preferred, md5 should be present for fallback
try:
from hashlib import md5Hash
except ImportError:
from md5 import new as md5Hash
challenge = s.authenticate(agent)
#challenge looks like:
# ['challenge', 'gGu$=_peL%u>78HF']
password = 'mySuperSecretPassword'
m = md5Hash()
m.update(password)
m.update(challenge[1])
r = m.digest()
binMd5 = xmlrpclib.Binary(r)
token = s.authenticate( agent, binMd5)
#token looks like:
# ['token', 'xv(eIMn$EC4fr$PB']
#
Arguments
Challenge Request:
- agent - string; Name of the agent to authenticate as
Authentication Attempt:
- agent - string; Name of the agent to authenticate as
- response - binary string; response hash
Return
authenticate always returns a two value tuple in the form ( 'message', 'value')
Challenge Request:
- message - string; 'challenge'
- value - string; the challenge string
Authentication Attempt:
- message - string; 'token'
- value - string; agent session token
Errors
If an error occurred, either internal or due to an invalid authentication attempt, an error tuple is returned. Errors always return a
value of 0.
- Internal Error - An unhandled exception or other unrecoverable error occurred and the requested data can't be processed. This error also occurs of the agent does not exist on the server
- Invalid Challenge - agent's challenge is invalid likely due to waiting too long between requesting a challenge and sending the response (default challenge TTL is 10 seconds)
- Invalid Response - Failed authentication attempt likely due to the wrong password used in the response hash
enableAccount(token, account, services=None, data=dict())
This method allows the client to enable services for a user. The one or more services can be enabled in a single request and additional information can be passed in. For example the ShellConnector needs to know the users full name (the gecos field in /etc/passwd) so the required information is passed to the ShellConnector via the data field.
An Example Python Client would look like this:
>>> #enable the shell account and zimbra email service for 'cpepe'
>>> s.enableAccount(token[1], 'cpepe', ('shell', 'zimbra'), {'ShellConnector':{'full_name':'Christopher Pepe'}})
{'ShellConnector': {'status': 'success', 'info': 'ShellConnector: Successfully enabled account for cpepe [PSR 1223916374.39]', 'request':
'{\'uid\': \'cpepe\', \'services\': "[\'shell\', \'zimbra\']", \'allow\': \'True\', \'action\': \'provisioning\', \'data\': "{\'ShellConnector\':
{\'full_name\': \'Christopher Pepe\'}}", \'id\': \'1223916374.39\'}', 'id': '1223916374.39', 'modDate': '2008-10-13 12:46:14'}, 'ZimbraConnector':
{'status': 'success', 'info': 'ZimbraConnector: Successfully enabled account for cpepe [PSR 1223916374.39]', 'request': '{\'uid\': \'cpepe\',
\'services\': "[\'shell\', \'zimbra\']", \'allow\': \'True\', \'action\': \'provisioning\', \'data\': "{\'ShellConnector\': {\'full_name\':
\'Christopher Pepe\'}}", \'id\': \'1223916374.39\'}', 'id': '1223916374.39', 'modDate': '2008-10-13 12:46:16'}}
disableAccount(token, account, services=None)
This method allows the client to disable services for a user. The one or more services can be disabled in a single request and additional information can be passed in. The 'data' argument is not currently used by any connector but is included for unforeseen future uses.
>>> #disable the shell account and zimbra email service for 'cpepe'
>>> s.disableAccount(token[1], 'cpepe', ('shell', 'zimbra'))
{'ShellConnector': {'status': 'success', 'info': 'ShellConnector: Successfully disabled account for cpepe [PSR 1223916887.89]', 'request':
'{\'uid\': \'cpepe\', \'services\': "[\'shell\', \'zimbra\']", \'allow\': \'False\', \'action\': \'provisioning\', \'data\': \'{}\', \'id\':
\'1223916887.89\'}', 'id': '1223916887.89', 'modDate': '2008-10-13 12:54:47'}, 'ZimbraConnector': {'status': 'success', 'info': 'ZimbraConnector:
Successfully disabled account for cpepe [PSR 1223916887.89]', 'request': '{\'uid\': \'cpepe\', \'services\': "[\'shell\', \'zimbra\']",
\'allow\': \'False\', \'action\': \'provisioning\', \'data\': \'{}\', \'id\': \'1223916887.89\'}', 'id': '1223916887.89', 'modDate': '2008-10-13
12:54:50'}}
updateAccount(token, account, data)
This method is used to modify the information associated with a users account in the provision systems. The specific fields to update are passed in via the data field and are provision system specific. Each provision system determines which field it supports and handles parsing the data passed to it via
updateAccount.
An Example Python Client would look like this:
uid = 'cpepe'
tc = dict()
tc['uid'] = 'bob' #NOTE: in a real system you can't change the uid!
tc['random'] = 42
my_data = { 'TestConnector': tc }
worked = s.updateAccount(token[1], 'cpepe', my_data)
print worked
""" worked =
{'TestConnector': {'status': 'success', 'info': 'TestConnector: Successfully updated account for cpepe [PSR 1219688414.97]',
'request': '{\'uid\': \'cpepe\', \'service\': \'update\', \'allow\': \'True\', \'action\': \'update\', \'data\':
"{\'TestConnector\': {\'active\': \'NA\', \'random\': 42, \'uid\': \'bob\'}}", \'id\': \'1219688414.97\'}',
'id': '1219688414.97', 'modDate': '2008-08-25 14:20:15'}}
"""
Arguments
- token - string; the clients session token assigned by authenticate
- account - string; the account identifier specifying which account to update (currently uid only)
- data - dictionary or equivalent; Contains the connector name as the key and a dictionary (or equivalent) of fields and new values for each provision system to be updated
Return
- TBD; currently returns the full result including status, info message, original request, request id, request timestamp
getAccountInformation(token, account, services, attrib='uid')
This method allows the client to gather the existing attributes for a user. Only systems requested by the
services field respond and there is currently no method to ask for all systems information except by specifying all systems in the
data field (See getServices below). This is an easy way to see which fields are supported by each provision system as well as gather all information stored in provision systems for a user.
Note - Systems can have
hidden writable attributes or read-only attributes (depending on how the connector is written). In general the client should know what can and cannot be manipulated without introspection.
An Example Python Client would look like this:
uid = 'cpepe'
services = ('test', 'zimbra', 'shell')
worked = s.getAccountInformation( token[1], uid, services )
print worked
""" worked =
{'TestConnector': {'status': 'success', 'info': {'active': 'NA', 'random': 78, 'uid': 'cpepe'}, 'request': '{\'uid\':
\'cpepe\', \'service\': \'info\', \'allow\': True, \'action\': \'info\', \'data\': "{\'TestConnector\': \'TestConnector\',
\'ZimbraConnector\': \'ZimbraConnector\', \'ShellConnector\': \'ShellConnector\'}", \'id\': \'1219689029.38\'}', 'id':
'1219689029.38', 'modDate': '2008-08-25 14:30:29'}, 'ZimbraConnector': {'status': 'success', 'info': {'cpepe':
{'givenName': 'Christopher', 'sn': 'Pepe', 'uid': 'cpepe'}}, 'request': '{\'uid\': \'cpepe\', \'service\': \'info\',
\'allow\': True, \'action\': \'info\', \'data\': "{\'TestConnector\': \'TestConnector\', \'ZimbraConnector\':
\'ZimbraConnector\', \'ShellConnector\': \'ShellConnector\'}", \'id\': \'1219689029.38\'}', 'id': '1219689029.38',
'modDate': '2008-08-25 14:30:31'}, 'ShellConnector': 'None'}
"""
Arguments
- token - string; the clients session token assigned by authenticate
- account - string; the account identifier specifying which account to update (currently uid only)
- services - list, tuple or equivalent; Contains the services from which toe request information
Return
- A dictionary of dictionaries is returned with the format { connectorName: { field1: value1, field2: value2, fieldN: valueN } }
- All fields are strings
getAccountStatus(token, account)

This method only supports zimbra directly and is not fully implemented. Do Not use this method unless the ZimbraConnector is installed and properly functioning!
This method returns the users status in each provisioning system. Statuses are TBD but likely will be 'active', 'inactive', 'disabled', 'no_account'.
An Example Python Client would look like this:
print s.getAccountStatus(token[1], 'cpepe')
#{'ZimbraConnector': 'active'}
Arguments
- token - string; the clients session token assigned by authenticate
- account - string; the account identifier specifying which account to update (currently uid only)
Return
- Returns a dictionary with keys of the provision system and values of the account status in said provision system
getServices(token)
This method returns a tuple of the services that are currently registered with the provision manager. A service can be supported by a single provision system or by many provision systems depending on what makes sense for the given service.
An Example Python Client would look like this:
print s.getServices( token[1] )
#['test', 'shell', 'zimbra']
Arguments
- token - string; the clients session token assigned by authenticate
Return
* tuple of strings; the names of the services registered with the provision manager
getServiceMap(token)
This method returns a dictionary of Connector names as keys and tuples of the services provided by said system. A service can be supported by a single provision system or by many provision systems depending on what makes sense for the given service. This method allows the client to inspect how the service is managed internally.
An Example Python Client would look like this:
print s.getServiceMap( token[1] )
#{'AdConnector': ['ad'], 'ZimbraConnector': ['zimbra', 'email'], 'WmdConnector': ['wmd']}
Arguments
- token - string; the clients session token assigned by authenticate
Return
* dictionary of connector name strings and tuple of strings; the connectors and services registered with the provision manager
getConnectors(token)
This method returns a tuple of the provision systems that are currently registered with the provision manager.
An Example Python Client would look like this:
conns = s.getConnectors( token[1] )
conns = dict( zip( conns, conns ) )
#{'TestConnector': 'TestConnector', 'ZimbraConnector': 'ZimbraConnector', 'ShellConnector': 'ShellConnector'}
Arguments
- token - string; the clients session token assigned by authenticate
Return
* dictionary of strings; the names of the provision systems registered with the provision manager
getConnectorsStatus(token)
This method returns a dictionary of { system name: system status } reflecting the current state of each system
getResponseById(token, myId)
This method is used to lookup the result of a provision request such as account enable/disable, or account update. It can be used to retrieve the result of any request by the request id. Every method returns the request id so the client can use it later if needed.
An Example Python Client would look like this:
info = s.getResponseById('1219690702.94')
"""
'TestConnector': {'status': 'success', 'info': {'active': 'NA', 'random': 38, 'uid': 'cpepe'}, 'request':
'{\'uid\': \'cpepe\', \'service\': \'info\', \'allow\': True, \'action\': \'info\', \'data\':
"{\'TestConnector\': 1}", \'id\': \'1219690702.94\'}', 'id': '1219690702.94', 'modDate': '2008-08-25 14:58:22'}}
"""
Arguments
- token - string; the clients session token assigned by authenticate
- myId - string; the request id of interest
Return
- TBD - TBD; currently returns the full result including status, info message, original request, request id, request timestamp
provisionRequest

This method is deprecated in the XML-RPC interface.
This method allows a provision system request [PSR] to be directly passed to the provision manager. As the service has grown various fields have become unecessary depending on the specific request type making it difficult to understand and use. It is not recommended that new clients use this method.
Arguments
- tuple; A provision system request
Return
- string; The provision request id assigned by the server