Example #1
0
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
Example #2
0
    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()
Example #3
0
    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
            )
Example #4
0
    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
            )
Example #6
0
    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
Example #7
0
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
Example #8
0
 def setUp(self):
     self.request = RequestXml()
Example #9
0
    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 setUp(self):
     self.request = RequestXml()
Example #12
0
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()
                    )
                )
Example #14
0
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']
Example #15
0
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']
Example #16
0
    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()))