Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
1f8dcea
Fix auth serializer to handle byte encoding and decoding
Feb 24, 2026
62563df
Enhance task_hook_wrapper to support both dict and legacy string form…
Feb 26, 2026
8f39350
Update hmac_verify to use CELERY__ prefix for security key retrieval
Feb 26, 2026
eb35166
Merge branch 'test-modules' of github.com:PROCYDE/iris-web into test-…
Feb 26, 2026
2c0fde0
Refactor hmac_verify to retrieve security key from Flask config or en…
Feb 26, 2026
a463e54
Merge branch 'test-modules' of github.com:PROCYDE/iris-web into test-…
Feb 26, 2026
320629c
Refactor hmac_sign and hmac_verify to retrieve the security key from …
Feb 26, 2026
f001c7b
Refactor hmac_verify to prioritize environment variable for security …
Feb 26, 2026
1f44247
Merge branch 'test-modules' of github.com:PROCYDE/iris-web into test-…
Feb 27, 2026
cfa4023
Enhance security key retrieval in hmac_sign and hmac_verify functions
Feb 27, 2026
5a9f40b
Add custom JSON encoder for Celery auth serializer to handle IIStatus…
Feb 27, 2026
4b7f9bf
Add detailed response structure for task status in task_hook_wrapper
Feb 27, 2026
45ba7a1
Merge branch 'test-modules' of github.com:PROCYDE/iris-web into test-…
Mar 2, 2026
77eaaa0
Refactor JSON serialization in _register_auth_serializer to handle va…
Mar 2, 2026
fb80bd3
Merge branch 'test-modules' of github.com:PROCYDE/iris-web into test-…
Mar 2, 2026
e6fa3cc
Remove custom JSON serializer registration from Celery setup
Mar 2, 2026
bf71d7d
Add a blank line before hmac_sign function for improved readability
Mar 2, 2026
627364f
Merge branch 'test-modules' of github.com:PROCYDE/iris-web into test-…
Mar 2, 2026
2a3e307
SIEM-12855: Register auth serializer with SQLAlchemy support and chec…
Mar 2, 2026
63bdfee
SIEM-12855: Always register auth serializer, only call setup_security…
Mar 2, 2026
273044c
Revert "SIEM-12855: Always register auth serializer, only call setup_…
Mar 2, 2026
a3b979a
Remove unused auth serializer registration from Celery setup
Mar 3, 2026
52e3fb1
Register auth serializer with JSON encoding and decoding before setup…
Mar 3, 2026
692a41f
refactor(celery): use imported timezone directly
Mar 3, 2026
4741ada
feat(celery): implement certificate loading patch for compatibility w…
Mar 3, 2026
e4b7cd3
fix(celery): enhance certificate loading to handle malformed framing …
Mar 3, 2026
d7cb558
Merge branch 'SIEM-12855-celery-auth-serializer' of github.com:PROCYD…
Mar 3, 2026
b21d500
fix(celery): improve error handling in certificate loading to avoid c…
Mar 3, 2026
dd33bc7
fix(celery): update certificate handling and improve auth serializati…
Mar 3, 2026
91784f0
chore(celery): add missing import for os module
Mar 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 43 additions & 7 deletions source/app/iris_engine/module_handler/module_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import traceback
from datetime import datetime, date

import base64
import importlib
Expand All @@ -28,6 +29,27 @@

from app import app
from app.blueprints.iris_user import iris_current_user


