def __call__(self, env, start_response):
     """ Handle incoming request. Transform. And send downstream. """
     request = Request(env)
     if env['KEYSTONE_API_VERSION'] in ['1.0', '1.1']:
         params = {
             "auth": {
                 "passwordCredentials": {
                     "username": utils.get_auth_user(request),
                     "password": utils.get_auth_key(request)
                 }
             }
         }
         #Make request to keystone
         new_request = Request.blank('/tokens')
         new_request.method = 'POST'
         new_request.headers['Content-type'] = 'application/json'
         new_request.accept = 'text/json'
         new_request.body = json.dumps(params)
         response = new_request.get_response(self.app)
         #Handle failures.
         if not str(response.status).startswith('20'):
             return response(env, start_response)
         headers = self.__transform_headers(json.loads(response.body))
         resp = utils.send_legacy_result(204, headers)
         return resp(env, start_response)
     else:
         # Other calls pass to downstream WSGI component
         return self.app(env, start_response)
Ejemplo n.º 2
0
 def __call__(self, env, start_response):
     """ Handle incoming request. Transform. And send downstream. """
     logger.debug("Entering AuthProtocol.__call__")
     request = Request(env)
     if env.get('KEYSTONE_API_VERSION') in ['1.0', '1.1']:
         logger.debug("This is a v%s call, so taking over" %
                      env.get('KEYSTONE_API_VERSION'))
         params = {"auth": {"passwordCredentials":
             {"username": utils.get_auth_user(request),
                 "password": utils.get_auth_key(request)}}}
         #Make request to keystone
         new_request = Request.blank('/tokens')
         new_request.method = 'POST'
         new_request.headers['Content-type'] = 'application/json'
         new_request.accept = 'application/json'
         new_request.body = json.dumps(params)
         logger.debug("Sending v2.0-formatted request downstream")
         response = new_request.get_response(self.app)
         logger.debug("Got back %s" % response.status)
         #Handle failures.
         if not str(response.status).startswith('20'):
             return response(env, start_response)
         headers = self.__transform_headers(
             json.loads(response.body))
         logger.debug("Transformed the response. Responding to v1.x client")
         resp = utils.send_legacy_result(204, headers)
         return resp(env, start_response)
     else:
         logger.debug("Not a v1.0/v1.1 call, so passing downstream")
         return self.app(env, start_response)
Ejemplo n.º 3
0
    def __call__(self, env, start_response):
        """ Handle incoming request. Transform. And send downstream. """
        request = Request(env)
        if 'KEYSTONE_API_VERSION' in env and \
                                    env['KEYSTONE_API_VERSION'] == '2.0':
            if request.path.startswith("/tokens"):
                is_d5_request = False
                if request.method == "POST":
                    try:
                        auth_with_credentials = \
                            utils.get_normalized_request_content(
                            D5AuthWithPasswordCredentials, request)
                        # Convert request body to Diablo syntax
                        if request.content_type == "application/xml":
                            request.body = auth_with_credentials.to_xml()
                        else:
                            request.body = auth_with_credentials.to_json()
                        is_d5_request = True
                    except:
                        pass

                    if is_d5_request:
                        response = request.get_response(self.app)
                        #Handle failures.
                        if not str(response.status).startswith('20'):
                            return response(env, start_response)
                        auth_data = utils.get_normalized_request_content(
                            D5toDiabloAuthData, response)
                        resp = utils.send_result(response.status_int, request,
                                                 auth_data)
                        return resp(env, start_response)
                    else:
                        # Pass through
                        return self.app(env, start_response)

                elif request.method == "GET":
                    if request.path.endswith("/endpoints"):
                        # Pass through
                        return self.app(env, start_response)
                    else:
                        response = request.get_response(self.app)
                        #Handle failures.
                        if not str(response.status).startswith('20'):
                            return response(env, start_response)
                        validate_data = utils.get_normalized_request_content(
                            D5ValidateData, response)
                        resp = utils.send_result(response.status_int, request,
                                                 validate_data)
                        return resp(env, start_response)

        # All other calls pass to downstream WSGI component
        return self.app(env, start_response)
