def test_valid_customer(self):
        """test a customer who should authenticate successfully"""
        request = MockRequest()

        key_list = list_customer_keys(self._connection, _test_username)
        self.assertEqual(len(key_list), 1)
        key_id, key_value = key_list[0]

        authentication_string = compute_authentication_string(
            key_id,
            key_value,
            _test_username,
            _test_method,
            current_timestamp(),
            _test_uri
        )
        request.__dict__["authorization"] = authentication_string.split()
        request.__dict__["method"] = _test_method
        request.__dict__["headers"] = {
            'x-nimbus-io-timestamp' : str(current_timestamp())
        } 
        request.__dict__["path_qs"] = _test_uri

        authenticator = SqlAuthenticator()
        authenticated = authenticator.authenticate(
            self._connection, _test_username, request
        )
        self.assertTrue(authenticated)
def _compute_headers(identity, method, path):
    timestamp = current_timestamp()

    headers = Headers()
    headers.addRawHeader("x-nimbus-io-timestamp", str(timestamp))
    headers.addRawHeader("agent", _agent_name)

    if identity is not None:
        authentication_string = \
            compute_authentication_string(identity.auth_key_id,
                                          identity.auth_key,
                                          identity.user_name, 
                                          method, 
                                          timestamp,
                                          urllib.unquote_plus(path))
        headers.addRawHeader("Authorization", authentication_string)

    return headers
Beispiel #3
0
    def test_valid_customer(self):
        """test a customer who should authenticate successfully"""
        request = MockRequest()

        key_list = list_customer_keys(self._connection, _test_username)
        self.assertEqual(len(key_list), 1)
        key_id, key_value = key_list[0]

        authentication_string = compute_authentication_string(
            key_id, key_value, _test_username, _test_method,
            current_timestamp(), _test_uri)
        request.__dict__["authorization"] = authentication_string.split()
        request.__dict__["method"] = _test_method
        request.__dict__["headers"] = {
            'x-nimbus-io-timestamp': str(current_timestamp())
        }
        request.__dict__["path_qs"] = _test_uri

        authenticator = SqlAuthenticator()
        authenticated = authenticator.authenticate(self._connection,
                                                   _test_username, request)
        self.assertTrue(authenticated)
    def request(self, 
                method, 
                uri, 
                body=None, 
                headers=None, 
                expected_status=OK):
        """
        method
            one of GET, PUT, POST, DELETE, HEAD

        uri
            the REST command for this request

        body
            if present, must be a string or an open file object

        headers
            a dictionary of key/value pairs to be added to the HTTP headers

        expected_status
            status indicating a successful result, for example 201 CREATED

        send an HTTP request over the connection
        return a HTTPResponse object, or raise an exception
        """
        retry_count = 0
        while not self._connected:
            try:
                self.connect()
            except Exception:
                instance = sys.exc_info()[1]
                # this could be an error from a real socket or a gevent 
                # monkeypatched socket. So we check the string
                if "DNSError".lower() in str(instance).lower():
                    retry_count += 1
                    if retry_count > _connection_retries:
                        self._log("DNSError: too many retries".format(
                            retry_count))
                        raise
                    self._log("DNSError retry {0} in {1} seconds".format(
                        retry_count, _connection_retry_seconds))
                    continue                       
                self._log.exception("Unhandled connection error {0}".format(
                    str(instance)))
                raise
            self._connected = True

        if headers is None:
            headers = dict()

        timestamp = current_timestamp()
        authentication_string = compute_authentication_string(
            self._auth_id,
            self._auth_key,
            self._user_name, 
            method, 
            timestamp,
            unquote_plus(uri)
        )

        headers.update({
            "Authorization"         : authentication_string,
            "x-nimbus-io-timestamp" : str(timestamp),
            "agent"                 : 'lumberyard/1.0'
        })

        # nginx will (rightly) reject with HTTP status 411 Length Required if
        # we send a PUT without a Content-Length header, even if the body size
        # is 0.  and our httplib base class won't add this header if body is
        # None.
        if method == "PUT":
            try:
                headers.setdefault("Content-Length", str(len(body)))
            except TypeError:
                if body is None:
                    headers.setdefault("Content-Length", str(0))

        # the body maybe beyond 7 bit ascii, so a unicode URL can't be combined
        # with it into a single string to form the request.

        try:
            _base_class.request(self, 
                                method, 
                                uri, 
                                body=body, 
                                headers=headers)
        except Exception:
            instance = sys.exc_info()[1]
            # 2012-02-14 dougfort -- we are getting timeouts here
            # on heavily loaded benchmark tests
            self._log.exception(str(instance))
            self.close()
            # 2012-10-12 dougfort -- if we get an exception here, it's not
            # an internal server error. So pass it on and let the caller deal
            # with it
            raise

        try:
            response = self.getresponse()
        except BadStatusLine:
            instance = sys.exc_info()[1]
            self._log.exception("BadStatusLine: '{0}'".format(instance))
            self.close()
            raise LumberyardHTTPError(INTERNAL_SERVER_ERROR, 
                                      "BadStatusLine")

        if response.status != expected_status:
            self._log.error("request failed {0} {1}".format(response.status, 
                                                            response.reason)) 

            # the server may have closed the connection already if this is an
            # error response
            try:
                response.read()
            except socket.error:
                pass

            self.close()

            # if we got 503 service unavailable
            # and there is a retry_after header with an integer value 
            # give the caller a chance to retry
            if response.status == SERVICE_UNAVAILABLE:
                retry_after = response.getheader("RETRY-AFTER", None)
                if retry_after is not None:
                    seconds = None
                    try:
                        seconds = int(retry_after)
                    except Exception:
                        pass
                    if seconds is not None and seconds > 0:
                        raise LumberyardRetryableHTTPError(seconds)

            raise LumberyardHTTPError(response.status, response.reason)

        return response