aspera-cli 4.27.5 → 4.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +160 -4
- data/CONTRIBUTING.md +4 -2
- data/README.md +1 -1
- data/bin/asession +1 -1
- data/docs/README.md +1086 -331
- data/docs/test-mcp-with-ai.md +5 -3
- data/lib/aspera/agent/direct.rb +15 -4
- data/lib/aspera/agent/factory.rb +2 -1
- data/lib/aspera/agent/node.rb +1 -1
- data/lib/aspera/api/cos_node.rb +1 -1
- data/lib/aspera/api/faspex.rb +1 -1
- data/lib/aspera/api/node.rb +6 -2
- data/lib/aspera/ascp/installation.rb +47 -11
- data/lib/aspera/ascp/management.rb +89 -43
- data/lib/aspera/cli/ascp_actions.rb +5 -19
- data/lib/aspera/cli/bootstrapper.rb +1 -2
- data/lib/aspera/cli/command_registry.rb +43 -3
- data/lib/aspera/cli/command_spec.rb +3 -0
- data/lib/aspera/cli/completion/ascli.bash +39 -5
- data/lib/aspera/cli/completion/ascli.fish +16 -8
- data/lib/aspera/cli/completion/ascli.ps1 +41 -0
- data/lib/aspera/cli/completion/ascli.zsh +20 -4
- data/lib/aspera/cli/completion_actions.rb +360 -0
- data/lib/aspera/cli/error.rb +42 -0
- data/lib/aspera/cli/extended_value.rb +30 -5
- data/lib/aspera/cli/formatter.rb +118 -56
- data/lib/aspera/cli/hints.rb +0 -1
- data/lib/aspera/cli/http.rb +6 -5
- data/lib/aspera/cli/info.rb +10 -4
- data/lib/aspera/cli/mailer.rb +1 -1
- data/lib/aspera/cli/mcp/http_servlet.rb +156 -0
- data/lib/aspera/cli/mcp/secrets.rb +143 -0
- data/lib/aspera/cli/mcp/tool.rb +231 -0
- data/lib/aspera/cli/option_value.rb +9 -1
- data/lib/aspera/cli/options.schema.yaml +390 -39
- data/lib/aspera/cli/parser.rb +14 -5
- data/lib/aspera/cli/plugins/aoc.rb +8 -11
- data/lib/aspera/cli/plugins/base.rb +36 -15
- data/lib/aspera/cli/plugins/config.rb +15 -44
- data/lib/aspera/cli/plugins/console.rb +3 -1
- data/lib/aspera/cli/plugins/factory.rb +1 -1
- data/lib/aspera/cli/plugins/faspex5.rb +9 -19
- data/lib/aspera/cli/plugins/faspio.rb +36 -5
- data/lib/aspera/cli/plugins/httpgw.rb +1 -0
- data/lib/aspera/cli/plugins/mcp.rb +177 -118
- data/lib/aspera/cli/plugins/node.rb +14 -8
- data/lib/aspera/cli/plugins/orchestrator.rb +351 -38
- data/lib/aspera/cli/plugins/server.rb +3 -1
- data/lib/aspera/cli/plugins/shares.rb +205 -35
- data/lib/aspera/cli/preset_actions.rb +15 -7
- data/lib/aspera/cli/preset_manager.rb +24 -2
- data/lib/aspera/cli/prompt.rb +3 -1
- data/lib/aspera/cli/result.rb +17 -4
- data/lib/aspera/cli/runner.rb +133 -43
- data/lib/aspera/cli/security.rb +134 -0
- data/lib/aspera/cli/table_fitter.rb +116 -0
- data/lib/aspera/cli/terminal_formatter.rb +23 -34
- data/lib/aspera/cli/transfer_agent.rb +4 -1
- data/lib/aspera/cli/vault_manager.rb +6 -5
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/cli/web_secret.html.erb +61 -0
- data/lib/aspera/cli/web_secret.rb +220 -0
- data/lib/aspera/cli/wizard.rb +19 -9
- data/lib/aspera/command_line_builder.rb +26 -0
- data/lib/aspera/data_repository.rb +38 -24
- data/lib/aspera/duration.rb +42 -0
- data/lib/aspera/environment.rb +88 -24
- data/lib/aspera/exec_spec.rb +6 -5
- data/lib/aspera/faspex_gw.rb +98 -32
- data/lib/aspera/faspex_postproc.rb +187 -44
- data/lib/aspera/formatter_interface.rb +0 -1
- data/lib/aspera/id_generator.rb +2 -1
- data/lib/aspera/json_rpc/client.rb +51 -32
- data/lib/aspera/json_rpc/version.rb +1 -0
- data/lib/aspera/keychain/base.rb +5 -0
- data/lib/aspera/keychain/encrypted_hash.rb +6 -2
- data/lib/aspera/keychain/factory.rb +2 -3
- data/lib/aspera/keychain/hashicorp_vault.rb +7 -4
- data/lib/aspera/keychain/macos_security.rb +119 -13
- data/lib/aspera/keychain/one_password_api.rb +8 -3
- data/lib/aspera/keychain/one_password_base.rb +14 -9
- data/lib/aspera/keychain/one_password_cli.rb +4 -2
- data/lib/aspera/log.rb +3 -6
- data/lib/aspera/markdown.rb +152 -115
- data/lib/aspera/mime.rb +6 -0
- data/lib/aspera/nagios.rb +3 -1
- data/lib/aspera/node_emulator.rb +98 -101
- data/lib/aspera/oauth/{base.rb → client/base.rb} +5 -4
- data/lib/aspera/oauth/{boot.rb → client/boot.rb} +3 -2
- data/lib/aspera/oauth/{factory.rb → client/factory.rb} +7 -0
- data/lib/aspera/oauth/{generic.rb → client/generic.rb} +1 -1
- data/lib/aspera/oauth/{json_credentials.rb → client/json_credentials.rb} +1 -1
- data/lib/aspera/oauth/{jwt.rb → client/jwt.rb} +1 -1
- data/lib/aspera/oauth/{url_json.rb → client/url_json.rb} +1 -1
- data/lib/aspera/oauth/{web.rb → client/web.rb} +2 -2
- data/lib/aspera/oauth/server/authorize.html.erb +34 -0
- data/lib/aspera/oauth/server/pkce.rb +426 -0
- data/lib/aspera/orchestrator_workflow_checker.rb +561 -0
- data/lib/aspera/preview/terminal.rb +3 -2
- data/lib/aspera/rainbow.rb +27 -1
- data/lib/aspera/rest/aspera_errors.rb +51 -59
- data/lib/aspera/rest/client.rb +21 -14
- data/lib/aspera/rest/error_analyzer.rb +9 -0
- data/lib/aspera/rest/list.rb +6 -6
- data/lib/aspera/rest/util.rb +7 -1
- data/lib/aspera/rest.rb +0 -1
- data/lib/aspera/schema/IBM Aspera Faspex API-5.0-enhanced.yaml +0 -2
- data/lib/aspera/schema/IBM Aspera Orchestrator API-v1-enhanced.yaml +4001 -0
- data/lib/aspera/schema/IBM Aspera faspio Gateway API-1.0.0-enhanced.yaml +1097 -0
- data/lib/aspera/schema/IBM Aspera on Cloud Automation API-1.0.5-enhanced.yaml +35 -35
- data/lib/aspera/schema/IBM_Aspera_Shares.yaml +819 -7
- data/lib/aspera/schema/documentation.rb +50 -78
- data/lib/aspera/schema/reader.rb +39 -11
- data/lib/aspera/schema/registry.rb +8 -2
- data/lib/aspera/secret_hider.rb +94 -15
- data/lib/aspera/secret_strength.rb +114 -0
- data/lib/aspera/servlet_helpers.rb +111 -0
- data/lib/aspera/sync/args.schema.yaml +3 -1
- data/lib/aspera/sync/conf.schema.yaml +16 -6
- data/lib/aspera/sync/operations.rb +21 -1
- data/lib/aspera/temp_file_manager.rb +79 -20
- data/lib/aspera/transfer/parameters.rb +5 -0
- data/lib/aspera/transfer/spec.rb +52 -12
- data/lib/aspera/transfer/spec.schema.yaml +8 -5
- data/lib/aspera/web_auth/index.html.erb +16 -0
- data/lib/aspera/web_auth/server.rb +18 -10
- data/lib/aspera/web_page.html.erb +262 -0
- data/lib/aspera/web_page.rb +61 -0
- data/lib/aspera/web_server_simple.rb +76 -10
- data.tar.gz.sig +0 -0
- metadata +47 -32
- metadata.gz.sig +0 -0
- data/lib/aspera/cli/mcp_tool.rb +0 -189
- data/lib/aspera/oauth.rb +0 -9
- data/lib/aspera/schema/IBM Aspera Orchestrator API-v1.yaml +0 -1784
- data/lib/aspera/schema/IBM Aspera faspio Gateway API-1.0.0.yaml +0 -249
- data/lib/aspera/web_auth/index.html +0 -147
|
@@ -0,0 +1,1097 @@
|
|
|
1
|
+
# DO NOT EDIT THIS FILE MANUALLY
|
|
2
|
+
# This file is automatically downloaded from:
|
|
3
|
+
# https://raw.githubusercontent.com/laurent-martin/aspera-api-examples/refs/heads/main/openapi/IBM%20Aspera%20faspio%20Gateway%20API-1.0.0-enhanced.yaml
|
|
4
|
+
# Use 'rake tools:openapi' to update this file
|
|
5
|
+
|
|
6
|
+
openapi: 3.1.0
|
|
7
|
+
info:
|
|
8
|
+
title: IBM Aspera faspio Gateway API
|
|
9
|
+
description: |
|
|
10
|
+
REST API for managing IBM Aspera faspio Gateway bridges and monitoring.
|
|
11
|
+
|
|
12
|
+
## Overview
|
|
13
|
+
IBM Aspera faspio Gateway bridges local TCP or UDP connections over the FASP (Fast, Adaptive, and Secure Protocol)
|
|
14
|
+
transport to a remote gateway peer. You can use this API to create, inspect, and delete **dynamic**
|
|
15
|
+
bridges at runtime without restarting the gateway.
|
|
16
|
+
|
|
17
|
+
Static bridges (defined in `gateway.toml`) are read-only via this API — they can be retrieved
|
|
18
|
+
but cannot be deleted or modified.
|
|
19
|
+
|
|
20
|
+
## Authentication
|
|
21
|
+
The API supports three authentication modes, configured in `gateway.toml` under `[admin]`:
|
|
22
|
+
|
|
23
|
+
| Mode | Description |
|
|
24
|
+
|------|-------------|
|
|
25
|
+
| `none` | No authentication (development only) |
|
|
26
|
+
| `basic` | HTTP Basic Authentication (username + SHA-512/PBKDF2 password digest) |
|
|
27
|
+
| `oauth2` | Bearer JWT token obtained via `POST /auth/token` |
|
|
28
|
+
|
|
29
|
+
## OAuth 2.0 quick start
|
|
30
|
+
|
|
31
|
+
This gateway implements the **JWT Bearer grant** (RFC 7523). There is no identity provider
|
|
32
|
+
involved — the gateway itself issues and verifies tokens using RSA key pairs you generate.
|
|
33
|
+
|
|
34
|
+
### Step 1 — Generate key pairs
|
|
35
|
+
|
|
36
|
+
The gateway needs **two** RSA key pairs:
|
|
37
|
+
|
|
38
|
+
| Key pair | Who holds it | Purpose |
|
|
39
|
+
|----------|-------------|---------|
|
|
40
|
+
| **Client key pair** | Your application | Sign JWT assertions sent to `POST /auth/token` |
|
|
41
|
+
| **Server key pair** | The gateway | Sign access tokens returned to your application |
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Client key pair (your application uses the private key to sign assertions)
|
|
45
|
+
openssl genrsa -out client_private.pem 2048
|
|
46
|
+
openssl rsa -in client_private.pem -pubout -out client_public.pem
|
|
47
|
+
|
|
48
|
+
# Server key pair (the gateway uses the private key to sign access tokens)
|
|
49
|
+
openssl genrsa -out server_private.pem 2048
|
|
50
|
+
openssl rsa -in server_private.pem -pubout -out server_public.pem
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Step 2 — Configure `gateway.toml`
|
|
54
|
+
|
|
55
|
+
Give the gateway the **client's public key** (to verify assertions) and the
|
|
56
|
+
**server's private key** (to sign access tokens):
|
|
57
|
+
|
|
58
|
+
```toml
|
|
59
|
+
[admin]
|
|
60
|
+
rest_api_auth = "oauth2"
|
|
61
|
+
rest_api_enabled = true
|
|
62
|
+
|
|
63
|
+
[admin.oauth2]
|
|
64
|
+
client_id = "my-gateway-client"
|
|
65
|
+
jwt_grant_enabled = true
|
|
66
|
+
jwt_verification_key = "/etc/faspio-gateway/client_public.pem" # verifies your assertion
|
|
67
|
+
jwt_signing_key = "/etc/faspio-gateway/server_private.pem" # signs the access token
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Step 3 — Create a JWT assertion
|
|
71
|
+
|
|
72
|
+
Your application signs a short-lived JWT with its **private key**.
|
|
73
|
+
The `iss` and `sub` claims must both equal the `client_id` in `gateway.toml`.
|
|
74
|
+
|
|
75
|
+
Example using Python (PyJWT):
|
|
76
|
+
```python
|
|
77
|
+
import jwt, time
|
|
78
|
+
|
|
79
|
+
with open("client_private.pem") as f:
|
|
80
|
+
private_key = f.read()
|
|
81
|
+
|
|
82
|
+
assertion = jwt.encode(
|
|
83
|
+
{"iss": "my-gateway-client", "sub": "my-gateway-client",
|
|
84
|
+
"exp": int(time.time()) + 300}, # valid for 5 minutes
|
|
85
|
+
private_key,
|
|
86
|
+
algorithm="RS256"
|
|
87
|
+
)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Example using `openssl` + `bash` (no extra libraries):
|
|
91
|
+
```bash
|
|
92
|
+
HEADER=$(echo -n '{"alg":"RS256","typ":"JWT"}' | base64url)
|
|
93
|
+
NOW=$(date +%s); EXP=$((NOW + 300))
|
|
94
|
+
PAYLOAD=$(echo -n "{\"iss\":\"my-gateway-client\",\"sub\":\"my-gateway-client\",\"exp\":$EXP}" | base64url)
|
|
95
|
+
SIG=$(echo -n "$HEADER.$PAYLOAD" | openssl dgst -sha256 -sign client_private.pem | base64url)
|
|
96
|
+
ASSERTION="$HEADER.$PAYLOAD.$SIG"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Step 4 — Exchange the assertion for an access token
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
curl -s -X POST http://127.0.0.1:8080/auth/token \
|
|
103
|
+
-H "Content-Type: application/json" \
|
|
104
|
+
-d "{\"grant_type\":\"urn:ietf:params:oauth:grant-type:jwt-bearer\",
|
|
105
|
+
\"assertion\":\"$ASSERTION\",
|
|
106
|
+
\"client_id\":\"my-gateway-client\"}"
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Response:
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"access_token": "<TOKEN>",
|
|
113
|
+
"token_type": "Bearer",
|
|
114
|
+
"expires_in": 3600
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Step 5 — Call the API with the access token
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
TOKEN="<TOKEN>"
|
|
122
|
+
|
|
123
|
+
# List all bridges
|
|
124
|
+
curl -s http://127.0.0.1:8080/bridges \
|
|
125
|
+
-H "Authorization: Bearer $TOKEN"
|
|
126
|
+
|
|
127
|
+
# Create a bridge
|
|
128
|
+
curl -s -X POST http://127.0.0.1:8080/bridges \
|
|
129
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
130
|
+
-H "Content-Type: application/json" \
|
|
131
|
+
-d '{"name":"Bridge-1","local":{"bind_address":"127.0.0.1","port":"2000","protocol":"tcp","tls_enabled":false},"forward":{"host":["10.0.0.2"],"port":"3000","protocol":"fasp","tls_enabled":false}}'
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
The access token expires after **1 hour** (`expires_in: 3600`). Repeat steps 3–4 to renew it.
|
|
135
|
+
|
|
136
|
+
## Bridge lifecycle
|
|
137
|
+
```text
|
|
138
|
+
POST /bridges
|
|
139
|
+
↓
|
|
140
|
+
(bridge created and started)
|
|
141
|
+
↓
|
|
142
|
+
GET /bridges/{id}
|
|
143
|
+
↓
|
|
144
|
+
DELETE /bridges/{id}
|
|
145
|
+
↓
|
|
146
|
+
(bridge stopped and removed)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Bridges created via the API are **dynamic** — they are persisted to a runtime state file
|
|
150
|
+
and survive gateway restarts.
|
|
151
|
+
contact:
|
|
152
|
+
name: IBM Aspera Support
|
|
153
|
+
email: Aspera-client-team@wwpdl.vnet.ibm.com
|
|
154
|
+
license:
|
|
155
|
+
name: © IBM. All rights reserved
|
|
156
|
+
url: https://www-40.ibm.com/software/sla/sladb.nsf/displaylis/0CF8A1C0BA2B994C002587F70069A8B5?OpenDocument
|
|
157
|
+
version: 1.0.0
|
|
158
|
+
servers:
|
|
159
|
+
- url: http://127.0.0.1:8080
|
|
160
|
+
description: Default local gateway admin endpoint (HTTP)
|
|
161
|
+
- url: https://127.0.0.1:8080
|
|
162
|
+
description: Default local gateway admin endpoint (HTTPS/TLS)
|
|
163
|
+
paths:
|
|
164
|
+
# ---------------------------------------------------------------------------
|
|
165
|
+
# Health
|
|
166
|
+
# ---------------------------------------------------------------------------
|
|
167
|
+
/ping:
|
|
168
|
+
get:
|
|
169
|
+
operationId: ping
|
|
170
|
+
summary: Liveness probe
|
|
171
|
+
description: |
|
|
172
|
+
Returns an empty JSON object `{}` when the gateway HTTP server is running.
|
|
173
|
+
This endpoint does **not** require authentication and is not subject to the
|
|
174
|
+
configured `rest_api_auth` scheme — it can be used by load balancers and
|
|
175
|
+
orchestrators for health checks.
|
|
176
|
+
# Note: /ping is intentionally unauthenticated — no 4xx responses apply.
|
|
177
|
+
# The linter warning `operation-4xx-response` is suppressed by design.
|
|
178
|
+
responses:
|
|
179
|
+
'200':
|
|
180
|
+
description: The gateway is running.
|
|
181
|
+
headers:
|
|
182
|
+
Cache-Control:
|
|
183
|
+
description: Always `no-cache` — do not cache liveness responses.
|
|
184
|
+
schema:
|
|
185
|
+
type: string
|
|
186
|
+
examples:
|
|
187
|
+
- no-cache
|
|
188
|
+
content:
|
|
189
|
+
application/json:
|
|
190
|
+
schema:
|
|
191
|
+
description: Empty JSON object.
|
|
192
|
+
type: object
|
|
193
|
+
examples:
|
|
194
|
+
- {}
|
|
195
|
+
security: [] # Explicitly unauthenticated
|
|
196
|
+
tags:
|
|
197
|
+
- Health
|
|
198
|
+
options:
|
|
199
|
+
tags:
|
|
200
|
+
- Health
|
|
201
|
+
summary: CORS preflight for /ping
|
|
202
|
+
description: Handles browser CORS preflight requests for the `/ping` endpoint.
|
|
203
|
+
operationId: pingOptions
|
|
204
|
+
security: []
|
|
205
|
+
# Note: OPTIONS preflight responses never return 4xx by CORS spec design.
|
|
206
|
+
responses:
|
|
207
|
+
'204':
|
|
208
|
+
description: No Content — CORS headers returned.
|
|
209
|
+
headers:
|
|
210
|
+
Access-Control-Allow-Origin:
|
|
211
|
+
schema:
|
|
212
|
+
type: string
|
|
213
|
+
examples:
|
|
214
|
+
- '*'
|
|
215
|
+
Access-Control-Allow-Methods:
|
|
216
|
+
schema:
|
|
217
|
+
type: string
|
|
218
|
+
examples:
|
|
219
|
+
- DELETE, GET, PUT, POST
|
|
220
|
+
Access-Control-Allow-Headers:
|
|
221
|
+
schema:
|
|
222
|
+
type: string
|
|
223
|
+
examples:
|
|
224
|
+
- Authorization, Content-Type
|
|
225
|
+
# ---------------------------------------------------------------------------
|
|
226
|
+
# Bridges — collection
|
|
227
|
+
# ---------------------------------------------------------------------------
|
|
228
|
+
/bridges:
|
|
229
|
+
get:
|
|
230
|
+
operationId: getBridges
|
|
231
|
+
summary: List all bridges
|
|
232
|
+
description: |
|
|
233
|
+
Returns an array of all configured bridges — both **static** (from `gateway.toml`)
|
|
234
|
+
and **dynamic** (created via `POST /bridges`).
|
|
235
|
+
|
|
236
|
+
An empty gateway returns `[]`.
|
|
237
|
+
responses:
|
|
238
|
+
'200':
|
|
239
|
+
description: Array of bridge configurations (may be empty).
|
|
240
|
+
content:
|
|
241
|
+
application/json:
|
|
242
|
+
schema:
|
|
243
|
+
type: array
|
|
244
|
+
items:
|
|
245
|
+
$ref: '#/components/schemas/BridgeResponse'
|
|
246
|
+
examples:
|
|
247
|
+
empty:
|
|
248
|
+
summary: No bridges configured
|
|
249
|
+
value: []
|
|
250
|
+
single_tcp_fasp:
|
|
251
|
+
summary: One TCP→FASP bridge
|
|
252
|
+
value:
|
|
253
|
+
- id: '1'
|
|
254
|
+
name: Bridge-1
|
|
255
|
+
source: dynamic
|
|
256
|
+
local:
|
|
257
|
+
bind_address: 127.0.0.1
|
|
258
|
+
port:
|
|
259
|
+
- 2000
|
|
260
|
+
- 2001
|
|
261
|
+
protocol: tcp
|
|
262
|
+
tls_enabled: false
|
|
263
|
+
forward:
|
|
264
|
+
host:
|
|
265
|
+
- gw2.example.com
|
|
266
|
+
- 10.0.0.2
|
|
267
|
+
port:
|
|
268
|
+
- 3000
|
|
269
|
+
- 3001
|
|
270
|
+
protocol: fasp
|
|
271
|
+
tls_enabled: false
|
|
272
|
+
'401':
|
|
273
|
+
$ref: '#/components/responses/Unauthorized'
|
|
274
|
+
tags:
|
|
275
|
+
- Bridges
|
|
276
|
+
post:
|
|
277
|
+
operationId: createBridge
|
|
278
|
+
summary: Create a new bridge
|
|
279
|
+
description: |
|
|
280
|
+
Creates a new **dynamic** bridge, starts it immediately, and persists it to the
|
|
281
|
+
runtime state file so it survives a gateway restart.
|
|
282
|
+
|
|
283
|
+
### Port syntax
|
|
284
|
+
The `port` field of the request body accepts either:
|
|
285
|
+
- A single port number as a string: `"2000"`
|
|
286
|
+
- A contiguous range: `"2000-2003"` (expands to ports 2000, 2001, 2002, 2003)
|
|
287
|
+
|
|
288
|
+
### Protocol combinations
|
|
289
|
+
| Local protocol | Forward protocol | Description |
|
|
290
|
+
|---------------|-----------------|-------------|
|
|
291
|
+
| `tcp` | `fasp` | Most common: accelerate TCP over FASP |
|
|
292
|
+
| `udp` | `fasp` | Accelerate UDP over FASP |
|
|
293
|
+
| `tcp` | `tcp` | TCP relay (no acceleration) |
|
|
294
|
+
| `udp` | `udp` | UDP relay |
|
|
295
|
+
|
|
296
|
+
### Static bridge limitation
|
|
297
|
+
This endpoint only creates dynamic bridges. Static bridges defined in `gateway.toml`
|
|
298
|
+
cannot be created via the API.
|
|
299
|
+
requestBody:
|
|
300
|
+
description: Bridge configuration to create.
|
|
301
|
+
required: true
|
|
302
|
+
content:
|
|
303
|
+
application/json:
|
|
304
|
+
schema:
|
|
305
|
+
$ref: '#/components/schemas/BridgeRequest'
|
|
306
|
+
examples:
|
|
307
|
+
tcp_to_fasp:
|
|
308
|
+
summary: Forward local TCP traffic over FASP
|
|
309
|
+
value:
|
|
310
|
+
name: Bridge-1
|
|
311
|
+
local:
|
|
312
|
+
bind_address: 127.0.0.1
|
|
313
|
+
port: 2000-2001
|
|
314
|
+
protocol: tcp
|
|
315
|
+
tls_enabled: false
|
|
316
|
+
forward:
|
|
317
|
+
host:
|
|
318
|
+
- gw2.example.com
|
|
319
|
+
- 10.0.0.2
|
|
320
|
+
port: 3000-3001
|
|
321
|
+
protocol: fasp
|
|
322
|
+
tls_enabled: false
|
|
323
|
+
udp_to_fasp:
|
|
324
|
+
summary: Forward local UDP traffic over FASP
|
|
325
|
+
value:
|
|
326
|
+
name: Bridge-UDP
|
|
327
|
+
local:
|
|
328
|
+
bind_address: 0.0.0.0
|
|
329
|
+
port: '4000'
|
|
330
|
+
protocol: udp
|
|
331
|
+
tls_enabled: false
|
|
332
|
+
forward:
|
|
333
|
+
host:
|
|
334
|
+
- 10.0.0.2
|
|
335
|
+
port: '5000'
|
|
336
|
+
protocol: fasp
|
|
337
|
+
tls_enabled: true
|
|
338
|
+
responses:
|
|
339
|
+
'201':
|
|
340
|
+
description: Bridge created and started successfully.
|
|
341
|
+
content:
|
|
342
|
+
application/json:
|
|
343
|
+
schema:
|
|
344
|
+
$ref: '#/components/schemas/BridgeResponse'
|
|
345
|
+
'401':
|
|
346
|
+
$ref: '#/components/responses/Unauthorized'
|
|
347
|
+
'415':
|
|
348
|
+
$ref: '#/components/responses/UnsupportedMediaType'
|
|
349
|
+
'422':
|
|
350
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
351
|
+
'500':
|
|
352
|
+
$ref: '#/components/responses/InternalServerError'
|
|
353
|
+
tags:
|
|
354
|
+
- Bridges
|
|
355
|
+
options:
|
|
356
|
+
tags:
|
|
357
|
+
- Bridges
|
|
358
|
+
summary: CORS preflight for /bridges
|
|
359
|
+
operationId: bridgesOptions
|
|
360
|
+
security: []
|
|
361
|
+
# Note: OPTIONS preflight responses never return 4xx by CORS spec design.
|
|
362
|
+
responses:
|
|
363
|
+
'204':
|
|
364
|
+
description: No Content — CORS headers returned.
|
|
365
|
+
# ---------------------------------------------------------------------------
|
|
366
|
+
# Bridges — single resource
|
|
367
|
+
# ---------------------------------------------------------------------------
|
|
368
|
+
/bridges/{id}:
|
|
369
|
+
parameters:
|
|
370
|
+
- $ref: '#/components/parameters/BridgeId'
|
|
371
|
+
get:
|
|
372
|
+
operationId: getBridgeById
|
|
373
|
+
summary: Get a bridge by ID
|
|
374
|
+
description: |
|
|
375
|
+
Returns the full configuration of a single bridge identified by `id`.
|
|
376
|
+
Works for both static and dynamic bridges.
|
|
377
|
+
responses:
|
|
378
|
+
'200':
|
|
379
|
+
description: Bridge configuration.
|
|
380
|
+
content:
|
|
381
|
+
application/json:
|
|
382
|
+
schema:
|
|
383
|
+
$ref: '#/components/schemas/BridgeResponse'
|
|
384
|
+
example:
|
|
385
|
+
id: '1'
|
|
386
|
+
name: Bridge-1
|
|
387
|
+
source: dynamic
|
|
388
|
+
local:
|
|
389
|
+
bind_address: 127.0.0.1
|
|
390
|
+
port:
|
|
391
|
+
- 2000
|
|
392
|
+
- 2001
|
|
393
|
+
protocol: tcp
|
|
394
|
+
tls_enabled: false
|
|
395
|
+
forward:
|
|
396
|
+
host:
|
|
397
|
+
- gw2.example.com
|
|
398
|
+
port:
|
|
399
|
+
- 3000
|
|
400
|
+
- 3001
|
|
401
|
+
protocol: fasp
|
|
402
|
+
tls_enabled: false
|
|
403
|
+
'400':
|
|
404
|
+
$ref: '#/components/responses/BadRequest'
|
|
405
|
+
'401':
|
|
406
|
+
$ref: '#/components/responses/Unauthorized'
|
|
407
|
+
'404':
|
|
408
|
+
$ref: '#/components/responses/NotFound'
|
|
409
|
+
tags:
|
|
410
|
+
- Bridges
|
|
411
|
+
delete:
|
|
412
|
+
operationId: deleteBridgeById
|
|
413
|
+
summary: Delete a bridge
|
|
414
|
+
description: |
|
|
415
|
+
Stops and removes a **dynamic** bridge by its `id`.
|
|
416
|
+
|
|
417
|
+
- Returns `204 No Content` on success.
|
|
418
|
+
- Returns `403 Forbidden` if the bridge is **static** (defined in `gateway.toml`) —
|
|
419
|
+
static bridges cannot be deleted via the API; edit the configuration file instead.
|
|
420
|
+
- Returns `404 Not Found` if no bridge with the given `id` exists.
|
|
421
|
+
responses:
|
|
422
|
+
'204':
|
|
423
|
+
description: Bridge stopped and deleted successfully. No response body.
|
|
424
|
+
'400':
|
|
425
|
+
$ref: '#/components/responses/BadRequest'
|
|
426
|
+
'401':
|
|
427
|
+
$ref: '#/components/responses/Unauthorized'
|
|
428
|
+
'403':
|
|
429
|
+
$ref: '#/components/responses/Forbidden'
|
|
430
|
+
'404':
|
|
431
|
+
$ref: '#/components/responses/NotFound'
|
|
432
|
+
'500':
|
|
433
|
+
$ref: '#/components/responses/InternalServerError'
|
|
434
|
+
tags:
|
|
435
|
+
- Bridges
|
|
436
|
+
put:
|
|
437
|
+
operationId: updateBridgeById
|
|
438
|
+
summary: Update a bridge (not yet implemented)
|
|
439
|
+
description: |
|
|
440
|
+
**Not implemented.** Reserved for future use.
|
|
441
|
+
|
|
442
|
+
When implemented, this endpoint will update only **dynamic** bridges.
|
|
443
|
+
Attempting to update a **static** bridge will return `403 Forbidden`.
|
|
444
|
+
requestBody:
|
|
445
|
+
required: true
|
|
446
|
+
content:
|
|
447
|
+
application/json:
|
|
448
|
+
schema:
|
|
449
|
+
$ref: '#/components/schemas/BridgeRequest'
|
|
450
|
+
# Note: PUT is not yet implemented — no 2xx response exists by design.
|
|
451
|
+
# The linter warning `operation-2xx-response` is suppressed by design.
|
|
452
|
+
responses:
|
|
453
|
+
'400':
|
|
454
|
+
$ref: '#/components/responses/BadRequest'
|
|
455
|
+
'401':
|
|
456
|
+
$ref: '#/components/responses/Unauthorized'
|
|
457
|
+
'403':
|
|
458
|
+
$ref: '#/components/responses/Forbidden'
|
|
459
|
+
'404':
|
|
460
|
+
$ref: '#/components/responses/NotFound'
|
|
461
|
+
'501':
|
|
462
|
+
description: Not Implemented — this endpoint is reserved for a future release.
|
|
463
|
+
tags:
|
|
464
|
+
- Bridges
|
|
465
|
+
options:
|
|
466
|
+
tags:
|
|
467
|
+
- Bridges
|
|
468
|
+
summary: CORS preflight for /bridges/{id}
|
|
469
|
+
operationId: bridgeByIdOptions
|
|
470
|
+
security: []
|
|
471
|
+
# Note: OPTIONS preflight responses never return 4xx by CORS spec design.
|
|
472
|
+
responses:
|
|
473
|
+
'204':
|
|
474
|
+
description: No Content — CORS headers returned.
|
|
475
|
+
# ---------------------------------------------------------------------------
|
|
476
|
+
# OAuth 2.0 token endpoint
|
|
477
|
+
# ---------------------------------------------------------------------------
|
|
478
|
+
/auth/token:
|
|
479
|
+
post:
|
|
480
|
+
operationId: createAccessToken
|
|
481
|
+
summary: Request an OAuth 2.0 access token
|
|
482
|
+
description: |
|
|
483
|
+
Issues a signed JWT access token using the
|
|
484
|
+
**JWT Bearer grant type** (`urn:ietf:params:oauth:grant-type:jwt-bearer`).
|
|
485
|
+
|
|
486
|
+
The client must supply a signed JWT assertion (signed with the client's private RSA key).
|
|
487
|
+
The gateway verifies the assertion against the configured `jwt_verification_key`, then
|
|
488
|
+
issues a short-lived RS256-signed JWT (default: 1 hour) signed with `jwt_signing_key`.
|
|
489
|
+
|
|
490
|
+
Supports two content types:
|
|
491
|
+
- `application/json` — fields as a JSON object body
|
|
492
|
+
- `application/x-www-form-urlencoded` — fields as URL-encoded form body
|
|
493
|
+
|
|
494
|
+
This endpoint is only available when `rest_api_auth = "oauth2"` is configured in
|
|
495
|
+
`gateway.toml`. It does **not** require a bearer token itself.
|
|
496
|
+
|
|
497
|
+
### JWT assertion requirements
|
|
498
|
+
The JWT assertion must contain:
|
|
499
|
+
- `iss` (issuer): the `client_id` configured in `gateway.toml`
|
|
500
|
+
- `sub` (subject): the `client_id` configured in `gateway.toml`
|
|
501
|
+
- `exp` (expiration): a future timestamp
|
|
502
|
+
|
|
503
|
+
The signature must be verifiable with the public key at `jwt_verification_key`.
|
|
504
|
+
requestBody:
|
|
505
|
+
required: true
|
|
506
|
+
content:
|
|
507
|
+
application/json:
|
|
508
|
+
schema:
|
|
509
|
+
$ref: '#/components/schemas/TokenRequest'
|
|
510
|
+
example:
|
|
511
|
+
grant_type: urn:ietf:params:oauth:grant-type:jwt-bearer
|
|
512
|
+
assertion: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
|
|
513
|
+
client_id: my-gateway-client
|
|
514
|
+
application/x-www-form-urlencoded:
|
|
515
|
+
schema:
|
|
516
|
+
$ref: '#/components/schemas/TokenRequest'
|
|
517
|
+
responses:
|
|
518
|
+
'200':
|
|
519
|
+
description: Access token issued successfully.
|
|
520
|
+
headers:
|
|
521
|
+
Cache-Control:
|
|
522
|
+
description: Always `no-cache`.
|
|
523
|
+
schema:
|
|
524
|
+
type: string
|
|
525
|
+
examples:
|
|
526
|
+
- no-cache
|
|
527
|
+
content:
|
|
528
|
+
application/json:
|
|
529
|
+
schema:
|
|
530
|
+
$ref: '#/components/schemas/TokenResponse'
|
|
531
|
+
'400':
|
|
532
|
+
description: |
|
|
533
|
+
Bad Request — the `grant_type` is not `urn:ietf:params:oauth:grant-type:jwt-bearer`,
|
|
534
|
+
the `assertion` field is empty, or required fields are missing.
|
|
535
|
+
content:
|
|
536
|
+
application/json:
|
|
537
|
+
schema:
|
|
538
|
+
$ref: '#/components/schemas/ErrorResponse'
|
|
539
|
+
'401':
|
|
540
|
+
description: |
|
|
541
|
+
Unauthorized — the JWT assertion failed verification (bad signature, wrong issuer/subject,
|
|
542
|
+
expired token, or missing `exp` claim).
|
|
543
|
+
content:
|
|
544
|
+
application/json:
|
|
545
|
+
schema:
|
|
546
|
+
$ref: '#/components/schemas/ErrorResponse'
|
|
547
|
+
'415':
|
|
548
|
+
$ref: '#/components/responses/UnsupportedMediaType'
|
|
549
|
+
'422':
|
|
550
|
+
$ref: '#/components/responses/UnprocessableEntity'
|
|
551
|
+
security: [] # Token endpoint itself is unauthenticated
|
|
552
|
+
tags:
|
|
553
|
+
- Auth
|
|
554
|
+
# ---------------------------------------------------------------------------
|
|
555
|
+
# Prometheus metrics
|
|
556
|
+
# ---------------------------------------------------------------------------
|
|
557
|
+
/metrics:
|
|
558
|
+
get:
|
|
559
|
+
operationId: getMetrics
|
|
560
|
+
summary: Prometheus metrics
|
|
561
|
+
description: |
|
|
562
|
+
Returns Prometheus-format metrics for all bridges managed by this gateway instance.
|
|
563
|
+
|
|
564
|
+
Supports gzip compression: include `Accept-Encoding: gzip` in the request to receive
|
|
565
|
+
a compressed response (the response will include `Content-Encoding: gzip`).
|
|
566
|
+
|
|
567
|
+
This endpoint is only exposed when `prometheus_enabled = true` in `gateway.toml`.
|
|
568
|
+
It can optionally require HTTP Basic authentication (`prometheus_auth = "basic"`).
|
|
569
|
+
parameters:
|
|
570
|
+
- name: Accept-Encoding
|
|
571
|
+
in: header
|
|
572
|
+
description: Set to `gzip` to receive a compressed response.
|
|
573
|
+
required: false
|
|
574
|
+
schema:
|
|
575
|
+
type: string
|
|
576
|
+
examples:
|
|
577
|
+
- gzip
|
|
578
|
+
responses:
|
|
579
|
+
'200':
|
|
580
|
+
description: Prometheus text exposition format (OpenMetrics 0.0.4 compatible).
|
|
581
|
+
headers:
|
|
582
|
+
Content-Encoding:
|
|
583
|
+
description: Present with value `gzip` when compression was requested and
|
|
584
|
+
applied.
|
|
585
|
+
schema:
|
|
586
|
+
type: string
|
|
587
|
+
examples:
|
|
588
|
+
- gzip
|
|
589
|
+
content:
|
|
590
|
+
text/plain:
|
|
591
|
+
schema:
|
|
592
|
+
description: Prometheus text exposition format, version 0.0.4.
|
|
593
|
+
type: string
|
|
594
|
+
examples:
|
|
595
|
+
- |
|
|
596
|
+
# HELP faspio_bridge_sessions_total Total number of sessions
|
|
597
|
+
# TYPE faspio_bridge_sessions_total counter
|
|
598
|
+
faspio_bridge_sessions_total{bridge="Bridge-1"} 42
|
|
599
|
+
'401':
|
|
600
|
+
$ref: '#/components/responses/Unauthorized'
|
|
601
|
+
'500':
|
|
602
|
+
$ref: '#/components/responses/InternalServerError'
|
|
603
|
+
tags:
|
|
604
|
+
- Metrics
|
|
605
|
+
# =============================================================================
|
|
606
|
+
# Components
|
|
607
|
+
# =============================================================================
|
|
608
|
+
components:
|
|
609
|
+
# ---------------------------------------------------------------------------
|
|
610
|
+
# Parameters
|
|
611
|
+
# ---------------------------------------------------------------------------
|
|
612
|
+
parameters:
|
|
613
|
+
BridgeId:
|
|
614
|
+
name: id
|
|
615
|
+
in: path
|
|
616
|
+
required: true
|
|
617
|
+
description: |
|
|
618
|
+
Unique identifier of the bridge. Bridge IDs are assigned by the gateway at creation time
|
|
619
|
+
and are stable for the lifetime of the gateway process.
|
|
620
|
+
schema:
|
|
621
|
+
type: string
|
|
622
|
+
examples:
|
|
623
|
+
- '1'
|
|
624
|
+
# ---------------------------------------------------------------------------
|
|
625
|
+
# Schemas
|
|
626
|
+
# ---------------------------------------------------------------------------
|
|
627
|
+
schemas:
|
|
628
|
+
# ------------------------------------------------------------------
|
|
629
|
+
# Enumerations (extracted from bridge_config.hpp / rest_api.cpp)
|
|
630
|
+
# ------------------------------------------------------------------
|
|
631
|
+
|
|
632
|
+
Protocol:
|
|
633
|
+
description: |
|
|
634
|
+
Transport protocol used on an abutment:
|
|
635
|
+
- `tcp`: Transmission Control Protocol (reliable, ordered byte stream)
|
|
636
|
+
- `udp`: User Datagram Protocol (unreliable, connectionless datagrams)
|
|
637
|
+
- `fasp`: IBM Aspera FASP (reliable high-speed UDP-based transfer protocol)
|
|
638
|
+
type: string
|
|
639
|
+
examples:
|
|
640
|
+
- fasp
|
|
641
|
+
enum:
|
|
642
|
+
- tcp
|
|
643
|
+
- udp
|
|
644
|
+
- fasp
|
|
645
|
+
BridgeSource:
|
|
646
|
+
description: |
|
|
647
|
+
Indicates the origin of a bridge configuration.
|
|
648
|
+
|
|
649
|
+
| Value | Description |
|
|
650
|
+
|-----------|-------------|
|
|
651
|
+
| `static` | Loaded from `gateway.toml` at startup. Read-only via the API — cannot be deleted or updated. |
|
|
652
|
+
| `dynamic` | Created at runtime via `POST /bridges`. Mutable and persisted to the runtime state file. |
|
|
653
|
+
type: string
|
|
654
|
+
examples:
|
|
655
|
+
- dynamic
|
|
656
|
+
enum:
|
|
657
|
+
- static
|
|
658
|
+
- dynamic
|
|
659
|
+
# ------------------------------------------------------------------
|
|
660
|
+
# Port representation
|
|
661
|
+
# ------------------------------------------------------------------
|
|
662
|
+
|
|
663
|
+
PortList:
|
|
664
|
+
description: |
|
|
665
|
+
Expanded list of port numbers (integers) as returned by the API.
|
|
666
|
+
A request range `"2000-2002"` is expanded to `[2000, 2001, 2002]`.
|
|
667
|
+
type: array
|
|
668
|
+
items:
|
|
669
|
+
type: integer
|
|
670
|
+
format: int32
|
|
671
|
+
minimum: 1
|
|
672
|
+
maximum: 65535
|
|
673
|
+
examples:
|
|
674
|
+
- - 2000
|
|
675
|
+
- 2001
|
|
676
|
+
minItems: 1
|
|
677
|
+
PortRange:
|
|
678
|
+
description: |
|
|
679
|
+
Port or port range string as accepted in request bodies.
|
|
680
|
+
|
|
681
|
+
- Single port: `"2000"`
|
|
682
|
+
- Contiguous range: `"2000-2003"` (inclusive, expands to 4 ports)
|
|
683
|
+
|
|
684
|
+
Port numbers must be between 1 and 65535.
|
|
685
|
+
type: string
|
|
686
|
+
examples:
|
|
687
|
+
- 2000-2001
|
|
688
|
+
pattern: ^\d{1,5}(-\d{1,5})?$
|
|
689
|
+
# ------------------------------------------------------------------
|
|
690
|
+
# Abutment schemas (request / response split)
|
|
691
|
+
# ------------------------------------------------------------------
|
|
692
|
+
|
|
693
|
+
LocalAbutmentRequest:
|
|
694
|
+
description: |
|
|
695
|
+
Configuration of the **local** abutment — the side that accepts incoming connections
|
|
696
|
+
on this gateway node.
|
|
697
|
+
type: object
|
|
698
|
+
properties:
|
|
699
|
+
bind_address:
|
|
700
|
+
description: |
|
|
701
|
+
IP address or hostname that the local abutment binds to.
|
|
702
|
+
Use `"0.0.0.0"` to listen on all interfaces.
|
|
703
|
+
type: string
|
|
704
|
+
examples:
|
|
705
|
+
- 127.0.0.1
|
|
706
|
+
port:
|
|
707
|
+
$ref: '#/components/schemas/PortRange'
|
|
708
|
+
protocol:
|
|
709
|
+
description: |
|
|
710
|
+
Protocol accepted on the local side. Typically `tcp` or `udp`.
|
|
711
|
+
example: tcp
|
|
712
|
+
$ref: '#/components/schemas/Protocol'
|
|
713
|
+
tls_enabled:
|
|
714
|
+
description: |
|
|
715
|
+
When `true`, the local abutment expects TLS-wrapped connections.
|
|
716
|
+
Requires `tls_certificate`, `cert_key` (or a combined `cert_chain`) to be
|
|
717
|
+
configured in `gateway.toml`.
|
|
718
|
+
type: boolean
|
|
719
|
+
examples:
|
|
720
|
+
- false
|
|
721
|
+
required:
|
|
722
|
+
- bind_address
|
|
723
|
+
- port
|
|
724
|
+
- protocol
|
|
725
|
+
- tls_enabled
|
|
726
|
+
ForwardAbutmentRequest:
|
|
727
|
+
description: |
|
|
728
|
+
Configuration of the **forward** abutment — the side that establishes outgoing connections
|
|
729
|
+
to the remote gateway peer.
|
|
730
|
+
type: object
|
|
731
|
+
properties:
|
|
732
|
+
host:
|
|
733
|
+
description: |
|
|
734
|
+
One or more hostnames or IP addresses of the remote peer gateway.
|
|
735
|
+
When multiple hosts are specified, the gateway will attempt each in order as a fallback
|
|
736
|
+
(first host is the primary; remaining hosts are used if the primary is unreachable).
|
|
737
|
+
type: array
|
|
738
|
+
items:
|
|
739
|
+
type: string
|
|
740
|
+
examples:
|
|
741
|
+
- - gw2.example.com
|
|
742
|
+
- 10.0.0.2
|
|
743
|
+
minItems: 1
|
|
744
|
+
bind_address:
|
|
745
|
+
description: |
|
|
746
|
+
Optional local IP address to bind the outgoing connection to.
|
|
747
|
+
When omitted, the OS selects the source address automatically.
|
|
748
|
+
type: string
|
|
749
|
+
examples:
|
|
750
|
+
- 192.168.1.10
|
|
751
|
+
port:
|
|
752
|
+
$ref: '#/components/schemas/PortRange'
|
|
753
|
+
protocol:
|
|
754
|
+
description: |
|
|
755
|
+
Protocol used to connect to the remote peer. Typically `fasp` for acceleration.
|
|
756
|
+
example: fasp
|
|
757
|
+
$ref: '#/components/schemas/Protocol'
|
|
758
|
+
tls_enabled:
|
|
759
|
+
description: |
|
|
760
|
+
When `true`, the outgoing connection to the remote peer is TLS-wrapped.
|
|
761
|
+
type: boolean
|
|
762
|
+
examples:
|
|
763
|
+
- false
|
|
764
|
+
required:
|
|
765
|
+
- host
|
|
766
|
+
- port
|
|
767
|
+
- protocol
|
|
768
|
+
- tls_enabled
|
|
769
|
+
LocalAbutmentResponse:
|
|
770
|
+
description: Local abutment as returned by the API (ports expanded to an integer
|
|
771
|
+
array).
|
|
772
|
+
type: object
|
|
773
|
+
properties:
|
|
774
|
+
bind_address:
|
|
775
|
+
type: string
|
|
776
|
+
examples:
|
|
777
|
+
- 127.0.0.1
|
|
778
|
+
port:
|
|
779
|
+
$ref: '#/components/schemas/PortList'
|
|
780
|
+
protocol:
|
|
781
|
+
$ref: '#/components/schemas/Protocol'
|
|
782
|
+
tls_enabled:
|
|
783
|
+
type: boolean
|
|
784
|
+
examples:
|
|
785
|
+
- false
|
|
786
|
+
required:
|
|
787
|
+
- bind_address
|
|
788
|
+
- port
|
|
789
|
+
- protocol
|
|
790
|
+
- tls_enabled
|
|
791
|
+
ForwardAbutmentResponse:
|
|
792
|
+
description: Forward abutment as returned by the API (ports expanded to an
|
|
793
|
+
integer array).
|
|
794
|
+
type: object
|
|
795
|
+
properties:
|
|
796
|
+
bind_address:
|
|
797
|
+
description: Local bind address for the outgoing connection, if configured.
|
|
798
|
+
type: string
|
|
799
|
+
examples:
|
|
800
|
+
- 192.168.1.10
|
|
801
|
+
host:
|
|
802
|
+
description: List of remote peer hostnames / IP addresses.
|
|
803
|
+
type: array
|
|
804
|
+
items:
|
|
805
|
+
type: string
|
|
806
|
+
examples:
|
|
807
|
+
- - gw2.example.com
|
|
808
|
+
- 10.0.0.2
|
|
809
|
+
port:
|
|
810
|
+
$ref: '#/components/schemas/PortList'
|
|
811
|
+
protocol:
|
|
812
|
+
$ref: '#/components/schemas/Protocol'
|
|
813
|
+
tls_enabled:
|
|
814
|
+
type: boolean
|
|
815
|
+
examples:
|
|
816
|
+
- false
|
|
817
|
+
required:
|
|
818
|
+
- host
|
|
819
|
+
- port
|
|
820
|
+
- protocol
|
|
821
|
+
- tls_enabled
|
|
822
|
+
# ------------------------------------------------------------------
|
|
823
|
+
# Bridge schemas
|
|
824
|
+
# ------------------------------------------------------------------
|
|
825
|
+
|
|
826
|
+
BridgeRequest:
|
|
827
|
+
description: |
|
|
828
|
+
Payload for creating a new bridge via `POST /bridges`.
|
|
829
|
+
|
|
830
|
+
The gateway generates the `id` automatically. The `source` field is always set to
|
|
831
|
+
`dynamic` for bridges created via the API.
|
|
832
|
+
type: object
|
|
833
|
+
properties:
|
|
834
|
+
name:
|
|
835
|
+
description: |
|
|
836
|
+
Human-readable label for the bridge. Does not have to be unique,
|
|
837
|
+
but a descriptive name helps with monitoring and troubleshooting.
|
|
838
|
+
type: string
|
|
839
|
+
examples:
|
|
840
|
+
- Bridge-1
|
|
841
|
+
minLength: 1
|
|
842
|
+
local:
|
|
843
|
+
$ref: '#/components/schemas/LocalAbutmentRequest'
|
|
844
|
+
forward:
|
|
845
|
+
$ref: '#/components/schemas/ForwardAbutmentRequest'
|
|
846
|
+
required:
|
|
847
|
+
- name
|
|
848
|
+
- local
|
|
849
|
+
- forward
|
|
850
|
+
BridgeResponse:
|
|
851
|
+
description: Full bridge configuration as returned by `GET /bridges` and `GET
|
|
852
|
+
/bridges/{id}`.
|
|
853
|
+
type: object
|
|
854
|
+
properties:
|
|
855
|
+
id:
|
|
856
|
+
description: |
|
|
857
|
+
Gateway-assigned unique identifier for this bridge.
|
|
858
|
+
Stable for the lifetime of the gateway process.
|
|
859
|
+
type: string
|
|
860
|
+
examples:
|
|
861
|
+
- '1'
|
|
862
|
+
name:
|
|
863
|
+
description: Human-readable label for the bridge.
|
|
864
|
+
type: string
|
|
865
|
+
examples:
|
|
866
|
+
- Bridge-1
|
|
867
|
+
source:
|
|
868
|
+
$ref: '#/components/schemas/BridgeSource'
|
|
869
|
+
local:
|
|
870
|
+
$ref: '#/components/schemas/LocalAbutmentResponse'
|
|
871
|
+
forward:
|
|
872
|
+
$ref: '#/components/schemas/ForwardAbutmentResponse'
|
|
873
|
+
required:
|
|
874
|
+
- id
|
|
875
|
+
- name
|
|
876
|
+
- source
|
|
877
|
+
- local
|
|
878
|
+
- forward
|
|
879
|
+
# ------------------------------------------------------------------
|
|
880
|
+
# OAuth 2.0
|
|
881
|
+
# ------------------------------------------------------------------
|
|
882
|
+
|
|
883
|
+
TokenRequest:
|
|
884
|
+
description: OAuth 2.0 token request body (JWT Bearer grant).
|
|
885
|
+
type: object
|
|
886
|
+
properties:
|
|
887
|
+
grant_type:
|
|
888
|
+
description: |
|
|
889
|
+
Must be `urn:ietf:params:oauth:grant-type:jwt-bearer` (RFC 7523).
|
|
890
|
+
type: string
|
|
891
|
+
examples:
|
|
892
|
+
- urn:ietf:params:oauth:grant-type:jwt-bearer
|
|
893
|
+
const: urn:ietf:params:oauth:grant-type:jwt-bearer
|
|
894
|
+
assertion:
|
|
895
|
+
description: |
|
|
896
|
+
A signed JWT (JWS) assertion issued by the client.
|
|
897
|
+
|
|
898
|
+
The JWT must contain:
|
|
899
|
+
- `iss`: the `client_id` configured in `gateway.toml`
|
|
900
|
+
- `sub`: the `client_id` configured in `gateway.toml`
|
|
901
|
+
- `exp`: a future expiry timestamp
|
|
902
|
+
|
|
903
|
+
The signature must be an RS256 signature verifiable with the public key
|
|
904
|
+
at `jwt_verification_key` in `gateway.toml`.
|
|
905
|
+
type: string
|
|
906
|
+
examples:
|
|
907
|
+
- eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJteS1jbGllbnQiLCJzdWIiOiJteS1jbGllbnQiLCJleHAiOjE3MDAwMDAwMDB9.signature
|
|
908
|
+
client_id:
|
|
909
|
+
description: |
|
|
910
|
+
Optional. The OAuth 2.0 client identifier. When provided, it is validated
|
|
911
|
+
against the `client_id` value in `gateway.toml`. If omitted, the `iss`/`sub`
|
|
912
|
+
claims of the assertion are used for validation.
|
|
913
|
+
type: string
|
|
914
|
+
examples:
|
|
915
|
+
- my-gateway-client
|
|
916
|
+
required:
|
|
917
|
+
- grant_type
|
|
918
|
+
- assertion
|
|
919
|
+
TokenResponse:
|
|
920
|
+
description: Successful OAuth 2.0 token response.
|
|
921
|
+
type: object
|
|
922
|
+
properties:
|
|
923
|
+
access_token:
|
|
924
|
+
description: |
|
|
925
|
+
RS256-signed JWT access token. Include this in the `Authorization: Bearer <token>`
|
|
926
|
+
header for subsequent API calls.
|
|
927
|
+
type: string
|
|
928
|
+
examples:
|
|
929
|
+
- eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
|
|
930
|
+
token_type:
|
|
931
|
+
description: Always `Bearer`.
|
|
932
|
+
type: string
|
|
933
|
+
examples:
|
|
934
|
+
- Bearer
|
|
935
|
+
const: Bearer
|
|
936
|
+
expires_in:
|
|
937
|
+
description: Token lifetime in seconds. Default is 3600 (1 hour).
|
|
938
|
+
type: integer
|
|
939
|
+
format: int64
|
|
940
|
+
examples:
|
|
941
|
+
- 3600
|
|
942
|
+
required:
|
|
943
|
+
- access_token
|
|
944
|
+
- token_type
|
|
945
|
+
- expires_in
|
|
946
|
+
# ------------------------------------------------------------------
|
|
947
|
+
# Error schema
|
|
948
|
+
# ------------------------------------------------------------------
|
|
949
|
+
|
|
950
|
+
ErrorResponse:
|
|
951
|
+
description: |
|
|
952
|
+
Generic error response body. Not all error responses include a body —
|
|
953
|
+
some HTTP status codes (for example, 204, 404) may return no content.
|
|
954
|
+
type: object
|
|
955
|
+
properties:
|
|
956
|
+
message:
|
|
957
|
+
description: Human-readable error description.
|
|
958
|
+
type: string
|
|
959
|
+
examples:
|
|
960
|
+
- bridge not found
|
|
961
|
+
required:
|
|
962
|
+
- message
|
|
963
|
+
# ---------------------------------------------------------------------------
|
|
964
|
+
# Reusable responses
|
|
965
|
+
# ---------------------------------------------------------------------------
|
|
966
|
+
responses:
|
|
967
|
+
BadRequest:
|
|
968
|
+
description: |
|
|
969
|
+
Bad Request — the request could not be parsed or the path parameter is invalid.
|
|
970
|
+
content:
|
|
971
|
+
application/json:
|
|
972
|
+
schema:
|
|
973
|
+
$ref: '#/components/schemas/ErrorResponse'
|
|
974
|
+
example:
|
|
975
|
+
message: invalid bridge id
|
|
976
|
+
Unauthorized:
|
|
977
|
+
description: |
|
|
978
|
+
Unauthorized — no credentials were provided, or the provided credentials are invalid.
|
|
979
|
+
|
|
980
|
+
The response includes a `WWW-Authenticate` header indicating the expected scheme:
|
|
981
|
+
- Basic auth: `WWW-Authenticate: Basic realm="faspio Gateway API", charset="utf-8"`
|
|
982
|
+
- Bearer auth: `WWW-Authenticate: Bearer realm="Bridges", charset="utf-8"`
|
|
983
|
+
headers:
|
|
984
|
+
WWW-Authenticate:
|
|
985
|
+
schema:
|
|
986
|
+
type: string
|
|
987
|
+
example: Basic realm="faspio Gateway API", charset="utf-8"
|
|
988
|
+
content:
|
|
989
|
+
text/plain:
|
|
990
|
+
schema:
|
|
991
|
+
type: string
|
|
992
|
+
example: Unauthorized
|
|
993
|
+
Forbidden:
|
|
994
|
+
description: |
|
|
995
|
+
Forbidden — the operation is not permitted on this resource.
|
|
996
|
+
This is returned when attempting to delete or update a **static** bridge
|
|
997
|
+
(one loaded from `gateway.toml`). Static bridges are immutable via the API.
|
|
998
|
+
content:
|
|
999
|
+
application/json:
|
|
1000
|
+
schema:
|
|
1001
|
+
$ref: '#/components/schemas/ErrorResponse'
|
|
1002
|
+
example:
|
|
1003
|
+
message: cannot delete static bridge via REST API
|
|
1004
|
+
NotFound:
|
|
1005
|
+
description: Not Found — no bridge with the given `id` exists.
|
|
1006
|
+
content:
|
|
1007
|
+
application/json:
|
|
1008
|
+
schema:
|
|
1009
|
+
$ref: '#/components/schemas/ErrorResponse'
|
|
1010
|
+
example:
|
|
1011
|
+
message: bridge not found
|
|
1012
|
+
UnsupportedMediaType:
|
|
1013
|
+
description: |
|
|
1014
|
+
Unsupported Media Type — the `Content-Type` header is missing or not
|
|
1015
|
+
`application/json` (or `application/x-www-form-urlencoded` for the token endpoint).
|
|
1016
|
+
content:
|
|
1017
|
+
application/json:
|
|
1018
|
+
schema:
|
|
1019
|
+
$ref: '#/components/schemas/ErrorResponse'
|
|
1020
|
+
example:
|
|
1021
|
+
message: Content-Type must be application/json
|
|
1022
|
+
UnprocessableEntity:
|
|
1023
|
+
description: |
|
|
1024
|
+
Unprocessable Entity — the request body is syntactically valid JSON but
|
|
1025
|
+
semantically incorrect (for example, a required field is missing, an enum value is
|
|
1026
|
+
unrecognized, or a port range is malformed).
|
|
1027
|
+
content:
|
|
1028
|
+
application/json:
|
|
1029
|
+
schema:
|
|
1030
|
+
$ref: '#/components/schemas/ErrorResponse'
|
|
1031
|
+
example:
|
|
1032
|
+
message: "JSON parse error: [json.exception.out_of_range.403] key 'name' not
|
|
1033
|
+
found"
|
|
1034
|
+
InternalServerError:
|
|
1035
|
+
description: Internal Server Error — an unexpected error occurred in the gateway.
|
|
1036
|
+
content:
|
|
1037
|
+
application/json:
|
|
1038
|
+
schema:
|
|
1039
|
+
$ref: '#/components/schemas/ErrorResponse'
|
|
1040
|
+
example:
|
|
1041
|
+
message: unexpected error creating bridge
|
|
1042
|
+
# ---------------------------------------------------------------------------
|
|
1043
|
+
# Security schemes
|
|
1044
|
+
# ---------------------------------------------------------------------------
|
|
1045
|
+
securitySchemes:
|
|
1046
|
+
basicAuth:
|
|
1047
|
+
type: http
|
|
1048
|
+
scheme: basic
|
|
1049
|
+
description: |
|
|
1050
|
+
HTTP Basic Authentication. The password is stored as a SHA-512 or PBKDF2 digest
|
|
1051
|
+
in `gateway.toml` under `[admin.basic_auth]`. Configure with:
|
|
1052
|
+
```toml
|
|
1053
|
+
[admin]
|
|
1054
|
+
rest_api_auth = "basic"
|
|
1055
|
+
[admin.basic_auth]
|
|
1056
|
+
username = "admin"
|
|
1057
|
+
password_digest = "<sha512-or-pbkdf2-hash>"
|
|
1058
|
+
```
|
|
1059
|
+
bearerAuth:
|
|
1060
|
+
type: http
|
|
1061
|
+
scheme: bearer
|
|
1062
|
+
bearerFormat: JWT
|
|
1063
|
+
description: |
|
|
1064
|
+
OAuth 2.0 Bearer token (RS256-signed JWT). Obtain a token from `POST /auth/token`
|
|
1065
|
+
using the JWT Bearer grant type. Configure the gateway with:
|
|
1066
|
+
```toml
|
|
1067
|
+
[admin]
|
|
1068
|
+
rest_api_auth = "oauth2"
|
|
1069
|
+
[admin.oauth2]
|
|
1070
|
+
client_id = "my-gateway-client"
|
|
1071
|
+
jwt_grant_enabled = true
|
|
1072
|
+
jwt_verification_key = "/etc/faspio-gateway/client_public.pem"
|
|
1073
|
+
jwt_signing_key = "/etc/faspio-gateway/server_private.pem"
|
|
1074
|
+
```
|
|
1075
|
+
tags:
|
|
1076
|
+
- name: Health
|
|
1077
|
+
description: Liveness probe — verify that the gateway process is reachable.
|
|
1078
|
+
- name: Bridges
|
|
1079
|
+
description: |
|
|
1080
|
+
Create and manage network bridges.
|
|
1081
|
+
A **bridge** is a bidirectional pipe that accepts connections on a local abutment (TCP or UDP)
|
|
1082
|
+
and forwards them to a remote peer via a forward abutment (FASP, TCP, or UDP).
|
|
1083
|
+
- name: Auth
|
|
1084
|
+
description: |
|
|
1085
|
+
OAuth 2.0 token endpoint. Only available when `rest_api_auth = "oauth2"` is set in `gateway.toml`.
|
|
1086
|
+
Uses the JWT Bearer grant type (`urn:ietf:params:oauth:grant-type:jwt-bearer`).
|
|
1087
|
+
- name: Metrics
|
|
1088
|
+
description: |
|
|
1089
|
+
Prometheus-compatible metrics endpoint. Only available when `prometheus_enabled = true`
|
|
1090
|
+
in `gateway.toml`. Supports gzip compression via `Accept-Encoding: gzip`.
|
|
1091
|
+
externalDocs:
|
|
1092
|
+
description: IBM Aspera faspio Gateway — Official Documentation
|
|
1093
|
+
url: https://www.ibm.com/docs/en/faspio-gateway
|
|
1094
|
+
security:
|
|
1095
|
+
- basicAuth: []
|
|
1096
|
+
- bearerAuth: []
|
|
1097
|
+
- {}
|