Ejemplo n.º 4
0
    def __call__(self, env, start_response):
        def custom_start_response(status, headers):
            if self.delay_auth_decision:
                headers.append(('WWW-Authenticate', "Basic realm='API Realm'"))
            return start_response(status, headers)

        #TODO(Rasib): PERFORM OPENID AUTH

        #Auth processed, headers added now decide how to pass on the call
        if self.app:
            # Pass to downstream WSGI component
            env['HTTP_AUTHORIZATION'] = "Basic %s" % self.service_pass
            return self.app(env, custom_start_response)

        proxy_headers = []
        proxy_headers['AUTHORIZATION'] = "Basic %s" % self.service_pass
        # We are forwarding to a remote service (no downstream WSGI app)
        req = Request(proxy_headers)
        parsed = urlparse(req.url)
        conn = http_connect(self.service_host, self.service_port, \
             req.method, parsed.path, \
             proxy_headers, \
             ssl=(self.service_protocol == 'https'))
        resp = conn.getresponse()
        data = resp.read()
        #TODO(ziad): use a more sophisticated proxy
        # we are rewriting the headers now
        return Response(status=resp.status, body=data)(env, start_response)
Ejemplo n.º 5
0
 def __call__(self, env, start_response):
     """ Handle incoming request. Transform. And send downstream. """
     self.start_response = start_response
     self.env = env
     self.request = Request(env)
     if self.request.path.startswith('/v1.0'
             ) or self.request.path.startswith('/v1.1'):
         params = {"passwordCredentials":
             {"username": utils.get_auth_user(self.request),
                 "password": utils.get_auth_key(self.request)}}
         #Make request to keystone
         new_request = Request.blank('/v2.0/tokens')
         new_request.method = 'POST'
         new_request.headers['Content-type'] = 'application/json'
         new_request.accept = 'text/json'
         new_request.body = json.dumps(params)
         response = new_request.get_response(self.app)
         #Handle failures.
         if not str(response.status).startswith('20'):
             return response(env, start_response)
         headers = self.__transform_headers(
             json.loads(response.body))
         resp = utils.send_legacy_result(204, headers)
         return resp(env, start_response)
     else:
         # Other calls pass to downstream WSGI component
         return self.app(self.env, self.start_response)
Ejemplo n.º 6
0
 def __call__(self, env, start_response):
     """ Handle incoming request. Transform. And send downstream. """
     logger.debug("Entering AuthProtocol.__call__")
     request = Request(env)
     if env.get('KEYSTONE_API_VERSION') in ['1.0', '1.1']:
         logger.debug("This is a v%s call, so taking over" %
                      env.get('KEYSTONE_API_VERSION'))
         params = {"auth": {"passwordCredentials":
             {"username": utils.get_auth_user(request),
                 "password": utils.get_auth_key(request)}}}
         #Make request to keystone
         new_request = Request.blank('/tokens')
         new_request.method = 'POST'
         new_request.headers['Content-type'] = 'application/json'
         new_request.accept = 'application/json'
         new_request.body = json.dumps(params)
         logger.debug("Sending v2.0-formatted request downstream")
         response = new_request.get_response(self.app)
         logger.debug("Got back %s" % response.status)
         #Handle failures.
         if not str(response.status).startswith('20'):
             return response(env, start_response)
         headers = self.__transform_headers(
             json.loads(response.body))
         logger.debug("Transformed the response. Responding to v1.x client")
         resp = utils.send_legacy_result(204, headers)
         return resp(env, start_response)
     else:
         logger.debug("Not a v1.0/v1.1 call, so passing downstream")
         return self.app(env, start_response)
Ejemplo n.º 7
0
    def __call__(self, env, start_response):
        """ Handle incoming request. Transform. And send downstream. """
        request = Request(env)
        if request.path == "/extensions":
            if env['KEYSTONE_API_VERSION'] == '2.0':
                request = Request(env)
                response = request.get_response(self.app)
                if response.status_int == 200:
                    if response.content_type == 'application/json':
                        #load json for this extension from file
                        thisextension = open(os.path.join(
                                                    os.path.dirname(__file__),
                                                   "extension.json")).read()
                        thisextensionjson = json.loads(thisextension)

                        #load json in response
                        body = json.loads(response.body)
                        extensionsarray = body["extensions"]["values"]

                        #add this extension and return the response
                        extensionsarray.append(thisextensionjson)
                        newresp = Response(
                            content_type='application/json',
                            body=json.dumps(body))
                        return newresp(env, start_response)
                    elif response.content_type == 'application/xml':
                        #load xml for this extension from file
                        thisextensionxml = etree.parse(os.path.join(
                                                    os.path.dirname(__file__),
                                                   "extension.xml")).getroot()
                        #load xml being returned in response
                        body = etree.fromstring(response.body)

                        #add this extension and return the response
                        body.append(thisextensionxml)
                        newresp = Response(
                            content_type='application/xml',
                            body=etree.tostring(body))
                        return newresp(env, start_response)

                # return the response
                return response(env, start_response)

        #default action, bypass
        return self.app(env, start_response)
