Sentry file, and header linting hints
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
# flake8: noqa: E203,E501,W503
|
||||
# pylint: disable=C0413,W0718,R0903,R0801
|
||||
# mypy: disable-error-code=unused-awaitable
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# flake8: noqa: E203,E501,W503
|
||||
# pylint: disable=C0413,W0718,R0903,R0801
|
||||
# mypy: disable-error-code=unused-awaitable
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# flake8: noqa: E203,E501,W503
|
||||
# pylint: disable=C0413,W0718,R0903,R0801
|
||||
# mypy: disable-error-code=unused-awaitable
|
||||
"""Binwalk Analyzer for Image Submissions."""
|
||||
|
||||
import shutil
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# flake8: noqa: E203,E501,W503
|
||||
# pylint: disable=C0413,W0718,R0903,R0801
|
||||
# mypy: disable-error-code=unused-awaitable
|
||||
"""Bits Decomposer Analyzer for Image Submissions."""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# flake8: noqa: E203,E501,W503
|
||||
# pylint: disable=C0413,W0718,R0903,R0801
|
||||
# mypy: disable-error-code=unused-awaitable
|
||||
"""Exiftool Analyzer for Image Submissions."""
|
||||
|
||||
import subprocess
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# flake8: noqa: E203,E501,W503
|
||||
# pylint: disable=C0413,W0718,R0903,R0801
|
||||
# mypy: disable-error-code=unused-awaitable
|
||||
"""Foremost Analyzer for Image Submissions."""
|
||||
|
||||
import shutil
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# flake8: noqa: E203,E501,W503
|
||||
# pylint: disable=C0413,W0718,R0903,R0801
|
||||
# mypy: disable-error-code=unused-awaitable
|
||||
"""Image size bruteforcer for common PNG sizes."""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# flake8: noqa: E203,E501,W503
|
||||
# pylint: disable=C0413,W0718,R0903,R0801
|
||||
# mypy: disable-error-code=unused-awaitable
|
||||
"""OpenStego Analyzer for Image Submissions."""
|
||||
|
||||
import shutil
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# flake8: noqa: E203,E501,W503
|
||||
# pylint: disable=C0413,W0718,R0903,R0801
|
||||
# mypy: disable-error-code=unused-awaitable
|
||||
"""Outguess Analyzer for Image Submissions."""
|
||||
|
||||
import shutil
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# flake8: noqa: E203,E501,W503
|
||||
# pylint: disable=C0413,W0718,R0903,R0801
|
||||
# mypy: disable-error-code=unused-awaitable
|
||||
"""Pngcheck Analyzer for Image Submissions."""
|
||||
|
||||
import subprocess
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# flake8: noqa: E203,E501,W503
|
||||
# pylint: disable=C0413,W0718,R0903,R0801
|
||||
# mypy: disable-error-code=unused-awaitable
|
||||
"""Steghide Analyzer for Image Submissions."""
|
||||
|
||||
import re
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# flake8: noqa: E203,E501,W503
|
||||
# pylint: disable=C0413,W0718,R0903,R0801
|
||||
# mypy: disable-error-code=unused-awaitable
|
||||
"""Strings Analyzer for Image Submissions."""
|
||||
|
||||
import subprocess
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# flake8: noqa: E203,E501,W503
|
||||
# pylint: disable=C0413,W0718,R0903,R0801
|
||||
# mypy: disable-error-code=unused-awaitable
|
||||
"""Custom Analyzer for Image Submissions."""
|
||||
|
||||
import shutil
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# flake8: noqa: E203,E501,W503
|
||||
# pylint: disable=C0413,W0718,R0903,R0801
|
||||
# mypy: disable-error-code=unused-awaitable
|
||||
"""Utility functions for analyzers modules."""
|
||||
|
||||
import fcntl
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# flake8: noqa: E203,E501,W503
|
||||
# pylint: disable=C0413,W0718,R0903,R0801
|
||||
# mypy: disable-error-code=unused-awaitable
|
||||
"""Zsteg Analyzer for Image Submissions."""
|
||||
|
||||
import subprocess
|
||||
|
||||
+7
-32
@@ -1,3 +1,6 @@
|
||||
# flake8: noqa: E203,E501,W503
|
||||
# pylint: disable=C0413,W0718,R0903,R0801
|
||||
# mypy: disable-error-code=unused-awaitable
|
||||
"""Aperi'Solve Flask application."""
|
||||
|
||||
import hashlib
|
||||
@@ -9,46 +12,18 @@ from pathlib import Path
|
||||
from typing import Any, Optional
|
||||
|
||||
import sentry_sdk
|
||||
from sentry_sdk.integrations.flask import FlaskIntegration
|
||||
from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration
|
||||
from sentry_sdk.integrations.rq import RqIntegration
|
||||
from sentry_sdk.integrations.threading import ThreadingIntegration
|
||||
|
||||
from flask import Flask, Response, abort, jsonify, render_template, request, send_file
|
||||
from redis import Redis
|
||||
from rq import Queue
|
||||
|
||||
from .sentry import initialize_sentry
|
||||
|
||||
initialize_sentry()
|
||||
|
||||
from .cleanup import cleanup_old_entries
|
||||
from .config import IMAGE_EXTENSIONS, RESULT_FOLDER, WORKER_FILES
|
||||
from .models import Image, Submission, db, init_db
|
||||
|
||||
SENTRY_DSN = os.environ.get("SENTRY_DSN")
|
||||
ENVIRONMENT = os.environ.get("ENVIRONMENT", "development")
|
||||
|
||||
if SENTRY_DSN:
|
||||
sentry_sdk.init(
|
||||
dsn=SENTRY_DSN,
|
||||
integrations=[
|
||||
FlaskIntegration(),
|
||||
SqlalchemyIntegration(),
|
||||
RqIntegration(),
|
||||
ThreadingIntegration(propagate_hub=True),
|
||||
],
|
||||
# Set traces_sample_rate to 1.0 to capture 100% of transactions for performance monitoring.
|
||||
# Adjust this value in production (e.g., 0.1 for 10%)
|
||||
traces_sample_rate=float(os.environ.get("SENTRY_TRACES_SAMPLE_RATE", "0.1")),
|
||||
# Set profiles_sample_rate to 1.0 to profile 100% of sampled transactions.
|
||||
profiles_sample_rate=float(os.environ.get("SENTRY_PROFILES_SAMPLE_RATE", "0.1")),
|
||||
# Environment tag (production, staging, development)
|
||||
environment=ENVIRONMENT,
|
||||
# Release version (use git commit hash or version number)
|
||||
release=os.environ.get("SENTRY_RELEASE", "1.0.0"),
|
||||
# Send default PII (user IPs, etc.) - set to False for privacy
|
||||
send_default_pii=False,
|
||||
# Enable automatic breadcrumb tracking
|
||||
enable_tracing=True,
|
||||
)
|
||||
|
||||
app: Flask = Flask(__name__)
|
||||
app.json.sort_keys = False # type: ignore
|
||||
app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get("DB_URI")
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# flake8: noqa: E203,E501,W503
|
||||
# pylint: disable=C0413,W0718,R0903,R0801
|
||||
# mypy: disable-error-code=unused-awaitable
|
||||
"""Cleanup old entries in the database and file system."""
|
||||
|
||||
import shutil
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# flake8: noqa: E203,E501,W503
|
||||
# pylint: disable=C0413,W0718,R0903,R0801
|
||||
# mypy: disable-error-code=unused-awaitable
|
||||
"""Aperi'Solve configuration variables."""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# flake8: noqa: E203,E501,W503
|
||||
# pylint: disable=C0413,W0718,R0903,R0801
|
||||
# mypy: disable-error-code=unused-awaitable
|
||||
"""This module defines the database models for the Aperi'Solve application."""
|
||||
|
||||
import itertools
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
# flake8: noqa: E203,E501,W503
|
||||
# pylint: disable=W0718,R0903,R0801
|
||||
# mypy: disable-error-code=unused-awaitable
|
||||
"""Sentry initialization for Aperisolve."""
|
||||
|
||||
import os
|
||||
|
||||
import sentry_sdk
|
||||
from sentry_sdk.integrations.flask import FlaskIntegration
|
||||
from sentry_sdk.integrations.rq import RqIntegration
|
||||
from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration
|
||||
from sentry_sdk.integrations.threading import ThreadingIntegration
|
||||
|
||||
SENTRY_DSN = os.environ.get("SENTRY_DSN")
|
||||
ENVIRONMENT = os.environ.get("ENVIRONMENT", "development")
|
||||
|
||||
|
||||
def initialize_sentry() -> None:
|
||||
"""Initialize Sentry SDK once, safely."""
|
||||
|
||||
# No DSN → do nothing
|
||||
dsn = os.environ.get("SENTRY_DSN")
|
||||
if not dsn:
|
||||
return
|
||||
|
||||
# Prevent double initialization (Flask + RQ, CLI, tests, etc.)
|
||||
if sentry_sdk.Hub.current.client is not None:
|
||||
return
|
||||
|
||||
sentry_sdk.init(
|
||||
dsn=dsn,
|
||||
integrations=[
|
||||
FlaskIntegration(),
|
||||
SqlalchemyIntegration(),
|
||||
RqIntegration(),
|
||||
ThreadingIntegration(propagate_hub=True),
|
||||
],
|
||||
traces_sample_rate=float(os.environ.get("SENTRY_TRACES_SAMPLE_RATE", "0.1")),
|
||||
profiles_sample_rate=float(
|
||||
os.environ.get("SENTRY_PROFILES_SAMPLE_RATE", "0.1")
|
||||
),
|
||||
environment=os.environ.get("ENVIRONMENT", "development"),
|
||||
release=os.environ.get("SENTRY_RELEASE", "1.0.0"),
|
||||
send_default_pii=False,
|
||||
enable_tracing=True,
|
||||
)
|
||||
+10
-24
@@ -1,32 +1,19 @@
|
||||
# flake8: noqa: E203,E501,W503
|
||||
# pylint: disable=C0413,W0718,R0903,R0801
|
||||
# mypy: disable-error-code=unused-awaitable
|
||||
"""Asynchronous worker for analyzing image submissions."""
|
||||
|
||||
import os
|
||||
import threading
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import sentry_sdk
|
||||
from sentry_sdk.integrations.rq import RqIntegration
|
||||
from sentry_sdk.integrations.threading import ThreadingIntegration
|
||||
from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration
|
||||
|
||||
# Initialize Sentry for workers (separate process from Flask app)
|
||||
SENTRY_DSN = os.environ.get("SENTRY_DSN")
|
||||
if SENTRY_DSN:
|
||||
sentry_sdk.init(
|
||||
dsn=SENTRY_DSN,
|
||||
integrations=[
|
||||
RqIntegration(),
|
||||
ThreadingIntegration(propagate_hub=True), # Capture exceptions in threads
|
||||
SqlalchemyIntegration(),
|
||||
],
|
||||
traces_sample_rate=float(os.environ.get("SENTRY_TRACES_SAMPLE_RATE", "0.1")),
|
||||
environment=os.environ.get("ENVIRONMENT", "development"),
|
||||
release=os.environ.get("SENTRY_RELEASE", "1.0.0"),
|
||||
send_default_pii=False,
|
||||
)
|
||||
from .sentry import initialize_sentry
|
||||
|
||||
from .analyzers.binwalk import analyze_binwalk
|
||||
initialize_sentry()
|
||||
|
||||
from .analyzers.binwalk import analyze_binwalk # pylint: disable=C0413
|
||||
from .analyzers.decomposer import analyze_decomposer
|
||||
from .analyzers.exiftool import analyze_exiftool
|
||||
from .analyzers.foremost import analyze_foremost
|
||||
@@ -74,8 +61,7 @@ def analyze_image(submission_hash: str) -> None:
|
||||
|
||||
if not submission or not image: # No submission found
|
||||
sentry_sdk.capture_message(
|
||||
f"Submission or image not found: {submission_hash}",
|
||||
level="warning"
|
||||
f"Submission or image not found: {submission_hash}", level="warning"
|
||||
)
|
||||
return
|
||||
|
||||
@@ -127,10 +113,10 @@ def analyze_image(submission_hash: str) -> None:
|
||||
for thread in threads:
|
||||
thread.join()
|
||||
|
||||
submission.status = "completed"
|
||||
submission.status = "completed" # type: ignore
|
||||
except Exception as e:
|
||||
sentry_sdk.capture_exception(e)
|
||||
submission.status = "error"
|
||||
submission.status = "error" # type: ignore
|
||||
finally:
|
||||
db.session.commit() # pylint: disable=no-member
|
||||
# Flush Sentry events - wait up to 5 seconds for events to be sent
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# flake8: noqa: E203,E501,W503
|
||||
# pylint: disable=C0413,W0718,R0903,R0801
|
||||
# mypy: disable-error-code=unused-awaitable
|
||||
"""Aperi'Solve WSGI runner."""
|
||||
|
||||
from .app import app as application
|
||||
|
||||
Reference in New Issue
Block a user