api

6 阅读9分钟

Onboarding Service Scanner Operations API - Consumer Guide Overview

来源:upwindsecurity.atlassian.net/wiki/spaces…
导出时间:2026-03-03


Overview

This guide provides practical examples for consuming the scanner operations endpoints. For complete API specifications, refer to the Swagger documentation available at:

http://onboarding-service.dev.internal:8082/swagger/index.html

Base URL: http://onboarding-service.dev.internal:8082/api/v1


Authentication

All endpoints require JWT bearer token authentication. Include your token in the Authorization header:

Authorization: Bearer <your-jwt-token>

The JWT token must contain an org-id claim that matches the {orgID} path parameter in the requests.


Understanding Operation Types

Asynchronous Operations (202 Accepted)

Operations that involve cloud infrastructure changes return 202 Accepted and execute in the background via Argo workflows:

  • Remove Scanner
  • Reinstall Scanner
  • Batch Remove Scanners
  • Batch Reinstall Scanners
  • Remove Cloud Organisation

Async Response Structure:

{
  "jobId": "rm-scan-cfg-scanner-123-1733980800",
  "statusUrl": "/api/v1/jobs/rm-scan-cfg-scanner-123-1733980800",
  "jobInfo": {}
}

Response Headers:

  • Location: /api/v1/jobs/{jobId} - URL to poll for status
  • Retry-After: 30 - Recommended polling interval (seconds)

What to do next:

  1. Store the jobId for tracking
  2. Poll the statusUrl to check operation status
  3. Wait at least 30 seconds between poll requests

Synchronous Operations (200 OK)

Operations that only update internal state return 200 OK immediately:

  • Disable Scanner (Pause)
  • Enable Scanner (Unpause)
  • Batch Pause Scanners
  • Batch Unpause Scanners

These complete instantly and return final results in the response.


Remove Scanner

Asynchronously removes a scanner's cloud infrastructure and configuration.

Request

curl -X POST "${HOST}/api/v1/${ORG_ID}/scanner/remove" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "configId": "'${CONFIG_ID}'",
    "cloudProvider": "aws"
  }'

Response (202 Accepted)

{
  "jobId": "rm-scan-cfg-scanner-123-1733980800",
  "statusUrl": "/api/v1/jobs/rm-scan-cfg-scanner-123-1733980800",
}

Poll Job Status

curl -X GET "${HOST}/api/v1/jobs/rm-scan-cfg-scanner-123-1733980800" \
  -H "Authorization: Bearer ${TOKEN}"

Status Response:

{
  "workflowName": "rm-scan-cfg-scanner-123-1733980800",
  "status": "running",
  "configId": "'${CONFIG_ID}'",
  "orgId": "org_abc123",
  "cloudProvider": "aws",
  "region": "us-east-1",
  "currentStep": "awaiting-stack-deleted",
  "retryAttempt": 2,
  "createdAt": "2025-01-12T10:00:00Z",
  "updatedAt": "2025-01-12T10:05:30Z",
  "error": null
}

Status Values:

  • pending - Workflow queued
  • running - Operation in progress
  • succeeded - Operation completed successfully
  • failed - Operation failed (see error field)

Batch Remove Scanners

Asynchronously removes multiple scanners in parallel via Argo workflows.

Each scanner in the batch is processed independently (best-effort). If one scanner fails validation or submission, the others continue. A parent correlation ID groups all child workflows for aggregated status tracking.

Request

curl -X POST "${HOST}/api/v1/${ORG_ID}/scanner/batch/remove" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "scanners": [
      { "configID": "cfg-scanner-001", "cloudProvider": "aws" },
      { "configID": "cfg-scanner-002", "cloudProvider": "aws" }
    ]
  }'

Response (202 Accepted)

{
  "jobId": "rm-scan-550e8400-e29b-41d4-a716-446655440000",
  "statusUrl": "/api/v1/jobs?parent-id=rm-scan-550e8400-e29b-41d4-a716-446655440000",
  "jobInfo": {
    "results": [
      {
        "configID": "cfg-scanner-001",
        "cloudProvider": "aws",
        "success": true,
        "status": "dispatched",
        "workflowName": "rm-scan-cfg-scanner-001-1733980800"
      },
      {
        "configID": "cfg-scanner-002",
        "cloudProvider": "aws",
        "success": true,
        "status": "dispatched",
        "workflowName": "rm-scan-cfg-scanner-002-1733980801"
      }
    ]
  }
}

Response Headers:

  • Location: /api/v1/jobs?parent-id={jobId} - URL to poll for aggregated status
  • Retry-After: 30 - Recommended polling interval (seconds)

Per-scanner result fields:

  • success: true — workflow submitted successfully (not yet completed)
  • success: false — submission failed; check error field
  • status"dispatched" (workflow created) or "error" (failed to submit)
  • workflowName — only present when success: true

Poll Batch Status

curl -X GET "${HOST}/api/v1/jobs?parent-id=rm-scan-550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer ${TOKEN}"

Batch Status Response:

{
  "parentID": "rm-scan-550e8400-e29b-41d4-a716-446655440000",
  "summary": {
    "total": 2,
    "running": 1,
    "completed": 1,
    "failed": 0
  },
  "jobs": [
    {
      "workflowName": "rm-scan-cfg-scanner-001-1733980800",
      "status": "completed",
      "configId": "cfg-scanner-001",
      "orgId": "org_abc123",
      "cloudProvider": "aws",
      "region": "us-east-1",
      "currentStep": "completed",
      "createdAt": "2025-01-12T10:00:00Z",
      "updatedAt": "2025-01-12T10:03:00Z"
    },
    {
      "workflowName": "rm-scan-cfg-scanner-002-1733980801",
      "status": "running",
      "configId": "cfg-scanner-002",
      "orgId": "org_abc123",
      "cloudProvider": "aws",
      "region": "eu-west-1",
      "currentStep": "awaiting-stack-deleted",
      "createdAt": "2025-01-12T10:00:00Z",
      "updatedAt": "2025-01-12T10:02:00Z"
    }
  ]
}

Batch Reinstall Scanners

Asynchronously reinstalls multiple scanners via the management reinstall path.

Each scanner is delegated to the management reinstall handler (OnReInstallCloudScanner), which provides concurrency control via distributed locks and a pending action queue. If a scanner already has a running workflow, the reinstall is queued and executed when the current workflow completes.

Request

curl -X POST "${HOST}/api/v1/${ORG_ID}/scanner/batch/reinstall" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "scanners": [
      { "configID": "cfg-scanner-001", "cloudProvider": "aws" },
      { "configID": "cfg-scanner-002", "cloudProvider": "aws" }
    ]
  }'

Response (202 Accepted)

{
  "jobId": "ri-scan-550e8400-e29b-41d4-a716-446655440000",
  "statusUrl": "/api/v1/jobs?parent-id=ri-scan-550e8400-e29b-41d4-a716-446655440000",
  "jobInfo": {
    "results": [
      {
        "configID": "cfg-scanner-001",
        "cloudProvider": "aws",
        "success": true,
        "status": "dispatched"
      },
      {
        "configID": "cfg-scanner-002",
        "cloudProvider": "aws",
        "success": true,
        "status": "dispatched"
      }
    ]
  }
}

Response Headers:

  • Location: /api/v1/jobs?parent-id={jobId} - URL to poll for aggregated status
  • Retry-After: 30 - Recommended polling interval (seconds)

Per-scanner result fields:

  • success: true — reinstall accepted
  • success: false — failed; check error field
  • status"dispatched" (accepted for processing) or "error" (validation/config failure)

Note: Unlike batch remove, workflowName is not returned in the initial response because workflows are created asynchronously by the management path. Poll the statusUrl to discover workflows as they appear.

Poll Batch Status

curl -X GET "${HOST}/api/v1/jobs?parent-id=ri-scan-550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer ${TOKEN}"

The response follows the same structure as batch remove status (see above). Workflows appear in the response once the management path has dispatched them. Configs that are queued (another workflow running) will not appear until their workflow is created.


Batch Pause Scanners

Synchronously pauses workers for multiple scanners in parallel.

Each scanner in the batch is processed independently (best-effort) with bounded concurrency (up to 10 in parallel). If one scanner fails, the others continue. The endpoint returns 200 OK once all operations have completed, with per-scanner results indicating success or failure.

This operation only updates the scanner configuration settings — it does not modify cloud infrastructure or resources state.

Request

curl -X POST "${HOST}/api/v1/${ORG_ID}/scanner/batch/pause" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "scanners": [
      { "configID": "cfg-scanner-001", "cloudProvider": "aws" },
      { "configID": "cfg-scanner-002", "cloudProvider": "aws" }
    ]
  }'

Response (200 OK)

{
  "results": [
    {
      "configID": "cfg-scanner-001",
      "cloudProvider": "aws",
      "success": true,
      "workersPaused": true
    },
    {
      "configID": "cfg-scanner-002",
      "cloudProvider": "aws",
      "success": true,
      "workersPaused": true
    }
  ]
}

Per-scanner result fields:

  • success: true — workers paused successfully (or were already paused)
  • success: false — operation failed; check error field
  • workersPaused — the final state of the scanner's workers (true = paused)
  • error — only present when success: false; describes what went wrong

Note: This is a synchronous endpoint. No polling is required — the response contains the final results for all scanners.

Error Responses

  • 400 Bad Request — Invalid JSON body or empty scanners list
  • 403 Forbidden — JWT org-id does not match path orgID

Batch Unpause Scanners

Synchronously unpauses workers for multiple scanners in parallel.

Follows the same semantics as batch pause — best-effort with bounded concurrency. Returns 200 OK once all operations have completed, with per-scanner results.

Request

curl -X POST "${HOST}/api/v1/${ORG_ID}/scanner/batch/unpause" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "scanners": [
      { "configID": "cfg-scanner-001", "cloudProvider": "aws" },
      { "configID": "cfg-scanner-002", "cloudProvider": "aws" }
    ]
  }'

Response (200 OK)

{
  "results": [
    {
      "configID": "cfg-scanner-001",
      "cloudProvider": "aws",
      "success": true,
      "workersPaused": false
    },
    {
      "configID": "cfg-scanner-002",
      "cloudProvider": "aws",
      "success": true,
      "workersPaused": false
    }
  ]
}

Per-scanner result fields:

  • success: true — workers unpaused successfully (or were already running)
  • success: false — operation failed; check error field
  • workersPaused — the final state of the scanner's workers (false = running)
  • error — only present when success: false; describes what went wrong

Note: This is a synchronous endpoint. No polling is required — the response contains the final results for all scanners.

Error Responses

  • 400 Bad Request — Invalid JSON body or empty scanners list
  • 403 Forbidden — JWT org-id does not match path orgID

Reinstall Scanner

Asynchronously reinstalls a scanner's cloud infrastructure.

This operation triggers an async workflow to delete and recreate the scanner's resources. It includes built-in concurrency control to prevent multiple simultaneous install/uninstall/update operations on the same configuration.

Request

curl -X POST "${HOST}/api/v1/${ORG_ID}/management/reinstall?config-id=${CONFIG_ID}" \
  -H "Authorization: Bearer ${TOKEN}"

Query Parameters:

  • config-id (required) - The scanner configuration ID

Request Body: None

Response (200 OK)

The endpoint returns an empty 200 OK response upon successfully initiating the reinstall workflow.

Note: Although the response is 200 OK, the reinstall operation executes asynchronously in the background. Use the Retry-After: 30 header guidance when polling for completion.


Disable Region

Synchronously disables a specific region for a scanner configuration.

This operation updates the organisation settings to remove the region from the enabled regions list. It is idempotent - calling it multiple times returns success even if the region is already disabled.

Request

curl -X POST "${HOST}/api/v1/${ORG_ID}/scanner/region/disable" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "configId": "'${CONFIG_ID}'",
    "cloudProvider": "aws"
  }'

Response (200 OK)

{
  "message": "Region disabled successfully",
  "region": "us-east-1",
  "cloudOrganizationId": "o-abc123xyz"
}

Note:

  • This operation completes immediately. No polling required.
  • The region is extracted from the scanner configuration.
  • If the region was already disabled, the message will be "Region already disabled".

Remove Cloud Organisation

Asynchronously removes all scanners in a cloud organisation, then deletes credentials.

Request

curl -X DELETE "${HOST}/api/v1/${ORG_ID}/cloud-organization" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "cloudOrganizationId": "o-abc123xyz",
    "cloudProvider": "aws"
  }'

Response (202 Accepted)

{
  "jobId": "rm-org-o-abc123xyz-1733981200",
  "statusUrl": "/api/v1/jobs?parent-id=rm-org-o-abc123xyz-1733981200"
}

Note: This operation may take longer than individual scanner operations as it:

  1. Discovers all scanners in the organisation
  2. Removes each scanner (parallel workflows)
  3. Deletes organisation credentials (after all scanners removed)

