devsecops-radar 0.3.5__tar.gz → 0.3.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {devsecops_radar-0.3.5/devsecops_radar.egg-info → devsecops_radar-0.3.7}/PKG-INFO +1 -1
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/core/auth.py +5 -4
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/core/models.py +5 -4
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7/devsecops_radar.egg-info}/PKG-INFO +1 -1
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/pyproject.toml +1 -1
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/tests/test_api.py +8 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/tests/test_cli.py +2 -1
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/LICENSE +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/MANIFEST.in +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/README.md +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/__init__.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/cli/__init__.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/cli/scanner.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/core/__init__.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/core/analyzer.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/core/attack_simulation.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/core/database.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/core/parser.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/core/rag.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/core/remediation.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/core/reporting.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/core/rule_fusion.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/core/sbom.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/core/settings.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/core/valuation.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/plugins/__init__.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/scanners/adapter.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/scanners/base.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/scanners/gitleaks.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/scanners/poutine.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/scanners/semgrep.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/scanners/trivy.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/scanners/zizmor.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/web/__init__.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/web/app.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/web/attack_paths/__init__.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/web/attack_paths/routes.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/web/dashboard/__init__.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/web/dashboard/routes.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/web/sentry/routes.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/web/static/css/bootstrap.min.css +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/web/static/css/style.css +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/web/static/js/bootstrap.bundle.min.js +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/web/static/js/chart.umd.min.js +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/web/static/js/dashboard.js +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/web/summary/__init__.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/web/summary/routes.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/web/templates/index.html +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/web/topology/__init__.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/web/topology/routes.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar.egg-info/SOURCES.txt +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar.egg-info/dependency_links.txt +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar.egg-info/entry_points.txt +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar.egg-info/requires.txt +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar.egg-info/top_level.txt +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/setup.cfg +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/tests/test_analyzer.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/tests/test_database.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/tests/test_rule_fusion.py +0 -0
- {devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/tests/test_scanners.py +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import os
|
|
1
2
|
import jwt
|
|
2
3
|
import datetime
|
|
3
4
|
from functools import wraps
|
|
@@ -18,11 +19,11 @@ def verify_token(token: str) -> dict:
|
|
|
18
19
|
def login_required(f):
|
|
19
20
|
@wraps(f)
|
|
20
21
|
def decorated(*args, **kwargs):
|
|
21
|
-
#
|
|
22
|
-
|
|
22
|
+
# Read directly from os.environ to support test patching
|
|
23
|
+
api_key = os.environ.get("PIPELINE_API_KEY", "disabled")
|
|
24
|
+
if api_key != "disabled":
|
|
23
25
|
key = request.headers.get("X-API-Key")
|
|
24
|
-
if key !=
|
|
26
|
+
if key != api_key:
|
|
25
27
|
return jsonify({"error": "API key required"}), 401
|
|
26
|
-
# Without an API key, all requests are permitted (default for local use).
|
|
27
28
|
return f(*args, **kwargs)
|
|
28
29
|
return decorated
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from sqlalchemy import create_engine, Column, Integer, String, DateTime, JSON, ForeignKey
|
|
2
2
|
from sqlalchemy.orm import declarative_base, sessionmaker, relationship
|
|
3
|
-
from pydantic import BaseModel,
|
|
3
|
+
from pydantic import BaseModel, field_validator
|
|
4
4
|
from typing import Optional
|
|
5
5
|
import datetime
|
|
6
6
|
import os
|
|
@@ -16,14 +16,15 @@ class FindingSchema(BaseModel):
|
|
|
16
16
|
description: Optional[str] = ""
|
|
17
17
|
line: Optional[int] = None
|
|
18
18
|
|
|
19
|
-
@
|
|
20
|
-
|
|
19
|
+
@field_validator('severity')
|
|
20
|
+
@classmethod
|
|
21
|
+
def severity_upper(cls, v: str) -> str:
|
|
21
22
|
return v.upper()
|
|
22
23
|
|
|
23
24
|
class Scan(Base):
|
|
24
25
|
__tablename__ = 'scans'
|
|
25
26
|
id = Column(Integer, primary_key=True)
|
|
26
|
-
timestamp = Column(DateTime, default=datetime.datetime.
|
|
27
|
+
timestamp = Column(DateTime, default=lambda: datetime.datetime.now(datetime.UTC))
|
|
27
28
|
findings_json = Column(JSON)
|
|
28
29
|
findings = relationship("Finding", back_populates="scan", cascade="all, delete-orphan")
|
|
29
30
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import pytest
|
|
2
|
+
from unittest.mock import patch
|
|
2
3
|
from devsecops_radar.web.app import create_app
|
|
3
4
|
|
|
4
5
|
@pytest.fixture
|
|
@@ -11,6 +12,13 @@ def app():
|
|
|
11
12
|
def client(app):
|
|
12
13
|
return app.test_client()
|
|
13
14
|
|
|
15
|
+
@pytest.fixture(autouse=True)
|
|
16
|
+
def mock_database():
|
|
17
|
+
# Mock the database function to avoid needing a real DB
|
|
18
|
+
with patch('devsecops_radar.web.dashboard.routes.get_findings_paginated') as mock:
|
|
19
|
+
mock.return_value = {"items": [], "total": 0, "page": 1, "per_page": 50}
|
|
20
|
+
yield
|
|
21
|
+
|
|
14
22
|
def test_dashboard_page(client):
|
|
15
23
|
resp = client.get('/')
|
|
16
24
|
assert resp.status_code == 200
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/web/attack_paths/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/web/static/css/bootstrap.min.css
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar/web/static/js/chart.umd.min.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{devsecops_radar-0.3.5 → devsecops_radar-0.3.7}/devsecops_radar.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|