3e370c25b695953e99eded1c234035e7b85b620d
webfortilog
Flask-based web application that converts WAF log files into aligned text reports or CSV exports.
Features
- Upload a UTF-8 log file where each line is a single record
- Parse shell-style
key=valueandkey="value with spaces"tokens - Support
vendormode with fixed columns andfullmode with dynamic columns - Filter by policy and severity with case-sensitive or case-insensitive partial matching
- Sort by combined datetime or severity ranking
- Preview results in the browser and download the generated file
- Run locally with Flask or in Docker with Gunicorn
Project structure
app/
services/
templates/
tests/
Dockerfile
pyproject.toml
wsgi.py
Local usage
Requirements
- Python 3.12
Install
python3.12 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
Run Container
export FLASK_APP=wsgi.py
export APP_ENV=development
export MAX_UPLOAD_SIZE_MB=100
flask run --debug
Open http://127.0.0.1:5000.
Example input file
If you have a local WAF export such as attack_download.log, you can use it as a real example upload.
- Example file:
attack_download.log - Approximate size in the current workspace:
98.5 MiB - The default
MAX_UPLOAD_SIZE_MB=100setting is sized to accept a file of that size
Test
pytest
Docker usage
Build
docker build -t webfortilog .
Run
docker run --rm -p 8000:8000 -e APP_ENV=development -e MAX_UPLOAD_SIZE_MB=100 webfortilog
Open http://127.0.0.1:8000.
Docker Compose usage
Start the web app
docker compose up --build web
Compose settings are stored in env. Update that file to change values such as:
SECRET_KEYAPP_ENVMAX_UPLOAD_SIZE_MBOUTPUT_DIRECTORYOUTPUT_RETENTION_HOURSCLEANUP_ON_STARTUPCLEANUP_AFTER_DOWNLOAD
For local Docker Compose usage, APP_ENV=development allows an internal development-only fallback secret key.
For production-like environments, set a strong SECRET_KEY explicitly.
Run the test suite in a container
docker compose run --rm test
Example usage
Browser upload
- Start the app with
flask run --debugordocker compose up --build web - Open the web UI
- Upload
attack_download.log - Try
vendormode withtextoutput for a readable preview - Try
fullmode withcsvoutput for complete export coverage
Command-line upload example
curl -X POST http://127.0.0.1:5000/convert \
-F "log_file=@attack_download.log" \
-F "mode=vendor" \
-F "output_format=text" \
-F "sort_by=datetime" \
-F "order=asc" \
-F "policy_cs=" \
-F "policy_ci=" \
-F "severity_cs=" \
-F "severity_ci="
Notes
- Temporary output files are written to
instance/outputs - Generated files are cleaned up according to the configured output retention policy
- The application does not require a database
- Gunicorn is used as the production WSGI server
- Parsing and export writing are streamed to reduce memory usage on large uploads
- Sorting still materializes the filtered record set because global ordering by datetime or severity requires the full filtered input
- Default upload limit is 100 MiB
- Set
MAX_UPLOAD_SIZE_MBto configure the upload limit in megabytes MAX_CONTENT_LENGTHis also supported as a lower-level byte-based overrideSECRET_KEYis required in production-like environments and must not use placeholder values such aschange-me- Development-only fallback secret key behavior is enabled only when
APP_ENV=developmentorFLASK_ENV=development OUTPUT_RETENTION_HOURScontrols how long generated output files are keptCLEANUP_ON_STARTUP=trueremoves expired generated files when the app startsCLEANUP_AFTER_DOWNLOAD=truedeletes a result only after the response finishes sending
Secure configuration example
Production-like environment
python3 - <<'PY'
import secrets
print(secrets.token_urlsafe(48))
PY
Use the generated value as SECRET_KEY, for example:
docker run --rm -p 8000:8000 \
-e SECRET_KEY='replace-with-a-long-random-secret' \
-e MAX_UPLOAD_SIZE_MB=100 \
webfortilog