2121
2222from minos .api_gateway .rest .database .models import (
2323 AuthRule ,
24+ AutzRule ,
2425)
2526from minos .api_gateway .rest .urlmatch .authmatch import (
2627 AuthMatch ,
2930from .database .repository import (
3031 Repository ,
3132)
33+ from .urlmatch .autzmatch import (
34+ AutzMatch ,
35+ )
3236
3337logger = logging .getLogger (__name__ )
3438
@@ -46,20 +50,44 @@ async def orchestrate(request: web.Request) -> web.Response:
4650 auth = request .app ["config" ].rest .auth
4751 user = None
4852 if auth is not None and auth .enabled :
49- if await check_auth (request = request , service = request .url .parts [1 ], url = str (request .url ), method = request .method ):
53+ if await check_authentication (
54+ request = request , service = request .url .parts [1 ], url = str (request .url ), method = request .method
55+ ):
5056 response = await validate_token (request )
5157 user = json .loads (response )
5258 user = user ["uuid" ]
5359
60+ if await check_authorization (
61+ request = request , service = request .url .parts [1 ], url = str (request .url ), method = request .method
62+ ):
63+ response = await validate_token (request )
64+ data = json .loads (response )
65+ user = data ["uuid" ]
66+ role = data ["role" ]
67+ if not await is_authorized_role (
68+ request = request , role = role , service = request .url .parts [1 ], url = str (request .url ), method = request .method
69+ ):
70+ return web .HTTPUnauthorized ()
71+
5472 microservice_response = await call (** discovery_data , original_req = request , user = user )
5573 return microservice_response
5674
5775
58- async def check_auth (request : web .Request , service : str , url : str , method : str ) -> bool :
59- records = Repository (request .app ["db_engine" ]).get_by_service (service )
76+ async def check_authentication (request : web .Request , service : str , url : str , method : str ) -> bool :
77+ records = Repository (request .app ["db_engine" ]).get_auth_rule_by_service (service )
78+ return AuthMatch .match (url = url , method = method , records = records )
79+
80+
81+ async def check_authorization (request : web .Request , service : str , url : str , method : str ) -> bool :
82+ records = Repository (request .app ["db_engine" ]).get_autz_rule_by_service (service )
6083 return AuthMatch .match (url = url , method = method , records = records )
6184
6285
86+ async def is_authorized_role (request : web .Request , role : int , service : str , url : str , method : str ) -> bool :
87+ records = Repository (request .app ["db_engine" ]).get_autz_rule_by_service (service )
88+ return AutzMatch .match (url = url , role = role , method = method , records = records )
89+
90+
6391async def authentication_default (request : web .Request ) -> web .Response :
6492 """ Orchestrate discovery and microservice call """
6593 auth_host = request .app ["config" ].rest .auth .host
@@ -239,9 +267,26 @@ async def get_endpoints(request: web.Request) -> web.Response:
239267 {"error" : "The requested endpoint is not available." }, status = web .HTTPServiceUnavailable .status_code
240268 )
241269
270+ @staticmethod
271+ async def get_roles (request : web .Request ) -> web .Response :
272+ auth_host = request .app ["config" ].rest .auth .host
273+ auth_port = request .app ["config" ].rest .auth .port
274+ auth_path = request .app ["config" ].rest .auth .path
275+
276+ url = URL .build (scheme = "http" , host = auth_host , port = auth_port , path = f"{ auth_path } /roles" )
277+
278+ try :
279+ async with ClientSession () as session :
280+ async with session .get (url = url ) as response :
281+ return await _clone_response (response )
282+ except ClientConnectorError :
283+ return web .json_response (
284+ {"error" : "The requested endpoint is not available." }, status = web .HTTPServiceUnavailable .status_code
285+ )
286+
242287 @staticmethod
243288 async def get_rules (request : web .Request ) -> web .Response :
244- records = Repository (request .app ["db_engine" ]).get_all ()
289+ records = Repository (request .app ["db_engine" ]).get_auth_rules ()
245290 return web .json_response (records )
246291
247292 @staticmethod
@@ -265,7 +310,7 @@ async def create_rule(request: web.Request) -> web.Response:
265310 updated_at = now ,
266311 )
267312
268- record = Repository (request .app ["db_engine" ]).create (rule )
313+ record = Repository (request .app ["db_engine" ]).create_auth_rule (rule )
269314
270315 return web .json_response (record )
271316 except Exception as e :
@@ -276,7 +321,17 @@ async def update_rule(request: web.Request) -> web.Response:
276321 try :
277322 id = int (request .url .name )
278323 content = await request .json ()
279- Repository (request .app ["db_engine" ]).update (id = id , ** content )
324+ Repository (request .app ["db_engine" ]).update_auth_rule (id = id , ** content )
325+ return web .json_response (status = web .HTTPOk .status_code )
326+ except Exception as e :
327+ return web .json_response ({"error" : str (e )}, status = web .HTTPBadRequest .status_code )
328+
329+ @staticmethod
330+ async def update_autz_rule (request : web .Request ) -> web .Response :
331+ try :
332+ id = int (request .url .name )
333+ content = await request .json ()
334+ Repository (request .app ["db_engine" ]).update_autz_rule (id = id , ** content )
280335 return web .json_response (status = web .HTTPOk .status_code )
281336 except Exception as e :
282337 return web .json_response ({"error" : str (e )}, status = web .HTTPBadRequest .status_code )
@@ -285,7 +340,54 @@ async def update_rule(request: web.Request) -> web.Response:
285340 async def delete_rule (request : web .Request ) -> web .Response :
286341 try :
287342 id = int (request .url .name )
288- Repository (request .app ["db_engine" ]).delete (id )
343+ Repository (request .app ["db_engine" ]).delete_auth_rule (id )
344+ return web .json_response (status = web .HTTPOk .status_code )
345+ except Exception as e :
346+ return web .json_response ({"error" : str (e )}, status = web .HTTPBadRequest .status_code )
347+
348+ @staticmethod
349+ async def delete_autz_rule (request : web .Request ) -> web .Response :
350+ try :
351+ id = int (request .url .name )
352+ Repository (request .app ["db_engine" ]).delete_autz_rule (id )
289353 return web .json_response (status = web .HTTPOk .status_code )
290354 except Exception as e :
291355 return web .json_response ({"error" : str (e )}, status = web .HTTPBadRequest .status_code )
356+
357+ @staticmethod
358+ async def create_autz_rule (request : web .Request ) -> web .Response :
359+ try :
360+ content = await request .json ()
361+
362+ if (
363+ "service" not in content
364+ and "rule" not in content
365+ and "roles" not in content
366+ and "methods" not in content
367+ ):
368+ return web .json_response (
369+ {"error" : "Wrong data. Provide 'service', 'rule', 'roles' and 'methods' parameters." },
370+ status = web .HTTPBadRequest .status_code ,
371+ )
372+
373+ now = datetime .now ()
374+
375+ rule = AutzRule (
376+ service = content ["service" ],
377+ rule = content ["rule" ],
378+ roles = content ["roles" ],
379+ methods = content ["methods" ],
380+ created_at = now ,
381+ updated_at = now ,
382+ )
383+
384+ record = Repository (request .app ["db_engine" ]).create_autz_rule (rule )
385+
386+ return web .json_response (record )
387+ except Exception as e :
388+ return web .json_response ({"error" : str (e )}, status = web .HTTPBadRequest .status_code )
389+
390+ @staticmethod
391+ async def get_autz_rules (request : web .Request ) -> web .Response :
392+ records = Repository (request .app ["db_engine" ]).get_autz_rules ()
393+ return web .json_response (records )
0 commit comments