Files
osmedeus/docs/api/runs.mdx
T
j3ssie 0269cf4e26 feat: update Next.js build assets and add cloud setup E2E tests
- Update Next.js generated chunk hashes and build IDs reflecting latest dashboard build
- Update CSS stylesheet references in workflow upload page metadata
- Add comprehensive cloud setup E2E test suite (cloud_setup_test.go) with SSH password/key auth, post-command variable expansion, and Ansible integration
- Fix API priority levels to include 'medium' priority in test coverage
- Add agent-sdk test workflows (minimal, config, codex, multi-agent, session variants)
- Update E2E test utilities with runCLIInBase helper for multi-step cloud config tests
- Fix stderr/stdout capture in dependencies_target_types_test assertions
2026-04-04 13:57:34 +08:00

723 lines
18 KiB
Plaintext

---
title: "Runs"
description: "Create and manage workflow executions"
---
# 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"
}'
```
**Request Body Parameters:**
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `flow` | string | No* | - | Flow workflow name to execute |
| `module` | string | No* | - | Module workflow name to execute |
| `target` | string | No** | - | Single target to scan |
| `targets` | array | No** | - | Multiple targets to scan |
| `target_file` | string | No** | - | Path to file containing targets |
| `params` | object | No | `{}` | Custom workflow parameters |
| `priority` | string | No | `normal` | Priority level: `low`, `normal`, `high`, `critical` |
| `timeout` | int | No | - | Timeout in minutes for the run |
| `concurrency` | int | No | 1 | Number of concurrent targets |
| `runner_type` | string | No | `host` | Execution environment: `host`, `docker`, `ssh` |
| `docker_image` | string | No | - | Docker image for docker runner |
| `ssh_host` | string | No | - | SSH host for ssh runner |
| `workspace` | string | No | auto | Custom workspace name |
| `run_mode` | string | No | `local` | Execution mode: `local`, `distributed`, `cloud` |
| `cloud_provider` | string | No | config default | Cloud provider: `aws`, `gcp`, `digitalocean`, `linode`, `azure`, `hetzner` |
| `cloud_instances` | int | No | 1 | Number of cloud instances to provision |
| `cloud_instance_type` | string | No | provider default | Instance size override (e.g., `t3.medium`, `s-2vcpu-4gb`) |
| `cloud_region` | string | No | provider default | Region override |
| `cloud_auto_destroy` | bool | No | `false` | Destroy cloud infrastructure when scan completes |
| `cloud_reuse_infra` | string | No | - | Existing infrastructure ID to reuse instead of provisioning |
| `cloud_use_spot` | bool | No | `false` | Use spot/preemptible instances for cost savings |
\* One of `flow` or `module` is required.
\** One of `target`, `targets`, or `target_file` is required.
**Response:**
```json
{
"message": "Run started",
"workflow": "subdomain-enum",
"kind": "flow",
"target": "example.com",
"target_count": 1,
"priority": "normal",
"run_mode": "local",
"job_id": "a1b2c3d4",
"run_uuid": "550e8400-e29b-41d4-a716-446655440000",
"status": "queued",
"poll_url": "/osm/api/jobs/a1b2c3d4",
"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": "Run started",
"workflow": "subdomain-enum",
"kind": "flow",
"target_count": 3,
"targets": ["example.com", "test.com", "demo.com"],
"concurrency": 3,
"priority": "normal",
"job_id": "b2c3d4e5",
"status": "queued",
"poll_url": "/osm/api/jobs/b2c3d4e5"
}
```
---
## 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`
---
## Distributed Mode
Submit scans to the distributed worker pool. Requires the server to be started with `--master` flag.
**Single target distributed scan:**
```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",
"run_mode": "distributed"
}'
```
**Multiple targets distributed across workers:**
```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"],
"run_mode": "distributed",
"priority": "high"
}'
```
Each target is submitted as a separate task to the distributed worker queue. Workers pick up tasks and execute them independently.
**Response:**
```json
{
"message": "Run started",
"workflow": "subdomain-enum",
"kind": "flow",
"target_count": 3,
"targets": ["example.com", "test.com", "demo.com"],
"priority": "high",
"run_mode": "distributed",
"job_id": "c3d4e5f6",
"status": "queued",
"poll_url": "/osm/api/jobs/c3d4e5f6"
}
```
**Error when server is not in master mode:**
```json
{
"error": true,
"message": "Distributed mode requires the server to be started with --master flag"
}
```
---
## Cloud Mode
Provision cloud infrastructure and execute scans on remote instances. Requires cloud features to be enabled in the configuration (`cloud.enabled: true` in `osm-settings.yaml`).
**Basic cloud scan (uses default provider from config):**
```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",
"run_mode": "cloud"
}'
```
**Cloud scan with multiple instances:**
```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"],
"run_mode": "cloud",
"cloud_provider": "digitalocean",
"cloud_instances": 3,
"cloud_auto_destroy": true
}'
```
Targets are distributed round-robin across the provisioned instances. When `cloud_auto_destroy` is `true`, infrastructure is torn down after all scans complete.
**Cloud scan with instance customization:**
```bash
curl -X POST http://localhost:8002/osm/api/runs \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"flow": "general",
"target": "example.com",
"run_mode": "cloud",
"cloud_provider": "aws",
"cloud_instances": 2,
"cloud_instance_type": "t3.large",
"cloud_region": "ap-southeast-1",
"cloud_use_spot": true,
"cloud_auto_destroy": true,
"priority": "high"
}'
```
**Cloud scan reusing existing infrastructure:**
```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",
"run_mode": "cloud",
"cloud_reuse_infra": "a1b2c3d4"
}'
```
Skip provisioning and run on existing infrastructure by passing the `cloud_reuse_infra` ID (from a previous `POST /cloud/instances` or cloud run response).
**Response:**
```json
{
"message": "Run started",
"workflow": "subdomain-enum",
"kind": "flow",
"target": "example.com",
"target_count": 1,
"priority": "high",
"run_mode": "cloud",
"job_id": "d4e5f6a7",
"run_uuid": "770e8400-e29b-41d4-a716-446655440000",
"status": "queued",
"poll_url": "/osm/api/jobs/d4e5f6a7",
"infra_id": "d4e5f6a7",
"infra_status_url": "/osm/api/cloud/instances/d4e5f6a7/status",
"cloud_provider": "aws",
"cloud_instances": 2
}
```
**Error when cloud is not enabled:**
```json
{
"error": true,
"message": "Cloud mode requires cloud features to be enabled in configuration"
}
```
**Error when provider credentials are invalid:**
```json
{
"error": true,
"message": "Cloud provider validation failed: invalid API token"
}
```
---
## 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": 1,
"run_uuid": "550e8400-e29b-41d4-a716-446655440000",
"workflow_name": "subdomain-enum",
"workflow_kind": "flow",
"target": "example.com",
"params": {"threads": "50"},
"status": "running",
"workspace": "example.com",
"started_at": "2025-01-15T10:00:00Z",
"completed_at": null,
"total_steps": 10,
"completed_steps": 3,
"current_pid": 12345,
"trigger_type": "manual",
"run_group_id": "a1b2c3d4",
"created_at": "2025-01-15T10:00:00Z",
"updated_at": "2025-01-15T10:03:00Z"
}
],
"pagination": {
"total": 50,
"offset": 0,
"limit": 20
}
}
```
**Note:** The `current_pid` field shows the process ID of the currently running command. This can be used to identify and cancel the running process. When the run completes, this field is cleared (set to 0 or omitted).
---
## 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
{
"data": {
"id": 1,
"run_uuid": "550e8400-e29b-41d4-a716-446655440000",
"workflow_name": "subdomain-enum",
"workflow_kind": "flow",
"target": "example.com",
"params": {"threads": "50"},
"status": "completed",
"workspace": "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": "",
"run_group_id": "a1b2c3d4",
"total_steps": 10,
"completed_steps": 10,
"created_at": "2025-01-15T10:00:00Z",
"updated_at": "2025-01-15T10:30:00Z"
}
}
```
**Note:** You can use either the numeric `id` or the `run_uuid` to fetch run details.
---
## Cancel Run
Cancel a running workflow execution. This will terminate all running processes associated with the run.
```bash
# Cancel by run_uuid
curl -X DELETE http://localhost:8002/osm/api/runs/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer $TOKEN"
# Or cancel by numeric id
curl -X DELETE http://localhost:8002/osm/api/runs/1 \
-H "Authorization: Bearer $TOKEN"
```
**Response (processes killed successfully):**
```json
{
"message": "Run cancelled successfully",
"id": 1,
"run_uuid": "550e8400-e29b-41d4-a716-446655440000",
"killed_pids": [12345, 12346],
"processes_terminated": 2,
"kill_method": "registry"
}
```
**Response (using database PID fallback):**
```json
{
"message": "Run cancelled successfully",
"id": 1,
"run_uuid": "550e8400-e29b-41d4-a716-446655440000",
"killed_pids": [12345],
"processes_terminated": 1,
"kill_method": "database_pid"
}
```
**Response (no active processes found):**
```json
{
"message": "Run cancelled successfully",
"id": 1,
"run_uuid": "550e8400-e29b-41d4-a716-446655440000",
"note": "No active processes found to terminate; database status updated"
}
```
**Kill Methods:**
- `registry` - Processes were tracked in memory and killed via the run registry (API-initiated runs)
- `database_pid` - Process was killed using the PID stored in the database (fallback method)
---
## Get Run Steps
Get all step results for a specific run.
```bash
# Using run_uuid
curl http://localhost:8002/osm/api/runs/550e8400-e29b-41d4-a716-446655440000/steps \
-H "Authorization: Bearer $TOKEN"
# Or using numeric id
curl http://localhost:8002/osm/api/runs/1/steps \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"data": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"run_id": 1,
"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": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"run_id": 1,
"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
# Using run_uuid
curl http://localhost:8002/osm/api/runs/550e8400-e29b-41d4-a716-446655440000/artifacts \
-H "Authorization: Bearer $TOKEN"
# Or using numeric id
curl http://localhost:8002/osm/api/runs/1/artifacts \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"data": [
{
"id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"run_id": 1,
"workspace": "example.com",
"name": "subdomains.txt",
"artifact_path": "/workspaces/example.com/subdomains.txt",
"artifact_type": "output",
"content_type": "txt",
"size_bytes": 4523,
"line_count": 150,
"description": "Discovered subdomains",
"created_at": "2025-01-15T10:01:45Z"
},
{
"id": "d4e5f6a7-b8c9-0123-def0-234567890123",
"run_id": 1,
"workspace": "example.com",
"name": "alive.txt",
"artifact_path": "/workspaces/example.com/alive.txt",
"artifact_type": "output",
"content_type": "txt",
"size_bytes": 2890,
"line_count": 89,
"description": "Alive HTTP endpoints",
"created_at": "2025-01-15T10:03:45Z"
},
{
"id": "e5f6a7b8-c9d0-1234-ef01-345678901234",
"run_id": 1,
"workspace": "example.com",
"name": "nuclei-results.json",
"artifact_path": "/workspaces/example.com/nuclei-results.json",
"artifact_type": "output",
"content_type": "json",
"size_bytes": 15234,
"line_count": 45,
"description": "Nuclei vulnerability scan results",
"created_at": "2025-01-15T10:15:00Z"
}
]
}
```
**Artifact Types:**
- `report` - Generated reports from the workflow's reports section
- `state_file` - State files like run-state.json, run-execution.log
- `output` - General output files from steps
- `screenshot` - Screenshots captured during the scan
**Content Types:**
- `json`, `jsonl`, `yaml`, `html`, `md`, `log`, `pdf`, `png`, `txt`, `zip`, `folder`, `unknown`
---
## Duplicate Run
Create a copy of an existing run with the same configuration.
```bash
curl -X POST http://localhost:8002/osm/api/runs/550e8400-e29b-41d4-a716-446655440000/duplicate \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"message": "Run duplicated",
"original_run_id": "550e8400-e29b-41d4-a716-446655440000",
"new_run_uuid": "660e8400-e29b-41d4-a716-446655440001",
"status": "pending"
}
```
---
## Start Run
Start a pending run that was created but not yet started.
```bash
curl -X POST http://localhost:8002/osm/api/runs/550e8400-e29b-41d4-a716-446655440000/start \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"message": "Run started",
"run_uuid": "550e8400-e29b-41d4-a716-446655440000",
"status": "running"
}
```
---
## Get Job Status
Get the status of a job (a group of runs from the same request). This is useful for tracking multi-target scans.
```bash
curl http://localhost:8002/osm/api/jobs/a1b2c3d4 \
-H "Authorization: Bearer $TOKEN"
```
**Response:**
```json
{
"job_id": "a1b2c3d4",
"total_runs": 3,
"completed": 2,
"running": 1,
"failed": 0,
"pending": 0,
"runs": [
{
"run_uuid": "550e8400-e29b-41d4-a716-446655440000",
"target": "example.com",
"status": "completed"
},
{
"run_uuid": "550e8400-e29b-41d4-a716-446655440001",
"target": "test.com",
"status": "completed"
},
{
"run_uuid": "550e8400-e29b-41d4-a716-446655440002",
"target": "demo.com",
"status": "running"
}
]
}
```
---
## Priority Levels
Runs can be assigned a priority level to control execution order when multiple runs are queued.
| Priority | Description |
|----------|-------------|
| `low` | Lowest priority, processed last |
| `normal` | Default priority (used when not specified) |
| `high` | Higher priority, processed before normal/low |
| `critical` | Highest priority, processed first |
**Note:** Priority defaults to `normal` when not specified in the request