Poll Job Status

Because remove-org spawns multiple child scanner-removal workflows, poll using the parent-id query parameter to get aggregated status across all child jobs:

curl -X GET "${HOST}/api/v1/jobs?parent-id=rm-org-o-abc123xyz-1733981200" \
  -H "Authorization: Bearer ${TOKEN}"

Status Response:

{
  "parentID": "rm-org-o-abc123xyz-1733981200",
  "summary": {
    "total": 2,
    "running": 1,
    "completed": 1,
    "failed": 0
  },
  "jobs": [
    {
      "workflowName": "rm-scan-ucsc-adc88239e1868737-1772552434",
      "status": "running",
      "configId": "ucsc-adc88239e1868737",
      "orgId": "org_mjFogBC37G1l7ERc",
      "cloudProvider": "aws",
      "region": "us-east-1",
      "currentStep": "delete-scanner-config",
      "createdAt": "2026-03-03T15:40:35Z",
      "updatedAt": "2026-03-03T15:43:02Z"
    },
    {
      "workflowName": "rm-scan-ucsc-188bc9b82e66c7fa-1772552434",
      "status": "completed",
      "configId": "ucsc-188bc9b82e66c7fa",
      "orgId": "org_mjFogBC37G1l7ERc",
      "cloudProvider": "aws",
      "region": "us-east-2",
      "currentStep": "post-status",
      "createdAt": "2026-03-03T15:40:36Z",
      "updatedAt": "2026-03-03T15:43:00Z"
    }
  ]
}

Response fields:

  • parentID — the correlation ID from the original remove-org request
  • summary — aggregated counts across all child workflows (total, running, completed, failed)
  • jobs — individual scanner-removal workflow statuses, each with the same fields as a single job status response

The operation is complete when summary.running == 0 (all jobs are either completed or failed).


Uninstall Scanner

Asynchronously uninstalls a scanner's cloud infrastructure.

This operation triggers an async workflow to remove the scanner. It includes built-in concurrency control to prevent multiple simultaneous install/uninstall/update operations on the same configuration.

Request

curl -X POST "${HOST}/api/v1/${ORG_ID}/management/uninstall?config-id=${CONFIG_ID}" \
  -H "Authorization: Bearer ${TOKEN}"

Query Parameters:

  • config-id (required) - The scanner configuration ID

Request Body: None

Response (200 OK)

The endpoint returns an empty 200 OK response upon successfully initiating the uninstall workflow.

Note: Although the response is 200 OK, the uninstall operation executes asynchronously in the background. Use the Retry-After: 30 header guidance when polling for completion.


Disable Scanner

Synchronously disable a scanner's workers.

This operation updates the scanner configuration to pause all workers. It is idempotent — calling it on an already-paused scanner returns success without making changes.

Request

curl -X POST "${HOST}/api/v1/${ORG_ID}/management/pause?config-id=${CONFIG_ID}" \
  -H "Authorization: Bearer ${TOKEN}"

Query Parameters:

  • config-id (required) - The scanner configuration ID

Request Body: None

Response (200 OK)

{
  "message": "workers paused successfully",
  "configId": "'${CONFIG_ID}'",
  "workersPaused": true
}

If already paused (idempotent):

{
  "message": "workers already paused",
  "configId": "'${CONFIG_ID}'",
  "workersPaused": true
}

Note: This operation completes immediately. No polling required.


Unpause Scanner

Synchronously unpauses a scanner's workers.

This operation updates the scanner configuration to resume all workers. It is idempotent — calling it on an already-running scanner returns success without making changes. Workers scale back up based on the job queue after unpausing.

Request

curl -X POST "${HOST}/api/v1/${ORG_ID}/management/unpause?config-id=${CONFIG_ID}" \
  -H "Authorization: Bearer ${TOKEN}"

Query Parameters:

  • config-id (required) - The scanner configuration ID

Request Body: None

Response (200 OK)

{
  "message": "workers unpaused successfully",
  "configId": "'${CONFIG_ID}'",
  "workersPaused": false
}

If already unpaused (idempotent):

{
  "message": "workers already unpaused",
  "configId": "'${CONFIG_ID}'",
  "workersPaused": false
}

Note: This operation completes immediately. No polling required.


Remove Cloud Provider

Asynchronously removes all cloud organisations for a given cloud provider.