def _serialize_value(obj):
if obj is None:
return None
if isinstance(obj, (datetime, date)):
return obj.isoformat()
if isinstance(obj, dict):
return {k: _serialize_value(v) for k, v in obj.items()}
if isinstance(obj, (list, tuple)):
return [_serialize_value(item) for item in obj]
if hasattr(obj, '__dict__'):
result = {}
for key, value in obj.__dict__.items():
if key.startswith('_sa_'):
continue
result[key] = _serialize_value(value)
return result
if hasattr(obj, '__iter__'):
return str(obj)
return obj
from app.logger import logger
from app import celery
from app import db
Expand Down Expand Up @@ -427,13 +449,20 @@ def task_hook_wrapper(self, module_name, hook_name, hook_ui_name, data, init_use
"""
try:
# Data is serialized, so deserialized
signature, pdata = data.encode("utf-8").split(b" ")
is_verified = hmac_verify(signature, pdata)
if is_verified is False:
logger.warning("data argument has not been correctly serialised")
raise Exception('Unable to instantiate target module. Data has not been correctly serialised')

deser_data = loads(base64.b64decode(pdata))
# Support both formats:
# 1. Dict (when using auth serializer with security enabled)
# 2. String with HMAC signature (legacy format)
if isinstance(data, dict):
# Auth serializer - data is already a dict
deser_data = data
else:
# Legacy format with HMAC signature
signature, pdata = data.encode("utf-8").split(b" ")
is_verified = hmac_verify(signature, pdata)
if is_verified is False:
logger.warning("data argument has not been correctly serialised")
raise Exception('Unable to instantiate target module. Data has not been correctly serialised')
deser_data = loads(base64.b64decode(pdata))

except Exception as e:
logger.exception(e)
Expand Down Expand Up @@ -487,6 +516,13 @@ def task_hook_wrapper(self, module_name, hook_name, hook_ui_name, data, init_use
logger.exception(e)
task_status = IStatus.I2Error(message=msg, logs=[traceback.format_exc()], user=init_user, caseid=caseid)

if hasattr(task_status, '__dict__'):
return {
'code': task_status.code,
'message': task_status.message,
'data': _serialize_value(task_status.data),
'logs': task_status.logs
}
return task_status


Expand Down
56 changes: 52 additions & 4 deletions source/app/iris_engine/tasker/celery.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.


import os
from celery import Celery
from celery.security import setup_security
from kombu.serialization import register
from app.configuration import CeleryConfig


def _patch_celery_cert_datetime():
import datetime
from celery.security.certificate import Certificate
Expand All @@ -39,25 +42,70 @@ def _patched_has_expired(self):

def _register_auth_serializer():
import json
from datetime import datetime, date

def _serialize_value(obj):
if obj is None:
return None
if isinstance(obj, (datetime, date)):
return obj.isoformat()
if isinstance(obj, dict):
return {k: _serialize_value(v) for k, v in obj.items()}
if isinstance(obj, (list, tuple)):
return [_serialize_value(item) for item in obj]
if hasattr(obj, '__dict__'):
result = {}
for key, value in obj.__dict__.items():
if key.startswith('_sa_'):
continue
result[key] = _serialize_value(value)
return result
if hasattr(obj, '__iter__'):
return str(obj)
return obj

class _CeleryJsonEncoder(json.JSONEncoder):
def default(self, obj):
return _serialize_value(obj)

def _encode_auth(data):
return json.dumps(data), 'application/auth'
return json.dumps(data, cls=_CeleryJsonEncoder).encode('utf-8'), 'application/auth'

def _decode_auth(data):
if isinstance(data, bytes):
data = data.decode('utf-8')
return json.loads(data)

register('auth', _encode_auth, _decode_auth, content_type='application/auth')


def make_celery(name):
_register_auth_serializer()
def _check_certificate_files():
key_path = CeleryConfig.security_key
cert_path = CeleryConfig.security_certificate
store_path = CeleryConfig.security_cert_store

if not key_path or not cert_path or not store_path:
return False

if not os.path.exists(key_path):
return False
if not os.path.exists(cert_path):
return False
if not os.path.exists(store_path):
return False

return True


def make_celery(name):
celery_app = Celery(
name,
config_source=CeleryConfig
)

if CeleryConfig.security_key and CeleryConfig.security_certificate:
_register_auth_serializer()

if _check_certificate_files():
_patch_celery_cert_datetime()
setup_security(
allowed_serializers=['auth'],
Expand Down
5 changes: 4 additions & 1 deletion source/app/iris_engine/tasker/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@

@task_prerun.connect
def on_task_init(*args, **kwargs):
db.engine.dispose()
try:
db.engine.dispose()
except Exception:
pass


def task_case_update(module, pipeline, pipeline_args, caseid):
Expand Down
23 changes: 21 additions & 2 deletions source/app/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,18 @@ def add_obj_history_entry(obj, action, commit=False):
return obj



def hmac_sign(data):
key = bytes(current_app.config.get("SECRET_KEY"), "utf-8")
import os
key = os.environ.get("SECRET_KEY")
if not key:
try:
key = current_app.config.get("SECRET_KEY")
except:
pass
if not key:
raise ValueError("SECRET_KEY not available")
key = bytes(key, "utf-8")
h = hmac.HMAC(key, hashes.SHA256())
h.update(data)
signature = base64.b64encode(h.finalize())
Expand All @@ -89,8 +99,17 @@ def hmac_sign(data):


def hmac_verify(signature_enc, data):
import os
signature = base64.b64decode(signature_enc)
key = bytes(current_app.config.get("SECRET_KEY"), "utf-8")
key = os.environ.get("SECRET_KEY")
if not key:
try:
key = current_app.config.get("SECRET_KEY")
except:
pass
if not key:
return False
key = bytes(key, "utf-8")
h = hmac.HMAC(key, hashes.SHA256())
h.update(data)

Expand Down
Loading