def communicate(comm, token, request_type, request_args): '''Send a request to Zimbra SOAP API and return response''' request = RequestXml() request.set_auth_token(token) request.add_request(request_type, request_args, u'urn:zimbraMail') response = ResponseXml() comm.send_request(request, response) return response
def request(self, name, data, urn): comm = Communication(self.url) account_request = RequestXml() account_request.set_auth_token(self.getToken()) account_request.add_request(name, data, urn) account_response = ResponseXml() comm.send_request(account_request, account_response) return account_response.get_response()
def test_fault_non_existing_folder_batch_xml(self): """ Request a non existing folder multiple times to get multiple faults """ config = get_config() if config.getboolean('fault_test', 'enabled'): comm = Communication(config.get('fault_test', 'url')) token = auth.authenticate(config.get('fault_test', 'url'), config.get('fault_test', 'account'), config.get('fault_test', 'preauthkey'), config.get('fault_test', 'account_by')) request = RequestXml() request.set_auth_token(token) request.enable_batch() request.add_request( "GetFolderRequest", { "folder": { "path": config.get('fault_test', 'folder') } }, "urn:zimbraMail" ) request.add_request( "GetFolderRequest", { "folder": { "path": config.get('fault_test', 'folder') } }, "urn:zimbraMail" ) response = ResponseXml() comm.send_request(request, response) self.check_response( response )
def gen_request(self, request_type="json", token=None, set_batch=False, batch_onerror=None): """ Convenience method to quickly generate a token :param request_type: Type of request (defaults to json) :param token: Authentication token :param set_batch: Also set this request to batch mode? :param batch_onerror: Onerror-parameter for batch mode :return: The request """ if request_type == "json": local_request = RequestJson() elif request_type == "xml": local_request = RequestXml() else: raise UnknownRequestType() if token is not None: local_request.set_auth_token(token) if set_batch: local_request.enable_batch(batch_onerror) return local_request
def test_autoresponse_xml(self): """ Create an XML-request and pass this to send_request expection a xml response. """ config = get_config() if config.getboolean("autoresponse_test", "enabled"): # Run only if enabled token = authenticate( config.get("autoresponse_test", "url"), config.get("autoresponse_test", "account"), config.get("autoresponse_test", "preauthkey") ) self.assertNotEqual( token, None, "Cannot authenticate." ) request = RequestXml() request.set_auth_token(token) request.add_request( "NoOpRequest", { }, "urn:zimbraMail" ) comm = Communication(config.get("autoresponse_test", "url")) response = comm.send_request(request) if response.is_fault(): self.fail( "Reponse failed: (%s) %s" % ( response.get_fault_code(), response.get_fault_message() ) ) self.assertEqual( response.response_type, "xml", "Invalid response type %s" % response.response_type )
def request(self, request_name, params=None, context=None, urn=None, opts={}): """ Send a single request to Zimbra; return the response as native python data. """ if 'xml' in opts and opts['xml']: request, response = RequestXml(), ResponseXml() else: request, response = RequestJson(), ResponseJson() try: if urn == None: urn = urn_for_request(request_name) request.add_request(request_name, params or {}, "urn:"+urn) if context: request.set_context_params(context) request.set_auth_token(self.token) except: log.exception("failed to build request: request_name=%s, params=%s, context=%s", request_name, params, context) return None if opts['debug']: if isinstance(request, RequestXml): print xml.dom.minidom.parseString(request.get_request()).toprettyxml(indent=". ") else: pprint.pprint(yaml.load(request.get_request())) try: self.comm.send_request(request, response) except urllib2.HTTPError as e: requestbody = request.get_request() responsebody = e.read() log.error('''send_request HTTP Error %s: %s; request="%s" response="%s"''', e.code, e.reason, requestbody, responsebody) if isinstance(request, RequestXml): requestdoc = xml.dom.minidom.parseString(requestbody) print "REQUEST=", requestdoc.toprettyxml(indent=". ") else: print "REQUEST=\n", pprint.pformat(yaml.load(requestbody)) if isinstance(response, ResponseXml): responsedoc = xml.dom.minidom.parseString(responsebody) print "RESPONSE=", responsedoc.toprettyxml(indent=". ") else: print "RESPONSE=\n", pprint.pformat(yaml.load(responsebody)) return None except Exception as e: log.exception("send_request failed (%s): request=%s", type(e), request.get_request()) return None if response.is_fault(): log.error("send_request returned fault: request=%s, response=%s", request.get_request(), response.get_response()) return None info = response.get_response() return info
class TestRequestXml(TestCase): """ Request tests """ request = None """ The request to be tested against """ def cleanUp(self): """ Clean up after one step to leave a dedicated result for the other test cases. """ self.setUp() def setUp(self): self.request = RequestXml() def test_empty_request(self): """ Create an empty request and check the created xml """ expected_result = '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3' \ '.org/2003/05/soap-envelope"><soap:Header><context' \ ' xmlns="urn:zimbra"><format ' \ 'type="xml"/></context></soap:Header><soap:Body' \ '/></soap:Envelope>' self.assertEqual(expected_result, self.request.get_request()) def test_set_context_params_failtype(self): """ Add context parameters to the request and expect the method to send an exception """ self.assertRaises( RequestHeaderContextException, self.request.set_context_params, {'invalidParam': { 'invalidAttribute': 'invalidValue' }}) def test_set_context_params(self): """ Add all currently accepted params and check the result """ self.request.set_context_params({ 'authToken': { '_content': '1234567890abcdef' }, 'authTokenControl': { 'voidOnExpired': '1' }, 'session': { 'id': '1234567890abcdef', 'seq': '1234567890', 'type': 'admin' }, 'account': { 'by': 'name', '_content': '*****@*****.**' }, 'change': { 'token': '1234567890abcdef', 'type': 'new' }, 'targetServer': { '_content': 'mailboxserver.zimbra.com' }, 'userAgent': { 'name': 'Mozilla', 'version': '1.0' }, 'via': { '_content': 'proxyserver.zimbra.com' } }) expected_result = '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3' \ '.org/2003/05/soap-envelope"><soap:Header><context ' \ 'xmlns="urn:zimbra"><format ' \ 'type="xml"/><authToken>1234567890abcdef</authToken' \ '><account by="name">user@zimbra' \ '.com</account><session id="1234567890abcdef" ' \ 'seq="1234567890" type="admin"/><authTokenControl ' \ 'voidOnExpired="1"/><targetServer>mailboxserver' \ '.zimbra.com</targetServer><via>proxyserver.zimbra' \ '.com</via><userAgent name="Mozilla" version="1' \ '.0"/><change token="1234567890abcdef" ' \ 'type="new"/></context></soap:Header><soap:Body' \ '/></soap:Envelope>' self.assertEqual(expected_result, self.request.get_request()) # Clean up after this test self.cleanUp() def test_enable_batch_default(self): """ Test enabling batch requests """ # Check with default parameter self.request.enable_batch('urn:zimbra') expected_result = \ '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap' \ ':Header><context xmlns="urn:zimbra"><format ' \ 'type="xml"/></context></soap:Header><soap:Body><BatchRequest ' \ 'onerror="urn:zimbra" ' \ 'xmlns="urn:zimbra"/></soap:Body></soap:Envelope>' self.assertEqual(expected_result, self.request.get_request()) # Clean up self.cleanUp() def test_enable_batch_stop(self): """ Test enabling batch requests with additional parameter """ self.request.enable_batch('stop') expected_result = '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3' \ '.org/2003/05/soap-envelope"><soap:Header><context ' \ 'xmlns="urn:zimbra"><format ' \ 'type="xml"/></context></soap:Header><soap:Body' \ '><BatchRequest onerror="stop" ' \ 'xmlns="urn:zimbra"/></soap:Body></soap:Envelope>' self.assertEqual(expected_result, self.request.get_request()) # Clean up self.cleanUp() def test_batch_add_request(self): """ Test adding multiple request to a batch request """ self.request.enable_batch() request_id = self.request.add_request('GetInfoRequest', {'sections': 'mbox,prefs'}, 'urn:zimbra') self.assertIsInstance( request_id, int, msg="Returned request_id for request 1 is not of type int, " "but of type %s" % (type(request_id))) self.assertEqual( 1, request_id, msg="Returned request_id for request 1 is not 1, but %s" % (str(request_id))) expected_result = \ '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap' \ ':Header><context xmlns="urn:zimbra"><format ' \ 'type="xml"/></context></soap:Header><soap:Body><BatchRequest ' \ 'onerror="continue" xmlns="urn:zimbra"><GetInfoRequest ' \ 'requestId="1" sections="mbox,prefs" ' \ 'xmlns="urn:zimbra"/></BatchRequest></soap:Body></soap:Envelope>' self.assertEqual(expected_result, self.request.get_request()) request_id = self.request.add_request('GetInfoRequest', {'sections': 'zimlets'}, 'urn:zimbra') self.assertIsInstance( request_id, int, msg="Returned request_id for request 2 is not of type int, " "but of type %s" % (type(request_id))) self.assertEqual( 2, request_id, msg="Returned request_id for request 2 is not 2, but %s" % (str(request_id))) expected_result = \ '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap' \ ':Header><context xmlns="urn:zimbra"><format ' \ 'type="xml"/></context></soap:Header><soap:Body><BatchRequest ' \ 'onerror="continue" xmlns="urn:zimbra"><GetInfoRequest ' \ 'requestId="1" sections="mbox,prefs" ' \ 'xmlns="urn:zimbra"/><GetInfoRequest requestId="2" ' \ 'sections="zimlets" ' \ 'xmlns="urn:zimbra"/></BatchRequest></soap:Body></soap:Envelope>' self.assertEqual(expected_result, self.request.get_request()) # Clean up self.setUp() def test_add_request(self): """ Test adding a request """ request_id = self.request.add_request('GetInfoRequest', {'sections': 'mbox,prefs'}, 'urn:zimbra') self.assertIsNone(request_id, msg="Returned request_id for request 1 is not none, " "but %s" % (str(request_id))) expected_result = '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3' \ '.org/2003/05/soap-envelope"><soap:Header><context ' \ 'xmlns="urn:zimbra"><format ' \ 'type="xml"/></context></soap:Header><soap:Body' \ '><GetInfoRequest sections="mbox,' \ 'prefs" ' \ 'xmlns="urn:zimbra"/></soap:Body></soap:Envelope>' self.assertEqual(expected_result, self.request.get_request()) # Clean up self.setUp() def tearDown(self): self.request = None
def setUp(self): self.request = RequestXml()
def run_admin_test(self, request_type): """ Actually do the work """ config = get_config() if config.getboolean("admin_request_test", "enabled"): # Run only if enabled token = authenticate( config.get("admin_request_test", "url"), config.get("admin_request_test", "account"), config.get("admin_request_test", "password"), config.get("admin_request_test", "account_by"), admin_auth=True, request_type=request_type ) if token is None: self.fail("Authentication with the configured settings " "was not successful") # Create an account comm = Communication(config.get("admin_request_test", "url")) if request_type == "xml": request = RequestXml() else: request = RequestJson() request.set_auth_token(token) request.add_request( "CreateAccountRequest", { "name": config.get("admin_request_test", "test_account"), "password": config.get( "admin_request_test", "test_password" ) }, "urn:zimbraAdmin" ) if request_type == "xml": response = ResponseXml() else: response = ResponseJson() comm.send_request(request, response) if response.is_fault(): self.fail( "CreateAccount faulted. %s" % (response.get_response()) ) account_id = response.get_response( )["CreateAccountResponse"]["account"]["id"] # Try to log in as the new account user_token = authenticate( config.get("admin_request_test", "user_url"), config.get("admin_request_test", "test_account"), config.get("admin_request_test", "test_password"), "name", request_type=request_type, use_password=True ) if user_token is None: self.fail("Cannot log in as the test user.") # Remove account request.clean() response.clean() request.set_auth_token(token) request.add_request( "DeleteAccountRequest", { "id": account_id }, "urn:zimbraAdmin" ) comm.send_request(request, response) if response.is_fault(): self.fail( "Cannot remove test account. %s" % response.get_response() )
class TestRequestXml(TestCase): """ Request tests """ request = None """ The request to be tested against """ def cleanUp(self): """ Clean up after one step to leave a dedicated result for the other test cases. """ self.setUp() def setUp(self): self.request = RequestXml() def tool_assert_equal_xml(self, xml_a, xml_b, message=None): self.assertEqual( dom_to_dict(minidom.parseString(xml_a).firstChild), dom_to_dict(minidom.parseString(xml_b).firstChild), message ) def test_empty_request(self): """ Create an empty request and check the created xml """ expected_result = '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3' \ '.org/2003/05/soap-envelope"><soap:Header><context' \ ' xmlns="urn:zimbra"><format ' \ 'type="xml"/></context></soap:Header><soap:Body' \ '/></soap:Envelope>' self.tool_assert_equal_xml( expected_result, self.request.get_request() ) def test_set_context_params_failtype(self): """ Add context parameters to the request and expect the method to send an exception """ self.assertRaises( RequestHeaderContextException, self.request.set_context_params, { 'invalidParam': { 'invalidAttribute': 'invalidValue' } } ) def test_set_context_params(self): """ Add all currently accepted params and check the result """ self.request.set_context_params( { 'authToken': { '_content': '1234567890abcdef' }, 'authTokenControl': { 'voidOnExpired': '1' }, 'session': { 'id': '1234567890abcdef', 'seq': '1234567890', 'type': 'admin' }, 'account': { 'by': 'name', '_content': '*****@*****.**' }, 'change': { 'token': '1234567890abcdef', 'type': 'new' }, 'targetServer': { '_content': 'mailboxserver.zimbra.com' }, 'userAgent': { 'name': 'Mozilla', 'version': '1.0' }, 'via': { '_content': 'proxyserver.zimbra.com' } } ) expected_result = '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3' \ '.org/2003/05/soap-envelope"><soap:Header><context ' \ 'xmlns="urn:zimbra"><format ' \ 'type="xml"/><authToken>1234567890abcdef</authToken' \ '><account by="name">user@zimbra' \ '.com</account><session id="1234567890abcdef" ' \ 'seq="1234567890" type="admin"/><authTokenControl ' \ 'voidOnExpired="1"/><targetServer>mailboxserver' \ '.zimbra.com</targetServer><via>proxyserver.zimbra' \ '.com</via><userAgent name="Mozilla" version="1' \ '.0"/><change token="1234567890abcdef" ' \ 'type="new"/></context></soap:Header><soap:Body' \ '/></soap:Envelope>' self.tool_assert_equal_xml( expected_result, self.request.get_request() ) # Clean up after this test self.cleanUp() def test_enable_batch_default(self): """ Test enabling batch requests """ # Check with default parameter self.request.enable_batch('urn:zimbra') expected_result = \ '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap' \ ':Header><context xmlns="urn:zimbra"><format ' \ 'type="xml"/></context></soap:Header><soap:Body><BatchRequest ' \ 'onerror="urn:zimbra" ' \ 'xmlns="urn:zimbra"/></soap:Body></soap:Envelope>' self.tool_assert_equal_xml( expected_result, self.request.get_request() ) # Clean up self.cleanUp() def test_enable_batch_stop(self): """ Test enabling batch requests with additional parameter """ self.request.enable_batch('stop') expected_result = '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3' \ '.org/2003/05/soap-envelope"><soap:Header><context ' \ 'xmlns="urn:zimbra"><format ' \ 'type="xml"/></context></soap:Header><soap:Body' \ '><BatchRequest onerror="stop" ' \ 'xmlns="urn:zimbra"/></soap:Body></soap:Envelope>' self.tool_assert_equal_xml( expected_result, self.request.get_request() ) # Clean up self.cleanUp() def test_batch_add_request(self): """ Test adding multiple request to a batch request """ self.request.enable_batch() request_id = self.request.add_request( 'GetInfoRequest', { 'sections': 'mbox,prefs' }, 'urn:zimbra' ) self.assertIsInstance( request_id, int, msg="Returned request_id for request 1 is not of type int, " "but of type %s" % ( type(request_id) ) ) self.assertEqual( 1, request_id, msg="Returned request_id for request 1 is not 1, but %s" % ( str(request_id) ) ) expected_result = \ '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap' \ ':Header><context xmlns="urn:zimbra"><format ' \ 'type="xml"/></context></soap:Header><soap:Body><BatchRequest ' \ 'onerror="continue" xmlns="urn:zimbra"><GetInfoRequest ' \ 'requestId="1" sections="mbox,prefs" ' \ 'xmlns="urn:zimbra"/></BatchRequest></soap:Body></soap:Envelope>' self.tool_assert_equal_xml( expected_result, self.request.get_request() ) request_id = self.request.add_request( 'GetInfoRequest', { 'sections': 'zimlets' }, 'urn:zimbra' ) self.assertIsInstance( request_id, int, msg="Returned request_id for request 2 is not of type int, " "but of type %s" % ( type(request_id) ) ) self.assertEqual( 2, request_id, msg="Returned request_id for request 2 is not 2, but %s" % ( str(request_id) ) ) expected_result = \ '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap' \ ':Header><context xmlns="urn:zimbra"><format ' \ 'type="xml"/></context></soap:Header><soap:Body><BatchRequest ' \ 'onerror="continue" xmlns="urn:zimbra"><GetInfoRequest ' \ 'requestId="1" sections="mbox,prefs" ' \ 'xmlns="urn:zimbra"/><GetInfoRequest requestId="2" ' \ 'sections="zimlets" ' \ 'xmlns="urn:zimbra"/></BatchRequest></soap:Body></soap:Envelope>' self.tool_assert_equal_xml( expected_result, self.request.get_request() ) # Clean up self.setUp() def test_add_request(self): """ Test adding a request """ request_id = self.request.add_request( 'GetInfoRequest', { 'sections': 'mbox,prefs' }, 'urn:zimbra' ) self.assertIsNone( request_id, msg="Returned request_id for request 1 is not none, " "but %s" % ( str(request_id) ) ) expected_result = '<?xml version="1.0" ?><soap:Envelope ' \ 'xmlns:soap="http://www.w3' \ '.org/2003/05/soap-envelope"><soap:Header><context ' \ 'xmlns="urn:zimbra"><format ' \ 'type="xml"/></context></soap:Header><soap:Body' \ '><GetInfoRequest sections="mbox,' \ 'prefs" ' \ 'xmlns="urn:zimbra"/></soap:Body></soap:Envelope>' self.tool_assert_equal_xml( expected_result, self.request.get_request() ) # Clean up self.setUp() def tearDown(self): self.request = None
def authenticate(url, account, key, by='name', expires=0, timestamp=None, timeout=None, request_type="xml", admin_auth=False, use_password=False, raise_on_error=False): """ Authenticate to the Zimbra server :param url: URL of Zimbra SOAP service :param account: The account to be authenticated against :param key: The preauth key of the domain of the account or a password (if admin_auth or use_password is True) :param by: If the account is specified as a name, an ID or a ForeignPrincipal :param expires: When the token expires (or 0 for default expiration) :param timestamp: When the token was requested (None for "now") :param timeout: Timeout for the communication with the server. Defaults to the urllib2-default :param request_type: Which type of request to use ("xml" (default) or "json") :param admin_auth: This request should authenticate and generate an admin token. The "key"-parameter therefore holds the admin password (implies use_password) :param use_password: The "key"-parameter holds a password. Do a password- based user authentication. :param raise_on_error: Should I raise an exception when an authentication error occurs or just return None? :return: The authentication token or None :rtype: str or None or unicode """ if timestamp is None: timestamp = int(time.time()) * 1000 pak = "" if not admin_auth: pak = preauth.create_preauth(account, key, by, expires, timestamp) if request_type == 'xml': auth_request = RequestXml() else: auth_request = RequestJson() request_data = {'account': {'by': by, '_content': account}} ns = "urn:zimbraAccount" if admin_auth: ns = "urn:zimbraAdmin" request_data['password'] = key elif use_password: request_data['password'] = {"_content": key} else: request_data['preauth'] = { 'timestamp': timestamp, 'expires': expires, '_content': pak } auth_request.add_request('AuthRequest', request_data, ns) server = Communication(url, timeout) if request_type == 'xml': response = ResponseXml() else: response = ResponseJson() server.send_request(auth_request, response) if response.is_fault(): if raise_on_error: raise AuthenticationFailed( "Cannot authenticate user: (%s) %s" % (response.get_fault_code(), response.get_fault_message())) return None return response.get_response()['AuthResponse']['authToken']['_content']
def run_admin_test(self, request_type): """ Actually do the work """ config = get_config() if config.getboolean("admin_request_test", "enabled"): # Run only if enabled token = authenticate( config.get("admin_request_test", "admin_url"), config.get("admin_request_test", "admin_account"), config.get("admin_request_test", "admin_password"), config.get("admin_request_test", "admin_account_by"), admin_auth=True, request_type=request_type ) if token is None: self.fail("Authentication with the configured settings " "was not successful") # Create an account comm = Communication(config.get("admin_request_test", "admin_url")) if request_type == "xml": request = RequestXml() else: request = RequestJson() request.set_auth_token(token) test_account = config.get("admin_request_test", "test_account") if "TEMP" in test_account: # Generate a random number and add it to the test account random.seed() temp_account = random.randint(1000000, 5000000) test_account = test_account.replace("TEMP", str(temp_account)) test_displayname = config.get( "admin_request_test", "test_displayname" ) if sys.version < '3': # Create unicode string for py2 test_displayname = test_displayname.decode("utf-8") request.add_request( "CreateAccountRequest", { "name": test_account, "password": config.get( "admin_request_test", "test_password" ), "a": { "n": "displayName", "_content": test_displayname } }, "urn:zimbraAdmin" ) if request_type == "xml": response = ResponseXml() else: response = ResponseJson() comm.send_request(request, response) if response.is_fault(): self.fail( "CreateAccount faulted. (%s) %s" % ( response.get_fault_code(), response.get_fault_message() ) ) account_id = response.get_response( )["CreateAccountResponse"]["account"]["id"] # Get account from database and compare display name to the setting request.clean() request.set_auth_token(token) response.clean() request.add_request( "GetAccountRequest", { "account": { "by": "name", "_content": test_account } }, "urn:zimbraAdmin" ) comm.send_request(request, response) if response.is_fault(): self.fail( "GetAccount faulted. (%s) %s" % ( response.get_fault_code(), response.get_fault_message() ) ) returned_name = get_value( response.get_response()["GetAccountResponse"]["account"]["a"], "displayName" ) self.assertEqual( returned_name, test_displayname, "Zimbra didn't save the display name as requested." ) # Try to log in as the new account user_token = authenticate( config.get("admin_request_test", "url"), test_account, config.get("admin_request_test", "test_password"), "name", request_type=request_type, use_password=True ) if user_token is None: self.fail("Cannot log in as the test user.") # Remove account request.clean() response.clean() request.set_auth_token(token) request.add_request( "DeleteAccountRequest", { "id": account_id }, "urn:zimbraAdmin" ) comm.send_request(request, response) if response.is_fault(): self.fail( "Cannot remove test account: (%s) %s" % ( response.get_fault_code(), response.get_fault_message() ) )
def authenticate(url, account, key, by='name', expires=0, timestamp=None, timeout=None, request_type="xml", admin_auth=False, use_password=False, raise_on_error=False): """ Authenticate to the Zimbra server :param url: URL of Zimbra SOAP service :param account: The account to be authenticated against :param key: The preauth key of the domain of the account or a password (if admin_auth or use_password is True) :param by: If the account is specified as a name, an ID or a ForeignPrincipal :param expires: When the token expires (or 0 for default expiration) :param timestamp: When the token was requested (None for "now") :param timeout: Timeout for the communication with the server. Defaults to the urllib2-default :param request_type: Which type of request to use ("xml" (default) or "json") :param admin_auth: This request should authenticate and generate an admin token. The "key"-parameter therefore holds the admin password (implies use_password) :param use_password: The "key"-parameter holds a password. Do a password- based user authentication. :param raise_on_error: Should I raise an exception when an authentication error occurs or just return None? :return: The authentication token or None :rtype: str or None or unicode """ if timestamp is None: timestamp = int(time.time()) * 1000 pak = "" if not admin_auth: pak = preauth.create_preauth(account, key, by, expires, timestamp) if request_type == 'xml': auth_request = RequestXml() else: auth_request = RequestJson() request_data = { 'account': { 'by': by, '_content': account } } ns = "urn:zimbraAccount" if admin_auth: ns = "urn:zimbraAdmin" request_data['password'] = key elif use_password: request_data['password'] = { "_content": key } else: request_data['preauth'] = { 'timestamp': timestamp, 'expires': expires, '_content': pak } auth_request.add_request( 'AuthRequest', request_data, ns ) server = Communication(url, timeout) if request_type == 'xml': response = ResponseXml() else: response = ResponseJson() server.send_request(auth_request, response) if response.is_fault(): if raise_on_error: raise AuthenticationFailed( "Cannot authenticate user: (%s) %s" % ( response.get_fault_code(), response.get_fault_message() ) ) return None return response.get_response()['AuthResponse']['authToken']
def authenticate(url, account, key, by='name', expires=0, timestamp=None, timeout=None, request_type="xml"): """ Authenticate to the Zimbra server :param url: URL of Zimbra SOAP service :param account: The account to be authenticated against :param key: The preauth key of the domain of the account :param by: If the account is specified as a name, an ID or a ForeignPrincipal :param expires: When the token expires (or 0 for default expiration) :param timestamp: When the token was requested (None for "now") :param timeout: Timeout for the communication with the server. Defaults to the urllib2-default :return: The authentication token :rtype: str or None or unicode """ if timestamp is None: timestamp = int(datetime.now().strftime("%s")) * 1000 pak = preauth.create_preauth(account, key, by, expires, timestamp) if request_type == 'xml': auth_request = RequestXml() else: auth_request = RequestJson() auth_request.add_request( 'AuthRequest', { 'account': { 'by': by, '_content': account }, 'preauth': { 'timestamp': timestamp, 'expires': expires, '_content': pak } }, 'urn:zimbraAccount' ) server = Communication(url, timeout) if request_type == 'xml': response = ResponseXml() else: response = ResponseJson() try: server.send_request(auth_request, response) except HTTPError: # A HTTPError (which is an AuthError in most cases) occured. Simply # return nothing return None return response.get_response()['AuthResponse']['authToken']['_content']
def run_admin_test(self, request_type): """ Actually do the work """ config = get_config() if config.getboolean("admin_request_test", "enabled"): # Run only if enabled token = authenticate(config.get("admin_request_test", "admin_url"), config.get("admin_request_test", "admin_account"), config.get("admin_request_test", "admin_password"), config.get("admin_request_test", "admin_account_by"), admin_auth=True, request_type=request_type) if token is None: self.fail("Authentication with the configured settings " "was not successful") # Create an account comm = Communication(config.get("admin_request_test", "admin_url")) if request_type == "xml": request = RequestXml() else: request = RequestJson() request.set_auth_token(token) request.add_request( "CreateAccountRequest", { "name": config.get("admin_request_test", "test_account"), "password": config.get("admin_request_test", "test_password") }, "urn:zimbraAdmin") if request_type == "xml": response = ResponseXml() else: response = ResponseJson() comm.send_request(request, response) if response.is_fault(): self.fail( "CreateAccount faulted. (%s) %s" % (response.get_fault_code(), response.get_fault_message())) account_id = response.get_response( )["CreateAccountResponse"]["account"]["id"] # Try to log in as the new account user_token = authenticate(config.get("admin_request_test", "url"), config.get("admin_request_test", "test_account"), config.get("admin_request_test", "test_password"), "name", request_type=request_type, use_password=True) if user_token is None: self.fail("Cannot log in as the test user.") # Remove account request.clean() response.clean() request.set_auth_token(token) request.add_request("DeleteAccountRequest", {"id": account_id}, "urn:zimbraAdmin") comm.send_request(request, response) if response.is_fault(): self.fail( "Cannot remove test account: (%s) %s" % (response.get_fault_code(), response.get_fault_message()))