Skip to content

Commit 904f1ca

Browse files
author
Jose Hernandez
committed
fixing to 1 system
1 parent 6c93616 commit 904f1ca

19 files changed

+891
-1085
lines changed

Diff for: Dockerfile

+28-7
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,38 @@
11
FROM python:3.11.4-slim-buster
22

33
# install dependencies
4-
RUN apt-get update
5-
RUN apt-get install -y git curl jq
4+
RUN apt-get update && apt-get install -y \
5+
git \
6+
curl \
7+
jq \
8+
python3-venv \
9+
build-essential \
10+
python3-dev \
11+
&& rm -rf /var/lib/apt/lists/*
12+
13+
# Install uv for main app dependencies
614
COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv
715

816
# define work directory
917
WORKDIR /app/
10-
COPY . /app
1118

12-
# install backend
13-
RUN cd backend && ./setup-sigma-versions.sh
19+
# Copy pyproject.toml first
20+
COPY pyproject.toml uv.lock ./
21+
22+
# Install main application dependencies with uv
23+
RUN uv venv && \
24+
. .venv/bin/activate && \
25+
uv pip install -e .
26+
27+
# Copy application files
28+
COPY app /app/app
29+
30+
# Make setup script executable
31+
RUN chmod +x /app/app/setup.py
32+
33+
# Setup Sigma versions using pip
34+
RUN cd /app/app && python setup.py
1435

15-
# launch front- and backend
36+
# launch application
1637
EXPOSE 8000
17-
ENTRYPOINT ["./entrypoint.sh"]
38+
CMD [".venv/bin/python", "-m", "app.main"]

Diff for: README.md

+11-7
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,22 @@ Welcome to sigconverter.io, a user-friendly converter for Sigma rules. This proj
99
- Easy-to-use interface for Sigma rule conversion
1010
- Supports multiple backends through pySigma
1111
- Continuously updated to stay in sync with pySigma
12+
- Multiple Sigma versions support through isolated environments
1213

1314
## 🚀 Getting Started
1415

1516
### Without Docker:
1617

1718
```bash
18-
poetry install
19-
poetry run ./run.py
19+
# Install dependencies
20+
cd backend
21+
pip install .
22+
23+
# Setup Sigma versions
24+
./setup-sigma-versions.sh
25+
26+
# Run the application
27+
python backend.py
2028
```
2129

2230
### With Docker:
@@ -26,11 +34,7 @@ poetry run ./run.py
2634
docker build -t sigconverter.io .
2735

2836
# Run the container
29-
# Note: We need to expose both the frontend port (8000) and backend ports (8100-8199)
30-
docker run -d \
31-
-p 8000:8000 \
32-
-p 8100-8199:8100-8199 \
33-
sigconverter.io
37+
docker run -d -p 8000:8000 sigconverter.io
3438
```
3539

3640
Visit the live instance at [https://sigconverter.io](https://sigconverter.io) or locally at [http://localhost:8000](http://localhost:8000).

Diff for: app/main.py

+132
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
#!/usr/bin/env python3
2+
import os
3+
import json
4+
import yaml
5+
import base64
6+
import subprocess
7+
from pathlib import Path
8+
from flask import Flask, render_template, jsonify, request, Response
9+
10+
app = Flask(__name__)
11+
12+
def run_sigma_command(version, endpoint, method='GET', data=None):
13+
"""Execute command in specific version's virtual environment"""
14+
version_path = Path(__file__).parent / "sigma" / version
15+
venv_path = version_path / "venv" / "bin" / "python"
16+
worker_path = Path(__file__).parent / "worker.py"
17+
18+
# Verify paths exist
19+
if not venv_path.exists():
20+
return None, f"Virtual environment not found for Sigma version {version}"
21+
if not worker_path.exists():
22+
return None, f"Worker script not found"
23+
24+
cmd = [str(venv_path), str(worker_path), endpoint]
25+
26+
# Add backend for formats and pipelines endpoints
27+
if endpoint in ['formats', 'pipelines'] and data and 'target' in data:
28+
cmd.append(data['target'])
29+
30+
# Add conversion parameters
31+
if endpoint == 'convert' and data:
32+
cmd.extend([
33+
data['target'],
34+
data['rule']
35+
])
36+
if data.get('format'):
37+
cmd.append(data['format'])
38+
if data.get('pipeline'):
39+
cmd.append(','.join(data['pipeline']))
40+
41+
try:
42+
result = subprocess.run(
43+
cmd,
44+
capture_output=True,
45+
text=True,
46+
check=True
47+
)
48+
return result.stdout, None
49+
except subprocess.CalledProcessError as e:
50+
return None, e.stderr
51+
52+
@app.route("/")
53+
def home():
54+
return render_template("index.html")
55+
56+
@app.route("/api/v1/sigma-versions", methods=["GET"])
57+
def get_versions():
58+
sigma_path = Path(__file__).parent / "sigma"
59+
versions = [
60+
d.name for d in sigma_path.iterdir()
61+
if d.is_dir() and (d / "venv").exists()
62+
]
63+
# Filter and sort versions
64+
clean_versions = []
65+
for version in versions:
66+
try:
67+
clean_version = version.lstrip('v')
68+
[int(x) for x in clean_version.split('.')]
69+
clean_versions.append(clean_version)
70+
except ValueError:
71+
continue
72+
73+
return jsonify(sorted(clean_versions, key=lambda v: tuple(map(int, v.split("."))), reverse=True))
74+
75+
@app.route("/api/v1/<version>/targets", methods=["GET"])
76+
def get_targets(version):
77+
output, error = run_sigma_command(version, 'targets')
78+
if error:
79+
return Response(f"Error: {error}", status=400)
80+
return Response(output, mimetype='application/json')
81+
82+
@app.route("/api/v1/<version>/formats", methods=["GET"])
83+
def get_formats(version):
84+
target = request.args.get('target', '').strip()
85+
if not target:
86+
return Response("Error: No backend specified", status=400)
87+
88+
data = {'target': target}
89+
output, error = run_sigma_command(version, 'formats', data=data)
90+
if error:
91+
return Response(error, status=400)
92+
return Response(output, mimetype='application/json')
93+
94+
@app.route("/api/v1/<version>/pipelines", methods=["GET"])
95+
def get_pipelines(version):
96+
target = request.args.get('target', '').strip()
97+
if not target:
98+
return Response("Error: No backend specified", status=400)
99+
100+
data = {'target': target}
101+
output, error = run_sigma_command(version, 'pipelines', data=data)
102+
if error:
103+
return Response(error, status=400)
104+
return Response(output, mimetype='application/json')
105+
106+
@app.route("/api/v1/<version>/convert", methods=["POST"])
107+
def convert(version):
108+
try:
109+
data = request.json
110+
rule = str(base64.b64decode(data["rule"]), "utf-8")
111+
yaml.safe_load(rule) # Validate YAML
112+
113+
# Prepare data for worker
114+
worker_data = {
115+
"rule": rule,
116+
"target": data["target"],
117+
"format": data.get("format"),
118+
"pipeline": data.get("pipeline", [])
119+
}
120+
121+
output, error = run_sigma_command(version, 'convert', data=worker_data)
122+
if error:
123+
return Response(error, status=400)
124+
return Response(output, mimetype='application/json')
125+
126+
except yaml.YAMLError:
127+
return Response("YamlError: Malformed yaml file", status=400)
128+
except Exception as e:
129+
return Response(f"Error: {str(e)}", status=400)
130+
131+
if __name__ == "__main__":
132+
app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 8000)))

Diff for: app/setup.py

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#!/usr/bin/env python3
2+
import os
3+
import json
4+
import subprocess
5+
from pathlib import Path
6+
7+
def install_core_backends(python_path, sigma_version):
8+
"""Install core backends that are known to work"""
9+
# First install required dependencies
10+
base_packages = [
11+
"pyyaml",
12+
f"sigma-cli=={sigma_version}",
13+
"pysigma>=0.9.0,<0.12.0", # Compatible with 1.0.x
14+
"setuptools",
15+
"wheel"
16+
]
17+
18+
# Install using pip instead of uv for better dependency resolution
19+
for package in base_packages:
20+
try:
21+
print(f"Installing {package}...")
22+
subprocess.run([
23+
python_path, "-m", "pip", "install", package
24+
], check=True)
25+
except subprocess.CalledProcessError as e:
26+
print(f"Warning: Failed to install {package}: {e}")
27+
return False
28+
29+
# Install minimal set of backends
30+
backends = [
31+
"pysigma-backend-splunk>=0.9.0",
32+
"pysigma-backend-elasticsearch>=0.9.0"
33+
]
34+
35+
for backend in backends:
36+
try:
37+
print(f"Installing {backend}...")
38+
subprocess.run([
39+
python_path, "-m", "pip", "install", backend
40+
], check=True)
41+
except subprocess.CalledProcessError as e:
42+
print(f"Warning: Failed to install {backend}: {e}")
43+
44+
# Verify installation
45+
try:
46+
verify_cmd = [python_path, "-c", "import yaml; import sigma.backends"]
47+
subprocess.run(verify_cmd, check=True)
48+
return True
49+
except subprocess.CalledProcessError:
50+
print("Failed to verify package installation")
51+
return False
52+
53+
def setup_sigma_versions():
54+
"""Setup Sigma versions with their virtual environments"""
55+
versions = ["1.0.0", "1.0.1", "1.0.2", "1.0.3", "1.0.4"] # Hardcode versions for now
56+
installed_count = 0
57+
base_path = Path(__file__).parent / "sigma"
58+
base_path.mkdir(parents=True, exist_ok=True)
59+
60+
for version in versions:
61+
print(f"\nSetting up Sigma version {version}")
62+
try:
63+
version_path = base_path / version
64+
version_path.mkdir(parents=True, exist_ok=True)
65+
66+
# Setup virtual environment using venv instead of uv
67+
venv_path = version_path / "venv"
68+
subprocess.run([
69+
"python3", "-m", "venv", str(venv_path)
70+
], check=True)
71+
72+
python_path = str(venv_path / "bin" / "python")
73+
74+
# Install core backends and verify
75+
if install_core_backends(python_path, version):
76+
# Copy worker script to version directory
77+
worker_path = Path(__file__).parent / "worker.py"
78+
if worker_path.exists():
79+
import shutil
80+
shutil.copy2(worker_path, version_path)
81+
82+
installed_count += 1
83+
print(f"Successfully set up version {version}")
84+
else:
85+
print(f"Warning: Failed to install backends for version {version}")
86+
87+
except Exception as e:
88+
print(f"Error setting up version {version}: {e}")
89+
continue
90+
91+
return installed_count
92+
93+
if __name__ == "__main__":
94+
count = setup_sigma_versions()
95+
if count == 0:
96+
print("Error: No Sigma versions were installed successfully")
97+
exit(1)
98+
print(f"Successfully installed {count} Sigma versions")
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)