Ejemplo n.º 8
0
    def __call__(self, env, start_response):
        """ Handle incoming request. Transform. And send downstream. """
        request = Request(env)
        if request.path == "/extensions":
            if env['KEYSTONE_API_VERSION'] == '2.0':
                request = Request(env)
                response = request.get_response(self.app)
                if response.status_int == 200:
                    if response.content_type == 'application/json':
                        #load json for this extension from file
                        thisextension = open(os.path.join(
                                                    os.path.dirname(__file__),
                                                   "extension.json")).read()
                        thisextensionjson = json.loads(thisextension)

                        #load json in response
                        body = json.loads(response.body)
                        extensionsarray = body["extensions"]["values"]

                        #add this extension and return the response
                        extensionsarray.append(thisextensionjson)
                        newresp = Response(
                            content_type='application/json',
                            body=json.dumps(body))
                        return newresp(env, start_response)
                    elif response.content_type == 'application/xml':
                        #load xml for this extension from file
                        thisextensionxml = etree.parse(os.path.join(
                                                    os.path.dirname(__file__),
                                                   "extension.xml")).getroot()
                        #load xml being returned in response
                        body = etree.fromstring(response.body)

                        #add this extension and return the response
                        body.append(thisextensionxml)
                        newresp = Response(
                            content_type='application/xml',
                            body=etree.tostring(body))
                        return newresp(env, start_response)

                # return the response
                return response(env, start_response)

        #default action, bypass
        return self.app(env, start_response)
Ejemplo n.º 9
0
    def __call__(self, env, start_response):
        """ Handle incoming request. Transform. And send downstream. """
        request = Request(env)
        if 'KEYSTONE_API_VERSION' in env and \
                                    env['KEYSTONE_API_VERSION'] == '2.0':
            if request.path.startswith("/tokens"):
                is_d5_request = False
                if request.method == "POST":
                    try:
                        auth_with_credentials = \
                            utils.get_normalized_request_content(
                            D5AuthWithPasswordCredentials, request)
                        # Convert request body to Diablo syntax
                        if request.content_type == "application/xml":
                            request.body = auth_with_credentials.to_xml()
                        else:
                            request.body = auth_with_credentials.to_json()
                        is_d5_request = True
                    except:
                        pass

                    if is_d5_request:
                        response = request.get_response(self.app)
                        #Handle failures.
                        if not str(response.status).startswith('20'):
                            return response(env, start_response)
                        auth_data = utils.get_normalized_request_content(
                            D5toDiabloAuthData, response)
                        resp = utils.send_result(response.status_int, request,
                                                 auth_data)
                        return resp(env, start_response)
                    else:
                        # Pass through
                        return self.app(env, start_response)

                elif request.method == "GET":
                    if request.path.endswith("/endpoints"):
                        # Pass through
                        return self.app(env, start_response)
                    else:
                        response = request.get_response(self.app)
                        #Handle failures.
                        if not str(response.status).startswith('20'):
                            return response(env, start_response)
                        validate_data = utils.get_normalized_request_content(
                            D5ValidateData, response)
                        resp = utils.send_result(response.status_int, request,
                                                 validate_data)
                        return resp(env, start_response)

        # All other calls pass to downstream WSGI component
        return self.app(env, start_response)
Ejemplo n.º 10
0
    def _forward_request(self, env, start_response, proxy_headers):
        """Token/Auth processed & claims added to headers"""
        self._decorate_request('AUTHORIZATION', "Basic %s" % self.service_pass,
                               env, proxy_headers)
        #now decide how to pass on the call
        if self.app:
            # Pass to downstream WSGI component
            logger.debug("Sending request to next app in WSGI pipeline")
            return self.app(env, start_response)
            #.custom_start_response)
        else:
            # We are forwarding to a remote service (no downstream WSGI app)
            logger.debug("Sending request to %s" % self.service_url)
            req = Request(proxy_headers)
            parsed = urlparse(req.url)

            # pylint: disable=E1101
            conn = http_connect(self.service_host,
                                self.service_port,
                                req.method,
                                parsed.path,
                                proxy_headers,
                                ssl=(self.service_protocol == 'https'),
                                timeout=self.service_timeout)
            resp = conn.getresponse()
            data = resp.read()
            logger.debug("Response was %s" % resp.status)

            #TODO(ziad): use a more sophisticated proxy
            # we are rewriting the headers now

            if resp.status in (401, 305):
                # Add our own headers to the list
                headers = [("WWW_AUTHENTICATE",
                            "Keystone uri='%s'" % self.auth_location)]
                return Response(status=resp.status,
                                body=data,
                                headerlist=headers)(env, start_response)
            else:
                return Response(status=resp.status, body=data)(env,
                                                               start_response)
