def _validate_claims(self, claims, retry=False): """Validate claims, and provide identity information if applicable """ # Step 1: We need to auth with the keystone service, so get an # admin token #TODO(ziad): Need to properly implement this, where to store creds # for now using token from ini #TODO(salvatore-orlando): Temporarily restoring auth token retrieval, # with credentials in configuration file if not self.admin_token: auth = self.get_admin_auth_token(self.admin_user, self.admin_password) self.admin_token = json.loads(auth)["auth"]["token"]["id"] # Step 2: validate the user's token with the auth service # since this is a priviledged op,m we need to auth ourselves # by using an admin token headers = {"Content-type": "application/json", "Accept": "text/json", "X-Auth-Token": self.admin_token} ##TODO(ziad):we need to figure out how to auth to keystone #since validate_token is a priviledged call #Khaled's version uses creds to get a token # "X-Auth-Token": admin_token} # we're using a test token from the ini file for now conn = http_connect(self.auth_host, self.auth_port, 'GET', self._build_token_uri(claims), headers=headers) resp = conn.getresponse() conn.close() if not str(resp.status).startswith('20'): # Keystone rejected claim # In case a 404 error it might just be that the token has expired # Therefore try and get a new token # of course assuming admin credentials have been specified # Note(salvatore-orlando): the 404 here is not really # what should be returned if self.admin_user and self.admin_password and \ not retry and str(resp.status) == '404': LOG.warn("Unable to validate token." + "Admin token possibly expired.") self.admin_token = None return self._validate_claims(claims, True) return False else: #TODO(Ziad): there is an optimization we can do here. We have just #received data from Keystone that we can use instead of making #another call in _expound_claims LOG.info("Claims successfully validated") return True
def _expound_claims(self): # Valid token. Get user data and put it in to the call # so the downstream service can use it headers = {"Content-type": "application/json", "Accept": "text/json", "X-Auth-Token": self.admin_token} ##TODO(ziad):we need to figure out how to auth to keystone #since validate_token is a priviledged call #Khaled's version uses creds to get a token # "X-Auth-Token": admin_token} # we're using a test token from the ini file for now conn = http_connect(self.auth_host, self.auth_port, 'GET', self._build_token_uri(self.claims), headers=headers) resp = conn.getresponse() data = resp.read() conn.close() if not str(resp.status).startswith('20'): raise LookupError('Unable to locate claims: %s' % resp.status) token_info = json.loads(data) #TODO(Ziad): make this more robust #first_group = token_info['auth']['user']['groups']['group'][0] roles = [] role_refs = token_info["auth"]["user"]["roleRefs"] if role_refs != None: for role_ref in role_refs: roles.append(role_ref["roleId"]) verified_claims = {'user': token_info['auth']['user']['username'], 'tenant': token_info['auth']['user']['tenantId'], 'roles': roles} # TODO(Ziad): removed groups for now # ,'group': '%s/%s' % (first_group['id'], # first_group['tenantId'])} return verified_claims
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) 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() #TODO(ziad): use a more sophisticated proxy # we are rewriting the headers now return Response(status=resp.status, body=data)(self.proxy_headers, self.start_response)