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.1rc3.tar.gz (36.1 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.1rc3-py3-none-any.whl (56.2 kB view details)

Uploaded Python 3

File details

Details for the file vehlo_code_scanner-0.1.1rc3.tar.gz.

File metadata

  • Download URL: vehlo_code_scanner-0.1.1rc3.tar.gz
  • Upload date:
  • Size: 36.1 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.1rc3.tar.gz
Algorithm Hash digest
SHA256 14fafdd6473301f5d9081fc98dbfcc5b6b30a8d3f499d5c5ae6df06dd9a538eb
MD5 99092412750e3e2b4037ea6ffbf763e0
BLAKE2b-256 b5eafea4f6311d8a1dc3df20107e50f25396adde4ddbc88a5b7f804ea55c5b62

See more details on using hashes here.

File details

Details for the file vehlo_code_scanner-0.1.1rc3-py3-none-any.whl.

File metadata

File hashes

Hashes for vehlo_code_scanner-0.1.1rc3-py3-none-any.whl
Algorithm Hash digest
SHA256 9a46d1fb06db372f6c0f896d5fcee13118cc646d45fa1a6204799dcef4f65779
MD5 ac061f765decf7050e619fe80e6cff5f
BLAKE2b-256 3a82582dbd50eb1284109fd5642f5f34413a378262ee344357dd71eb6725325c

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