Skip to content

Commit

Permalink
Merge 6160562 into d498fe3
Browse files Browse the repository at this point in the history
  • Loading branch information
wphyojpl authored Oct 25, 2022
2 parents d498fe3 + 6160562 commit 8d57d81
Show file tree
Hide file tree
Showing 22 changed files with 682 additions and 1 deletion.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from abc import ABC, abstractmethod


class UDSAuthorizorAbstract(ABC):
@abstractmethod
def add_authorized_group(self, action: [str], project: str, venue: str, ldap_group_name: str):
return

@abstractmethod
def delete_authorized_group(self, project: str, venue: str, ldap_group_name: str):
return

@abstractmethod
def list_authorized_groups_for(self, project: str, venue: str):
return

@abstractmethod
def update_authorized_group(self, action: [str], project: str, venue: str, ldap_group_name: str):
return

@abstractmethod
def get_authorized_tenant(self, username: str, action: str) -> list:
return []
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import logging
import os

from cumulus_lambda_functions.lib.authorization.uds_authorizer_abstract import UDSAuthorizorAbstract
from cumulus_lambda_functions.lib.aws.aws_cognito import AwsCognito
from cumulus_lambda_functions.lib.aws.es_abstract import ESAbstract
from cumulus_lambda_functions.lib.aws.es_factory import ESFactory
from cumulus_lambda_functions.lib.uds_db.db_constants import DBConstants

LOGGER = logging.getLogger(__name__)


class UDSAuthorizorEsIdentityPool(UDSAuthorizorAbstract):

def __init__(self, user_pool_id: str) -> None:
super().__init__()
es_url = os.getenv('ES_URL') # TODO validation
self.__authorization_index = os.getenv('AUTHORIZATION_INDEX') # LDAP_Group_Permission
es_port = int(os.getenv('ES_PORT', '443'))
self.__cognito = AwsCognito(user_pool_id)
self.__es: ESAbstract = ESFactory().get_instance('AWS',
index=self.__authorization_index,
base_url=es_url,
port=es_port)

def add_authorized_group(self, action: [str], project: str, venue: str, ldap_group_name: str):
self.__es.index_one({
DBConstants.action_key: action,
DBConstants.project: project,
DBConstants.project_venue: venue,
DBConstants.authorized_group_name_key: ldap_group_name,
}, f'{project}__{venue}__{ldap_group_name}', self.__authorization_index)
return

def delete_authorized_group(self, project: str, venue: str, ldap_group_name: str):
self.__es.delete_by_query({
'query': {
'bool': {
'must': [
{'term': {DBConstants.project: project}},
{'term': {DBConstants.project_venue: venue}},
{'term': {DBConstants.authorized_group_name_key: ldap_group_name}},
]
}
}
})
return

def list_authorized_groups_for(self, project: str, venue: str):
result = self.__es.query_pages({
'query': {
'bool': {
'must': [
{'term': {DBConstants.project: project}},
{'term': {DBConstants.project_venue: venue}},
]
}
},
'sort': [
{DBConstants.project: {'order': 'asc'}},
{DBConstants.project_venue: {'order': 'asc'}},
{DBConstants.authorized_group_name_key: {'order': 'asc'}},
]
})
result = [k['_source'] for k in result['hits']['hits']]
return result

def update_authorized_group(self, action: [str], project: str, venue: str, ldap_group_name: str):
self.__es.update_one({
DBConstants.action_key: action,
DBConstants.project: project,
DBConstants.project_venue: venue,
DBConstants.authorized_group_name_key: ldap_group_name,
}, f'{project}__{venue}__{ldap_group_name}', self.__authorization_index)
return

def get_authorized_tenant(self, username: str, action: str) -> list:
belonged_groups = set(self.__cognito.get_groups(username))

authorized_groups = self.__es.query({
'query': {
'bool': {
'must': [
{
'terms': {
DBConstants.authorized_group_name_key: list(belonged_groups),
}
},
{
'term': {
DBConstants.action_key: action,
}
}
]
}
}
})
return [k['_source'] for k in authorized_groups['hits']['hits']]

