def create_client(self): dataset = DictDBWrap(USERDB) # The scope to dataset operation map dataset.register_scope('https://dirg.org.umu.se/uma/read', 'get') client = Client({}, client_authn_methods=CLIENT_AUTHN_METHOD) resource_owner = 'hans' self.rsh = ResourceSetHandler(dataset, client, resource_owner) self.rsh.client.provider_info = { "resource_set_registration_endpoint": 'https://as.example.com/rsr' } # No the real PAT obviously self.rsh.token["PAT"] = 'pat' # map client API operation (HTTP GET) to scope self.rsh.op2scope = {'GET': 'https://dirg.org.umu.se/uma/read'}
def __init__(self, dataset, resource_owner, client, symkey="", **kwargs): # self.client = Client(client_id=client_id, ca_certs=ca_certs, # client_authn_methods=client_authn_methods, # keyjar=keyjar, server_info=server_info, # authz_page=authz_page, # flow_type=flow_type, password=password, # registration_info=registration_info, # response_type=response_type, scope=scope) self.client = client self.rs_handler = ResourceSetHandler(dataset, self.client, resource_owner) self.resource_owner = resource_owner self.symkey = symkey self.kwargs = kwargs self.srv_discovery_url = "" self.cookie_handler = http_util.CookieDealer(self) self.cookie_name = "resource_server" self.rsd_map = {} self.pat = None self.keyjar = self.client.keyjar self.kid = {"sig": {}, "enc": {}}
def create_client(self): dataset = DictDBWrap(USERDB) # The scope to dataset operation map dataset.register_scope('https://dirg.org.umu.se/uma/read', 'get') client = Client({}, client_authn_methods=CLIENT_AUTHN_METHOD) resource_owner = 'hans' self.rsh = ResourceSetHandler(dataset, client, resource_owner) self.rsh.client.provider_info = { "resource_set_registration_endpoint": 'https://as.example.com/rsr'} # No the real PAT obviously self.rsh.token["PAT"] = 'pat' # map client API operation (HTTP GET) to scope self.rsh.op2scope = {'GET': 'https://dirg.org.umu.se/uma/read'}
class TestResourceSetHandler(object): @pytest.fixture(autouse=True) def create_client(self): dataset = DictDBWrap(USERDB) # The scope to dataset operation map dataset.register_scope('https://dirg.org.umu.se/uma/read', 'get') client = Client({}, client_authn_methods=CLIENT_AUTHN_METHOD) resource_owner = 'hans' self.rsh = ResourceSetHandler(dataset, client, resource_owner) self.rsh.client.provider_info = { "resource_set_registration_endpoint": 'https://as.example.com/rsr' } # No the real PAT obviously self.rsh.token["PAT"] = 'pat' # map client API operation (HTTP GET) to scope self.rsh.op2scope = {'GET': 'https://dirg.org.umu.se/uma/read'} def test_register_init(self): res_set_desc = self.rsh.register_init() assert len(res_set_desc) == 5 def test_com_args(self): request_args = { 'name': 'gloria', 'scopes': ['https://dirg.org.umu.se/uma/read'] } rsid = 'abcd' _kwargs = self.rsh.com_args(ResourceSetDescription, 'PUT', request_args=request_args, content_type=JSON_ENCODED, rsid=rsid) assert _kwargs['url'] == 'https://as.example.com/rsr/resource_set/abcd' assert _kwargs['body'] in [ '{"scopes": ["https://dirg.org.umu.se/uma/read"], "name": "gloria"}', '{"name": "gloria", "scopes": ["https://dirg.org.umu.se/uma/read"]}' ] assert _kwargs["http_args"] == { 'headers': { 'Content-Type': 'application/json', 'Authorization': 'Bearer pat' } } def test_create_rsd(self): res_set_desc = self.rsh.register_init() # http_args = {'headers': {'Authorization': auth}} for lid, _desc in res_set_desc.items(): res = self.rsh.com_args(ResourceSetDescription, "POST", request_args=_desc, content_type=JSON_ENCODED) assert res["url"] == 'https://as.example.com/rsr/resource_set' assert res["http_args"] == { 'headers': { 'Content-Type': 'application/json', 'Authorization': 'Bearer pat' } } def test_first_args(self): # Used by read and delete args = self.rsh.first_args("123456") assert args["url"] == 'https://as.example.com/rsr/resource_set/123456' assert args["http_args"] == { 'headers': { 'Authorization': 'Bearer pat' } } # used by list args = self.rsh.first_args() assert args["url"] == 'https://as.example.com/rsr/resource_set' assert args["http_args"] == { 'headers': { 'Authorization': 'Bearer pat' } } def test_update_rsd(self): res_set_desc = self.rsh.register_init() _desc = res_set_desc[list(res_set_desc)[0]] res = self.rsh.com_args(ResourceSetDescription, "POST", request_args=_desc, rsid="foo", content_type=JSON_ENCODED) assert res["url"] == 'https://as.example.com/rsr/resource_set/foo' assert res["http_args"] == { 'headers': { 'Content-Type': 'application/json', 'Authorization': 'Bearer pat' } } def test_query2permission_registration_request_primer(self): self.rsh.register_init() _prim = self.rsh.query2permission_registration_request_primer( 'GET', 'hans', 'attr=givenName') assert _prim == [('hans:givenName:Hans', 'https://dirg.org.umu.se/uma/read')]
class ResourceServer(object): """ One ResourceServer per resource_owner+dataset pair """ def __init__(self, dataset, resource_owner, client, symkey="", **kwargs): # self.client = Client(client_id=client_id, ca_certs=ca_certs, # client_authn_methods=client_authn_methods, # keyjar=keyjar, server_info=server_info, # authz_page=authz_page, # flow_type=flow_type, password=password, # registration_info=registration_info, # response_type=response_type, scope=scope) self.client = client self.rs_handler = ResourceSetHandler(dataset, self.client, resource_owner) self.resource_owner = resource_owner self.symkey = symkey self.kwargs = kwargs self.srv_discovery_url = "" self.cookie_handler = http_util.CookieDealer(self) self.cookie_name = "resource_server" self.rsd_map = {} self.pat = None self.keyjar = self.client.keyjar self.kid = {"sig": {}, "enc": {}} @staticmethod def _get_bearer_token(authz): try: if authz.startswith("Bearer"): return authz[len("Bearer "):] else: return None except KeyError: return None def do_introspection(self, rpt, path=None): """ The resource server doing introspection on a RPT at the AuthzServer :param rpt: Resource access token :param path: path representing the resource :returns: """ pat = self.client.token[self.resource_owner]['PAT'] ir = IntrospectionRequest(token=rpt) # if path: # fpath = self.rs_handler.dataset.resource_name(path) # ir["resource_id"] = self.rs_handler.path2rsid[fpath] request_args = {"access_token": pat} ht_args = self.client.client_authn_method[ "bearer_header"](self).construct(ir, request_args=request_args) url = list(self.client.provider_info.values())[0][ "introspection_endpoint"] return self.client.request_and_return(url, IntrospectionResponse, body=ir.to_json(), body_type="json", http_args=ht_args) # ======================================================================== # Below is the client API methods # ======================================================================== def result(self, environ, start_response, result): resp = Response(mako_template="opresult.mako", template_lookup=self.kwargs["template_lookup"], headers=[]) argv = { "result": result } return resp(environ, start_response, **argv) def create_permission_request(self, operation, uid, query): res_set = self.rs_handler.query2permission_registration_request_primer( operation, uid, query) pre_rpp = [(self.rs_handler.rsd_map[lid]['_id'], [scope]) for lid, scope in res_set] prrs = [] for rsid, scopes in pre_rpp: prrs.append(PermissionRegistrationRequest(resource_set_id=rsid, scopes=scopes).to_dict()) return prrs def do_permission_request(self, prrs): pat = self.rs_handler.token['PAT'] kwargs = { "headers": {"Authorization": "Bearer %s" % pat}, "body": prrs} url = self.client.provider_info["rpt_endpoint"] resp = self.client.send(url, "POST", **kwargs) assert resp.status == "201 Created" return PermissionRegistrationResponse().from_json(resp.message)[ "ticket"] @staticmethod def filter_by_permission(intro, scope=None): """ :param intro: An IntrospectionResponse instance :param scope: The scope that access is asked for :return: list of resource_set_description ids :rtype: list """ rsids = [] now = utc_time_sans_frac() try: assert now < intro["exp"] except KeyError: pass except AssertionError: return False for perm in intro["permissions"]: try: assert now < perm["exp"] except KeyError: pass except AssertionError: continue try: assert scope in perm["scopes"] except AssertionError: pass else: rsids.append(perm["resource_set_id"]) return rsids def collect_info(self, introspection_response, scope): """ :param introspection_response: :param scope: :return: Dictionary of attributes and values :rtype: dict """ rsids = self.filter_by_permission(introspection_response, scope) # Collect information res = {} for rsid in rsids: lid = self.rs_handler.rsid2lid[rsid] part = lid.split(':') if len(part) == 2: # every value for an attribute res[part[1]] = self.rs_handler.get_info(part[0], part[1]) else: try: res[part[1]].append(part[2]) except KeyError: res[part[1]] = [part[2]] return res # ---------------------------------------------------------------------- # ---------------------------------------------------------------------- def resource_endpoint(self, operation, path, auth=None, query=None): """ This is where the client sends its requests. Assumes a HTTP interface. Three possible cases: - No RPT - A RPT that doesn't give the necessary access - A valid RPT :param auth: Authentication information, HTTP Authorization header :param operation: A HTTP operation: "GET","POST", ... :param path: The URL path :param query: A possible URL query part :return: HTTP response """ rpt = self._get_bearer_token(auth) if auth is None: # no RPT rssp = self.rs_handler.query2permission_registration_request_primer( operation, path, query) resp = self.client.do_register_permission_request( self.resource_owner, json.dumps(rssp)) else: self.do_introspection(rpt) return Response
class TestResourceSetHandler(object): @pytest.fixture(autouse=True) def create_client(self): dataset = DictDBWrap(USERDB) # The scope to dataset operation map dataset.register_scope('https://dirg.org.umu.se/uma/read', 'get') client = Client({}, client_authn_methods=CLIENT_AUTHN_METHOD) resource_owner = 'hans' self.rsh = ResourceSetHandler(dataset, client, resource_owner) self.rsh.client.provider_info = { "resource_set_registration_endpoint": 'https://as.example.com/rsr'} # No the real PAT obviously self.rsh.token["PAT"] = 'pat' # map client API operation (HTTP GET) to scope self.rsh.op2scope = {'GET': 'https://dirg.org.umu.se/uma/read'} def test_register_init(self): res_set_desc = self.rsh.register_init() assert len(res_set_desc) == 5 def test_com_args(self): request_args = {'name': 'gloria', 'scopes': ['https://dirg.org.umu.se/uma/read']} rsid = 'abcd' _kwargs = self.rsh.com_args(ResourceSetDescription, 'PUT', request_args=request_args, content_type=JSON_ENCODED, rsid=rsid) assert _kwargs['url'] == 'https://as.example.com/rsr/resource_set/abcd' assert _kwargs['body'] in [ '{"scopes": ["https://dirg.org.umu.se/uma/read"], "name": "gloria"}', '{"name": "gloria", "scopes": ["https://dirg.org.umu.se/uma/read"]}' ] assert _kwargs["http_args"] == { 'headers': {'Content-Type': 'application/json', 'Authorization': 'Bearer pat'}} def test_create_rsd(self): res_set_desc = self.rsh.register_init() # http_args = {'headers': {'Authorization': auth}} for lid, _desc in res_set_desc.items(): res = self.rsh.com_args(ResourceSetDescription, "POST", request_args=_desc, content_type=JSON_ENCODED) assert res["url"] == 'https://as.example.com/rsr/resource_set' assert res["http_args"] == { 'headers': {'Content-Type': 'application/json', 'Authorization': 'Bearer pat'}} def test_first_args(self): # Used by read and delete args = self.rsh.first_args("123456") assert args["url"] == 'https://as.example.com/rsr/resource_set/123456' assert args["http_args"] == {'headers': {'Authorization': 'Bearer pat'}} # used by list args = self.rsh.first_args() assert args["url"] == 'https://as.example.com/rsr/resource_set' assert args["http_args"] == {'headers': {'Authorization': 'Bearer pat'}} def test_update_rsd(self): res_set_desc = self.rsh.register_init() _desc = res_set_desc[list(res_set_desc)[0]] res = self.rsh.com_args(ResourceSetDescription, "POST", request_args=_desc, rsid="foo", content_type=JSON_ENCODED) assert res["url"] == 'https://as.example.com/rsr/resource_set/foo' assert res["http_args"] == { 'headers': {'Content-Type': 'application/json', 'Authorization': 'Bearer pat'}} def test_query2permission_registration_request_primer(self): self.rsh.register_init() _prim = self.rsh.query2permission_registration_request_primer( 'GET', 'hans', 'attr=givenName') assert _prim == [('hans:givenName:Hans', 'https://dirg.org.umu.se/uma/read')]