mirror of
https://github.com/j3ssie/osmedeus.git
synced 2026-09-09 19:27:48 +02:00
Complete rewrite and re-architecture Osmedeus Engine in v5
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
# Osmedeus API Documentation
|
||||
|
||||
## Overview
|
||||
|
||||
The Osmedeus API provides a RESTful interface for managing security automation workflows, runs, and distributed task execution.
|
||||
|
||||
**Base URL:** `http://localhost:8002`
|
||||
|
||||
**Default Port:** `8002`
|
||||
|
||||
## Authentication
|
||||
|
||||
Most API endpoints require JWT authentication. First, obtain a token via the login endpoint, then include it in subsequent requests using the `Authorization: Bearer <token>` header.
|
||||
|
||||
See [Authentication](authentication.md) for details.
|
||||
|
||||
## API Reference
|
||||
|
||||
| Category | Description |
|
||||
|----------|-------------|
|
||||
| [Public Endpoints](public.md) | Server info, health checks, Swagger docs |
|
||||
| [Authentication](authentication.md) | Login and JWT token management |
|
||||
| [Workflows](workflows.md) | List, view, and refresh workflows |
|
||||
| [Runs](runs.md) | Create and manage workflow executions |
|
||||
| [File Uploads](uploads.md) | Upload target files and workflows |
|
||||
| [Snapshots](snapshots.md) | Download workspace snapshots |
|
||||
| [Workspaces](workspaces.md) | List and manage workspaces |
|
||||
| [Assets](assets.md) | View discovered assets |
|
||||
| [Vulnerabilities](vulnerabilities.md) | View and manage vulnerabilities |
|
||||
| [Event Logs](event-logs.md) | View execution event logs |
|
||||
| [Functions](functions.md) | Execute and list utility functions |
|
||||
| [System Statistics](system.md) | Get aggregated system stats |
|
||||
| [Settings](settings.md) | Manage server configuration |
|
||||
| [Installation](install.md) | Install binaries and workflows |
|
||||
| [Schedules](schedules.md) | Manage scheduled workflows |
|
||||
| [Distributed Mode](distributed.md) | Worker and task management |
|
||||
| [LLM API](llm.md) | Large Language Model API |
|
||||
| [Reference](reference.md) | Error codes, pagination, cron expressions, step types |
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Get server info (no auth required)
|
||||
curl http://localhost:8002/server-info
|
||||
|
||||
# Login and get token
|
||||
export TOKEN=$(curl -s -X POST http://localhost:8002/osm/api/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username": "osmedeus", "password": "admin"}' | jq -r '.token')
|
||||
|
||||
# List workflows
|
||||
curl http://localhost:8002/osm/api/workflows \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
|
||||
# Start a scan
|
||||
curl -X POST http://localhost:8002/osm/api/runs \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"flow": "subdomain-enum", "target": "example.com"}'
|
||||
```
|
||||
@@ -0,0 +1,123 @@
|
||||
# Assets
|
||||
|
||||
## List Assets
|
||||
|
||||
Get a paginated list of assets with optional workspace filtering.
|
||||
|
||||
**List all assets:**
|
||||
```bash
|
||||
curl http://localhost:8002/osm/api/assets \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**List assets with pagination:**
|
||||
```bash
|
||||
curl "http://localhost:8002/osm/api/assets?offset=0&limit=100" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Filter by workspace:**
|
||||
```bash
|
||||
curl "http://localhost:8002/osm/api/assets?workspace=example.com" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Combine workspace filter with pagination:**
|
||||
```bash
|
||||
curl "http://localhost:8002/osm/api/assets?workspace=example.com&offset=50&limit=25" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"id": 1,
|
||||
"workspace": "example.com",
|
||||
"asset_value": "api.example.com",
|
||||
"url": "https://api.example.com",
|
||||
"input": "api.example.com",
|
||||
"scheme": "https",
|
||||
"method": "GET",
|
||||
"path": "/",
|
||||
"status_code": 200,
|
||||
"content_type": "application/json",
|
||||
"content_length": 4523,
|
||||
"title": "API Documentation",
|
||||
"words": 523,
|
||||
"lines": 89,
|
||||
"host_ip": "93.184.216.34",
|
||||
"a": ["93.184.216.34", "93.184.216.35"],
|
||||
"tls": "TLS 1.3",
|
||||
"asset_type": "web",
|
||||
"tech": ["nginx/1.21.0", "nodejs", "express"],
|
||||
"time": "245ms",
|
||||
"remarks": "production",
|
||||
"source": "httpx",
|
||||
"created_at": "2025-01-15T10:30:00Z",
|
||||
"updated_at": "2025-01-15T10:30:00Z"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"workspace": "example.com",
|
||||
"asset_value": "admin.example.com",
|
||||
"url": "https://admin.example.com",
|
||||
"input": "admin.example.com",
|
||||
"scheme": "https",
|
||||
"method": "GET",
|
||||
"path": "/login",
|
||||
"status_code": 401,
|
||||
"content_type": "text/html",
|
||||
"content_length": 2156,
|
||||
"title": "Admin Login - Example Corp",
|
||||
"words": 156,
|
||||
"lines": 45,
|
||||
"host_ip": "93.184.216.36",
|
||||
"a": ["93.184.216.36"],
|
||||
"tls": "TLS 1.2",
|
||||
"asset_type": "web",
|
||||
"tech": ["nginx/1.20.0", "php/8.1", "wordpress"],
|
||||
"time": "312ms",
|
||||
"remarks": "admin-panel",
|
||||
"source": "httpx",
|
||||
"created_at": "2025-01-15T10:31:00Z",
|
||||
"updated_at": "2025-01-15T10:31:00Z"
|
||||
}
|
||||
],
|
||||
"pagination": {
|
||||
"total": 500,
|
||||
"offset": 0,
|
||||
"limit": 20
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Asset Fields Reference:**
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `id` | int | Unique asset identifier |
|
||||
| `workspace` | string | Workspace/scan target name |
|
||||
| `asset_value` | string | Primary asset identifier (hostname/subdomain) |
|
||||
| `url` | string | Full URL of the asset |
|
||||
| `input` | string | Original input value |
|
||||
| `scheme` | string | Protocol scheme (http, https) |
|
||||
| `method` | string | HTTP method used |
|
||||
| `path` | string | URL path |
|
||||
| `status_code` | int | HTTP response status code |
|
||||
| `content_type` | string | Response content type |
|
||||
| `content_length` | int | Response body size in bytes |
|
||||
| `title` | string | HTML page title |
|
||||
| `words` | int | Word count in response |
|
||||
| `lines` | int | Line count in response |
|
||||
| `host_ip` | string | Resolved IP address |
|
||||
| `a` | array | DNS A records |
|
||||
| `tls` | string | TLS version information |
|
||||
| `asset_type` | string | Asset type classification |
|
||||
| `tech` | array | Detected technologies |
|
||||
| `time` | string | Response time |
|
||||
| `remarks` | string | Custom labels/remarks |
|
||||
| `source` | string | Discovery source (httpx, nuclei, etc.) |
|
||||
| `created_at` | timestamp | Creation timestamp |
|
||||
| `updated_at` | timestamp | Last update timestamp |
|
||||
@@ -0,0 +1,108 @@
|
||||
# Authentication
|
||||
|
||||
Most API endpoints require JWT authentication. First, obtain a token via the login endpoint, then include it in subsequent requests.
|
||||
|
||||
## Login
|
||||
|
||||
**POST** `/osm/api/login`
|
||||
|
||||
Authenticate and obtain a JWT token.
|
||||
|
||||
### Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"username": "osmedeus",
|
||||
"password": "your-password"
|
||||
}'
|
||||
```
|
||||
|
||||
### Request Body
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `username` | string | Yes | Username configured in server settings |
|
||||
| `password` | string | Yes | Password for the user |
|
||||
|
||||
### Response (200 OK)
|
||||
|
||||
```json
|
||||
{
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Im9zbWVkZXVzIiwiZXhwIjoxNzA0MDY3MjAwLCJpYXQiOjE3MDQwNjM2MDB9.abc123..."
|
||||
}
|
||||
```
|
||||
|
||||
### Error Responses
|
||||
|
||||
**400 Bad Request** - Invalid request body:
|
||||
```json
|
||||
{
|
||||
"error": true,
|
||||
"message": "Invalid request body"
|
||||
}
|
||||
```
|
||||
|
||||
**401 Unauthorized** - Invalid credentials:
|
||||
```json
|
||||
{
|
||||
"error": true,
|
||||
"message": "Invalid credentials"
|
||||
}
|
||||
```
|
||||
|
||||
## Token Details
|
||||
|
||||
- **Algorithm**: HS256 (HMAC-SHA256)
|
||||
- **Expiration**: Configurable via `server.jwt.expiration_minutes` in settings (default: 60 minutes)
|
||||
- **Claims**: Contains `username`, `exp` (expiration), and `iat` (issued at)
|
||||
|
||||
## Using the Token
|
||||
|
||||
Include the token in subsequent requests using the `Authorization: Bearer <token>` header:
|
||||
|
||||
```bash
|
||||
# Store token in environment variable
|
||||
export TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||||
|
||||
# Use in API requests
|
||||
curl http://localhost:8002/osm/api/workflows \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
### Authentication Errors
|
||||
|
||||
**401 Unauthorized** - Missing header:
|
||||
```json
|
||||
{
|
||||
"error": true,
|
||||
"message": "Missing authorization header"
|
||||
}
|
||||
```
|
||||
|
||||
**401 Unauthorized** - Invalid format:
|
||||
```json
|
||||
{
|
||||
"error": true,
|
||||
"message": "Invalid authorization header format"
|
||||
}
|
||||
```
|
||||
|
||||
**401 Unauthorized** - Expired or invalid token:
|
||||
```json
|
||||
{
|
||||
"error": true,
|
||||
"message": "Invalid or expired token"
|
||||
}
|
||||
```
|
||||
|
||||
## Disabling Authentication
|
||||
|
||||
Authentication can be disabled by starting the server with the `--no-auth` flag:
|
||||
|
||||
```bash
|
||||
osmedeus server --no-auth
|
||||
```
|
||||
|
||||
When disabled, all API endpoints are accessible without a token.
|
||||
@@ -0,0 +1,241 @@
|
||||
# Distributed Mode
|
||||
|
||||
These endpoints are only available when running the server in master mode.
|
||||
|
||||
## List Workers
|
||||
|
||||
Get a list of all registered workers in the distributed pool.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8002/osm/api/workers \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"id": "worker-001",
|
||||
"hostname": "worker1.example.com",
|
||||
"ip_address": "192.168.1.10",
|
||||
"status": "idle",
|
||||
"current_task": null,
|
||||
"joined_at": "2025-01-15T08:00:00Z",
|
||||
"last_heartbeat": "2025-01-15T10:30:00Z",
|
||||
"tasks_complete": 150,
|
||||
"tasks_failed": 2,
|
||||
"capabilities": ["docker", "nmap", "nuclei"],
|
||||
"cpu_cores": 8,
|
||||
"memory_gb": 16,
|
||||
"version": "1.0.0"
|
||||
},
|
||||
{
|
||||
"id": "worker-002",
|
||||
"hostname": "worker2.example.com",
|
||||
"ip_address": "192.168.1.11",
|
||||
"status": "busy",
|
||||
"current_task": "task-12345",
|
||||
"joined_at": "2025-01-15T08:05:00Z",
|
||||
"last_heartbeat": "2025-01-15T10:30:05Z",
|
||||
"tasks_complete": 120,
|
||||
"tasks_failed": 1,
|
||||
"capabilities": ["docker", "nmap", "nuclei", "masscan"],
|
||||
"cpu_cores": 16,
|
||||
"memory_gb": 32,
|
||||
"version": "1.0.0"
|
||||
}
|
||||
],
|
||||
"count": 2
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Get Worker
|
||||
|
||||
Get details of a specific worker.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8002/osm/api/workers/worker-001 \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"id": "worker-001",
|
||||
"hostname": "worker1.example.com",
|
||||
"ip_address": "192.168.1.10",
|
||||
"status": "busy",
|
||||
"current_task": "task-12345",
|
||||
"joined_at": "2025-01-15T08:00:00Z",
|
||||
"last_heartbeat": "2025-01-15T10:30:00Z",
|
||||
"tasks_complete": 150,
|
||||
"tasks_failed": 2,
|
||||
"capabilities": ["docker", "nmap", "nuclei"],
|
||||
"cpu_cores": 8,
|
||||
"memory_gb": 16,
|
||||
"version": "1.0.0"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## List Tasks
|
||||
|
||||
Get a list of all running and completed tasks.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8002/osm/api/tasks \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"running": [
|
||||
{
|
||||
"id": "task-12345",
|
||||
"scan_id": "scan-abc123",
|
||||
"workflow_name": "subdomain-enum",
|
||||
"workflow_kind": "flow",
|
||||
"target": "example.com",
|
||||
"params": {"threads": "50", "timeout": "60"},
|
||||
"status": "running",
|
||||
"worker_id": "worker-001",
|
||||
"progress": 45,
|
||||
"current_step": "run-httpx",
|
||||
"created_at": "2025-01-15T10:00:00Z",
|
||||
"started_at": "2025-01-15T10:01:00Z"
|
||||
},
|
||||
{
|
||||
"id": "task-12346",
|
||||
"scan_id": "scan-def456",
|
||||
"workflow_name": "port-scan",
|
||||
"workflow_kind": "module",
|
||||
"target": "test.com",
|
||||
"params": {"ports": "top-1000"},
|
||||
"status": "running",
|
||||
"worker_id": "worker-002",
|
||||
"progress": 80,
|
||||
"current_step": "nmap-scan",
|
||||
"created_at": "2025-01-15T10:05:00Z",
|
||||
"started_at": "2025-01-15T10:06:00Z"
|
||||
}
|
||||
],
|
||||
"completed": [
|
||||
{
|
||||
"task_id": "task-12340",
|
||||
"scan_id": "scan-xyz789",
|
||||
"status": "completed",
|
||||
"output": "Scan completed: 150 subdomains found, 89 alive hosts",
|
||||
"error": "",
|
||||
"exports": {
|
||||
"subdomains": "/workspaces/example.com/subdomains.txt",
|
||||
"alive_hosts": "/workspaces/example.com/alive.txt"
|
||||
},
|
||||
"completed_at": "2025-01-15T09:30:00Z",
|
||||
"duration_seconds": 1800
|
||||
},
|
||||
{
|
||||
"task_id": "task-12339",
|
||||
"scan_id": "scan-uvw456",
|
||||
"status": "failed",
|
||||
"output": "",
|
||||
"error": "Connection timeout to target",
|
||||
"exports": {},
|
||||
"completed_at": "2025-01-15T09:15:00Z",
|
||||
"duration_seconds": 300
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Get Task
|
||||
|
||||
Get details of a specific task.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8002/osm/api/tasks/task-12345 \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response (running task):**
|
||||
```json
|
||||
{
|
||||
"id": "task-12345",
|
||||
"scan_id": "scan-abc123",
|
||||
"workflow_name": "subdomain-enum",
|
||||
"workflow_kind": "flow",
|
||||
"target": "example.com",
|
||||
"params": {"threads": "50", "timeout": "60"},
|
||||
"status": "running",
|
||||
"worker_id": "worker-001",
|
||||
"progress": 45,
|
||||
"current_step": "run-httpx",
|
||||
"created_at": "2025-01-15T10:00:00Z",
|
||||
"started_at": "2025-01-15T10:01:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Response (completed task):**
|
||||
```json
|
||||
{
|
||||
"task_id": "task-12345",
|
||||
"scan_id": "scan-abc123",
|
||||
"status": "completed",
|
||||
"output": "Scan completed: 150 subdomains found, 89 alive hosts",
|
||||
"error": "",
|
||||
"exports": {
|
||||
"subdomains": "/workspaces/example.com/subdomains.txt",
|
||||
"alive_hosts": "/workspaces/example.com/alive.txt",
|
||||
"httpx_json": "/workspaces/example.com/httpx.json"
|
||||
},
|
||||
"completed_at": "2025-01-15T10:30:00Z",
|
||||
"duration_seconds": 1740
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Submit Task
|
||||
|
||||
Submit a new task to the distributed worker queue.
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/tasks \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"workflow_name": "subdomain-enum",
|
||||
"workflow_kind": "flow",
|
||||
"target": "example.com"
|
||||
}'
|
||||
```
|
||||
|
||||
**With parameters:**
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/tasks \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"workflow_name": "subdomain-enum",
|
||||
"workflow_kind": "flow",
|
||||
"target": "example.com",
|
||||
"params": {
|
||||
"threads": 50,
|
||||
"timeout": 30
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"message": "Task submitted",
|
||||
"task_id": "task-12346"
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,178 @@
|
||||
# Event Logs
|
||||
|
||||
## List Event Logs
|
||||
|
||||
Get a paginated list of event logs with optional filtering.
|
||||
|
||||
**List all event logs:**
|
||||
```bash
|
||||
curl http://localhost:8002/osm/api/event-logs \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**With pagination:**
|
||||
```bash
|
||||
curl "http://localhost:8002/osm/api/event-logs?offset=0&limit=50" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Filter by workspace:**
|
||||
```bash
|
||||
curl "http://localhost:8002/osm/api/event-logs?workspace=example.com" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Filter by topic:**
|
||||
```bash
|
||||
curl "http://localhost:8002/osm/api/event-logs?topic=run.completed" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Filter by run ID:**
|
||||
```bash
|
||||
curl "http://localhost:8002/osm/api/event-logs?run_id=abc12345" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Multiple filters:**
|
||||
```bash
|
||||
curl "http://localhost:8002/osm/api/event-logs?workspace=example.com&processed=false&limit=100" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Query Parameters:**
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `topic` | string | Filter by event topic (e.g., "run.started", "run.completed") |
|
||||
| `name` | string | Filter by event name |
|
||||
| `source` | string | Filter by event source (e.g., "executor", "scheduler", "api") |
|
||||
| `workspace` | string | Filter by workspace name |
|
||||
| `run_id` | string | Filter by run ID |
|
||||
| `workflow_name` | string | Filter by workflow name |
|
||||
| `processed` | bool | Filter by processed status ("true" or "false") |
|
||||
| `offset` | int | Pagination offset (default: 0) |
|
||||
| `limit` | int | Maximum records to return (default: 20, max: 10000) |
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"id": 1,
|
||||
"topic": "run.completed",
|
||||
"event_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"name": "subdomain-enum-completed",
|
||||
"source": "executor",
|
||||
"data_type": "scan",
|
||||
"data": "{\"scan_id\":\"abc12345\",\"target\":\"example.com\",\"duration_ms\":3600000,\"assets_found\":150,\"steps_completed\":10}",
|
||||
"workspace": "example.com",
|
||||
"run_id": "abc12345",
|
||||
"workflow_name": "subdomain-enum",
|
||||
"processed": true,
|
||||
"processed_at": "2025-01-15T10:30:00Z",
|
||||
"error": "",
|
||||
"created_at": "2025-01-15T09:30:00Z"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"topic": "run.started",
|
||||
"event_id": "660e8400-e29b-41d4-a716-446655440001",
|
||||
"name": "port-scan-started",
|
||||
"source": "api",
|
||||
"data_type": "scan",
|
||||
"data": "{\"scan_id\":\"def67890\",\"target\":\"test.com\",\"params\":{\"ports\":\"top-1000\"}}",
|
||||
"workspace": "test.com",
|
||||
"run_id": "def67890",
|
||||
"workflow_name": "port-scan",
|
||||
"processed": true,
|
||||
"processed_at": "2025-01-15T11:00:00Z",
|
||||
"error": "",
|
||||
"created_at": "2025-01-15T11:00:00Z"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"topic": "asset.discovered",
|
||||
"event_id": "770e8400-e29b-41d4-a716-446655440002",
|
||||
"name": "httpx-asset-found",
|
||||
"source": "executor",
|
||||
"data_type": "asset",
|
||||
"data": "{\"url\":\"https://api.example.com\",\"status_code\":200,\"title\":\"API Documentation\",\"tech\":[\"nginx\",\"nodejs\"]}",
|
||||
"workspace": "example.com",
|
||||
"run_id": "abc12345",
|
||||
"workflow_name": "subdomain-enum",
|
||||
"processed": true,
|
||||
"processed_at": "2025-01-15T10:15:00Z",
|
||||
"error": "",
|
||||
"created_at": "2025-01-15T10:15:00Z"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"topic": "schedule.triggered",
|
||||
"event_id": "880e8400-e29b-41d4-a716-446655440003",
|
||||
"name": "daily-scan-triggered",
|
||||
"source": "scheduler",
|
||||
"data_type": "schedule",
|
||||
"data": "{\"schedule_id\":\"sch_1234567890\",\"trigger_type\":\"cron\",\"schedule\":\"0 2 * * *\"}",
|
||||
"workspace": "example.com",
|
||||
"run_id": "ghi11111",
|
||||
"workflow_name": "subdomain-enum",
|
||||
"processed": true,
|
||||
"processed_at": "2025-01-16T02:00:00Z",
|
||||
"error": "",
|
||||
"created_at": "2025-01-16T02:00:00Z"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"topic": "run.failed",
|
||||
"event_id": "990e8400-e29b-41d4-a716-446655440004",
|
||||
"name": "nuclei-scan-failed",
|
||||
"source": "executor",
|
||||
"data_type": "scan",
|
||||
"data": "{\"scan_id\":\"jkl22222\",\"target\":\"unreachable.com\",\"error\":\"connection timeout\"}",
|
||||
"workspace": "unreachable.com",
|
||||
"run_id": "jkl22222",
|
||||
"workflow_name": "nuclei-scan",
|
||||
"processed": false,
|
||||
"processed_at": null,
|
||||
"error": "connection timeout after 5 retries",
|
||||
"created_at": "2025-01-15T14:00:00Z"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"topic": "step.completed",
|
||||
"event_id": "aae8400-e29b-41d4-a716-446655440005",
|
||||
"name": "run-subfinder-completed",
|
||||
"source": "executor",
|
||||
"data_type": "step",
|
||||
"data": "{\"step_name\":\"run-subfinder\",\"duration_ms\":45000,\"output_lines\":150}",
|
||||
"workspace": "example.com",
|
||||
"run_id": "abc12345",
|
||||
"workflow_name": "subdomain-enum",
|
||||
"processed": true,
|
||||
"processed_at": "2025-01-15T10:01:45Z",
|
||||
"error": "",
|
||||
"created_at": "2025-01-15T10:01:45Z"
|
||||
}
|
||||
],
|
||||
"pagination": {
|
||||
"total": 150,
|
||||
"offset": 0,
|
||||
"limit": 20
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Available Event Topics:**
|
||||
|
||||
| Topic | Description |
|
||||
|-------|-------------|
|
||||
| `run.started` | Workflow execution started |
|
||||
| `run.completed` | Workflow execution completed successfully |
|
||||
| `run.failed` | Workflow execution failed |
|
||||
| `asset.discovered` | New asset discovered during scan |
|
||||
| `asset.updated` | Existing asset information updated |
|
||||
| `webhook.received` | External webhook received |
|
||||
| `schedule.triggered` | Scheduled workflow triggered |
|
||||
| `step.completed` | Individual step completed |
|
||||
| `step.failed` | Individual step failed |
|
||||
@@ -0,0 +1,149 @@
|
||||
# Functions
|
||||
|
||||
## Execute Utility Function
|
||||
|
||||
Execute a utility function script with template rendering and JavaScript execution.
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/functions/eval \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"script": "trim(\" hello \")"
|
||||
}'
|
||||
```
|
||||
|
||||
**With target variable:**
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/functions/eval \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"script": "fileExists(\"{{target}}\")",
|
||||
"target": "/tmp/test.txt"
|
||||
}'
|
||||
```
|
||||
|
||||
**With custom parameters:**
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/functions/eval \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"script": "log_info(\"{{host}}:{{port}}\")",
|
||||
"params": {
|
||||
"host": "localhost",
|
||||
"port": "8080"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
**Request Body:**
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `script` | string | Yes | The JavaScript script to execute |
|
||||
| `target` | string | No | Target value for `{{target}}` variable |
|
||||
| `params` | object | No | Additional parameters for template rendering |
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"result": "hello",
|
||||
"rendered_script": "trim(\" hello \")"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## List Utility Functions
|
||||
|
||||
Get a categorized list of all available utility functions.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8002/osm/api/functions/list \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"functions": {
|
||||
"file": [
|
||||
{"name": "fileExists(path)", "description": "Check if file exists", "return_type": "bool"},
|
||||
{"name": "fileLength(path)", "description": "Count non-empty lines in file", "return_type": "int"},
|
||||
{"name": "readFile(path)", "description": "Read entire file contents", "return_type": "string"},
|
||||
{"name": "writeFile(path, content)", "description": "Write content to file", "return_type": "bool"},
|
||||
{"name": "appendFile(path, content)", "description": "Append content to file", "return_type": "bool"},
|
||||
{"name": "removeFile(path)", "description": "Delete a file", "return_type": "bool"},
|
||||
{"name": "copyFile(src, dst)", "description": "Copy file to destination", "return_type": "bool"},
|
||||
{"name": "mergeFiles(pattern, output)", "description": "Merge multiple files matching pattern", "return_type": "bool"}
|
||||
],
|
||||
"string": [
|
||||
{"name": "trim(str)", "description": "Trim whitespace", "return_type": "string"},
|
||||
{"name": "split(str, delim)", "description": "Split string by delimiter", "return_type": "[]string"},
|
||||
{"name": "replace(str, old, new)", "description": "Replace all occurrences", "return_type": "string"},
|
||||
{"name": "contains(str, substr)", "description": "Check if string contains substring", "return_type": "bool"},
|
||||
{"name": "toLowerCase(str)", "description": "Convert string to lowercase", "return_type": "string"},
|
||||
{"name": "toUpperCase(str)", "description": "Convert string to uppercase", "return_type": "string"},
|
||||
{"name": "join(array, delim)", "description": "Join array elements with delimiter", "return_type": "string"}
|
||||
],
|
||||
"utility": [
|
||||
{"name": "len(val)", "description": "Get length of string or array", "return_type": "int"},
|
||||
{"name": "exec_cmd(command)", "description": "Execute bash command and return output", "return_type": "string"},
|
||||
{"name": "isEmpty(val)", "description": "Check if value is empty/nil", "return_type": "bool"},
|
||||
{"name": "commandExists(name)", "description": "Check if command is installed", "return_type": "bool"},
|
||||
{"name": "sleep(seconds)", "description": "Sleep for specified seconds", "return_type": "void"}
|
||||
],
|
||||
"http": [
|
||||
{"name": "http_get(url)", "description": "Make HTTP GET request", "return_type": "object"},
|
||||
{"name": "http_post(url, body)", "description": "Make HTTP POST request with JSON body", "return_type": "object"},
|
||||
{"name": "httpRequest(url, method, headers, body)", "description": "Make HTTP request with full control", "return_type": "object"}
|
||||
],
|
||||
"logging": [
|
||||
{"name": "log_info(message)", "description": "Log info message with [INFO] prefix", "return_type": "void"},
|
||||
{"name": "log_debug(message)", "description": "Log debug message with [DEBUG] prefix", "return_type": "void"},
|
||||
{"name": "log_warn(message)", "description": "Log warning message with [WARN] prefix", "return_type": "void"},
|
||||
{"name": "log_error(message)", "description": "Log error message with [ERROR] prefix", "return_type": "void"}
|
||||
],
|
||||
"generation": [
|
||||
{"name": "randomString(length)", "description": "Generate random alphanumeric string", "return_type": "string"},
|
||||
{"name": "uuid()", "description": "Generate UUID v4", "return_type": "string"},
|
||||
{"name": "timestamp()", "description": "Get current Unix timestamp", "return_type": "int"}
|
||||
],
|
||||
"encoding": [
|
||||
{"name": "base64Encode(str)", "description": "Encode string to base64", "return_type": "string"},
|
||||
{"name": "base64Decode(str)", "description": "Decode base64 string", "return_type": "string"},
|
||||
{"name": "urlEncode(str)", "description": "URL encode string", "return_type": "string"},
|
||||
{"name": "urlDecode(str)", "description": "URL decode string", "return_type": "string"}
|
||||
],
|
||||
"unix_commands": [
|
||||
{"name": "sortUnix(inputFile, outputFile)", "description": "Sort file and remove duplicates", "return_type": "bool"},
|
||||
{"name": "diff_unix(file1, file2, outputFile)", "description": "Get difference between two files", "return_type": "bool"},
|
||||
{"name": "gitClone(url, destPath)", "description": "Clone git repository", "return_type": "bool"},
|
||||
{"name": "gitPull(repoPath)", "description": "Pull latest changes from git remote", "return_type": "bool"}
|
||||
],
|
||||
"database": [
|
||||
{"name": "db_insert_asset(workspace, data)", "description": "Insert asset into database", "return_type": "bool"},
|
||||
{"name": "db_query_assets(workspace, filter)", "description": "Query assets from database", "return_type": "[]object"},
|
||||
{"name": "db_update_workspace_stats(workspace)", "description": "Update workspace statistics", "return_type": "bool"}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Available Function Categories:**
|
||||
- `file` - File operations (fileExists, readFile, removeFile, etc.)
|
||||
- `string` - String manipulation (trim, split, replace, etc.)
|
||||
- `type_conversion` - Type conversions (parseInt, toString, etc.)
|
||||
- `utility` - General utilities (len, isEmpty, exec_cmd)
|
||||
- `logging` - Logging functions (log_info, log_debug)
|
||||
- `http` - HTTP requests
|
||||
- `generation` - Random values (randomString, uuid)
|
||||
- `encoding` - Base64 encode/decode
|
||||
- `notification` - Telegram notifications
|
||||
- `cdn_storage` - Cloud storage operations
|
||||
- `unix_commands` - Unix command wrappers (sortUnix, gitClone, etc.)
|
||||
- `archive` - Archive operations (zip_dir, unzip_dir)
|
||||
- `markdown` - Markdown rendering functions
|
||||
- `database` - Database operations
|
||||
@@ -0,0 +1,300 @@
|
||||
# Installation
|
||||
|
||||
## Get Registry Info
|
||||
|
||||
Fetch binary registry metadata with installation status. Supports two modes:
|
||||
- `direct-fetch` (default): Binary download URLs from registry JSON
|
||||
- `nix-build`: Nix flake binaries grouped by category
|
||||
|
||||
**Query Parameters:**
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `registry_mode` | string | `direct-fetch` | Registry mode: `direct-fetch` or `nix-build` |
|
||||
|
||||
---
|
||||
|
||||
### Direct-Fetch Mode (Default)
|
||||
|
||||
Returns binary metadata with download URLs for each platform/architecture.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8002/osm/api/registry-info \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"registry_mode": "direct-fetch",
|
||||
"registry_url": "https://raw.githubusercontent.com/osmedeus/osmedeus-base/main/registry-metadata.json",
|
||||
"binaries": {
|
||||
"nuclei": {
|
||||
"desc": "Vulnerability scanner",
|
||||
"tags": ["vuln", "scanner"],
|
||||
"version": "3.0.0",
|
||||
"linux": {
|
||||
"amd64": "https://github.com/projectdiscovery/nuclei/releases/download/v3.0.0/nuclei_3.0.0_linux_amd64.zip",
|
||||
"arm64": "https://github.com/projectdiscovery/nuclei/releases/download/v3.0.0/nuclei_3.0.0_linux_arm64.zip"
|
||||
},
|
||||
"darwin": {
|
||||
"amd64": "https://github.com/projectdiscovery/nuclei/releases/download/v3.0.0/nuclei_3.0.0_darwin_amd64.zip",
|
||||
"arm64": "https://github.com/projectdiscovery/nuclei/releases/download/v3.0.0/nuclei_3.0.0_darwin_arm64.zip"
|
||||
},
|
||||
"installed": true,
|
||||
"path": "/usr/local/bin/nuclei"
|
||||
},
|
||||
"amass": {
|
||||
"desc": "In-depth attack surface mapping",
|
||||
"tags": ["recon", "subdomain"],
|
||||
"version": "4.0.0",
|
||||
"linux": {
|
||||
"amd64": "https://github.com/owasp-amass/amass/releases/download/v4.0.0/amass_linux_amd64.zip"
|
||||
},
|
||||
"darwin": {
|
||||
"amd64": "https://github.com/owasp-amass/amass/releases/download/v4.0.0/amass_darwin_amd64.zip"
|
||||
},
|
||||
"installed": false,
|
||||
"path": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response Fields (direct-fetch):**
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `registry_mode` | string | Always `"direct-fetch"` |
|
||||
| `registry_url` | string | URL of the binary registry source |
|
||||
| `binaries` | object | Map of binary names to their metadata |
|
||||
| `binaries[name].desc` | string | Description of the binary tool |
|
||||
| `binaries[name].tags` | []string | Tags/categories for the binary |
|
||||
| `binaries[name].version` | string | Version of the binary |
|
||||
| `binaries[name].linux` | object | Linux download URLs by architecture (amd64, arm64) |
|
||||
| `binaries[name].darwin` | object | macOS download URLs by architecture |
|
||||
| `binaries[name].windows` | object | Windows download URLs by architecture |
|
||||
| `binaries[name].command-linux` | object | Linux install commands by architecture |
|
||||
| `binaries[name].command-darwin` | object | macOS install commands by architecture |
|
||||
| `binaries[name].installed` | boolean | Whether the binary is currently installed |
|
||||
| `binaries[name].path` | string | Full path to the installed binary |
|
||||
|
||||
---
|
||||
|
||||
### Nix-Build Mode
|
||||
|
||||
Returns Nix flake binaries grouped by category with registry metadata.
|
||||
|
||||
```bash
|
||||
curl "http://localhost:8002/osm/api/registry-info?registry_mode=nix-build" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"registry_mode": "nix-build",
|
||||
"nix_installed": true,
|
||||
"categories": [
|
||||
{
|
||||
"name": "Subdomain",
|
||||
"tools": [
|
||||
{
|
||||
"name": "amass",
|
||||
"desc": "In-depth attack surface mapping and asset discovery",
|
||||
"tags": ["recon", "subdomain"],
|
||||
"version": "4.2.0",
|
||||
"repo_link": "https://github.com/owasp-amass/amass",
|
||||
"installed": true,
|
||||
"path": "/home/user/.nix-profile/bin/amass"
|
||||
},
|
||||
{
|
||||
"name": "subfinder",
|
||||
"desc": "Fast passive subdomain enumeration tool",
|
||||
"tags": ["recon", "subdomain"],
|
||||
"version": "2.6.0",
|
||||
"installed": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Vuln",
|
||||
"tools": [
|
||||
{
|
||||
"name": "nuclei",
|
||||
"desc": "Fast, customizable vulnerability scanner",
|
||||
"tags": ["vuln", "scanner"],
|
||||
"version": "3.0.0",
|
||||
"installed": true,
|
||||
"path": "/home/user/.nix-profile/bin/nuclei"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Response Fields (nix-build):**
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `registry_mode` | string | Always `"nix-build"` |
|
||||
| `nix_installed` | boolean | Whether Nix package manager is installed |
|
||||
| `categories` | array | List of tool categories from flake.nix |
|
||||
| `categories[].name` | string | Category name (e.g., "Subdomain", "Vuln") |
|
||||
| `categories[].tools` | array | List of tools in this category |
|
||||
| `categories[].tools[].name` | string | Binary name |
|
||||
| `categories[].tools[].desc` | string | Description from registry |
|
||||
| `categories[].tools[].tags` | []string | Tags from registry |
|
||||
| `categories[].tools[].version` | string | Version from registry |
|
||||
| `categories[].tools[].repo_link` | string | Repository URL |
|
||||
| `categories[].tools[].installed` | boolean | Whether the binary is installed |
|
||||
| `categories[].tools[].path` | string | Full path to installed binary |
|
||||
|
||||
---
|
||||
|
||||
## Install Binaries or Workflows
|
||||
|
||||
Install binaries from registry or workflows from git/zip URL. Supports two installation modes for binaries.
|
||||
|
||||
**Endpoint:** `POST /osm/api/registry-install`
|
||||
|
||||
**Request Body:**
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `type` | string | **Required.** Either `"binary"` or `"workflow"` |
|
||||
| `names` | []string | Binary names to install (for `type=binary`) |
|
||||
| `install_all` | bool | Install all binaries from registry (for `type=binary`) |
|
||||
| `source` | string | Git URL, zip URL, or file path (for `type=workflow`) |
|
||||
| `registry_url` | string | Custom registry URL (optional, for `type=binary`) |
|
||||
| `registry_mode` | string | `"direct-fetch"` (default) or `"nix-build"` |
|
||||
|
||||
---
|
||||
|
||||
### Install Binaries (Direct-Fetch Mode)
|
||||
|
||||
Downloads binaries directly from GitHub releases or configured URLs.
|
||||
|
||||
**Install specific binaries:**
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/registry-install \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"type": "binary",
|
||||
"names": ["nuclei", "httpx", "ffuf"]
|
||||
}'
|
||||
```
|
||||
|
||||
**Install all binaries from registry:**
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/registry-install \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"type": "binary",
|
||||
"install_all": true
|
||||
}'
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"message": "Binary installation completed",
|
||||
"registry_mode": "direct-fetch",
|
||||
"installed": ["nuclei", "httpx"],
|
||||
"installed_count": 2,
|
||||
"binaries_folder": "/home/user/osmedeus-base/binaries",
|
||||
"failed": [
|
||||
{"name": "ffuf", "error": "download failed"}
|
||||
],
|
||||
"failed_count": 1
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Install Binaries (Nix-Build Mode)
|
||||
|
||||
Installs binaries via Nix package manager using `nix profile add`.
|
||||
|
||||
**Install specific binaries via Nix:**
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/registry-install \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"type": "binary",
|
||||
"names": ["amass", "subfinder", "nuclei"],
|
||||
"registry_mode": "nix-build"
|
||||
}'
|
||||
```
|
||||
|
||||
**Install all Nix binaries:**
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/registry-install \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"type": "binary",
|
||||
"install_all": true,
|
||||
"registry_mode": "nix-build"
|
||||
}'
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"message": "Nix binary installation completed",
|
||||
"registry_mode": "nix-build",
|
||||
"installed": ["amass", "subfinder", "nuclei"],
|
||||
"installed_count": 3,
|
||||
"binaries_folder": "/home/user/osmedeus-base/binaries"
|
||||
}
|
||||
```
|
||||
|
||||
**Error (Nix not installed):**
|
||||
```json
|
||||
{
|
||||
"error": true,
|
||||
"message": "Nix is not installed. Install Nix first or use registry_mode=direct-fetch"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Install Workflow
|
||||
|
||||
Install a workflow from a git repository or zip archive.
|
||||
|
||||
**Install workflow from git URL:**
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/registry-install \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"type": "workflow",
|
||||
"source": "https://github.com/osmedeus/osmedeus-workflow.git"
|
||||
}'
|
||||
```
|
||||
|
||||
**Install workflow from zip URL:**
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/registry-install \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"type": "workflow",
|
||||
"source": "https://example.com/custom-workflow.zip"
|
||||
}'
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"message": "Workflow installed successfully",
|
||||
"source": "https://github.com/osmedeus/osmedeus-workflow.git",
|
||||
"workflow_folder": "/home/user/osmedeus-base/workflow"
|
||||
}
|
||||
```
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
# LLM API
|
||||
|
||||
Direct API access to Large Language Model capabilities without requiring workflow execution.
|
||||
|
||||
## Chat Completion
|
||||
|
||||
Send a chat completion request to the configured LLM provider.
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/llm/v1/chat/completions \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"messages": [
|
||||
{"role": "system", "content": "You are a security analyst."},
|
||||
{"role": "user", "content": "Analyze the security posture of example.com"}
|
||||
],
|
||||
"max_tokens": 1000,
|
||||
"temperature": 0.7
|
||||
}'
|
||||
```
|
||||
|
||||
**Request Body:**
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `messages` | array | Yes | Array of message objects with `role` and `content` |
|
||||
| `model` | string | No | Model to use (defaults to provider's default model) |
|
||||
| `max_tokens` | int | No | Maximum tokens in response |
|
||||
| `temperature` | float | No | Sampling temperature (0.0-2.0) |
|
||||
| `top_p` | float | No | Top-p sampling parameter |
|
||||
| `top_k` | int | No | Top-k sampling parameter |
|
||||
| `n` | int | No | Number of completions to generate |
|
||||
| `stream` | bool | No | Enable streaming (not yet supported) |
|
||||
| `tools` | array | No | Tool definitions for function calling |
|
||||
| `tool_choice` | string/object | No | Tool selection strategy |
|
||||
| `response_format` | object | No | Response format (`{"type": "json_object"}`) |
|
||||
|
||||
**Message Roles:**
|
||||
- `system` - System prompt to set assistant behavior
|
||||
- `user` - User message
|
||||
- `assistant` - Previous assistant response
|
||||
- `tool` - Tool call result
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"id": "chatcmpl-abc123",
|
||||
"model": "gpt-4",
|
||||
"content": "Based on my analysis of example.com...",
|
||||
"finish_reason": "stop",
|
||||
"usage": {
|
||||
"prompt_tokens": 50,
|
||||
"completion_tokens": 200,
|
||||
"total_tokens": 250
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## With Tools (Function Calling)
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/llm/v1/chat/completions \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"messages": [
|
||||
{"role": "user", "content": "What DNS records exist for example.com?"}
|
||||
],
|
||||
"tools": [
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "dns_lookup",
|
||||
"description": "Look up DNS records for a domain",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"domain": {"type": "string", "description": "Domain to look up"},
|
||||
"record_type": {"type": "string", "enum": ["A", "AAAA", "MX", "TXT", "NS"]}
|
||||
},
|
||||
"required": ["domain"]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"tool_choice": "auto"
|
||||
}'
|
||||
```
|
||||
|
||||
**Response with Tool Calls:**
|
||||
```json
|
||||
{
|
||||
"id": "chatcmpl-xyz789",
|
||||
"model": "gpt-4",
|
||||
"content": null,
|
||||
"finish_reason": "tool_calls",
|
||||
"tool_calls": [
|
||||
{
|
||||
"id": "call_abc123",
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "dns_lookup",
|
||||
"arguments": "{\"domain\": \"example.com\", \"record_type\": \"A\"}"
|
||||
}
|
||||
}
|
||||
],
|
||||
"usage": {
|
||||
"prompt_tokens": 100,
|
||||
"completion_tokens": 25,
|
||||
"total_tokens": 125
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Generate Embeddings
|
||||
|
||||
Generate vector embeddings for input text.
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/llm/v1/embeddings \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"input": ["security analysis", "vulnerability assessment"],
|
||||
"model": "text-embedding-3-small"
|
||||
}'
|
||||
```
|
||||
|
||||
**Request Body:**
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `input` | array | Yes | Array of strings to embed |
|
||||
| `model` | string | No | Embedding model (defaults to provider's model) |
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"model": "text-embedding-3-small",
|
||||
"embeddings": [
|
||||
[0.0023, -0.0045, 0.0178, ...],
|
||||
[0.0112, -0.0067, 0.0234, ...]
|
||||
],
|
||||
"usage": {
|
||||
"prompt_tokens": 10,
|
||||
"total_tokens": 10
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,95 @@
|
||||
# Public Endpoints
|
||||
|
||||
These endpoints do not require authentication.
|
||||
|
||||
## Server Info
|
||||
|
||||
Get server version and information.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8002/server-info
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"message": "Oh dear me, how delightful to notice you're taking a look at this! I'm ever so pleased to let you know that osmedeus is ticking along quite nicely, thank you.",
|
||||
"version": "v5.0.0",
|
||||
"repo": "https://github.com/j3ssie/osmedeus",
|
||||
"author": "j3ssie",
|
||||
"docs": "https://docs.osmedeus.org"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Health Check
|
||||
|
||||
Check if the server is running.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8002/health
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "ok"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Readiness Check
|
||||
|
||||
Check if the server is ready to accept requests.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8002/health/ready
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "ready"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Swagger Documentation
|
||||
|
||||
Access the interactive Swagger UI documentation.
|
||||
|
||||
```bash
|
||||
# Open in browser
|
||||
open http://localhost:8002/swagger/index.html
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Web UI
|
||||
|
||||
The web UI is served at the root path. It uses embedded UI files by default, with an option to serve from an external path.
|
||||
|
||||
```bash
|
||||
# Access the web UI in browser
|
||||
open http://localhost:8002/
|
||||
```
|
||||
|
||||
**UI Serving Priority:**
|
||||
1. If `ui_path` is configured and exists, serves from that directory
|
||||
2. Otherwise, serves embedded UI files from `public/ui/`
|
||||
|
||||
---
|
||||
|
||||
## Workspace Files
|
||||
|
||||
Scan output files can be accessed directly via the workspace path. This endpoint is only available when `workspace_prefix` is configured in server settings.
|
||||
|
||||
```bash
|
||||
# Access run outputs (no authentication required)
|
||||
curl http://localhost:8002/ws/{workspace_prefix}/example.com/subdomain/final.txt
|
||||
```
|
||||
|
||||
The workspace path serves files from the configured workspaces directory with directory listing enabled.
|
||||
@@ -0,0 +1,374 @@
|
||||
# API Reference
|
||||
|
||||
## Error Responses
|
||||
|
||||
All endpoints return errors in a consistent format:
|
||||
|
||||
```json
|
||||
{
|
||||
"error": true,
|
||||
"message": "Error description"
|
||||
}
|
||||
```
|
||||
|
||||
**Common HTTP Status Codes:**
|
||||
- `200` - Success
|
||||
- `201` - Created
|
||||
- `202` - Accepted (async operation started)
|
||||
- `400` - Bad Request (invalid input)
|
||||
- `401` - Unauthorized (missing or invalid token)
|
||||
- `404` - Not Found
|
||||
- `500` - Internal Server Error
|
||||
|
||||
---
|
||||
|
||||
## Pagination
|
||||
|
||||
Endpoints that return lists support pagination via query parameters:
|
||||
|
||||
| Parameter | Default | Max | Description |
|
||||
|-----------|---------|-----|-------------|
|
||||
| `offset` | 0 | - | Number of records to skip |
|
||||
| `limit` | 20 | 10000 | Maximum records to return |
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
curl "http://localhost:8002/osm/api/assets?offset=100&limit=50" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Cron Expression Reference
|
||||
|
||||
Schedules use standard cron expressions:
|
||||
|
||||
```
|
||||
┌───────────── minute (0-59)
|
||||
│ ┌───────────── hour (0-23)
|
||||
│ │ ┌───────────── day of month (1-31)
|
||||
│ │ │ ┌───────────── month (1-12)
|
||||
│ │ │ │ ┌───────────── day of week (0-6, Sunday=0)
|
||||
│ │ │ │ │
|
||||
* * * * *
|
||||
```
|
||||
|
||||
**Examples:**
|
||||
- `0 2 * * *` - Every day at 2:00 AM
|
||||
- `0 0 * * 0` - Every Sunday at midnight
|
||||
- `*/30 * * * *` - Every 30 minutes
|
||||
- `0 9-17 * * 1-5` - Every hour from 9 AM to 5 PM, Monday to Friday
|
||||
|
||||
---
|
||||
|
||||
## Workflow Step Types
|
||||
|
||||
Reference documentation for workflow step types used in YAML workflow definitions.
|
||||
|
||||
### bash
|
||||
|
||||
Execute shell commands on the local system or configured runner.
|
||||
|
||||
```yaml
|
||||
- name: run-nuclei
|
||||
type: bash
|
||||
log: "Running nuclei scan"
|
||||
command: nuclei -u {{Target}} -o {{Output}}/nuclei.txt
|
||||
timeout: 3600
|
||||
exports:
|
||||
nuclei_results: "{{Output}}/nuclei.txt"
|
||||
```
|
||||
|
||||
**Fields:**
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `name` | string | Yes | Unique step name |
|
||||
| `type` | string | Yes | Must be `bash` |
|
||||
| `command` | string | No* | Single command to execute |
|
||||
| `commands` | array | No* | Sequential commands |
|
||||
| `parallel_commands` | array | No* | Commands to run in parallel |
|
||||
| `timeout` | int | No | Timeout in seconds |
|
||||
| `log` | string | No | Log message displayed during execution |
|
||||
| `pre_condition` | string | No | Condition that must be true to run |
|
||||
| `exports` | map | No | Variables to export after execution |
|
||||
|
||||
*One of `command`, `commands`, or `parallel_commands` is required.
|
||||
|
||||
---
|
||||
|
||||
### function
|
||||
|
||||
Execute utility functions written in JavaScript via Otto VM.
|
||||
|
||||
```yaml
|
||||
- name: check-file
|
||||
type: function
|
||||
log: "Checking if results exist"
|
||||
function: fileExists("{{Output}}/results.txt")
|
||||
exports:
|
||||
has_results: "{{check_file_output}}"
|
||||
```
|
||||
|
||||
**Fields:**
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `name` | string | Yes | Unique step name |
|
||||
| `type` | string | Yes | Must be `function` |
|
||||
| `function` | string | No* | Single function to execute |
|
||||
| `functions` | array | No* | Sequential functions |
|
||||
| `parallel_functions` | array | No* | Functions to run in parallel |
|
||||
|
||||
*One of `function`, `functions`, or `parallel_functions` is required.
|
||||
|
||||
---
|
||||
|
||||
### parallel-steps
|
||||
|
||||
Run multiple steps concurrently.
|
||||
|
||||
```yaml
|
||||
- name: parallel-scans
|
||||
type: parallel-steps
|
||||
log: "Running scans in parallel"
|
||||
parallel_steps:
|
||||
- name: nuclei-scan
|
||||
type: bash
|
||||
command: nuclei -u {{Target}}
|
||||
- name: httpx-scan
|
||||
type: bash
|
||||
command: httpx -u {{Target}}
|
||||
```
|
||||
|
||||
**Fields:**
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `name` | string | Yes | Unique step name |
|
||||
| `type` | string | Yes | Must be `parallel-steps` |
|
||||
| `parallel_steps` | array | Yes | Array of steps to run concurrently |
|
||||
|
||||
---
|
||||
|
||||
### foreach
|
||||
|
||||
Iterate over items from a file or array.
|
||||
|
||||
```yaml
|
||||
- name: scan-subdomains
|
||||
type: foreach
|
||||
log: "Scanning each subdomain"
|
||||
input: "{{Output}}/subdomains.txt"
|
||||
variable: subdomain
|
||||
step:
|
||||
name: scan-subdomain
|
||||
type: bash
|
||||
command: httpx -u [[subdomain]]
|
||||
```
|
||||
|
||||
**Fields:**
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `name` | string | Yes | Unique step name |
|
||||
| `type` | string | Yes | Must be `foreach` |
|
||||
| `input` | string | Yes | File path or array to iterate over |
|
||||
| `variable` | string | Yes | Loop variable name (use `[[variable]]`) |
|
||||
| `step` | object | Yes | Step to execute for each item |
|
||||
| `parallel` | int | No | Number of parallel iterations |
|
||||
|
||||
---
|
||||
|
||||
### remote-bash
|
||||
|
||||
Execute commands in Docker containers or via SSH.
|
||||
|
||||
```yaml
|
||||
- name: docker-scan
|
||||
type: remote-bash
|
||||
log: "Running scan in Docker"
|
||||
step_runner: docker
|
||||
step_runner_config:
|
||||
image: "projectdiscovery/nuclei:latest"
|
||||
volumes:
|
||||
- "{{Output}}:/output"
|
||||
command: nuclei -u {{Target}} -o /output/nuclei.txt
|
||||
```
|
||||
|
||||
**Fields:**
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `name` | string | Yes | Unique step name |
|
||||
| `type` | string | Yes | Must be `remote-bash` |
|
||||
| `step_runner` | string | Yes | `docker` or `ssh` |
|
||||
| `step_runner_config` | object | No | Runner-specific configuration |
|
||||
| `command` | string | No* | Command to execute |
|
||||
| `commands` | array | No* | Sequential commands |
|
||||
|
||||
**Docker Configuration:**
|
||||
```yaml
|
||||
step_runner_config:
|
||||
image: "image:tag"
|
||||
volumes: ["host:container"]
|
||||
env:
|
||||
KEY: value
|
||||
network: "host"
|
||||
workdir: "/app"
|
||||
```
|
||||
|
||||
**SSH Configuration:**
|
||||
```yaml
|
||||
step_runner_config:
|
||||
host: "worker.example.com"
|
||||
user: "ubuntu"
|
||||
key_file: "~/.ssh/id_rsa"
|
||||
port: 22
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### http
|
||||
|
||||
Make HTTP requests and capture responses.
|
||||
|
||||
```yaml
|
||||
- name: api-request
|
||||
type: http
|
||||
log: "Calling API"
|
||||
url: "https://api.example.com/endpoint"
|
||||
method: POST
|
||||
headers:
|
||||
Content-Type: "application/json"
|
||||
Authorization: "Bearer {{api_token}}"
|
||||
request_body: '{"domain": "{{Target}}"}'
|
||||
timeout: 30
|
||||
exports:
|
||||
api_response: "{{api_request_body}}"
|
||||
```
|
||||
|
||||
**Fields:**
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `name` | string | Yes | Unique step name |
|
||||
| `type` | string | Yes | Must be `http` |
|
||||
| `url` | string | Yes | Request URL |
|
||||
| `method` | string | No | HTTP method (default: GET) |
|
||||
| `headers` | map | No | Request headers |
|
||||
| `request_body` | string | No | Request body for POST/PUT |
|
||||
| `timeout` | int | No | Timeout in seconds |
|
||||
|
||||
**Auto-Exports:**
|
||||
- `<step_name>_status_code` - HTTP status code
|
||||
- `<step_name>_body` - Response body
|
||||
- `<step_name>_headers` - Response headers
|
||||
|
||||
---
|
||||
|
||||
### llm
|
||||
|
||||
Execute LLM (Large Language Model) API calls for AI-powered analysis.
|
||||
|
||||
```yaml
|
||||
- name: analyze-target
|
||||
type: llm
|
||||
log: "Analyzing target with LLM"
|
||||
messages:
|
||||
- role: system
|
||||
content: "You are a security analyst."
|
||||
- role: user
|
||||
content: "Analyze the security of {{Target}}"
|
||||
llm_config:
|
||||
max_tokens: 1000
|
||||
temperature: 0.7
|
||||
timeout: 60
|
||||
exports:
|
||||
analysis: "{{analyze_target_content}}"
|
||||
```
|
||||
|
||||
**Fields:**
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `name` | string | Yes | Unique step name |
|
||||
| `type` | string | Yes | Must be `llm` |
|
||||
| `messages` | array | No* | Chat messages (role + content) |
|
||||
| `is_embedding` | bool | No | Set to true for embeddings |
|
||||
| `embedding_input` | array | No* | Strings to embed |
|
||||
| `llm_config` | object | No | Step-level LLM configuration |
|
||||
| `tools` | array | No | Tool definitions for function calling |
|
||||
| `tool_choice` | string | No | Tool selection (`auto`, `none`, etc.) |
|
||||
| `extra_llm_parameters` | map | No | Additional provider-specific params |
|
||||
| `timeout` | int | No | Timeout in seconds |
|
||||
|
||||
*Either `messages` or `embedding_input` (with `is_embedding: true`) is required.
|
||||
|
||||
**Message Format:**
|
||||
```yaml
|
||||
messages:
|
||||
- role: system
|
||||
content: "System prompt"
|
||||
- role: user
|
||||
content: "User message with {{variables}}"
|
||||
```
|
||||
|
||||
**Multimodal Messages (with images):**
|
||||
```yaml
|
||||
messages:
|
||||
- role: user
|
||||
content:
|
||||
- type: text
|
||||
text: "What do you see in this screenshot?"
|
||||
- type: image_url
|
||||
image_url:
|
||||
url: "data:image/png;base64,{{screenshot_base64}}"
|
||||
```
|
||||
|
||||
**LLM Configuration Override:**
|
||||
```yaml
|
||||
llm_config:
|
||||
model: "gpt-4"
|
||||
max_tokens: 2000
|
||||
temperature: 0.3
|
||||
response_format:
|
||||
type: json_object
|
||||
```
|
||||
|
||||
**Embeddings:**
|
||||
```yaml
|
||||
- name: generate-embeddings
|
||||
type: llm
|
||||
is_embedding: true
|
||||
embedding_input:
|
||||
- "{{Target}} security analysis"
|
||||
- "vulnerability assessment"
|
||||
exports:
|
||||
embeddings: "{{generate_embeddings_llm_resp}}"
|
||||
```
|
||||
|
||||
**Tool Calling:**
|
||||
```yaml
|
||||
- name: with-tools
|
||||
type: llm
|
||||
messages:
|
||||
- role: user
|
||||
content: "What DNS records exist for {{Target}}?"
|
||||
tools:
|
||||
- type: function
|
||||
function:
|
||||
name: dns_lookup
|
||||
description: "Look up DNS records"
|
||||
parameters:
|
||||
type: object
|
||||
properties:
|
||||
domain:
|
||||
type: string
|
||||
required: [domain]
|
||||
tool_choice: auto
|
||||
```
|
||||
|
||||
**Auto-Exports:**
|
||||
- `<step_name>_llm_resp` - Full response object (id, model, usage, content, tool_calls)
|
||||
- `<step_name>_content` - Just the content string for easy access
|
||||
@@ -0,0 +1,352 @@
|
||||
# Runs (Scans)
|
||||
|
||||
## Create a New Scan
|
||||
|
||||
Execute a workflow against a target.
|
||||
|
||||
**Basic scan with flow workflow:**
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/runs \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"flow": "subdomain-enum",
|
||||
"target": "example.com"
|
||||
}'
|
||||
```
|
||||
|
||||
**Basic scan with module workflow:**
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/runs \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"module": "port-scan",
|
||||
"target": "example.com"
|
||||
}'
|
||||
```
|
||||
|
||||
**Scan with custom parameters:**
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/runs \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"flow": "subdomain-enum",
|
||||
"target": "example.com",
|
||||
"params": {
|
||||
"threads": "50",
|
||||
"timeout": "30"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
**Scan with priority and timeout:**
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/runs \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"flow": "subdomain-enum",
|
||||
"target": "example.com",
|
||||
"priority": "high",
|
||||
"timeout": 60
|
||||
}'
|
||||
```
|
||||
|
||||
**Scan with Docker runner:**
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/runs \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"flow": "subdomain-enum",
|
||||
"target": "example.com",
|
||||
"runner_type": "docker",
|
||||
"docker_image": "osmedeus/osmedeus:latest"
|
||||
}'
|
||||
```
|
||||
|
||||
**Scan with SSH runner:**
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/runs \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"flow": "subdomain-enum",
|
||||
"target": "example.com",
|
||||
"runner_type": "ssh",
|
||||
"ssh_host": "worker1.example.com"
|
||||
}'
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"message": "Run started",
|
||||
"workflow": "subdomain-enum",
|
||||
"kind": "flow",
|
||||
"target": "example.com",
|
||||
"target_count": 1,
|
||||
"priority": "high",
|
||||
"runner_type": "docker",
|
||||
"timeout": 60
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Multi-Target Scanning
|
||||
|
||||
Scan multiple targets with concurrency control:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/runs \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"flow": "subdomain-enum",
|
||||
"targets": ["example.com", "test.com", "demo.com"],
|
||||
"concurrency": 3
|
||||
}'
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"message": "Scan started",
|
||||
"workflow": "subdomain-enum",
|
||||
"kind": "flow",
|
||||
"target_count": 3,
|
||||
"targets": ["example.com", "test.com", "demo.com"],
|
||||
"concurrency": 3,
|
||||
"priority": "medium"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Scan from Uploaded Target File
|
||||
|
||||
Use an uploaded target file (from `/osm/api/upload-file`) for running:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/runs \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"module": "port-scan",
|
||||
"target_file": "/home/user/osmedeus-base/data/uploads/targets.txt",
|
||||
"concurrency": 5
|
||||
}'
|
||||
```
|
||||
|
||||
This is similar to CLI's `-T` flag: `osmedeus run -m port-scan -T targets.txt`
|
||||
|
||||
---
|
||||
|
||||
## List Runs
|
||||
|
||||
Get a paginated list of all runs.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8002/osm/api/runs \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Query Parameters:**
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `status` | string | - | Filter by status: `pending`, `running`, `completed`, `failed` |
|
||||
| `workflow_name` | string | - | Filter by workflow name |
|
||||
| `target` | string | - | Filter by target |
|
||||
| `offset` | int | 0 | Pagination offset |
|
||||
| `limit` | int | 20 | Maximum records to return |
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"id": "run-abc123",
|
||||
"run_id": "run-2025-01-15-subdomain-enum-example.com",
|
||||
"workflow_name": "subdomain-enum",
|
||||
"workflow_kind": "flow",
|
||||
"target": "example.com",
|
||||
"params": {"threads": "50"},
|
||||
"status": "running",
|
||||
"workspace_path": "/home/user/osmedeus-base/workspaces/example.com",
|
||||
"started_at": "2025-01-15T10:00:00Z",
|
||||
"completed_at": null,
|
||||
"total_steps": 10,
|
||||
"completed_steps": 3,
|
||||
"trigger_type": "manual",
|
||||
"created_at": "2025-01-15T10:00:00Z",
|
||||
"updated_at": "2025-01-15T10:03:00Z"
|
||||
}
|
||||
],
|
||||
"pagination": {
|
||||
"total": 50,
|
||||
"offset": 0,
|
||||
"limit": 20
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Get Run Details
|
||||
|
||||
Get details of a specific run by ID.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8002/osm/api/runs/run-abc123 \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"id": "run-abc123",
|
||||
"run_id": "run-2025-01-15-subdomain-enum-example.com",
|
||||
"workflow_name": "subdomain-enum",
|
||||
"workflow_kind": "flow",
|
||||
"target": "example.com",
|
||||
"params": {"threads": "50"},
|
||||
"status": "completed",
|
||||
"workspace_path": "/home/user/osmedeus-base/workspaces/example.com",
|
||||
"started_at": "2025-01-15T10:00:00Z",
|
||||
"completed_at": "2025-01-15T10:30:00Z",
|
||||
"error_message": "",
|
||||
"schedule_id": "",
|
||||
"trigger_type": "manual",
|
||||
"trigger_name": "",
|
||||
"total_steps": 10,
|
||||
"completed_steps": 10,
|
||||
"created_at": "2025-01-15T10:00:00Z",
|
||||
"updated_at": "2025-01-15T10:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Cancel Run
|
||||
|
||||
Cancel a running workflow execution.
|
||||
|
||||
```bash
|
||||
curl -X DELETE http://localhost:8002/osm/api/runs/run-abc123 \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"message": "Run cancellation requested",
|
||||
"id": "run-abc123"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Get Run Steps
|
||||
|
||||
Get all step results for a specific run.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8002/osm/api/runs/run-abc123/steps \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"id": "step-xyz789",
|
||||
"run_id": "run-abc123",
|
||||
"step_name": "run-subfinder",
|
||||
"step_type": "bash",
|
||||
"status": "completed",
|
||||
"command": "subfinder -d example.com -o subdomains.txt",
|
||||
"output": "Found 150 subdomains",
|
||||
"error_message": "",
|
||||
"exports": {"subdomains_file": "subdomains.txt"},
|
||||
"duration_ms": 45000,
|
||||
"log_file": "/workspaces/example.com/logs/run-subfinder.log",
|
||||
"started_at": "2025-01-15T10:01:00Z",
|
||||
"completed_at": "2025-01-15T10:01:45Z",
|
||||
"created_at": "2025-01-15T10:01:00Z"
|
||||
},
|
||||
{
|
||||
"id": "step-def456",
|
||||
"run_id": "run-abc123",
|
||||
"step_name": "run-httpx",
|
||||
"step_type": "bash",
|
||||
"status": "completed",
|
||||
"command": "httpx -l subdomains.txt -o alive.txt",
|
||||
"output": "Probed 150 hosts, 89 alive",
|
||||
"error_message": "",
|
||||
"exports": {"alive_file": "alive.txt"},
|
||||
"duration_ms": 120000,
|
||||
"log_file": "/workspaces/example.com/logs/run-httpx.log",
|
||||
"started_at": "2025-01-15T10:01:45Z",
|
||||
"completed_at": "2025-01-15T10:03:45Z",
|
||||
"created_at": "2025-01-15T10:01:45Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Get Run Artifacts
|
||||
|
||||
Get all output artifacts for a specific run.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8002/osm/api/runs/run-abc123/artifacts \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"id": "artifact-001",
|
||||
"run_id": "run-abc123",
|
||||
"name": "subdomains.txt",
|
||||
"path": "/workspaces/example.com/subdomains.txt",
|
||||
"type": "text",
|
||||
"size_bytes": 4523,
|
||||
"line_count": 150,
|
||||
"description": "Discovered subdomains",
|
||||
"created_at": "2025-01-15T10:01:45Z"
|
||||
},
|
||||
{
|
||||
"id": "artifact-002",
|
||||
"run_id": "run-abc123",
|
||||
"name": "alive.txt",
|
||||
"path": "/workspaces/example.com/alive.txt",
|
||||
"type": "text",
|
||||
"size_bytes": 2890,
|
||||
"line_count": 89,
|
||||
"description": "Alive HTTP endpoints",
|
||||
"created_at": "2025-01-15T10:03:45Z"
|
||||
},
|
||||
{
|
||||
"id": "artifact-003",
|
||||
"run_id": "run-abc123",
|
||||
"name": "nuclei-results.json",
|
||||
"path": "/workspaces/example.com/nuclei-results.json",
|
||||
"type": "json",
|
||||
"size_bytes": 15234,
|
||||
"line_count": 45,
|
||||
"description": "Nuclei vulnerability scan results",
|
||||
"created_at": "2025-01-15T10:15:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,273 @@
|
||||
# Schedules
|
||||
|
||||
## List Schedules
|
||||
|
||||
Get a paginated list of all scheduled workflows.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8002/osm/api/schedules \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**With pagination:**
|
||||
```bash
|
||||
curl "http://localhost:8002/osm/api/schedules?offset=0&limit=50" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"id": "sch_1234567890",
|
||||
"name": "daily-scan",
|
||||
"workflow_name": "subdomain-enum",
|
||||
"workflow_path": "/home/user/osmedeus-base/workflows/flows/subdomain-enum.yaml",
|
||||
"trigger_name": "daily-scan-trigger",
|
||||
"trigger_type": "cron",
|
||||
"schedule": "0 2 * * *",
|
||||
"event_topic": "",
|
||||
"watch_path": "",
|
||||
"input_config": {
|
||||
"target": "example.com",
|
||||
"threads": "50"
|
||||
},
|
||||
"is_enabled": true,
|
||||
"last_run": "2025-01-15T02:00:00Z",
|
||||
"next_run": "2025-01-16T02:00:00Z",
|
||||
"run_count": 30,
|
||||
"created_at": "2025-01-01T00:00:00Z",
|
||||
"updated_at": "2025-01-15T02:00:00Z"
|
||||
},
|
||||
{
|
||||
"id": "sch_0987654321",
|
||||
"name": "weekly-full-recon",
|
||||
"workflow_name": "full-recon",
|
||||
"workflow_path": "/home/user/osmedeus-base/workflows/flows/full-recon.yaml",
|
||||
"trigger_name": "weekly-trigger",
|
||||
"trigger_type": "cron",
|
||||
"schedule": "0 0 * * 0",
|
||||
"event_topic": "",
|
||||
"watch_path": "",
|
||||
"input_config": {
|
||||
"target": "example.com",
|
||||
"threads": "100",
|
||||
"runner_type": "docker"
|
||||
},
|
||||
"is_enabled": true,
|
||||
"last_run": "2025-01-12T00:00:00Z",
|
||||
"next_run": "2025-01-19T00:00:00Z",
|
||||
"run_count": 5,
|
||||
"created_at": "2025-01-01T00:00:00Z",
|
||||
"updated_at": "2025-01-12T00:00:00Z"
|
||||
}
|
||||
],
|
||||
"pagination": {
|
||||
"total": 5,
|
||||
"offset": 0,
|
||||
"limit": 20
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Create Schedule
|
||||
|
||||
Create a new scheduled workflow execution.
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/schedules \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"name": "daily-scan",
|
||||
"workflow_name": "subdomain-enum",
|
||||
"workflow_kind": "flow",
|
||||
"target": "example.com",
|
||||
"schedule": "0 2 * * *",
|
||||
"enabled": true
|
||||
}'
|
||||
```
|
||||
|
||||
**With additional parameters:**
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/schedules \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"name": "weekly-full-scan",
|
||||
"workflow_name": "full-recon",
|
||||
"workflow_kind": "flow",
|
||||
"target": "example.com",
|
||||
"schedule": "0 0 * * 0",
|
||||
"enabled": true,
|
||||
"params": {
|
||||
"threads": "100"
|
||||
},
|
||||
"runner_type": "docker"
|
||||
}'
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"message": "Schedule created",
|
||||
"data": {
|
||||
"id": "sch_1234567890",
|
||||
"name": "daily-scan",
|
||||
"workflow_name": "subdomain-enum",
|
||||
"schedule": "0 2 * * *",
|
||||
"is_enabled": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Get Schedule
|
||||
|
||||
Get details of a specific schedule.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8002/osm/api/schedules/sch_1234567890 \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"id": "sch_1234567890",
|
||||
"name": "daily-scan",
|
||||
"workflow_name": "subdomain-enum",
|
||||
"workflow_path": "/home/user/osmedeus-base/workflows/flows/subdomain-enum.yaml",
|
||||
"trigger_name": "daily-scan-trigger",
|
||||
"trigger_type": "cron",
|
||||
"schedule": "0 2 * * *",
|
||||
"event_topic": "",
|
||||
"watch_path": "",
|
||||
"input_config": {
|
||||
"target": "example.com",
|
||||
"threads": "50"
|
||||
},
|
||||
"is_enabled": true,
|
||||
"last_run": "2025-01-15T02:00:00Z",
|
||||
"next_run": "2025-01-16T02:00:00Z",
|
||||
"run_count": 30,
|
||||
"created_at": "2025-01-01T00:00:00Z",
|
||||
"updated_at": "2025-01-15T02:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Update Schedule
|
||||
|
||||
Update an existing schedule.
|
||||
|
||||
```bash
|
||||
curl -X PUT http://localhost:8002/osm/api/schedules/sch_1234567890 \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"name": "updated-daily-scan",
|
||||
"schedule": "0 3 * * *"
|
||||
}'
|
||||
```
|
||||
|
||||
**Update only the schedule:**
|
||||
```bash
|
||||
curl -X PUT http://localhost:8002/osm/api/schedules/sch_1234567890 \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"schedule": "0 4 * * *"
|
||||
}'
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"message": "Schedule updated",
|
||||
"data": {
|
||||
"id": "sch_1234567890",
|
||||
"name": "updated-daily-scan",
|
||||
"schedule": "0 3 * * *"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Delete Schedule
|
||||
|
||||
Delete a schedule.
|
||||
|
||||
```bash
|
||||
curl -X DELETE http://localhost:8002/osm/api/schedules/sch_1234567890 \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"message": "Schedule deleted"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Enable Schedule
|
||||
|
||||
Enable a disabled schedule.
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/schedules/sch_1234567890/enable \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"message": "Schedule enabled"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Disable Schedule
|
||||
|
||||
Disable an enabled schedule.
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/schedules/sch_1234567890/disable \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"message": "Schedule disabled"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Trigger Schedule
|
||||
|
||||
Manually trigger a scheduled workflow execution.
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/schedules/sch_1234567890/trigger \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"message": "Schedule triggered",
|
||||
"schedule": "daily-scan",
|
||||
"workflow": "subdomain-enum"
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,72 @@
|
||||
# Settings
|
||||
|
||||
Manage server configuration settings.
|
||||
|
||||
## Get YAML Configuration
|
||||
|
||||
Get the entire YAML configuration file with sensitive fields redacted. Fields containing `_key`, `secret`, `password`, `username`, or `_token` are replaced with `[REDACTED]`.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8002/osm/api/settings/yaml \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:** (text/yaml)
|
||||
```yaml
|
||||
# =============================================================================
|
||||
# Osmedeus Configuration File
|
||||
# =============================================================================
|
||||
base_folder: ~/osmedeus-base
|
||||
|
||||
environments:
|
||||
binaries_path: "{{base_folder}}/binaries"
|
||||
# ... more config
|
||||
|
||||
server:
|
||||
host: "0.0.0.0"
|
||||
port: 8002
|
||||
workspace_prefix_key: "[REDACTED]"
|
||||
simple_user_map_key: "[REDACTED]"
|
||||
jwt:
|
||||
secret_signing_key: "[REDACTED]"
|
||||
expiration_minutes: 180
|
||||
|
||||
database:
|
||||
host: ""
|
||||
port: 5432
|
||||
username: "[REDACTED]"
|
||||
password: "[REDACTED]"
|
||||
# ... more config
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Update YAML Configuration
|
||||
|
||||
Replace the entire YAML configuration file with new content. A backup of the existing configuration is created before overwriting.
|
||||
|
||||
```bash
|
||||
curl -X PUT http://localhost:8002/osm/api/settings/yaml \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: text/yaml" \
|
||||
--data-binary @new-config.yaml
|
||||
```
|
||||
|
||||
**Request Body:** Raw YAML configuration content
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"message": "Configuration updated successfully",
|
||||
"path": "/home/user/osmedeus-base/osm-settings.yaml",
|
||||
"backup": "/home/user/osmedeus-base/osm-settings.yaml.backup"
|
||||
}
|
||||
```
|
||||
|
||||
**Error Response (Invalid YAML):**
|
||||
```json
|
||||
{
|
||||
"error": true,
|
||||
"message": "Invalid YAML configuration: yaml: unmarshal errors: ..."
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,206 @@
|
||||
# Snapshots
|
||||
|
||||
## List Snapshots
|
||||
|
||||
Get a list of available snapshot files in the snapshot directory.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8002/osm/api/snapshots \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"name": "example.com_1704067200.zip",
|
||||
"path": "/home/user/osmedeus-base/snapshot/example.com_1704067200.zip",
|
||||
"size": 15728640,
|
||||
"created_at": "2025-01-01T12:00:00Z"
|
||||
},
|
||||
{
|
||||
"name": "test.com_1704153600.zip",
|
||||
"path": "/home/user/osmedeus-base/snapshot/test.com_1704153600.zip",
|
||||
"size": 8388608,
|
||||
"created_at": "2025-01-02T12:00:00Z"
|
||||
}
|
||||
],
|
||||
"count": 2,
|
||||
"path": "/home/user/osmedeus-base/snapshot"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Export Workspace Snapshot
|
||||
|
||||
Export a workspace to a compressed zip archive and download it.
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/snapshots/export \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"workspace": "example.com"}' \
|
||||
--output example.com_snapshot.zip
|
||||
```
|
||||
|
||||
**Request Body:**
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `workspace` | string | Yes | Name of the workspace to export |
|
||||
|
||||
**Response:**
|
||||
- On success: Returns the zip file as a binary download
|
||||
- Response headers include:
|
||||
- `Content-Disposition: attachment; filename=<workspace>_<timestamp>.zip`
|
||||
- `Content-Type: application/zip`
|
||||
- `X-Snapshot-Size: <size_in_bytes>`
|
||||
|
||||
**Error Response (404):**
|
||||
```json
|
||||
{
|
||||
"error": true,
|
||||
"message": "Workspace not found: example.com"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Import Workspace Snapshot
|
||||
|
||||
Import a workspace from an uploaded zip file or URL.
|
||||
|
||||
**Import from file upload:**
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/snapshots/import \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-F "file=@example.com_1704067200.zip"
|
||||
```
|
||||
|
||||
**Import from URL:**
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/snapshots/import \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-F "url=https://example.com/snapshots/workspace.zip"
|
||||
```
|
||||
|
||||
**Import with force overwrite:**
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/snapshots/import \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-F "file=@example.com_snapshot.zip" \
|
||||
-F "force=true"
|
||||
```
|
||||
|
||||
**Import files only (skip database):**
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/snapshots/import \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-F "file=@example.com_snapshot.zip" \
|
||||
-F "skip_db=true"
|
||||
```
|
||||
|
||||
**Form Parameters:**
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------|----------|-------------|
|
||||
| `file` | file | No* | Snapshot zip file to import |
|
||||
| `url` | string | No* | URL of snapshot to download and import |
|
||||
| `force` | bool | No | Overwrite existing workspace if present (default: false) |
|
||||
| `skip_db` | bool | No | Skip database import, extract files only (default: false) |
|
||||
|
||||
*Either `file` or `url` is required.
|
||||
|
||||
**Response (200):**
|
||||
```json
|
||||
{
|
||||
"message": "Workspace imported successfully",
|
||||
"workspace": "example.com",
|
||||
"local_path": "/home/user/workspaces-osmedeus/example.com",
|
||||
"data_source": "imported",
|
||||
"files_count": 1523,
|
||||
"warning": "Imported workspace database state may be unstable. Only import from trusted sources."
|
||||
}
|
||||
```
|
||||
|
||||
**Error Response (400):**
|
||||
```json
|
||||
{
|
||||
"error": true,
|
||||
"message": "Either file or url is required"
|
||||
}
|
||||
```
|
||||
|
||||
**Error Response (500 - workspace exists):**
|
||||
```json
|
||||
{
|
||||
"error": true,
|
||||
"message": "Failed to import snapshot: workspace already exists: /home/user/workspaces-osmedeus/example.com (use --force to overwrite)"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Delete Snapshot
|
||||
|
||||
Delete a snapshot file by name.
|
||||
|
||||
```bash
|
||||
curl -X DELETE http://localhost:8002/osm/api/snapshots/example.com_1704067200.zip \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"message": "Snapshot deleted successfully",
|
||||
"name": "example.com_1704067200.zip"
|
||||
}
|
||||
```
|
||||
|
||||
**Error Response (404):**
|
||||
```json
|
||||
{
|
||||
"error": true,
|
||||
"message": "Snapshot not found: example.com_1704067200.zip"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Legacy Endpoint
|
||||
|
||||
The legacy snapshot download endpoint is still available for backward compatibility:
|
||||
|
||||
```bash
|
||||
curl http://localhost:8002/osm/api/snapshot-download/example.com \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
--output snapshot.zip
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Data Source Values
|
||||
|
||||
When a workspace is imported, its `data_source` field is set to indicate how it was created:
|
||||
|
||||
| Value | Description |
|
||||
|-------|-------------|
|
||||
| `local` | Created locally via scan (default) |
|
||||
| `cloud` | Synced from cloud storage |
|
||||
| `imported` | Imported from snapshot file |
|
||||
|
||||
---
|
||||
|
||||
## Security Considerations
|
||||
|
||||
**Warning:** Only import snapshots from trusted sources!
|
||||
|
||||
Imported workspace data may contain:
|
||||
- Database records that could conflict with existing data
|
||||
- File paths that reference external resources
|
||||
- Configuration that may not be compatible
|
||||
|
||||
The imported workspace database state may be unstable. Use the `skip_db=true` parameter if you only need the files without database import.
|
||||
@@ -0,0 +1,67 @@
|
||||
# System Statistics
|
||||
|
||||
## Get System Stats
|
||||
|
||||
Get aggregated system statistics including workflows, runs, workspaces, assets, vulnerabilities, and schedules.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8002/osm/api/stats \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"workflows": {
|
||||
"total": 25,
|
||||
"flows": 10,
|
||||
"modules": 15
|
||||
},
|
||||
"runs": {
|
||||
"total": 150,
|
||||
"completed": 120,
|
||||
"running": 5,
|
||||
"failed": 10,
|
||||
"pending": 15
|
||||
},
|
||||
"workspaces": {
|
||||
"total": 50
|
||||
},
|
||||
"assets": {
|
||||
"total": 5000
|
||||
},
|
||||
"vulnerabilities": {
|
||||
"total": 150,
|
||||
"critical": 10,
|
||||
"high": 25,
|
||||
"medium": 50,
|
||||
"low": 65
|
||||
},
|
||||
"schedules": {
|
||||
"total": 8,
|
||||
"enabled": 5
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Statistics Fields:**
|
||||
|
||||
| Category | Field | Description |
|
||||
|----------|-------|-------------|
|
||||
| workflows.total | int | Total number of workflows (flows + modules) |
|
||||
| workflows.flows | int | Number of flow-type workflows |
|
||||
| workflows.modules | int | Number of module-type workflows |
|
||||
| runs.total | int | Total number of runs |
|
||||
| runs.completed | int | Successfully completed runs |
|
||||
| runs.running | int | Currently running workflows |
|
||||
| runs.failed | int | Failed runs |
|
||||
| runs.pending | int | Pending runs waiting to start |
|
||||
| workspaces.total | int | Total number of scan workspaces |
|
||||
| assets.total | int | Total discovered assets across all workspaces |
|
||||
| vulnerabilities.total | int | Total vulnerabilities (sum of all severities) |
|
||||
| vulnerabilities.critical | int | Critical severity vulnerabilities |
|
||||
| vulnerabilities.high | int | High severity vulnerabilities |
|
||||
| vulnerabilities.medium | int | Medium severity vulnerabilities |
|
||||
| vulnerabilities.low | int | Low severity vulnerabilities |
|
||||
| schedules.total | int | Total configured schedules |
|
||||
| schedules.enabled | int | Currently enabled schedules |
|
||||
@@ -0,0 +1,49 @@
|
||||
# File Uploads
|
||||
|
||||
## Upload Input File
|
||||
|
||||
Upload a file containing a list of inputs (targets, URLs, etc.) for later use in runs.
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/upload-file \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-F "file=@targets.txt"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"message": "File uploaded",
|
||||
"filename": "1704326400000000000_targets.txt",
|
||||
"path": "/home/user/osmedeus-base/data/uploads/1704326400000000000_targets.txt",
|
||||
"size": 1024,
|
||||
"lines": 50
|
||||
}
|
||||
```
|
||||
|
||||
The returned `path` can be used as a target in subsequent run requests.
|
||||
|
||||
---
|
||||
|
||||
## Upload Workflow
|
||||
|
||||
Upload a raw YAML workflow file and save it to the workflows directory.
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/workflow-upload \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-F "file=@my-custom-workflow.yaml"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"message": "Workflow uploaded",
|
||||
"name": "my-custom-workflow",
|
||||
"kind": "module",
|
||||
"description": "A custom security workflow",
|
||||
"path": "/home/user/osmedeus-base/workflows/modules/my-custom-workflow.yaml"
|
||||
}
|
||||
```
|
||||
|
||||
The workflow file must be a valid YAML with `.yaml` or `.yml` extension. It will be saved to either the `flows/` or `modules/` subdirectory based on the workflow kind.
|
||||
@@ -0,0 +1,317 @@
|
||||
# Vulnerabilities
|
||||
|
||||
## List Vulnerabilities
|
||||
|
||||
Get a paginated list of vulnerabilities with optional filtering by workspace, severity, confidence, or asset value.
|
||||
|
||||
**List all vulnerabilities:**
|
||||
```bash
|
||||
curl http://localhost:8002/osm/api/vulnerabilities \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**List vulnerabilities with pagination:**
|
||||
```bash
|
||||
curl "http://localhost:8002/osm/api/vulnerabilities?offset=0&limit=100" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Filter by workspace:**
|
||||
```bash
|
||||
curl "http://localhost:8002/osm/api/vulnerabilities?workspace=example.com" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Filter by severity:**
|
||||
```bash
|
||||
curl "http://localhost:8002/osm/api/vulnerabilities?severity=critical" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Filter by confidence:**
|
||||
```bash
|
||||
curl "http://localhost:8002/osm/api/vulnerabilities?confidence=Certain" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Filter by asset value (partial match):**
|
||||
```bash
|
||||
curl "http://localhost:8002/osm/api/vulnerabilities?asset_value=api.example" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Combine filters:**
|
||||
```bash
|
||||
curl "http://localhost:8002/osm/api/vulnerabilities?workspace=example.com&severity=high&offset=0&limit=50" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Query Parameters:**
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `workspace` | string | - | Filter by workspace name |
|
||||
| `severity` | string | - | Filter by severity (critical, high, medium, low, info) |
|
||||
| `confidence` | string | - | Filter by confidence (Certain, Firm, Tentative, Manual Review Required) |
|
||||
| `asset_value` | string | - | Filter by asset value (partial match) |
|
||||
| `offset` | int | 0 | Number of records to skip |
|
||||
| `limit` | int | 20 | Maximum records to return (max 10000) |
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"id": 1,
|
||||
"workspace": "example.com",
|
||||
"vuln_info": "CVE-2024-1234",
|
||||
"vuln_title": "SQL Injection in Login Form",
|
||||
"vuln_desc": "The login form is vulnerable to SQL injection via the username parameter.",
|
||||
"vuln_poc": "username=' OR '1'='1' --&password=test",
|
||||
"severity": "critical",
|
||||
"confidence": "Certain",
|
||||
"asset_type": "web",
|
||||
"asset_value": "https://example.com/login",
|
||||
"tags": ["sqli", "owasp-top10", "authentication"],
|
||||
"detail_http_request": "POST /login HTTP/1.1\nHost: example.com\n...",
|
||||
"detail_http_response": "HTTP/1.1 200 OK\n...",
|
||||
"raw_vuln_json": "{\"template\":\"sqli-login.yaml\",...}",
|
||||
"created_at": "2025-01-15T10:30:00Z",
|
||||
"updated_at": "2025-01-15T10:30:00Z"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"workspace": "example.com",
|
||||
"vuln_info": "CVE-2024-5678",
|
||||
"vuln_title": "Cross-Site Scripting (XSS) in Search",
|
||||
"vuln_desc": "Reflected XSS vulnerability in the search functionality.",
|
||||
"vuln_poc": "<script>alert('XSS')</script>",
|
||||
"severity": "high",
|
||||
"confidence": "Firm",
|
||||
"asset_type": "web",
|
||||
"asset_value": "https://example.com/search",
|
||||
"tags": ["xss", "owasp-top10"],
|
||||
"detail_http_request": "GET /search?q=<script>alert(1)</script> HTTP/1.1\n...",
|
||||
"detail_http_response": "HTTP/1.1 200 OK\n...",
|
||||
"raw_vuln_json": "{\"template\":\"xss-reflected.yaml\",...}",
|
||||
"created_at": "2025-01-15T10:31:00Z",
|
||||
"updated_at": "2025-01-15T10:31:00Z"
|
||||
}
|
||||
],
|
||||
"pagination": {
|
||||
"total": 15,
|
||||
"offset": 0,
|
||||
"limit": 20
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Get Vulnerability Summary
|
||||
|
||||
Get a summary of vulnerabilities grouped by severity, optionally filtered by workspace.
|
||||
|
||||
**Get summary for all workspaces:**
|
||||
```bash
|
||||
curl http://localhost:8002/osm/api/vulnerabilities/summary \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Get summary for a specific workspace:**
|
||||
```bash
|
||||
curl "http://localhost:8002/osm/api/vulnerabilities/summary?workspace=example.com" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Query Parameters:**
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `workspace` | string | - | Filter by workspace name |
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"by_severity": {
|
||||
"critical": 2,
|
||||
"high": 5,
|
||||
"medium": 8,
|
||||
"low": 12,
|
||||
"info": 3
|
||||
},
|
||||
"total": 30,
|
||||
"workspace": "example.com"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Get Vulnerability by ID
|
||||
|
||||
Retrieve a single vulnerability by its ID.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8002/osm/api/vulnerabilities/1 \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"id": 1,
|
||||
"workspace": "example.com",
|
||||
"vuln_info": "CVE-2024-1234",
|
||||
"vuln_title": "SQL Injection in Login Form",
|
||||
"vuln_desc": "The login form is vulnerable to SQL injection via the username parameter.",
|
||||
"vuln_poc": "username=' OR '1'='1' --&password=test",
|
||||
"severity": "critical",
|
||||
"confidence": "Certain",
|
||||
"asset_type": "web",
|
||||
"asset_value": "https://example.com/login",
|
||||
"tags": ["sqli", "owasp-top10", "authentication"],
|
||||
"detail_http_request": "POST /login HTTP/1.1\nHost: example.com\n...",
|
||||
"detail_http_response": "HTTP/1.1 200 OK\n...",
|
||||
"raw_vuln_json": "{\"template\":\"sqli-login.yaml\",...}",
|
||||
"created_at": "2025-01-15T10:30:00Z",
|
||||
"updated_at": "2025-01-15T10:30:00Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Error Response (404):**
|
||||
```json
|
||||
{
|
||||
"error": true,
|
||||
"message": "Vulnerability not found"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Create Vulnerability
|
||||
|
||||
Create a new vulnerability record.
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/vulnerabilities \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"workspace": "example.com",
|
||||
"vuln_info": "CVE-2024-9999",
|
||||
"vuln_title": "Remote Code Execution",
|
||||
"vuln_desc": "Critical RCE vulnerability in admin panel.",
|
||||
"vuln_poc": "curl -X POST /admin/exec -d \"cmd=id\"",
|
||||
"severity": "critical",
|
||||
"asset_type": "web",
|
||||
"asset_value": "https://example.com/admin",
|
||||
"tags": ["rce", "critical", "admin"],
|
||||
"detail_http_request": "POST /admin/exec HTTP/1.1\n...",
|
||||
"detail_http_response": "HTTP/1.1 200 OK\nuid=0(root)...",
|
||||
"raw_vuln_json": "{\"template\":\"rce-admin.yaml\"}"
|
||||
}'
|
||||
```
|
||||
|
||||
**Request Body:**
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `workspace` | string | Yes | Workspace/target name |
|
||||
| `vuln_info` | string | No | CVE or vulnerability identifier |
|
||||
| `vuln_title` | string | No | Short title for the vulnerability |
|
||||
| `vuln_desc` | string | No | Detailed description |
|
||||
| `vuln_poc` | string | No | Proof of concept |
|
||||
| `severity` | string | No | Severity level (critical, high, medium, low, info) |
|
||||
| `confidence` | string | No | Confidence level (Certain, Firm, Tentative, Manual Review Required) |
|
||||
| `asset_type` | string | No | Type of asset (web, api, network, etc.) |
|
||||
| `asset_value` | string | No | Affected asset URL or identifier |
|
||||
| `tags` | array | No | Tags for categorization |
|
||||
| `detail_http_request` | string | No | Raw HTTP request |
|
||||
| `detail_http_response` | string | No | Raw HTTP response |
|
||||
| `raw_vuln_json` | string | No | Raw JSON from scanner (nuclei, etc.) |
|
||||
|
||||
**Response (201 Created):**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"id": 15,
|
||||
"workspace": "example.com",
|
||||
"vuln_info": "CVE-2024-9999",
|
||||
"vuln_title": "Remote Code Execution",
|
||||
"vuln_desc": "Critical RCE vulnerability in admin panel.",
|
||||
"vuln_poc": "curl -X POST /admin/exec -d \"cmd=id\"",
|
||||
"severity": "critical",
|
||||
"confidence": "Certain",
|
||||
"asset_type": "web",
|
||||
"asset_value": "https://example.com/admin",
|
||||
"tags": ["rce", "critical", "admin"],
|
||||
"detail_http_request": "POST /admin/exec HTTP/1.1\n...",
|
||||
"detail_http_response": "HTTP/1.1 200 OK\nuid=0(root)...",
|
||||
"raw_vuln_json": "{\"template\":\"rce-admin.yaml\"}",
|
||||
"created_at": "2025-01-15T14:25:00Z",
|
||||
"updated_at": "2025-01-15T14:25:00Z"
|
||||
},
|
||||
"message": "Vulnerability created successfully"
|
||||
}
|
||||
```
|
||||
|
||||
**Error Response (400):**
|
||||
```json
|
||||
{
|
||||
"error": true,
|
||||
"message": "Workspace is required"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Delete Vulnerability
|
||||
|
||||
Delete a vulnerability by ID.
|
||||
|
||||
```bash
|
||||
curl -X DELETE http://localhost:8002/osm/api/vulnerabilities/15 \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"message": "Vulnerability deleted successfully"
|
||||
}
|
||||
```
|
||||
|
||||
**Error Response (404):**
|
||||
```json
|
||||
{
|
||||
"error": true,
|
||||
"message": "Vulnerability not found"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Vulnerability Fields Reference
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `id` | int | Unique vulnerability identifier |
|
||||
| `workspace` | string | Workspace/scan target name |
|
||||
| `vuln_info` | string | CVE or vulnerability identifier |
|
||||
| `vuln_title` | string | Short descriptive title |
|
||||
| `vuln_desc` | string | Detailed vulnerability description |
|
||||
| `vuln_poc` | string | Proof of concept exploit |
|
||||
| `severity` | string | Severity level (critical, high, medium, low, info) |
|
||||
| `confidence` | string | Confidence level (Certain, Firm, Tentative, Manual Review Required) |
|
||||
| `asset_type` | string | Type of affected asset |
|
||||
| `asset_value` | string | Affected asset URL or identifier |
|
||||
| `tags` | array | Categorization tags |
|
||||
| `detail_http_request` | string | Raw HTTP request that triggered the vulnerability |
|
||||
| `detail_http_response` | string | Raw HTTP response from the vulnerable endpoint |
|
||||
| `raw_vuln_json` | string | Raw JSON output from vulnerability scanner |
|
||||
| `created_at` | timestamp | Record creation timestamp |
|
||||
| `updated_at` | timestamp | Last update timestamp |
|
||||
@@ -0,0 +1,251 @@
|
||||
# Workflows
|
||||
|
||||
## List All Workflows
|
||||
|
||||
Get a paginated list of all available workflows with filtering support.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8002/osm/api/workflows \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Query Parameters:**
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `source` | string | `db` | Data source: `db` (database) or `filesystem` (direct file scan) |
|
||||
| `tags` | string | - | Comma-separated list of tags to filter by |
|
||||
| `kind` | string | - | Filter by workflow kind: `flow` or `module` |
|
||||
| `search` | string | - | Search in workflow name and description |
|
||||
| `offset` | int | 0 | Pagination offset |
|
||||
| `limit` | int | 50 | Maximum records to return |
|
||||
|
||||
**Examples:**
|
||||
|
||||
```bash
|
||||
# Filter by tags
|
||||
curl "http://localhost:8002/osm/api/workflows?tags=recon,subdomain" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
|
||||
# Filter by kind
|
||||
curl "http://localhost:8002/osm/api/workflows?kind=module" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
|
||||
# Search workflows
|
||||
curl "http://localhost:8002/osm/api/workflows?search=enum" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
|
||||
# Load directly from filesystem (bypasses database)
|
||||
curl "http://localhost:8002/osm/api/workflows?source=filesystem" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
|
||||
# Pagination
|
||||
curl "http://localhost:8002/osm/api/workflows?offset=10&limit=20" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"name": "subdomain-enum",
|
||||
"kind": "flow",
|
||||
"description": "Comprehensive subdomain enumeration and probing workflow",
|
||||
"tags": ["recon", "subdomain", "httpx"],
|
||||
"file_path": "/home/user/osmedeus-base/workflows/flows/subdomain-enum.yaml",
|
||||
"params": [
|
||||
{"name": "target", "required": true, "default": "", "generator": ""},
|
||||
{"name": "threads", "required": false, "default": "50", "generator": ""},
|
||||
{"name": "timeout", "required": false, "default": "30", "generator": ""},
|
||||
{"name": "wordlist", "required": false, "default": "", "generator": "default_wordlist"}
|
||||
],
|
||||
"required_params": ["target"],
|
||||
"step_count": 8,
|
||||
"module_count": 3,
|
||||
"checksum": "sha256:abc123...",
|
||||
"indexed_at": "2025-01-15T08:00:00Z"
|
||||
},
|
||||
{
|
||||
"name": "port-scan",
|
||||
"kind": "module",
|
||||
"description": "Port scanning module using nmap and masscan",
|
||||
"tags": ["recon", "portscan", "nmap"],
|
||||
"file_path": "/home/user/osmedeus-base/workflows/modules/port-scan.yaml",
|
||||
"params": [
|
||||
{"name": "target", "required": true, "default": "", "generator": ""},
|
||||
{"name": "ports", "required": false, "default": "top-1000", "generator": ""},
|
||||
{"name": "rate", "required": false, "default": "1000", "generator": ""}
|
||||
],
|
||||
"required_params": ["target"],
|
||||
"step_count": 4,
|
||||
"module_count": 0,
|
||||
"checksum": "sha256:def456...",
|
||||
"indexed_at": "2025-01-15T08:00:00Z"
|
||||
}
|
||||
],
|
||||
"pagination": {
|
||||
"total": 25,
|
||||
"offset": 0,
|
||||
"limit": 50
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Get Workflow Tags
|
||||
|
||||
Get all unique tags from indexed workflows.
|
||||
|
||||
```bash
|
||||
curl http://localhost:8002/osm/api/workflows/tags \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"tags": ["recon", "subdomain", "portscan", "vulnerability", "nuclei"],
|
||||
"count": 5
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Refresh Workflow Index
|
||||
|
||||
Re-index all workflows from filesystem to database. Use this after adding or modifying workflow files.
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8002/osm/api/workflows/refresh \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Query Parameters:**
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `force` | bool | false | Force re-index all workflows regardless of checksum |
|
||||
|
||||
**Force re-index all:**
|
||||
```bash
|
||||
curl -X POST "http://localhost:8002/osm/api/workflows/refresh?force=true" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"message": "Workflows indexed successfully",
|
||||
"added": 5,
|
||||
"updated": 2,
|
||||
"removed": 1,
|
||||
"errors": []
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Get Workflow Details
|
||||
|
||||
Get workflow content. Returns raw YAML by default, or JSON with full parsed details.
|
||||
|
||||
```bash
|
||||
# Get raw YAML content (default)
|
||||
curl http://localhost:8002/osm/api/workflows/subdomain-enum \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
```bash
|
||||
# Get workflow details as JSON
|
||||
curl "http://localhost:8002/osm/api/workflows/subdomain-enum?json=true" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Query Parameters:**
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `json` | bool | false | Return JSON with parsed details instead of raw YAML |
|
||||
|
||||
**Response (YAML - default):**
|
||||
```yaml
|
||||
name: subdomain-enum
|
||||
kind: flow
|
||||
description: Subdomain enumeration
|
||||
params:
|
||||
- name: target
|
||||
required: true
|
||||
steps:
|
||||
- name: run-subfinder
|
||||
command: subfinder -d {{target}}
|
||||
...
|
||||
```
|
||||
|
||||
**Response (JSON with `?json=true`):**
|
||||
```json
|
||||
{
|
||||
"name": "subdomain-enum",
|
||||
"kind": "flow",
|
||||
"description": "Comprehensive subdomain enumeration and probing workflow",
|
||||
"file_path": "/home/user/osmedeus-base/workflows/flows/subdomain-enum.yaml",
|
||||
"params": [
|
||||
{"name": "target", "required": true, "default": "", "generator": ""},
|
||||
{"name": "threads", "required": false, "default": "50", "generator": ""},
|
||||
{"name": "output_dir", "required": false, "default": "{{Workspace}}", "generator": "workspace_path"},
|
||||
{"name": "wordlist", "required": false, "default": "", "generator": "default_wordlist"}
|
||||
],
|
||||
"steps": [
|
||||
{
|
||||
"index": 0,
|
||||
"name": "run-subfinder",
|
||||
"type": "bash",
|
||||
"command": "subfinder -d {{target}} -t {{threads}} -o {{output_dir}}/subdomains-subfinder.txt",
|
||||
"timeout": "30m",
|
||||
"pre_condition": "",
|
||||
"exports": {"subfinder_output": "{{output_dir}}/subdomains-subfinder.txt"}
|
||||
},
|
||||
{
|
||||
"index": 1,
|
||||
"name": "run-amass",
|
||||
"type": "bash",
|
||||
"command": "amass enum -passive -d {{target}} -o {{output_dir}}/subdomains-amass.txt",
|
||||
"timeout": "60m",
|
||||
"pre_condition": "commandExists('amass')",
|
||||
"exports": {"amass_output": "{{output_dir}}/subdomains-amass.txt"}
|
||||
},
|
||||
{
|
||||
"index": 2,
|
||||
"name": "merge-subdomains",
|
||||
"type": "function",
|
||||
"command": "mergeFiles('{{output_dir}}/subdomains-*.txt', '{{output_dir}}/all-subdomains.txt')",
|
||||
"timeout": "",
|
||||
"pre_condition": "",
|
||||
"exports": {"all_subdomains": "{{output_dir}}/all-subdomains.txt"}
|
||||
},
|
||||
{
|
||||
"index": 3,
|
||||
"name": "run-httpx",
|
||||
"type": "bash",
|
||||
"command": "httpx -l {{all_subdomains}} -t {{threads}} -o {{output_dir}}/alive.txt -json -o {{output_dir}}/httpx.json",
|
||||
"timeout": "60m",
|
||||
"pre_condition": "fileLength('{{all_subdomains}}') > 0",
|
||||
"exports": {"alive_hosts": "{{output_dir}}/alive.txt", "httpx_json": "{{output_dir}}/httpx.json"}
|
||||
}
|
||||
],
|
||||
"modules": [
|
||||
{"index": 0, "name": "port-scan", "path": "modules/port-scan.yaml", "depends_on": [], "condition": ""},
|
||||
{"index": 1, "name": "nuclei-scan", "path": "modules/nuclei-scan.yaml", "depends_on": ["port-scan"], "condition": "fileLength('{{alive_hosts}}') > 0"},
|
||||
{"index": 2, "name": "screenshot", "path": "modules/screenshot.yaml", "depends_on": ["port-scan"], "condition": ""}
|
||||
],
|
||||
"triggers": [
|
||||
{"name": "daily-scan", "on": "cron", "schedule": "0 2 * * *", "enabled": true},
|
||||
{"name": "on-new-asset", "on": "event", "topic": "asset.discovered", "enabled": false}
|
||||
],
|
||||
"dependencies": {
|
||||
"commands": ["subfinder", "amass", "httpx", "nuclei", "nmap"],
|
||||
"files": ["{{wordlist}}"]
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,159 @@
|
||||
# Workspaces
|
||||
|
||||
## List Workspaces
|
||||
|
||||
Get a list of all run workspaces.
|
||||
|
||||
**List workspaces from database (default):**
|
||||
```bash
|
||||
curl http://localhost:8002/osm/api/workspaces \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**List workspaces with pagination:**
|
||||
```bash
|
||||
curl "http://localhost:8002/osm/api/workspaces?offset=0&limit=50" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**List workspaces from filesystem/assets:**
|
||||
```bash
|
||||
curl "http://localhost:8002/osm/api/workspaces?filesystem=true" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Combine pagination with filesystem mode:**
|
||||
```bash
|
||||
curl "http://localhost:8002/osm/api/workspaces?filesystem=true&offset=20&limit=10" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response (database mode):**
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "example.com",
|
||||
"local_path": "/home/user/osmedeus-base/workspaces/example.com",
|
||||
"total_assets": 150,
|
||||
"total_subdomains": 120,
|
||||
"total_urls": 500,
|
||||
"total_vulns": 12,
|
||||
"vuln_critical": 2,
|
||||
"vuln_high": 3,
|
||||
"vuln_medium": 4,
|
||||
"vuln_low": 3,
|
||||
"vuln_potential": 0,
|
||||
"risk_score": 7.5,
|
||||
"tags": ["production", "priority"],
|
||||
"last_run": "2025-01-15T10:30:00Z",
|
||||
"run_workflow": "subdomain-enum",
|
||||
"created_at": "2025-01-10T08:00:00Z",
|
||||
"updated_at": "2025-01-15T10:30:00Z"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "test.com",
|
||||
"local_path": "/home/user/osmedeus-base/workspaces/test.com",
|
||||
"total_assets": 50,
|
||||
"total_subdomains": 35,
|
||||
"total_urls": 120,
|
||||
"total_vulns": 3,
|
||||
"vuln_critical": 0,
|
||||
"vuln_high": 1,
|
||||
"vuln_medium": 2,
|
||||
"vuln_low": 0,
|
||||
"vuln_potential": 5,
|
||||
"risk_score": 4.2,
|
||||
"tags": ["staging"],
|
||||
"last_run": "2025-01-14T15:00:00Z",
|
||||
"run_workflow": "port-scan",
|
||||
"created_at": "2025-01-12T12:00:00Z",
|
||||
"updated_at": "2025-01-14T15:00:00Z"
|
||||
}
|
||||
],
|
||||
"pagination": {
|
||||
"total": 100,
|
||||
"offset": 0,
|
||||
"limit": 20
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Workspace Fields Reference:**
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `id` | int | Unique workspace identifier |
|
||||
| `name` | string | Workspace name (usually the target domain) |
|
||||
| `local_path` | string | Full path to workspace directory |
|
||||
| `total_assets` | int | Total discovered assets |
|
||||
| `total_subdomains` | int | Total discovered subdomains |
|
||||
| `total_urls` | int | Total discovered URLs |
|
||||
| `total_vulns` | int | Total vulnerabilities found |
|
||||
| `vuln_critical` | int | Critical severity vulnerabilities |
|
||||
| `vuln_high` | int | High severity vulnerabilities |
|
||||
| `vuln_medium` | int | Medium severity vulnerabilities |
|
||||
| `vuln_low` | int | Low severity vulnerabilities |
|
||||
| `vuln_potential` | int | Potential/informational findings |
|
||||
| `risk_score` | float | Calculated risk score (0-10) |
|
||||
| `tags` | array | Custom tags for organization |
|
||||
| `last_run` | timestamp | Last workflow run timestamp |
|
||||
| `run_workflow` | string | Name of last executed workflow |
|
||||
| `state_execution_log` | string | Path to execution log file |
|
||||
| `state_completed_file` | string | Path to completed marker file |
|
||||
| `state_workflow_file` | string | Path to workflow YAML file |
|
||||
| `state_workflow_folder` | string | Path to workflow folder |
|
||||
| `created_at` | timestamp | Workspace creation timestamp |
|
||||
| `updated_at` | timestamp | Last update timestamp |
|
||||
|
||||
---
|
||||
|
||||
## Get Workspace State File
|
||||
|
||||
Retrieve the content of a workspace state file. This endpoint provides access to execution logs, completion markers, and workflow files associated with a workspace.
|
||||
|
||||
**Get execution log:**
|
||||
```bash
|
||||
curl "http://localhost:8002/osm/api/workspaces/example.com/state-file?state_file=execution_log" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Get completed file:**
|
||||
```bash
|
||||
curl "http://localhost:8002/osm/api/workspaces/example.com/state-file?state_file=completed_file" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Get workflow file:**
|
||||
```bash
|
||||
curl "http://localhost:8002/osm/api/workspaces/example.com/state-file?state_file=workflow_file" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"workspace": "example.com",
|
||||
"state_file": "execution_log",
|
||||
"file_path": "/home/user/osmedeus-base/workspaces/example.com/log/execution.log",
|
||||
"content": "2025-01-15 10:30:00 [INFO] Starting workflow...\n2025-01-15 10:30:05 [INFO] Step 1 completed...\n..."
|
||||
}
|
||||
```
|
||||
|
||||
**State File Types:**
|
||||
|
||||
| Type | Description |
|
||||
|------|-------------|
|
||||
| `execution_log` | Detailed execution log with timestamps and step output |
|
||||
| `completed_file` | Marker file indicating workflow completion status |
|
||||
| `workflow_file` | The YAML workflow definition that was executed |
|
||||
|
||||
**Error Responses:**
|
||||
|
||||
| Status | Description |
|
||||
|--------|-------------|
|
||||
| 400 | Invalid workspace name or missing state_file parameter |
|
||||
| 403 | Path traversal attempt detected |
|
||||
| 404 | Workspace or state file not found |
|
||||
Reference in New Issue
Block a user