def authorize(self, username, resource, action) -> bool:
belonged_groups = set(self.__cognito.get_groups(username))
authorized_groups = self.__es.query({
'query': {
'match_all': {} # TODO
}
})
LOGGER.debug(f'belonged_groups for {username}: {belonged_groups}')
authorized_groups = set([k['_source']['group_name'] for k in authorized_groups['hits']['hits']])
LOGGER.debug(f'authorized_groups for {resource}-{action}: {authorized_groups}')
if any([k in authorized_groups for k in belonged_groups]):
LOGGER.debug(f'{username} is authorized for {resource}-{action}')
return True
LOGGER.debug(f'{username} is NOT authorized for {resource}-{action}')
return False
20 changes: 20 additions & 0 deletions cumulus_lambda_functions/lib/aws/aws_cognito.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from cumulus_lambda_functions.lib.aws.aws_cred import AwsCred


class AwsCognito(AwsCred):
def __init__(self, user_pool_id: str):
super().__init__()
self.__cognito = self.get_client('cognito-idp')
self.__user_pool_id = user_pool_id

def get_groups(self, username: str):
response = self.__cognito.admin_list_groups_for_user(
Username=username,
UserPoolId=self.__user_pool_id,
Limit=60,
# NextToken='string'
)
if response is None or 'Groups' not in response:
return []
belonged_groups = [k['GroupName'] for k in response['Groups']]
return belonged_groups
16 changes: 16 additions & 0 deletions cumulus_lambda_functions/lib/aws/aws_cred.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,19 @@ def __init__(self):
else:
LOGGER.debug('using default session as there is no aws_access_key_id')

@property
def region(self):
return self.__region

@region.setter
def region(self, val):
"""
:param val:
:return: None
"""
self.__region = val
return

@property
def boto3_session(self):
return self.__boto3_session
Expand All @@ -56,6 +69,9 @@ def boto3_session(self, val):
self.__boto3_session = val
return

def get_session(self):
return boto3.Session(**self.boto3_session)

def get_resource(self, service_name: str):
return boto3.Session(**self.boto3_session).resource(service_name)

Expand Down
63 changes: 63 additions & 0 deletions cumulus_lambda_functions/lib/aws/es_abstract.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from abc import ABC, abstractmethod
from typing import Any, Union, Callable

DEFAULT_TYPE = '_doc'


class ESAbstract(ABC):
@abstractmethod
def create_index(self, index_name, index_body):
return

@abstractmethod
def has_index(self, index_name):
return

@abstractmethod
def create_alias(self, index_name, alias_name):
return

@abstractmethod
def delete_index(self, index_name):
return

@abstractmethod
def index_many(self, docs=None, doc_ids=None, doc_dict=None, index=None):
return

@abstractmethod
def index_one(self, doc, doc_id, index=None):
return

@abstractmethod
def update_many(self, docs=None, doc_ids=None, doc_dict=None, index=None):
return

@abstractmethod
def update_one(self, doc, doc_id, index=None):
return

@staticmethod
@abstractmethod
def get_result_size(result):
return

@abstractmethod
def query_with_scroll(self, dsl, querying_index=None):
return

@abstractmethod
def query(self, dsl, querying_index=None):
return

@abstractmethod
def delete_by_query(self, dsl, querying_index=None):
return

@abstractmethod
def query_pages(self, dsl, querying_index=None):
return

@abstractmethod
def query_by_id(self, doc_id):
return
16 changes: 16 additions & 0 deletions cumulus_lambda_functions/lib/aws/es_factory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from cumulus_lambda_functions.lib.aws.factory_abstract import FactoryAbstract


class ESFactory(FactoryAbstract):
NO_AUTH = 'NO_AUTH'
AWS = 'AWS'

def get_instance(self, class_type, **kwargs):
ct = class_type.upper()
if ct == self.NO_AUTH:
from cumulus_lambda_functions.lib.aws.es_middleware import ESMiddleware
return ESMiddleware(kwargs['index'], kwargs['base_url'], port=kwargs['port'])
if ct == self.AWS:
from cumulus_lambda_functions.lib.aws.es_middleware_aws import EsMiddlewareAws
return EsMiddlewareAws(kwargs['index'], kwargs['base_url'], port=kwargs['port'])
raise ModuleNotFoundError(f'cannot find ES class for {ct}')
Loading

0 comments on commit 8d57d81

Please sign in to comment.