Skip to main content

Multi-tenant security scanning platform wrapping Amazon Security Helper

Project description

Vehlo Code Scanner

Multi-tenant security scanning platform wrapping Amazon Security Helper (ASH). Runs ASH across Vehlo's 500+ repos, centralizes findings in PostgreSQL, and surfaces them through a React dashboard with triage workflows and analytics.

Architecture

CI/CD pipeline → ASH scan → vcs CLI (--push) → POST /api/v1/scans → FastAPI + PostgreSQL → React Dashboard

Three components:

  • CLI / scanner — Python package (vcs) that wraps ASH. Supports container, local, and pre-commit modes. Outputs rich terminal tables, optionally pushes results to the central API, and can fail the build on a severity threshold.
  • API service — FastAPI monolith handling ingest, findings lifecycle, and analytics. Backed by PostgreSQL. Auto-resolves findings when they disappear from subsequent scans.
  • Dashboard — React + Vite SPA. Overview, findings browser, per-repo drill-down, scan history, and analytics.

Quick Start

# Start all services
docker compose up

# API → http://localhost:8002
# Dashboard → http://localhost:5175

Installation

Distribution is dual-mode: a public path (PyPI + ECR Public, no AWS account needed) and an AWS-gated path (CodeArtifact + private ECR) for internal users. The tool itself is open to install — the API token gates pushing results and SSO gates viewing them. The [scan] extra adds the ASH engine (vehlo-ash, a rename-only repackaging of AWS's Apache-2.0 automated-security-helper — see packaging/vehlo-ash/); without it you still get the CLI, --push, and the client.

Public (no AWS):

# pip from PyPI
pip install 'vehlo-code-scanner[scan]'

# Docker from ECR Public (ASH bundled, nothing else to install)
docker run --rm -v "$PWD:/src" \
  public.ecr.aws/<alias>/vehlo-code-scanner:latest scan /src

AWS-gated (internal): authenticate once with aws sso login, then:

# pip via CodeArtifact (configures the index, then installs)
aws codeartifact login --tool pip \
  --domain "$VCS_CA_DOMAIN" --repository "$VCS_CA_REPO"
pip install 'vehlo-code-scanner[scan]'

# Docker via ECR
aws ecr get-login-password --region "$AWS_REGION" \
  | docker login --username AWS --password-stdin "$ECR_REGISTRY"
docker run --rm -v "$PWD:/src" \
  "$ECR_REGISTRY/vehlo-code-scanner:latest" scan /src

GitHub Actions (the calling job needs permissions: id-token: write):

- uses: Vehlo-CyberSec/vehlo-code-scanner@v1
  with:
    api-url: ${{ vars.VCS_API_URL }}
    api-token: ${{ secrets.VCS_API_TOKEN }}
    image: ${{ vars.VCS_ECR_IMAGE }}      # full ECR URI
    aws-role: ${{ secrets.VCS_AWS_ROLE }} # OIDC role with ECR pull
    aws-region: ${{ vars.AWS_REGION }}
    fail-on: high

ASH is git-only upstream (and its PyPI name is squatted), so vcs scan without the engine prints install guidance. The container images bundle ASH; pip users get it via the [scan] extra (vehlo-ash from PyPI or CodeArtifact, depending on the index you install from).

For local development from a checkout:

uv tool install '.[scan]'   # or: uv sync --group local-scan  (ASH from git)

After installation, vcs (and vcs-admin) are available on your PATH.

Local development

# Install Python deps
uv sync

# Apply migrations
VCS_DATABASE_URL=postgresql+psycopg://vcs:<password>@localhost:5433/vcs alembic upgrade head
# (dev password: see docker-compose.yml)

# Run API
VCS_DATABASE_URL=... uvicorn vcs.api.app:create_app --factory --reload

# Run dashboard (in ./dashboard)
npm run dev

Running a scan

# Scan current directory and print results
vcs scan .

# Scan and push results to central API
VCS_API_URL=http://localhost:8002 VCS_API_TOKEN=<token> vcs scan . --push

# Fail CI if critical or high findings exist
vcs scan . --push --fail-on high

Project Structure

src/vcs/
├── api/
│   ├── routes/         # health, ingest, findings, repos, scans, overview, analytics
│   ├── services/       # ingest logic, auto-resolve
│   ├── app.py          # FastAPI factory
│   ├── deps.py         # DB session injection
│   └── schemas.py      # Pydantic request/response models
├── models/             # SQLAlchemy ORM: org, group, user, repo, scan, finding, api_token
├── scanner/            # ASH wrapper: runner, parser, result models
├── cli/                # Typer CLI: scan command, rich output
├── client/             # HTTP client for pushing results to API
├── db.py               # Database connection factory
├── enums.py            # Severity, FindingStatus, etc.
└── config.py           # Settings from environment

dashboard/src/
├── pages/              # Overview, Findings, FindingDetail, Repos, RepoDetail, Scans, Analytics
├── components/         # Layout, SeverityBadge, StatusBadge, Pagination, Panel, etc.
├── api/                # TanStack Query hooks
└── types.ts            # TypeScript types

alembic/versions/       # Database migrations
tests/                  # Unit + integration tests

Environment Variables

Variable Description Default
VCS_DATABASE_URL PostgreSQL connection string required
VCS_API_URL Central API base URL (CLI push) required for --push
VCS_API_TOKEN Bearer token for API auth (CLI push) required for --push
VCS_REDIS_URL Celery broker/result backend redis://localhost:6380/0
VCS_S3_ENDPOINT S3/MinIO endpoint for raw-result archiving http://localhost:9002
VCS_SESSION_SECRET Secret for signing dashboard session cookies dev default (required once OIDC is configured — startup fails without it)
VCS_CORS_ORIGINS Comma-separated allowed CORS origins; empty value = deny cross-origin (prod) unset → any localhost port (dev)
VCS_OIDC_ISSUER OIDC issuer URL (enables dashboard SSO) unset → SSO disabled
VCS_OIDC_CLIENT_ID / VCS_OIDC_CLIENT_SECRET OIDC client credentials unset
VCS_OIDC_REDIRECT_URI OIDC callback URL .../api/v1/auth/callback
VCS_OIDC_GROUPS_CLAIM Claim holding the user's group names groups
VCS_DASHBOARD_URL Post-login redirect target http://localhost:5175
VCS_DEV_LOGIN Dev only — enables /api/v1/auth/dev-login (one-click local session, no IdP). Never set in prod. unset → disabled

Running Tests

pytest
pytest --cov=vcs --cov-report=term-missing

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

vehlo_code_scanner-0.1.2.tar.gz (36.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

vehlo_code_scanner-0.1.2-py3-none-any.whl (56.3 kB view details)

Uploaded Python 3

File details

Details for the file vehlo_code_scanner-0.1.2.tar.gz.

File metadata

  • Download URL: vehlo_code_scanner-0.1.2.tar.gz
  • Upload date:
  • Size: 36.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for vehlo_code_scanner-0.1.2.tar.gz
Algorithm Hash digest
SHA256 cd3b0cd0a50ed4099e15b83e980edb1304d1577bc3534f0dff27583c5490a847
MD5 a6e38d2cd71b2d5b921807827340f19f
BLAKE2b-256 3326910241229ece758347737e74dab5b026f1b2b6ce7a2d4047b434ef8c6aa1

See more details on using hashes here.

File details

Details for the file vehlo_code_scanner-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for vehlo_code_scanner-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 f2ee90e0d3a34736fe41068176cc3ce40ea1964bb72647a758bea50f5fcbb3e2
MD5 abb6afda0a992e873aa31803cdceb5a9
BLAKE2b-256 8291495eece572da5ff6d377949104630f95c70a49af682380f06eda944bde4d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page