Ejemplo n.º 11
0
 def _forward_request(self):
     """Token/Auth processed & claims added to headers"""
     #now decide how to pass on the call
     if self.app:
         # Pass to downstream WSGI component
         return self.app(self.env, self.start_response)
         #.custom_start_response)
     else:
         # We are forwarding to a remote service (no downstream WSGI app)
         req = Request(self.proxy_headers)
         # pylint: disable=E1101
         parsed = urlparse(req.url)
         conn = http_connect(self.service_host,
                             self.service_port,
                             req.method,
                             parsed.path,
                             self.proxy_headers,
                             ssl=(self.service_protocol == 'https'))
         resp = conn.getresponse()
         data = resp.read()
         return Response(status=resp.status, body=data)(self.proxy_headers,
                                                        self.start_response)
Ejemplo n.º 12
0
    def command_generate(self):
        from front.environment import FrontEnvironment, environment
        from front.urls import app
        env = VersionedStorage(FrontEnvironment,
                               Request.blank('/'),
                               Reverse.from_handler(app))
        for lang in self.langs:
            env.lang = Lang(env, lang)
            env.models = getattr(models.front, lang)
            for error in self.errors:
                handler = environment | (
                        lambda env, data: env.render_to_string('errors/' + error, {}))
                tmpl = handler(env, VersionedStorage()).encode('utf-8')
                out = os.path.join(env.cfg.STATIC, lang, error+'.html')

                if os.path.isfile(out):
                    with open(out, 'r') as f:
                        existing = f.read()
                        if existing == tmpl:
                            continue

                with open(out, 'w') as f:
                    f.write(tmpl)
                logger.info("Rendered %s/%s.html", lang, error)
Ejemplo n.º 13
0
    def __call__(self, env, start_response):
        def custom_start_response(status, headers):
            if self.delay_auth_decision:
                headers.append(('WWW-Authenticate',
                                "Basic realm='Use guest/guest'"))
            return start_response(status, headers)

        #Prep headers to proxy request to remote service
        proxy_headers = env.copy()
        user = ''

        #Look for authentication
        if 'HTTP_AUTHORIZATION' not in env:
            #No credentials were provided
            if self.delay_auth_decision:
                _decorate_request_headers("X_IDENTITY_STATUS", "Invalid",
                                          proxy_headers, env)
            else:
                # If the user isn't authenticated, we reject the request and
                # return 401 indicating we need Basic Auth credentials.
                ret = HTTPUnauthorized("Authentication required",
                        [('WWW-Authenticate',
                          'Basic realm="Use guest/guest"')])
                return ret(env, start_response)
        else:
            # Claims were provided - validate them
            import base64
            auth_header = env['HTTP_AUTHORIZATION']
            _auth_type, encoded_creds = auth_header.split(None, 1)
            user, password = base64.b64decode(encoded_creds).split(':', 1)
            if not self.validateCreds(user, password):
                #Claims were rejected
                if not self.delay_auth_decision:
                    # Reject request (or ask for valid claims)
                    ret = HTTPUnauthorized("Authentication required",
                            [('WWW-Authenticate',
                              'Basic realm="Use guest/guest"')])
                    return ret(env, start_response)
                else:
                    # Claims are valid, forward request
                    _decorate_request_headers("X_IDENTITY_STATUS", "Invalid",
                                              proxy_headers, env)

            # TODO(Ziad): add additional details we may need,
            #             like tenant and group info
            _decorate_request_headers('X_AUTHORIZATION', "Proxy %s" % user,
                                      proxy_headers, env)
            _decorate_request_headers("X_IDENTITY_STATUS", "Confirmed",
                                      proxy_headers, env)
            _decorate_request_headers('X_TENANT', 'blank',
                                      proxy_headers, env)
            #Auth processed, headers added now decide how to pass on the call
            if self.app:
                # Pass to downstream WSGI component
                env['HTTP_AUTHORIZATION'] = "Basic %s" % self.service_pass
                return self.app(env, custom_start_response)

            proxy_headers['AUTHORIZATION'] = "Basic %s" % self.service_pass
            # We are forwarding to a remote service (no downstream WSGI app)
            req = Request(proxy_headers)
            parsed = urlparse(req.url)
            conn = http_connect(self.service_host, self.service_port, \
                                req.method, parsed.path, \
                                proxy_headers, \
                                ssl=(self.service_protocol == 'https'))
            resp = conn.getresponse()
            data = resp.read()
            #TODO(ziad): use a more sophisticated proxy
            # we are rewriting the headers now
            return Response(status=resp.status, body=data)(env, start_response)