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
|
@@ -29,6 +29,98 @@ components:
|
|
|
29
29
|
type: boolean
|
|
30
30
|
description: Show passwords and secrets in logs.
|
|
31
31
|
default: false
|
|
32
|
+
UiOptions:
|
|
33
|
+
type: object
|
|
34
|
+
description: >-
|
|
35
|
+
User interface: how URLs to open, secrets and files are presented to the user.
|
|
36
|
+
A plain value, e.g. `--ui=terminal`, is the `mode`.
|
|
37
|
+
additionalProperties: false
|
|
38
|
+
properties:
|
|
39
|
+
mode:
|
|
40
|
+
type: string
|
|
41
|
+
description: >-
|
|
42
|
+
`auto`: `browser` on Windows and macOS, or if env var `DISPLAY` is set, else `terminal`.
|
|
43
|
+
`terminal`: URLs and files to open are displayed on terminal, and secrets are entered on terminal.
|
|
44
|
+
`browser`: a browser opens URLs, secrets are entered on a web page, and a text editor opens files.
|
|
45
|
+
`text` is an alias for `terminal`, and `graphical` is an alias for `browser`.
|
|
46
|
+
enum:
|
|
47
|
+
- auto
|
|
48
|
+
- terminal
|
|
49
|
+
- browser
|
|
50
|
+
- text
|
|
51
|
+
- graphical
|
|
52
|
+
default: auto
|
|
53
|
+
command:
|
|
54
|
+
type: array
|
|
55
|
+
description: >-
|
|
56
|
+
Command that opens a URL, instead of the system default.
|
|
57
|
+
First item is the executable, then its arguments. The URL is added as last argument.
|
|
58
|
+
When set, it is used to open URLs, whatever the `mode`.
|
|
59
|
+
items:
|
|
60
|
+
type: string
|
|
61
|
+
SecurityOptions:
|
|
62
|
+
type: object
|
|
63
|
+
description: >-
|
|
64
|
+
Restrictions of the features that access local resources or execute code.
|
|
65
|
+
On the command line, the default level is `low`.
|
|
66
|
+
In MCP server mode, the default level is `high`, and commands of the client cannot change the security options.
|
|
67
|
+
additionalProperties: false
|
|
68
|
+
properties:
|
|
69
|
+
level:
|
|
70
|
+
type: string
|
|
71
|
+
description: >-
|
|
72
|
+
`low`: no restriction.
|
|
73
|
+
`medium`: `@file:` reads only files in `allowed_paths`, `@ruby:`, `@uri:` and `@env:` are refused.
|
|
74
|
+
`high`: `@ruby:`, `@file:`, `@uri:` and `@env:` are refused.
|
|
75
|
+
enum:
|
|
76
|
+
- low
|
|
77
|
+
- medium
|
|
78
|
+
- high
|
|
79
|
+
allowed_paths:
|
|
80
|
+
type: array
|
|
81
|
+
description: >-
|
|
82
|
+
With level `medium`: files and folders that `@file:` can read.
|
|
83
|
+
A symbolic link leading outside of them is refused.
|
|
84
|
+
items:
|
|
85
|
+
type: string
|
|
86
|
+
TempOptions:
|
|
87
|
+
type: object
|
|
88
|
+
description: >-
|
|
89
|
+
Temporary files.
|
|
90
|
+
A plain value, e.g. `--temp=/tmp`, is the `folder`.
|
|
91
|
+
additionalProperties: false
|
|
92
|
+
properties:
|
|
93
|
+
folder:
|
|
94
|
+
type: string
|
|
95
|
+
description: >-
|
|
96
|
+
Folder for temporary files, e.g. certificate for WSS transfers, logs of `transferd`.
|
|
97
|
+
`@sys`: temporary folder of the system for the current user (Ruby `Etc.systmpdir`).
|
|
98
|
+
`@env`: from environment variables, e.g. `TMPDIR` (Ruby `Dir.tmpdir`).
|
|
99
|
+
default: '@sys'
|
|
100
|
+
clean:
|
|
101
|
+
type: boolean
|
|
102
|
+
description: >-
|
|
103
|
+
Delete temporary files created by the command when it ends.
|
|
104
|
+
`false` keeps them, e.g. for debugging.
|
|
105
|
+
Files left by previous commands are still deleted according to `expiry`.
|
|
106
|
+
default: true
|
|
107
|
+
expiry:
|
|
108
|
+
oneOf:
|
|
109
|
+
- type: string
|
|
110
|
+
- type: number
|
|
111
|
+
minimum: 0
|
|
112
|
+
- type: boolean
|
|
113
|
+
enum:
|
|
114
|
+
- false
|
|
115
|
+
description: >-
|
|
116
|
+
Age after which file lists of `ascp` left by previous commands (e.g. interrupted) are deleted, when a command starts.
|
|
117
|
+
They are in folder `filelists` of the main folder (option `home`).
|
|
118
|
+
A duration, e.g. `5d`, `12h`, `1w`, `1h 30m`, `1d 02:00:00`, a plain number is seconds.
|
|
119
|
+
`false` or `null` (`@none:`): never delete them.
|
|
120
|
+
`0`: delete all of them, including file lists of transfers in progress in other executions of ascli.
|
|
121
|
+
Such a transfer fails if `ascp` reads its file list again: next session of a multi-session transfer, or resume after an error.
|
|
122
|
+
Use `0` only when no other transfer is in progress, not in a permanent configuration.
|
|
123
|
+
default: 5d
|
|
32
124
|
McpServerOptions:
|
|
33
125
|
type: object
|
|
34
126
|
description: MCP server configuration for the `mcp server` command.
|
|
@@ -51,14 +143,60 @@ components:
|
|
|
51
143
|
type: integer
|
|
52
144
|
description: Maximum JSON frame size for stdio transport.
|
|
53
145
|
default: 4194304
|
|
146
|
+
url:
|
|
147
|
+
type: string
|
|
148
|
+
description: >-
|
|
149
|
+
Address and port the HTTP transport listens on, without path.
|
|
150
|
+
Use `https://` for TLS, with `cert` and `key`.
|
|
151
|
+
default: http://127.0.0.1:3000
|
|
152
|
+
cert:
|
|
153
|
+
$ref: "#/components/schemas/WebServerOptions/properties/cert"
|
|
154
|
+
key:
|
|
155
|
+
$ref: "#/components/schemas/WebServerOptions/properties/key"
|
|
156
|
+
chain:
|
|
157
|
+
$ref: "#/components/schemas/WebServerOptions/properties/chain"
|
|
54
158
|
port:
|
|
55
159
|
type: integer
|
|
56
|
-
description: TCP port for HTTP transport.
|
|
57
|
-
default: 3000
|
|
160
|
+
description: "Deprecated: use `url`. TCP port for HTTP transport."
|
|
58
161
|
bind:
|
|
59
162
|
type: string
|
|
60
|
-
description: Bind address for HTTP transport.
|
|
61
|
-
|
|
163
|
+
description: "Deprecated: use `url`. Bind address for HTTP transport."
|
|
164
|
+
public_url:
|
|
165
|
+
type: string
|
|
166
|
+
description: >-
|
|
167
|
+
URL of the server for clients, used in OAuth metadata and in the URL of secret pages (`@secret:`), for example `http://myhost:3000`.
|
|
168
|
+
|
|
169
|
+
Default: built from `url`. Mandatory with `oauth` when `url` has host `0.0.0.0` or `::`.
|
|
170
|
+
auth_token:
|
|
171
|
+
type: string
|
|
172
|
+
description: >-
|
|
173
|
+
Bearer token required in the `Authorization` header of HTTP requests.
|
|
174
|
+
It is also the access code asked on the secret pages (`@secret:`), and on the consent page with `oauth`.
|
|
175
|
+
|
|
176
|
+
If not set, HTTP requests are not authenticated.
|
|
177
|
+
Mandatory when the host of `url` or `public_url` is not loopback.
|
|
178
|
+
Generate it with `openssl rand -hex 32`: a weak token is refused (see `auth_token_min_bits`).
|
|
179
|
+
auth_token_min_bits:
|
|
180
|
+
type: integer
|
|
181
|
+
minimum: 0
|
|
182
|
+
default: 80
|
|
183
|
+
description: >-
|
|
184
|
+
Minimum estimated strength of `auth_token`, in bits (log2 of the number of guesses to find it).
|
|
185
|
+
The strength is estimated with gem `zxcvbn` if installed, else with a built-in estimate
|
|
186
|
+
that detects repeats, sequences, keyboard rows, words and years.
|
|
187
|
+
`0` disables the check.
|
|
188
|
+
oauth:
|
|
189
|
+
type: boolean
|
|
190
|
+
description: Enable OAuth 2.0 PKCE flow with dynamic client registration.
|
|
191
|
+
default: false
|
|
192
|
+
oauth_access_token_ttl:
|
|
193
|
+
type: integer
|
|
194
|
+
description: OAuth access token lifetime in seconds.
|
|
195
|
+
default: 3600
|
|
196
|
+
oauth_refresh_token_ttl:
|
|
197
|
+
type: integer
|
|
198
|
+
description: OAuth refresh token lifetime in seconds.
|
|
199
|
+
default: 2592000
|
|
62
200
|
stateless:
|
|
63
201
|
type: boolean
|
|
64
202
|
description: Run HTTP transport in stateless mode.
|
|
@@ -419,7 +557,8 @@ components:
|
|
|
419
557
|
enum: [system]
|
|
420
558
|
name:
|
|
421
559
|
type: string
|
|
422
|
-
description: Name of the keychain to use.
|
|
560
|
+
description: Name of the keychain to use (file `<name>.keychain-db` in the keychain search list).
|
|
561
|
+
default: ascli
|
|
423
562
|
VaultOnePasswordOptions:
|
|
424
563
|
type: object
|
|
425
564
|
description: 1Password secret store (Connect REST API or CLI).
|
|
@@ -518,8 +657,9 @@ components:
|
|
|
518
657
|
default: false
|
|
519
658
|
double:
|
|
520
659
|
type: boolean
|
|
521
|
-
description:
|
|
522
|
-
|
|
660
|
+
description: >-
|
|
661
|
+
Use double vertical resolution via half-block characters (Unicode).
|
|
662
|
+
Default is `true` if the terminal supports Unicode (see `utf8`).
|
|
523
663
|
font_ratio:
|
|
524
664
|
type: number
|
|
525
665
|
format: float
|
|
@@ -647,11 +787,24 @@ components:
|
|
|
647
787
|
Username expected from clients in HTTP Basic authentication.
|
|
648
788
|
Set together with `password`.
|
|
649
789
|
When not set, requests are accepted without authentication.
|
|
790
|
+
Mandatory when `url` is not a loopback address (`localhost`, `127.0.0.0/8`, `::1`).
|
|
650
791
|
example: node_user
|
|
651
792
|
password:
|
|
652
793
|
type: string
|
|
653
|
-
description:
|
|
794
|
+
description: >-
|
|
795
|
+
Password expected from clients in HTTP Basic authentication, for the above `username`.
|
|
796
|
+
Generate it with `openssl rand -hex 32`: a weak password is refused (see `password_min_bits`).
|
|
654
797
|
example: my_password
|
|
798
|
+
password_min_bits:
|
|
799
|
+
type: integer
|
|
800
|
+
minimum: 0
|
|
801
|
+
default: 80
|
|
802
|
+
description: >-
|
|
803
|
+
Minimum estimated strength of `password`, in bits (log2 of the number of guesses to find it).
|
|
804
|
+
The strength is estimated with gem `zxcvbn` if installed, else with a built-in estimate
|
|
805
|
+
that detects repeats, sequences, keyboard rows, words and years.
|
|
806
|
+
`0` disables the check.
|
|
807
|
+
A random password of 32 bytes (`openssl rand -hex 32`) is far above the default.
|
|
655
808
|
NodeTelemetryOptions:
|
|
656
809
|
type: object
|
|
657
810
|
description: >-
|
|
@@ -713,40 +866,88 @@ components:
|
|
|
713
866
|
Valid keys are defined by the workflow's input specification.
|
|
714
867
|
Use `orchestrator workflows inputs WORKFLOW_ID` to discover required parameters.
|
|
715
868
|
additionalProperties: true
|
|
716
|
-
|
|
869
|
+
OrchestratorWorkflowExport:
|
|
717
870
|
type: object
|
|
718
|
-
description:
|
|
719
|
-
|
|
720
|
-
- name
|
|
871
|
+
description: Options of `orchestrator workflows export`.
|
|
872
|
+
additionalProperties: false
|
|
721
873
|
properties:
|
|
722
|
-
|
|
723
|
-
type:
|
|
724
|
-
description:
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
874
|
+
dependencies:
|
|
875
|
+
type: boolean
|
|
876
|
+
description: >-
|
|
877
|
+
Export the sub-workflows and remote nodes used by the workflow in a package (`.wkf`),
|
|
878
|
+
saved in the folder given by option `to_folder` (default: current folder), instead of displaying the workflow.
|
|
879
|
+
default: false
|
|
880
|
+
OrchestratorWorkflowImport:
|
|
881
|
+
type: object
|
|
882
|
+
description: Options of `orchestrator workflows import`.
|
|
883
|
+
additionalProperties: false
|
|
884
|
+
properties:
|
|
885
|
+
folder_id:
|
|
886
|
+
type: integer
|
|
887
|
+
description: >-
|
|
888
|
+
Folder of the new workflow (default: the default folder).
|
|
889
|
+
The `folder_id` of existing workflows is in `orchestrator workflows list`.
|
|
890
|
+
publish:
|
|
891
|
+
type: boolean
|
|
892
|
+
description: >-
|
|
893
|
+
Publish the workflow after import.
|
|
894
|
+
If not set, the server option `publish_api_imported_workflow` decides.
|
|
895
|
+
link_to_subworkflows:
|
|
896
|
+
type: boolean
|
|
897
|
+
description: Link to existing sub-workflows instead of importing those of the package (`.wkf`).
|
|
898
|
+
default: false
|
|
733
899
|
OrchestratorImportWithConstraints:
|
|
734
900
|
type: object
|
|
735
|
-
description:
|
|
901
|
+
description: >-
|
|
902
|
+
Import of a workflow file present on the Orchestrator host, as a new workflow or as a new revision of an existing workflow.
|
|
903
|
+
`orchestrator workflows import` stores each uploaded file in `<run_dir>/workflows/import/`.
|
|
904
|
+
Conflicts with existing global templates, sub-workflows and remote nodes are resolved by name.
|
|
905
|
+
Use `orchestrator workflows find_constraints` to list the conflicts, and `orchestrator workflows check_import` to check the file beforehand.
|
|
906
|
+
additionalProperties: false
|
|
736
907
|
required:
|
|
737
|
-
-
|
|
738
|
-
- constraints
|
|
908
|
+
- filename
|
|
739
909
|
properties:
|
|
740
|
-
|
|
910
|
+
filename:
|
|
911
|
+
type: string
|
|
912
|
+
description: Path of the workflow file (`.yml` or `.wkf`) on the Orchestrator host.
|
|
913
|
+
example: /opt/aspera/orchestrator/var/run/orchestrator/workflows/import/my_workflow.yml
|
|
914
|
+
add_as_revision:
|
|
915
|
+
type: integer
|
|
916
|
+
description: >-
|
|
917
|
+
ID of an existing workflow: the file is imported as a new revision of this workflow (to be published).
|
|
918
|
+
If not set, a new workflow is created.
|
|
919
|
+
example: 123
|
|
920
|
+
subwf_constraints:
|
|
741
921
|
type: object
|
|
742
|
-
description:
|
|
743
|
-
|
|
922
|
+
description: 'Resolution for each sub-workflow, by name: `Map to the Existing Sub-Workflow`, `Create a new Sub-Workflow with a unique name`, or `Add a new revision to the existing Sub-Workflow`.'
|
|
923
|
+
additionalProperties:
|
|
924
|
+
type: string
|
|
925
|
+
enum:
|
|
926
|
+
- Map to the Existing Sub-Workflow
|
|
927
|
+
- Create a new Sub-Workflow with a unique name
|
|
928
|
+
- Add a new revision to the existing Sub-Workflow
|
|
929
|
+
action_template_constraints:
|
|
744
930
|
type: object
|
|
745
|
-
description:
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
931
|
+
description: 'Resolution for each global action template, by name: `Map to the existing Global Template`, `Create a new Global Template with a different name`, or `Override the existing Global Template with this new template`.'
|
|
932
|
+
additionalProperties:
|
|
933
|
+
type: string
|
|
934
|
+
enum:
|
|
935
|
+
- Map to the existing Global Template
|
|
936
|
+
- Create a new Global Template with a different name
|
|
937
|
+
- Override the existing Global Template with this new template
|
|
938
|
+
remote_node_constraints:
|
|
939
|
+
type: object
|
|
940
|
+
description: 'Resolution for each remote node, by name: `Map to the existing Remote Node`, `Create a new Remote Node with a different name`, or `Override the Existing Remote Node with this importing node`.'
|
|
941
|
+
additionalProperties:
|
|
942
|
+
type: string
|
|
943
|
+
enum:
|
|
944
|
+
- Map to the existing Remote Node
|
|
945
|
+
- Create a new Remote Node with a different name
|
|
946
|
+
- Override the Existing Remote Node with this importing node
|
|
947
|
+
auto_enable_missing_plugins:
|
|
948
|
+
type: boolean
|
|
949
|
+
description: Enable the plugins used by the workflow that are not enabled.
|
|
950
|
+
default: false
|
|
750
951
|
OrchestratorReloadPluginSet:
|
|
751
952
|
type: object
|
|
752
953
|
description: Set of plugins to reload.
|
|
@@ -792,8 +993,13 @@ components:
|
|
|
792
993
|
`ALL` for all fields, `DEF` for default fields.
|
|
793
994
|
Prefix a field name with `-` to exclude it.
|
|
794
995
|
select:
|
|
795
|
-
|
|
796
|
-
|
|
996
|
+
description: >-
|
|
997
|
+
Select only matching items from a list:
|
|
998
|
+
`Hash` of field/value, or Ruby lambda (`@ruby:`) returning `true` for items to keep.
|
|
999
|
+
query:
|
|
1000
|
+
description: >-
|
|
1001
|
+
Filter and reshape an object or list result, before `select` and `fields`:
|
|
1002
|
+
JMESPath expression (https://jmespath.org), or Ruby lambda (`@ruby:`) called with the data and returning the new data.
|
|
797
1003
|
table:
|
|
798
1004
|
$ref: "#/components/schemas/TableOptions"
|
|
799
1005
|
flat:
|
|
@@ -808,11 +1014,156 @@ components:
|
|
|
808
1014
|
type: boolean
|
|
809
1015
|
description: >-
|
|
810
1016
|
Use ANSI colors and styles in terminal output and logs.
|
|
811
|
-
Default is auto-detected:
|
|
1017
|
+
Default is auto-detected: disabled if `NO_COLOR` is set or results are written to a file,
|
|
1018
|
+
else enabled if `CLICOLOR_FORCE` is set and not `0`,
|
|
1019
|
+
else enabled if both stdout and stderr are terminals, `TERM` is not `dumb` and `CLICOLOR` is not `0`.
|
|
812
1020
|
utf8:
|
|
813
1021
|
type: boolean
|
|
814
1022
|
description: >-
|
|
815
|
-
Use Unicode characters in terminal output (e.g. table borders, check marks).
|
|
816
|
-
Default is auto-detected: enabled if stdout is a terminal and the locale is UTF-8.
|
|
1023
|
+
Use Unicode characters in terminal output (e.g. table borders, check marks, hidden secrets), else ASCII replacements.
|
|
1024
|
+
Default is auto-detected: enabled if stdout is a terminal and the locale is UTF-8, or on Windows, the terminal renders Unicode (e.g. Windows Terminal, VS Code).
|
|
817
1025
|
img:
|
|
818
1026
|
$ref: "#/components/schemas/ImageOptions"
|
|
1027
|
+
WebServerOptions:
|
|
1028
|
+
type: object
|
|
1029
|
+
description: >-
|
|
1030
|
+
Address and TLS configuration for a local web server (`WebServerSimple`).
|
|
1031
|
+
Used by commands that start an embedded HTTP(S) listener (`faspex5 gateway`,
|
|
1032
|
+
`faspex5 postprocessing`, `aoc gateway`, `node emulator`, …).
|
|
1033
|
+
properties:
|
|
1034
|
+
url:
|
|
1035
|
+
type: string
|
|
1036
|
+
description: >-
|
|
1037
|
+
Address and port the server listens on.
|
|
1038
|
+
Use `https://` with `cert`/`key` for TLS.
|
|
1039
|
+
default: http://localhost:8080
|
|
1040
|
+
cert:
|
|
1041
|
+
type: string
|
|
1042
|
+
description: >-
|
|
1043
|
+
Path to the TLS certificate file.
|
|
1044
|
+
Accepted formats: PEM (`.pem`) or PKCS12 (`.p12` / `.pfx`).
|
|
1045
|
+
example: /path/to/cert.pem
|
|
1046
|
+
key:
|
|
1047
|
+
type: string
|
|
1048
|
+
description: >-
|
|
1049
|
+
Path to the PEM private key file, or the PKCS12 passphrase when `cert` is a `.p12`/`.pfx` file.
|
|
1050
|
+
example: /path/to/key.pem
|
|
1051
|
+
chain:
|
|
1052
|
+
type: string
|
|
1053
|
+
description: Path to the PEM certificate chain file (appended as extra chain certificates).
|
|
1054
|
+
example: /path/to/chain.pem
|
|
1055
|
+
Faspex4GatewayOptions:
|
|
1056
|
+
description: >-
|
|
1057
|
+
Configuration for the Faspex 4 gateway emulator (`faspex5 gateway`, `aoc gateway`).
|
|
1058
|
+
The command starts a local HTTP server that accepts Faspex 4 API calls and translates them
|
|
1059
|
+
to Faspex 5 / AoC API calls.
|
|
1060
|
+
Clients authenticate with HTTP Basic, as on Faspex 4, when `username` and `password` are set.
|
|
1061
|
+
By default the server binds to loopback; use a routable address only when clients must reach
|
|
1062
|
+
the host from outside: then `username` and `password` are required.
|
|
1063
|
+
allOf:
|
|
1064
|
+
- $ref: "#/components/schemas/WebServerOptions"
|
|
1065
|
+
- type: object
|
|
1066
|
+
# List properties solely to allow them under additionalProperties: false.
|
|
1067
|
+
# Types and descriptions are already defined in WebServerOptions above.
|
|
1068
|
+
additionalProperties: false
|
|
1069
|
+
properties:
|
|
1070
|
+
url: {}
|
|
1071
|
+
cert: {}
|
|
1072
|
+
key: {}
|
|
1073
|
+
chain: {}
|
|
1074
|
+
username:
|
|
1075
|
+
type: string
|
|
1076
|
+
description: >-
|
|
1077
|
+
Username expected from clients in HTTP Basic authentication.
|
|
1078
|
+
Set together with `password`.
|
|
1079
|
+
When not set, requests are accepted without authentication.
|
|
1080
|
+
Mandatory when `url` is not a loopback address (`localhost`, `127.0.0.0/8`, `::1`).
|
|
1081
|
+
example: fx4_user
|
|
1082
|
+
password:
|
|
1083
|
+
type: string
|
|
1084
|
+
description: >-
|
|
1085
|
+
Password expected from clients in HTTP Basic authentication, for the above `username`.
|
|
1086
|
+
Generate it with `openssl rand -hex 32`: a weak password is refused (see `password_min_bits`).
|
|
1087
|
+
example: my_password
|
|
1088
|
+
password_min_bits:
|
|
1089
|
+
type: integer
|
|
1090
|
+
minimum: 0
|
|
1091
|
+
default: 80
|
|
1092
|
+
description: >-
|
|
1093
|
+
Minimum estimated strength of `password`, in bits (log2 of the number of guesses to find it).
|
|
1094
|
+
The strength is estimated with gem `zxcvbn` if installed, else with a built-in estimate
|
|
1095
|
+
that detects repeats, sequences, keyboard rows, words and years.
|
|
1096
|
+
`0` disables the check.
|
|
1097
|
+
A random password of 32 bytes (`openssl rand -hex 32`) is far above the default.
|
|
1098
|
+
Faspex4PostProcOptions:
|
|
1099
|
+
description: >-
|
|
1100
|
+
Configuration for the Faspex 4-style post-processing webhook receiver (`faspex5 postprocessing`).
|
|
1101
|
+
The command starts a local HTTP(S) server that Faspex 5 calls after each package upload.
|
|
1102
|
+
It maps the URL path to a script under `script_folder` and executes it with the values of the
|
|
1103
|
+
webhook JSON body whose key starts with `faspex_` as environment variables.
|
|
1104
|
+
By default the server binds to loopback; use a routable address only when Faspex containers
|
|
1105
|
+
must reach the host: then `secret_token` or `allowed_ips` is required.
|
|
1106
|
+
allOf:
|
|
1107
|
+
- $ref: "#/components/schemas/WebServerOptions"
|
|
1108
|
+
- type: object
|
|
1109
|
+
additionalProperties: false
|
|
1110
|
+
properties:
|
|
1111
|
+
# Listed solely to allow them under additionalProperties: false (defined in WebServerOptions).
|
|
1112
|
+
url: {}
|
|
1113
|
+
cert: {}
|
|
1114
|
+
key: {}
|
|
1115
|
+
chain: {}
|
|
1116
|
+
script_folder:
|
|
1117
|
+
type: string
|
|
1118
|
+
description: >-
|
|
1119
|
+
Folder containing the post-processing scripts.
|
|
1120
|
+
The URL path (after the base path) is appended to this folder to locate the script to execute.
|
|
1121
|
+
default: "."
|
|
1122
|
+
example: /opt/faspex/scripts
|
|
1123
|
+
fail_on_error:
|
|
1124
|
+
type: boolean
|
|
1125
|
+
description: >-
|
|
1126
|
+
When `true`, return HTTP 500 if the script exits with a non-zero status code.
|
|
1127
|
+
When `false` (default), the exit code is reported in the response body but HTTP 200 is returned.
|
|
1128
|
+
default: false
|
|
1129
|
+
timeout_seconds:
|
|
1130
|
+
type: integer
|
|
1131
|
+
minimum: 1
|
|
1132
|
+
description: >-
|
|
1133
|
+
Maximum time in seconds to wait for the script to complete before killing it.
|
|
1134
|
+
default: 60
|
|
1135
|
+
secret_token:
|
|
1136
|
+
type: string
|
|
1137
|
+
minLength: 1
|
|
1138
|
+
description: >-
|
|
1139
|
+
Shared secret for webhook authentication.
|
|
1140
|
+
When set, every incoming request must include `?token=<value>` in the URL;
|
|
1141
|
+
requests without the correct token are rejected with HTTP 401.
|
|
1142
|
+
Configure the Faspex webhook URL as `http://host:port/path/script.sh?token=<value>`.
|
|
1143
|
+
This parameter or `allowed_ips` is required when `url` is not a local address.
|
|
1144
|
+
Generate it with `openssl rand -hex 32`: a weak token is refused (see `secret_token_min_bits`).
|
|
1145
|
+
secret_token_min_bits:
|
|
1146
|
+
type: integer
|
|
1147
|
+
minimum: 0
|
|
1148
|
+
default: 80
|
|
1149
|
+
description: >-
|
|
1150
|
+
Minimum estimated strength of `secret_token`, in bits (log2 of the number of guesses to find it).
|
|
1151
|
+
The strength is estimated with gem `zxcvbn` if installed, else with a built-in estimate
|
|
1152
|
+
that detects repeats, sequences, keyboard rows, words and years.
|
|
1153
|
+
`0` disables the check.
|
|
1154
|
+
A random token of 32 bytes (`openssl rand -hex 32`) is far above the default.
|
|
1155
|
+
allowed_ips:
|
|
1156
|
+
description: >-
|
|
1157
|
+
IP address or network (CIDR, e.g. `10.89.0.0/24`), or list of them, allowed to call the listener.
|
|
1158
|
+
Requests from any other source IP are rejected with HTTP 403.
|
|
1159
|
+
When not set, no IP restriction is applied.
|
|
1160
|
+
This parameter or `secret_token` is required when `url` is not a local address.
|
|
1161
|
+
oneOf:
|
|
1162
|
+
- type: string
|
|
1163
|
+
example: "192.168.1.10"
|
|
1164
|
+
- type: array
|
|
1165
|
+
items:
|
|
1166
|
+
type: string
|
|
1167
|
+
example:
|
|
1168
|
+
- "192.168.1.10"
|
|
1169
|
+
- "10.89.0.0/24"
|
data/lib/aspera/cli/parser.rb
CHANGED
|
@@ -205,8 +205,9 @@ module Aspera
|
|
|
205
205
|
# @param validation [Class, Array, nil] Accepted value type(s) or list of Symbols
|
|
206
206
|
# @param aliases [Hash] map of aliases: key = alias, value = real value
|
|
207
207
|
# @param default [Object] default value
|
|
208
|
+
# @param raw [Boolean] `true`: value is not evaluated as extended value
|
|
208
209
|
# @return [Object, Array, nil] one value, list or nil (if optional and no default)
|
|
209
|
-
def get_next_argument(descr, mandatory: true, multiple: false, accept_list: nil, validation: Type::STRING, aliases: nil, default: nil, schema: nil)
|
|
210
|
+
def get_next_argument(descr, mandatory: true, multiple: false, accept_list: nil, validation: Type::STRING, aliases: nil, default: nil, schema: nil, raw: false)
|
|
210
211
|
ensure_parsed
|
|
211
212
|
Aspera.assert_array_all(accept_list, Symbol) unless accept_list.nil?
|
|
212
213
|
Aspera.assert_hash_all(aliases, Symbol, Symbol) unless aliases.nil?
|
|
@@ -215,7 +216,7 @@ module Aspera
|
|
|
215
216
|
Aspera.assert_array_all(validation, Class) { 'validation' } unless validation.nil?
|
|
216
217
|
descr = "#{descr}#{add_types_info(validation)}"
|
|
217
218
|
result =
|
|
218
|
-
if !@command_line.pending_arguments.empty? then read_arguments(descr, multiple: multiple, validation: validation, accept_list: accept_list, aliases: aliases)
|
|
219
|
+
if !@command_line.pending_arguments.empty? then read_arguments(descr, multiple: multiple, validation: validation, accept_list: accept_list, aliases: aliases, raw: raw)
|
|
219
220
|
elsif !default.nil? then default
|
|
220
221
|
elsif mandatory then get_interactive(descr, multiple: multiple, accept_list: accept_list, aliases: aliases, schema: schema)
|
|
221
222
|
end
|
|
@@ -353,6 +354,14 @@ module Aspera
|
|
|
353
354
|
values.include?(@command_line.pending_arguments.first)
|
|
354
355
|
end
|
|
355
356
|
|
|
357
|
+
# Check the next pending positional arguments, without consuming them
|
|
358
|
+
# @param values [Array<String>] values to compare with, in order
|
|
359
|
+
# @return [Boolean] true if the next pending positional arguments are values
|
|
360
|
+
def next_arguments?(values)
|
|
361
|
+
ensure_parsed
|
|
362
|
+
@command_line.pending_arguments.first(values.length).eql?(values)
|
|
363
|
+
end
|
|
364
|
+
|
|
356
365
|
# Check for unprocessed options or arguments error messages
|
|
357
366
|
# @return [Array<String>] list of error messages for unprocessed tokens
|
|
358
367
|
def final_errors
|
|
@@ -516,11 +525,11 @@ module Aspera
|
|
|
516
525
|
" (#{types.map(&:name).join(', ')})"
|
|
517
526
|
end
|
|
518
527
|
|
|
519
|
-
# Consume and evaluate
|
|
528
|
+
# Consume positional arguments, and evaluate them unless `raw`
|
|
520
529
|
# @return [Object, Array] one value, or list if `multiple`
|
|
521
|
-
def read_arguments(descr, multiple:, validation:, accept_list:, aliases:)
|
|
530
|
+
def read_arguments(descr, multiple:, validation:, accept_list:, aliases:, raw:)
|
|
522
531
|
values = @command_line.shift_arguments(multiple)
|
|
523
|
-
values = values.map { |v| ExtendedValue.instance.evaluate(v, context: "argument: #{descr}", allowed: validation) }
|
|
532
|
+
values = values.map { |v| ExtendedValue.instance.evaluate(v, context: "argument: #{descr}", allowed: validation) } unless raw
|
|
524
533
|
# If expecting list and only one arg of type array : it is the list
|
|
525
534
|
values = values.first if multiple && values.length.eql?(1) && values.first.is_a?(Array)
|
|
526
535
|
if accept_list
|
|
@@ -6,6 +6,7 @@ require 'aspera/cli/plugins/node'
|
|
|
6
6
|
require 'aspera/cli/plugins/ats'
|
|
7
7
|
require 'aspera/cli/transfer_agent'
|
|
8
8
|
require 'aspera/cli/special_values'
|
|
9
|
+
require 'aspera/environment'
|
|
9
10
|
require 'aspera/cli/wizard'
|
|
10
11
|
require 'aspera/agent/node'
|
|
11
12
|
require 'aspera/transfer/result'
|
|
@@ -198,6 +199,7 @@ module Aspera
|
|
|
198
199
|
}
|
|
199
200
|
preset_value[:password] = options.get_option(:password, mandatory: true) if pub_info['password_protected']
|
|
200
201
|
return {
|
|
202
|
+
preset_ids: [],
|
|
201
203
|
preset_value: preset_value,
|
|
202
204
|
test_args: 'organization'
|
|
203
205
|
}
|
|
@@ -213,7 +215,7 @@ module Aspera
|
|
|
213
215
|
private_key_path = wizard.ask_private_key(
|
|
214
216
|
user: wiz_username,
|
|
215
217
|
url: app_url,
|
|
216
|
-
page: '👤
|
|
218
|
+
page: [Environment.char('👤'), 'Account Settings', 'Profile', 'Public Key']
|
|
217
219
|
)
|
|
218
220
|
client_id = options.get_option(:client_id)
|
|
219
221
|
client_secret = options.get_option(:client_secret)
|
|
@@ -227,7 +229,7 @@ module Aspera
|
|
|
227
229
|
else
|
|
228
230
|
formatter.display_status('Using organization specific client_id.')
|
|
229
231
|
formatter.display_status('Please login to your Aspera on Cloud instance.'.red)
|
|
230
|
-
|
|
232
|
+
wizard.display_navigation(Environment.char('𓃑'), 'Admin', 'Integrations', 'API Clients')
|
|
231
233
|
formatter.display_status('Check or create in integration:')
|
|
232
234
|
formatter.display_status('- name: cli')
|
|
233
235
|
formatter.display_status("- redirect uri: #{REDIRECT_LOCALHOST}")
|
|
@@ -259,6 +261,7 @@ module Aspera
|
|
|
259
261
|
aoc_api.update("clients/#{options.get_option(:client_id)}", {'jwt_grant_enabled' => true, 'explicit_authorization_required' => false})
|
|
260
262
|
end
|
|
261
263
|
return {
|
|
264
|
+
preset_ids: [myself['email'], client_id].compact,
|
|
262
265
|
preset_value: {
|
|
263
266
|
url: app_url,
|
|
264
267
|
username: myself['email'],
|
|
@@ -805,7 +808,7 @@ module Aspera
|
|
|
805
808
|
end
|
|
806
809
|
command :automation, description: 'Manage automation (BETA)', setup: :setup_automation_api
|
|
807
810
|
command :gateway, description: 'Start AoC Faspex4 gateway',
|
|
808
|
-
arguments: [{name: :parameters, type: Hash, mandatory: false, default: {}}]
|
|
811
|
+
arguments: [{name: :parameters, type: Hash, mandatory: false, default: {}, schema: Schema::Registry::GATEWAY_OPTIONS}]
|
|
809
812
|
|
|
810
813
|
# user sub-commands
|
|
811
814
|
commands_under :user do
|
|
@@ -1050,8 +1053,7 @@ module Aspera
|
|
|
1050
1053
|
end
|
|
1051
1054
|
package_data['encryption_at_rest'] = true if transfer.user_transfer_spec['content_protection'].eql?('encrypt')
|
|
1052
1055
|
created_package = aoc_api.create_package_simple(package_data, option_validate, new_user_option)
|
|
1053
|
-
Runner.
|
|
1054
|
-
return Result::SingleObject.new(created_package[:info])
|
|
1056
|
+
return Runner.result_object_transfer(created_package[:info], transfer.start(created_package[:spec], rest_token: created_package[:node]))
|
|
1055
1057
|
end
|
|
1056
1058
|
|
|
1057
1059
|
# packages > receive — package_id: from arguments:(:identifier) (or overridden by public_link)
|
|
@@ -1608,12 +1610,7 @@ module Aspera
|
|
|
1608
1610
|
|
|
1609
1611
|
def action_gateway(parameters: {}, **)
|
|
1610
1612
|
require 'aspera/faspex_gw'
|
|
1611
|
-
parameters
|
|
1612
|
-
uri = URI.parse(parameters.delete(:url) { WebServerSimple::DEFAULT_URL })
|
|
1613
|
-
server = WebServerSimple.new(uri, **parameters.slice(*WebServerSimple::PARAMS))
|
|
1614
|
-
Aspera.assert(parameters.except(*WebServerSimple::PARAMS).empty?) { "unexpected parameters: #{parameters.except(*WebServerSimple::PARAMS).keys}" }
|
|
1615
|
-
server.mount(uri.path, Faspex4GWServlet, aoc_api, aoc_api.workspace_info[:id])
|
|
1616
|
-
server.start
|
|
1613
|
+
Faspex4GWServlet.serve(parameters.symbolize_keys, type: Cli::BadArgument) { [aoc_api, aoc_api.workspace_info[:id]] }
|
|
1617
1614
|
return Result::Status.new('Gateway terminated')
|
|
1618
1615
|
end
|
|
1619
1616
|
end
|