diff --git a/exercise.py b/exercise.py index 0971f97..f00ecdc 100644 --- a/exercise.py +++ b/exercise.py @@ -2,7 +2,6 @@ import functools import time -from collections import defaultdict from pathlib import Path import json import re @@ -312,9 +311,9 @@ def get_progress(): return progress -def check_inject(user_id: int, inject: dict, data: dict, context: dict) -> bool: +async def check_inject(user_id: int, inject: dict, data: dict, context: dict) -> bool: for inject_evaluation in inject['inject_evaluation']: - success = inject_checker_router(user_id, inject_evaluation, data, context) + success = await inject_checker_router(user_id, inject_evaluation, data, context) if not success: logger.info(f"Task not completed: {inject['uuid']}") return False @@ -338,14 +337,14 @@ def is_valid_evaluation_context(user_id: int, inject_evaluation: dict, data: dic return False return False -def inject_checker_router(user_id: int, inject_evaluation: dict, data: dict, context: dict) -> bool: +async def inject_checker_router(user_id: int, inject_evaluation: dict, data: dict, context: dict) -> bool: if not is_valid_evaluation_context(user_id, inject_evaluation, data, context): return False if 'evaluation_strategy' not in inject_evaluation: return False - data_to_validate = get_data_to_validate(user_id, inject_evaluation, data) + data_to_validate = await get_data_to_validate(user_id, inject_evaluation, data) if data_to_validate is None: logger.debug('Could not fetch data to validate') return False @@ -361,16 +360,16 @@ def inject_checker_router(user_id: int, inject_evaluation: dict, data: dict, con return False -def get_data_to_validate(user_id: int, inject_evaluation: dict, data: dict) -> Union[dict, list, str, None]: +async def get_data_to_validate(user_id: int, inject_evaluation: dict, data: dict) -> Union[dict, list, str, None]: data_to_validate = None if inject_evaluation['evaluation_strategy'] == 'data_filtering': event_id = parse_event_id_from_log(data) - data_to_validate = fetch_data_for_data_filtering(event_id=event_id) + data_to_validate = await fetch_data_for_data_filtering(event_id=event_id) elif inject_evaluation['evaluation_strategy'] == 'query_mirror': perfomed_query = parse_performed_query_from_log(data) - data_to_validate = fetch_data_for_query_mirror(user_id, inject_evaluation, perfomed_query) + data_to_validate = await fetch_data_for_query_mirror(user_id, inject_evaluation, perfomed_query) elif inject_evaluation['evaluation_strategy'] == 'query_search': - data_to_validate = fetch_data_for_query_search(user_id, inject_evaluation) + data_to_validate = await fetch_data_for_query_search(user_id, inject_evaluation) return data_to_validate @@ -416,14 +415,14 @@ def parse_performed_query_from_log(data: dict) -> Union[dict, None]: return None -def fetch_data_for_data_filtering(event_id=None) -> Union[None, dict]: +async def fetch_data_for_data_filtering(event_id=None) -> Union[None, dict]: data = None if event_id is not None: - data = misp_api.getEvent(event_id) + data = await misp_api.getEvent(event_id) return data -def fetch_data_for_query_mirror(user_id: int, inject_evaluation: dict, perfomed_query: dict) -> Union[None, dict]: +async def fetch_data_for_query_mirror(user_id: int, inject_evaluation: dict, perfomed_query: dict) -> Union[None, dict]: data = None authkey = db.USER_ID_TO_AUTHKEY_MAPPING[user_id] if perfomed_query is not None: @@ -433,8 +432,8 @@ def fetch_data_for_query_mirror(user_id: int, inject_evaluation: dict, perfomed_ expected_method = query_context['request_method'] expected_url = query_context['url'] expected_payload = inject_evaluation['parameters'][0] - expected_data = misp_api.doRestQuery(authkey, expected_method, expected_url, expected_payload) - data_to_validate = misp_api.doRestQuery(authkey, perfomed_query['request_method'], perfomed_query['url'], perfomed_query['payload']) + expected_data = await misp_api.doRestQuery(authkey, expected_method, expected_url, expected_payload) + data_to_validate = await misp_api.doRestQuery(authkey, perfomed_query['request_method'], perfomed_query['url'], perfomed_query['payload']) data = { 'expected_data' : expected_data, 'data_to_validate' : data_to_validate, @@ -442,20 +441,20 @@ def fetch_data_for_query_mirror(user_id: int, inject_evaluation: dict, perfomed_ return data -def fetch_data_for_query_search(user_id: int, inject_evaluation: dict) -> Union[None, dict]: +async def fetch_data_for_query_search(user_id: int, inject_evaluation: dict) -> Union[None, dict]: authkey = db.USER_ID_TO_AUTHKEY_MAPPING[user_id] if 'evaluation_context' not in inject_evaluation and 'query_context' not in inject_evaluation['evaluation_context']: return None query_context = inject_evaluation['evaluation_context']['query_context'] search_method = query_context['request_method'] search_url = query_context['url'] - search_payload = inject_evaluation['payload'] - search_data = misp_api.doRestQuery(authkey, search_method, search_url, search_payload) + search_payload = query_context['payload'] + search_data = await misp_api.doRestQuery(authkey, search_method, search_url, search_payload) return search_data @debounce_check_active_tasks(debounce_seconds=2) -def check_active_tasks(user_id: int, data: dict, context: dict) -> bool: +async def check_active_tasks(user_id: int, data: dict, context: dict) -> bool: succeeded_once = False available_tasks = get_available_tasks_for_user(user_id) for task_uuid in available_tasks: @@ -463,7 +462,7 @@ def check_active_tasks(user_id: int, data: dict, context: dict) -> bool: if inject['exercise_uuid'] not in db.SELECTED_EXERCISES: continue logger.debug(f"[{task_uuid}] :: checking: {inject['name']}") - completed = check_inject(user_id, inject, data, context) + completed = await check_inject(user_id, inject, data, context) if completed: succeeded_once = True return succeeded_once \ No newline at end of file diff --git a/exercises/basic-event-creation.json b/exercises/basic-event-creation.json index 6def47b..bee3a29 100644 --- a/exercises/basic-event-creation.json +++ b/exercises/basic-event-creation.json @@ -138,15 +138,15 @@ { "parameters": [ { - ".Event.user_id": { + ".response[].Event.event_creator_email": { "comparison": "equals", "values": [ - "{{user_id}}" + "{{user_email}}" ] } }, { - ".Event.info": { + ".response[].Event.info": { "comparison": "contains", "values": [ "event", diff --git a/inject_evaluator.py b/inject_evaluator.py index fb66403..ecab64e 100644 --- a/inject_evaluator.py +++ b/inject_evaluator.py @@ -17,6 +17,8 @@ def jq_extract(path: str, data: dict, extract_type='first'): # Replace the substring `{{variable}}` by context[variable] in the provided string def apply_replacement_from_context(string: str, context: dict) -> str: replacement_regex = r"{{(\w+)}}" + if r'{{' not in string and r'}}' not in string: + return string matches = re.fullmatch(replacement_regex, string, re.MULTILINE) if not matches: return string diff --git a/server.py b/server.py index e6e3210..d692cbd 100755 --- a/server.py +++ b/server.py @@ -51,7 +51,7 @@ zsocket.setsockopt_string(zmq.SUBSCRIBE, '') # Initialize Socket.IO server # sio = socketio.Server(cors_allowed_origins='*', async_mode='eventlet') -sio = socketio.AsyncServer(cors_allowed_origins='*', async_mode='aiohttp', logger=True, engineio_logger=True) +sio = socketio.AsyncServer(cors_allowed_origins='*', async_mode='aiohttp') app = web.Application() sio.attach(app) @@ -146,8 +146,8 @@ async def handleMessage(topic, s, message): user_id = notification_model.get_user_id(data) if user_id is not None: if exercise_model.is_accepted_query(data): - context = get_context(user_id, data) - succeeded_once = exercise_model.check_active_tasks(user_id, data, context) + context = get_context(topic, user_id, data) + succeeded_once = await exercise_model.check_active_tasks(user_id, data, context) if succeeded_once: await sendRefreshScore() @@ -157,9 +157,12 @@ async def sendRefreshScore(): await sio.emit('refresh_score') -def get_context(user_id: int, data: dict) -> dict: +def get_context(topic: str, user_id: int, data: dict) -> dict: context = { + 'zmq_topic': topic, 'user_id': user_id, + 'user_email': db.USER_ID_TO_EMAIL_MAPPING.get(user_id, None), + 'user_authkey': db.USER_ID_TO_AUTHKEY_MAPPING.get(user_id, None), } if 'Log' in data: if 'request_is_rest' in data['Log']: @@ -208,7 +211,6 @@ async def forward_zmq_to_socketio(): ZMQ_LAST_TIME = time.time() # await handleMessage(topic, s, m) except Exception as e: - print(e) logger.error('Error handling message %s', e) diff --git a/src/components/TheSocketConnectionState.vue b/src/components/TheSocketConnectionState.vue index f739fa3..393df35 100644 --- a/src/components/TheSocketConnectionState.vue +++ b/src/components/TheSocketConnectionState.vue @@ -2,10 +2,14 @@ import { ref, onMounted } from "vue" import { socketConnected, zmqLastTime } from "@/socket"; - const zmqLastTimeSecond = ref(0) + const zmqLastTimeSecond = ref('?') function refreshLastTime() { - zmqLastTimeSecond.value = parseInt(((new Date()).getTime() - zmqLastTime.value * 1000) / 1000) + if (zmqLastTime.value !== false) { + zmqLastTimeSecond.value = parseInt(((new Date()).getTime() - zmqLastTime.value * 1000) / 1000) + } else { + zmqLastTimeSecond.value = '?' + } } onMounted(() => {