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)
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)
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)
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)
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)
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)
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)
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)
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)
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)