|
2 | 2 | from base64 import urlsafe_b64encode
|
3 | 3 |
|
4 | 4 | from satosa.context import Context
|
| 5 | +from satosa.internal import InternalData |
| 6 | + |
5 | 7 | from .base import RequestMicroService
|
6 | 8 | from ..exception import SATOSAConfigurationError
|
7 | 9 | from ..exception import SATOSAError
|
|
10 | 12 | logger = logging.getLogger(__name__)
|
11 | 13 |
|
12 | 14 |
|
| 15 | +class DecideBackendByTarget(RequestMicroService): |
| 16 | + """ |
| 17 | + Select which backend should be used based on who is the SAML IDP |
| 18 | + """ |
| 19 | + |
| 20 | + def __init__(self, config, *args, **kwargs): |
| 21 | + """ |
| 22 | + Constructor. |
| 23 | + :param config: microservice configuration loaded from yaml file |
| 24 | + :type config: Dict[str, Dict[str, str]] |
| 25 | + """ |
| 26 | + super().__init__(*args, **kwargs) |
| 27 | + self.target_mapping = config['target_mapping'] |
| 28 | + self.endpoint_path = config['endpoint_path'] |
| 29 | + |
| 30 | + def register_endpoints(self): |
| 31 | + """ |
| 32 | + URL mapping of additional endpoints this micro service needs to register for callbacks. |
| 33 | +
|
| 34 | + Example of a mapping from the url path '/callback' to the callback() method of a micro service: |
| 35 | + reg_endp = [ |
| 36 | + ("^/callback1$", self.callback), |
| 37 | + ] |
| 38 | +
|
| 39 | + :rtype List[Tuple[str, Callable[[satosa.context.Context, Any], satosa.response.Response]]] |
| 40 | +
|
| 41 | + :return: A list with functions and args bound to a specific endpoint url, |
| 42 | + [(regexp, Callable[[satosa.context.Context], satosa.response.Response]), ...] |
| 43 | + """ |
| 44 | + |
| 45 | + # this intercepts disco response |
| 46 | + return [ |
| 47 | + (self.endpoint_path , self.backend_by_entityid), |
| 48 | + ] |
| 49 | + |
| 50 | + def backend_by_entityid(self, context): |
| 51 | + entity_id = context.request.get('entityID') |
| 52 | + tr_backend = self.target_mapping.get(entity_id) |
| 53 | + |
| 54 | + if not all((context.request, |
| 55 | + entity_id, |
| 56 | + entity_id in self.target_mapping.keys(), |
| 57 | + tr_backend)): |
| 58 | + return |
| 59 | + |
| 60 | + context.internal_data['target_entity_id'] = entity_id |
| 61 | + context.target_frontend = context.state['ROUTER'] |
| 62 | + |
| 63 | + data_serialized = context.state.get(self.name, {}).get("internal", {}) |
| 64 | + data = InternalData.from_dict(data_serialized) |
| 65 | + |
| 66 | + native_backend = context.target_backend |
| 67 | + msg = (f'Found DecideBackendByTarget ({self.name} microservice) ' |
| 68 | + f'redirecting {entity_id} from {native_backend} ' |
| 69 | + f'backend to {tr_backend}') |
| 70 | + logger.info(msg) |
| 71 | + context.target_backend = tr_backend |
| 72 | + return super().process(context, data) |
| 73 | + |
| 74 | + |
13 | 75 | class DecideBackendByRequester(RequestMicroService):
|
14 | 76 | """
|
15 | 77 | Select which backend should be used based on who the requester is.
|
|
0 commit comments