This operation discovers all cloud organisation IDs for the specified organisation and cloud provider, then submits one remove-org workflow per organisation. Each workflow removes all scanners in that organisation before deleting the organisation credentials.

The handler uses best-effort submission — if one workflow fails to submit, it continues with the rest and returns all results (a mix of successes and failures).

Request

curl -X DELETE "${HOST}/api/v1/${ORG_ID}/cloud-provider/${CLOUD_PROVIDER}" \
  -H "Authorization: Bearer ${TOKEN}"

Path Parameters:

  • orgID (required) - Organisation ID (must match JWT claim)
  • cloudProvider (required) - Cloud provider name: aws, azure, gcp, or oracle

Request Body: None

Response (202 Accepted)

{
  "jobId": "rm-cp-aws-550e8400-e29b-41d4-a716-446655440000",
  "statusUrl": "/api/v1/jobs?parent-id=rm-cp-aws-550e8400-e29b-41d4-a716-446655440000",
  "jobInfo": {
    "results": [
      {
        "cloudOrganizationId": "o-abc123xyz",
        "success": true,
        "workflowName": "rm-org-o-abc123xyz-1733981200"
      },
      {
        "cloudOrganizationId": "o-def456uvw",
        "success": true,
        "workflowName": "rm-org-o-def456uvw-1733981201"
      }
    ]
  }
}

Response Headers:

  • Location: /api/v1/jobs?parent-id={jobId} - URL to poll for status
  • Retry-After: 30 - Recommended polling interval (seconds)

Important:

  • The jobInfo.results array shows immediate submission results for each cloud organisation
  • success: true means the workflow was submitted successfully (not that removal completed)
  • success: false means the workflow could not be submitted — check the error field for details
  • Poll the statusUrl to track overall progress

Error Responses

  • 400 Bad Request - Invalid cloudProvider value
  • 404 Not Found - No cloud organisations found for this provider

Quick Reference

EndpointMethodOperation TypeResponse CodePoll Required?
/scanner/removePOSTAsync202 AcceptedYes
/scanner/batch/removePOSTAsync (batch)202 AcceptedYes
/scanner/batch/reinstallPOSTAsync (batch)202 AcceptedYes
/scanner/batch/pausePOSTSync (batch)200 OKNo
/scanner/batch/unpausePOSTSync (batch)200 OKNo
/management/reinstallPOSTAsync200 OKYes
/scanner/region/disablePOSTSync200 OKNo
/cloud-organizationDELETEAsync202 AcceptedYes
/cloud-provider/{cloudProvider}DELETEAsync202 AcceptedYes
/management/uninstallPOSTAsync200 OKYes
/management/pausePOSTSync200 OKNo
/management/unpausePOSTSync200 OKNo
/jobs/{jobId}GETStatus Check200 OKN/A
/jobs?parent-id={parentId}GETBatch Status200 OKN/A

Error Responses

All endpoints may return standard error responses:

400 Bad Request

{
  "error": "configId is required"
}

401 Unauthorised

{
  "error": "Unauthorised"
}

403 Forbidden

{
  "error": "Access denied"
}

404 Not Found

{
  "error": "Config not found"
}

500 Internal Server Error

{
  "error": "Internal server error"
}

Best Practices

Polling Strategy

For async operations:

  1. Wait at least 30 seconds between poll requests (honour the Retry-After header)
  2. Implement exponential backoff for long-running operations
  3. Set a reasonable timeout (15-20 minutes for scanner operations)
  4. Handle failed status gracefully and check the error field for details

Batch Operations

  1. Use batch endpoints when operating on multiple scanners to get a single correlation ID (async) or aggregated results (sync)
  2. Check individual results in the response — some scanners may fail whilst others succeed
  3. For batch reinstall, workflows appear in the status endpoint asynchronously; poll until summary.total matches the expected count
  4. Configs with an already-running workflow will be queued and processed after the current workflow completes
  5. Batch pause/unpause are synchronous — the response is final with no polling needed

Error Handling

  1. 400 Bad Request: Validate your request payload before retrying
  2. 401 Unauthorised: Refresh your JWT token
  3. 403 Forbidden: Verify your JWT org-id matches the path parameter
  4. 404 Not Found: The scanner config doesn't exist or was already deleted
  5. 500 Internal Server Error: Retry with exponential backoff (3-5 attempts)