Skip to content

[Feature] ASM manager proxy blueprint + ASMConfig #6

@PenguinzTech

Description

@PenguinzTech

Context

Depends on #5 (worker-scanner ASM routes). The manager service needs a proxy blueprint to expose ASM endpoints to the WebUI and external clients with auth enforcement.

Files to Create / Modify

New: `services/manager-new/api/v1/asm.py`

Quart Blueprint `bp` with prefix `/api/v1/asm`.

Internal helper `_proxy(method, path, **kwargs)`:

  • Forwards to `WORKER_SCANNER_URL/api/v1/asm{path}`
  • Passes `Authorization` header from incoming request
  • Returns `(jsonify(data), resp.status_code)`
  • Handles `httpx.TimeoutException` → 504, `ConnectError` → 503

Routes (all `@auth_required`):

  • `POST /scans` → proxy POST /scans
  • `GET /scans` → proxy GET /scans (pass query params)
  • `GET /scans/` → proxy GET /scans/
  • `GET /scans//hosts` → proxy
  • `GET /scans//screenshots` → proxy
  • `GET /scans//certs` → proxy
  • `GET /scans//diff` → proxy
  • `GET /scans//report` → proxy
  • `GET /settings/ports` → proxy
  • `PUT /settings/ports` → proxy (also `@role_required("admin")`)

`WORKER_SCANNER_URL` from env var `WORKER_SCANNER_URL` (default: `http://worker-scanner:5001\`).

Follow pattern from `services/manager-new/api/v1/s3_scan.py` for auth decorators and Quart async patterns.

Modify: `services/manager-new/main.py`

Find where blueprints are registered (search for `register_blueprint`). Add:
```python
from api.v1 import asm as asm_api
app.register_blueprint(asm_api.bp, url_prefix="/api/v1/asm")
```

Modify: `services/manager-new/config.py`

Add `ASMConfig` Pydantic model before `ManagerConfig`:
```python
class ASMConfig(BaseModel):
enabled: bool = Field(default=True)
worker_scanner_url: str = Field(default="http://worker-scanner:5001")
s3_bucket: str = Field(default="skauswatch-asm-artifacts")
```

Add to `ManagerConfig` (or top-level config class):
```python
asm: ASMConfig = Field(default_factory=ASMConfig)
```

Modify: `docker-compose.yml`

Add `WORKER_SCANNER_URL=http://worker-scanner:5001\` to the manager-new service environment block if not already present.

Acceptance Criteria

  • All 10 proxy routes work end-to-end (manager → worker-scanner)
  • Auth enforced: unauthenticated requests return 401
  • Admin-only `PUT /settings/ports` returns 403 for non-admin
  • Timeout/connection errors return 504/503 (not 500)
  • Blueprint registered in main.py without import errors
  • Linting passes

Notes

  • Manager uses Quart (async), not Flask — all route handlers must be `async def`
  • Use `httpx.AsyncClient` for proxying (already in manager deps)
  • Follow `api/v1/s3_scan.py` for the auth decorator pattern

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions