def _get_cached_signatures(signature_cache, query_hash): try: s = signature_cache.get(query_hash) if s is None or s == b'': return s return make_file_response(s, f"al_signatures_{query_hash[:7]}.zip", len(s), content_type="application/zip") except Exception: # pylint: disable=W0702 LOGGER.exception('Failed to read cached signatures:') return None
def oauth_validate(**_): """ Validate and oAuth session and return it's associated username, avatar and oAuth Token Variables: None Arguments: provider => Which oAuth provider to validate the token against * => All parameters returned by your oAuth provider callback... Data Block: None Result example: { "avatar": "data:image...", "oauth_token": "123123...123213", "username": "******" } """ oauth_provider = request.values.get('provider', None) avatar = None username = None email_adr = None oauth_token = None if config.auth.oauth.enabled: oauth = current_app.extensions.get('authlib.integrations.flask_client') provider = oauth.create_client(oauth_provider) if provider: # noinspection PyBroadException try: oauth_provider_config = config.auth.oauth.providers[ oauth_provider] if oauth_provider_config.app_provider: # Validate the token that we've received using the secret token = provider.authorize_access_token( client_secret=oauth_provider_config.client_secret) # Initialize the app_provider app_provider = OAuth2Session( oauth_provider_config.app_provider.client_id or oauth_provider_config.client_id, oauth_provider_config.app_provider.client_secret or oauth_provider_config.client_secret, scope=oauth_provider_config.app_provider.scope) app_provider.fetch_token( oauth_provider_config.app_provider.access_token_url, grant_type="client_credentials") else: # Validate the token token = provider.authorize_access_token() app_provider = None user_data = None if oauth_provider_config.jwks_uri: user_data = provider.parse_id_token(token) # Get user data from endpoint if app_provider and oauth_provider_config.app_provider.user_get: url = oauth_provider_config.app_provider.user_get uid = user_data.get('id', None) if not uid and user_data and oauth_provider_config.uid_field: uid = user_data.get(oauth_provider_config.uid_field, None) if uid: url = url.format(id=uid) resp = app_provider.get(url) if resp.ok: user_data = resp.json() elif not user_data: resp = provider.get(oauth_provider_config.user_get) if resp.ok: user_data = resp.json() # Add group data if API is configured for it groups = [] if app_provider and oauth_provider_config.app_provider.group_get: url = oauth_provider_config.app_provider.group_get uid = user_data.get('id', None) if not uid and user_data and oauth_provider_config.uid_field: uid = user_data.get(oauth_provider_config.uid_field, None) if uid: url = url.format(id=uid) resp_grp = app_provider.get(url) if resp_grp.ok: groups = resp_grp.json() elif oauth_provider_config.user_groups: resp_grp = provider.get(oauth_provider_config.user_groups) if resp_grp.ok: groups = resp_grp.json() if groups: if oauth_provider_config.user_groups_data_field: groups = groups[ oauth_provider_config.user_groups_data_field] if oauth_provider_config.user_groups_name_field: groups = [ x[oauth_provider_config.user_groups_name_field] for x in groups ] user_data['groups'] = groups if user_data: data = parse_profile(user_data, oauth_provider_config) has_access = data.pop('access', False) if has_access and data['email'] is not None: oauth_avatar = data.pop('avatar', None) # Find if user already exists users = STORAGE.user.search(f"email:{data['email']}", fl="*", as_obj=False)['items'] if users: cur_user = users[0] # Do not update username and password from the current user data['uname'] = cur_user.get( 'uname', data['uname']) data['password'] = cur_user.get( 'password', data['password']) else: if data['uname'] != data['email']: # Username was computed using a regular expression, lets make sure we don't # assign the same username to two users res = STORAGE.user.search( f"uname:{data['uname']}", rows=0, as_obj=False) if res['total'] > 0: cnt = res['total'] new_uname = f"{data['uname']}{cnt}" while STORAGE.user.get( new_uname) is not None: cnt += 1 new_uname = f"{data['uname']}{cnt}" data['uname'] = new_uname cur_user = {} username = data['uname'] email_adr = data['email'] # Add add dynamic classification group data['classification'] = get_dynamic_classification( data['classification'], data['email']) # Make sure the user exists in AL and is in sync if (not cur_user and oauth_provider_config.auto_create) or \ (cur_user and oauth_provider_config.auto_sync): # Update the current user cur_user.update(data) # Save avatar if oauth_avatar: avatar = fetch_avatar(oauth_avatar, provider, oauth_provider_config) if avatar: STORAGE.user_avatar.save(username, avatar) # Save updated user STORAGE.user.save(username, cur_user) if cur_user: if avatar is None: avatar = STORAGE.user_avatar.get( username ) or "/static/images/user_default.png" oauth_token = hashlib.sha256( str(token).encode( "utf-8", errors='replace')).hexdigest() get_token_store(username).add(oauth_token) else: return make_api_response( {"err_code": 3}, err="User auto-creation is disabled", status_code=403) else: return make_api_response( {"err_code": 2}, err="This user is not allowed access to the system", status_code=403) except OAuthError as err: return make_api_response({"err_code": 1}, err=str(err), status_code=401) except Exception as err: LOGGER.exception(str(err)) return make_api_response( { "err_code": 1, "exception": str(err) }, err= "Unhandled exception occured while processing oAuth token", status_code=401) if username is None: return make_api_response({"err_code": 0}, err="oAuth disabled on the server", status_code=401) return make_api_response({ "avatar": avatar, "username": username, "oauth_token": oauth_token, "email_adr": email_adr })
# TODO: this needs testing that can only be done when a service datasource is available. path = cfg cfg = config for point in path.split('.'): if 'enabled' in cfg: if not cfg['enabled']: raise SkipDatasource() cfg = cfg.get(point) cls = load_module_by_path(classpath) obj = cls(LOGGER, **cfg) sources[name] = create_query_datasource(obj) except SkipDatasource: continue except Exception: LOGGER.exception( "Problem creating %s datasource (%s)", name, classpath ) except Exception: LOGGER.exception("No datasources") # noinspection PyUnusedLocal @hash_search_api.route("/<file_hash>/", methods=["GET"]) @api_login(required_priv=['R']) def search_hash(file_hash, *args, **kwargs): """ Search for a hash in multiple data sources as configured in the seed. Variables: file_hash => Hash to search in the multiple data sources [MD5, SHA1 or SHA256]