aspera-cli 4.15.0 → 4.17.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/BUGS.md +29 -3
- data/CHANGELOG.md +375 -280
- data/CONTRIBUTING.md +71 -18
- data/README.md +1978 -1656
- data/bin/ascli +13 -31
- data/bin/asession +32 -22
- data/examples/dascli +2 -2
- data/lib/aspera/agent/alpha.rb +117 -0
- data/lib/aspera/agent/base.rb +61 -0
- data/lib/aspera/{fasp/agent_connect.rb → agent/connect.rb} +13 -11
- data/lib/aspera/{fasp/agent_direct.rb → agent/direct.rb} +116 -116
- data/lib/aspera/{fasp/agent_httpgw.rb → agent/httpgw.rb} +21 -19
- data/lib/aspera/{fasp/agent_node.rb → agent/node.rb} +21 -33
- data/lib/aspera/agent/trsdk.rb +188 -0
- data/lib/aspera/api/aoc.rb +586 -0
- data/lib/aspera/api/ats.rb +46 -0
- data/lib/aspera/api/cos_node.rb +95 -0
- data/lib/aspera/api/node.rb +344 -0
- data/lib/aspera/ascmd.rb +47 -14
- data/lib/aspera/{fasp → ascp}/installation.rb +54 -15
- data/lib/aspera/{fasp → ascp}/management.rb +14 -14
- data/lib/aspera/{fasp → ascp}/products.rb +1 -1
- data/lib/aspera/assert.rb +45 -0
- data/lib/aspera/cli/basic_auth_plugin.rb +11 -10
- data/lib/aspera/cli/extended_value.rb +5 -5
- data/lib/aspera/cli/formatter.rb +27 -14
- data/lib/aspera/cli/hints.rb +7 -6
- data/lib/aspera/cli/main.rb +49 -29
- data/lib/aspera/cli/manager.rb +46 -36
- data/lib/aspera/cli/plugin.rb +34 -20
- data/lib/aspera/cli/plugin_factory.rb +61 -0
- data/lib/aspera/cli/plugins/alee.rb +7 -7
- data/lib/aspera/cli/plugins/aoc.rb +168 -132
- data/lib/aspera/cli/plugins/ats.rb +33 -33
- data/lib/aspera/cli/plugins/bss.rb +3 -4
- data/lib/aspera/cli/plugins/config.rb +250 -272
- data/lib/aspera/cli/plugins/console.rb +8 -6
- data/lib/aspera/cli/plugins/cos.rb +20 -19
- data/lib/aspera/cli/plugins/faspex.rb +71 -60
- data/lib/aspera/cli/plugins/faspex5.rb +212 -133
- data/lib/aspera/cli/plugins/node.rb +83 -75
- data/lib/aspera/cli/plugins/orchestrator.rb +36 -44
- data/lib/aspera/cli/plugins/preview.rb +33 -31
- data/lib/aspera/cli/plugins/server.rb +33 -32
- data/lib/aspera/cli/plugins/shares.rb +39 -33
- data/lib/aspera/cli/sync_actions.rb +9 -9
- data/lib/aspera/cli/transfer_agent.rb +45 -25
- data/lib/aspera/cli/transfer_progress.rb +2 -3
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/colors.rb +5 -0
- data/lib/aspera/command_line_builder.rb +16 -14
- data/lib/aspera/coverage.rb +21 -0
- data/lib/aspera/data_repository.rb +33 -2
- data/lib/aspera/environment.rb +5 -4
- data/lib/aspera/faspex_gw.rb +13 -11
- data/lib/aspera/faspex_postproc.rb +6 -5
- data/lib/aspera/id_generator.rb +4 -2
- data/lib/aspera/json_rpc.rb +10 -8
- data/lib/aspera/keychain/encrypted_hash.rb +46 -11
- data/lib/aspera/keychain/macos_security.rb +29 -22
- data/lib/aspera/log.rb +5 -4
- data/lib/aspera/nagios.rb +7 -2
- data/lib/aspera/node_simulator.rb +213 -0
- data/lib/aspera/oauth/base.rb +143 -0
- data/lib/aspera/oauth/factory.rb +124 -0
- data/lib/aspera/oauth/generic.rb +34 -0
- data/lib/aspera/oauth/jwt.rb +51 -0
- data/lib/aspera/oauth/url_json.rb +31 -0
- data/lib/aspera/oauth/web.rb +50 -0
- data/lib/aspera/oauth.rb +5 -328
- data/lib/aspera/open_application.rb +7 -7
- data/lib/aspera/persistency_action_once.rb +13 -14
- data/lib/aspera/persistency_folder.rb +3 -2
- data/lib/aspera/preview/file_types.rb +53 -267
- data/lib/aspera/preview/generator.rb +7 -5
- data/lib/aspera/preview/terminal.rb +17 -7
- data/lib/aspera/preview/utils.rb +8 -7
- data/lib/aspera/proxy_auto_config.rb +6 -3
- data/lib/aspera/rest.rb +187 -140
- data/lib/aspera/rest_error_analyzer.rb +1 -0
- data/lib/aspera/rest_errors_aspera.rb +5 -3
- data/lib/aspera/resumer.rb +77 -0
- data/lib/aspera/secret_hider.rb +5 -2
- data/lib/aspera/ssh.rb +15 -8
- data/lib/aspera/temp_file_manager.rb +1 -1
- data/lib/aspera/{fasp → transfer}/error.rb +3 -3
- data/lib/aspera/{fasp → transfer}/error_info.rb +1 -1
- data/lib/aspera/{fasp → transfer}/faux_file.rb +1 -1
- data/lib/aspera/{fasp → transfer}/parameters.rb +95 -120
- data/lib/aspera/{fasp/transfer_spec.rb → transfer/spec.rb} +23 -19
- data/lib/aspera/{fasp/parameters.yaml → transfer/spec.yaml} +4 -99
- data/lib/aspera/transfer/sync.rb +273 -0
- data/lib/aspera/{fasp → transfer}/uri.rb +10 -9
- data/lib/aspera/web_server_simple.rb +12 -3
- data.tar.gz.sig +0 -0
- metadata +92 -68
- metadata.gz.sig +0 -0
- data/lib/aspera/aoc.rb +0 -606
- data/lib/aspera/ats_api.rb +0 -47
- data/lib/aspera/cos_node.rb +0 -93
- data/lib/aspera/fasp/agent_aspera.rb +0 -126
- data/lib/aspera/fasp/agent_base.rb +0 -48
- data/lib/aspera/fasp/agent_trsdk.rb +0 -146
- data/lib/aspera/fasp/resume_policy.rb +0 -77
- data/lib/aspera/node.rb +0 -338
- data/lib/aspera/sync.rb +0 -219
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# cspell:ignore initdemo genkey asperasoft
|
|
3
|
+
# cspell:ignore initdemo genkey pubkey asperasoft
|
|
4
4
|
require 'aspera/cli/basic_auth_plugin'
|
|
5
5
|
require 'aspera/cli/extended_value'
|
|
6
6
|
require 'aspera/cli/version'
|
|
7
7
|
require 'aspera/cli/formatter'
|
|
8
8
|
require 'aspera/cli/info'
|
|
9
9
|
require 'aspera/cli/transfer_progress'
|
|
10
|
-
require 'aspera/
|
|
11
|
-
require 'aspera/
|
|
12
|
-
require 'aspera/
|
|
13
|
-
require 'aspera/
|
|
14
|
-
require 'aspera/
|
|
10
|
+
require 'aspera/ascp/installation'
|
|
11
|
+
require 'aspera/ascp/products'
|
|
12
|
+
require 'aspera/transfer/error_info'
|
|
13
|
+
require 'aspera/transfer/parameters'
|
|
14
|
+
require 'aspera/transfer/spec'
|
|
15
15
|
require 'aspera/keychain/encrypted_hash'
|
|
16
16
|
require 'aspera/keychain/macos_security'
|
|
17
17
|
require 'aspera/proxy_auto_config'
|
|
@@ -19,9 +19,12 @@ require 'aspera/open_application'
|
|
|
19
19
|
require 'aspera/persistency_action_once'
|
|
20
20
|
require 'aspera/id_generator'
|
|
21
21
|
require 'aspera/persistency_folder'
|
|
22
|
+
require 'aspera/data_repository'
|
|
22
23
|
require 'aspera/line_logger'
|
|
23
24
|
require 'aspera/rest'
|
|
24
25
|
require 'aspera/log'
|
|
26
|
+
require 'aspera/assert'
|
|
27
|
+
require 'aspera/oauth'
|
|
25
28
|
require 'open3'
|
|
26
29
|
require 'date'
|
|
27
30
|
require 'erb'
|
|
@@ -30,31 +33,31 @@ module Aspera
|
|
|
30
33
|
module Cli
|
|
31
34
|
module Plugins
|
|
32
35
|
# manage the CLI config file
|
|
33
|
-
class Config <
|
|
36
|
+
class Config < Cli::Plugin
|
|
34
37
|
# folder in $HOME for application files (config, cache)
|
|
35
38
|
ASPERA_HOME_FOLDER_NAME = '.aspera'
|
|
36
39
|
# default config file
|
|
37
40
|
DEFAULT_CONFIG_FILENAME = 'config.yaml'
|
|
41
|
+
DEFAULT_VAULT_FILENAME = 'vault.bin'
|
|
38
42
|
# reserved preset names
|
|
39
43
|
CONF_PRESET_CONFIG = 'config'
|
|
40
44
|
CONF_PRESET_VERSION = 'version'
|
|
41
|
-
|
|
45
|
+
CONF_PRESET_DEFAULTS = 'default'
|
|
42
46
|
CONF_PRESET_GLOBAL = 'global_common_defaults'
|
|
47
|
+
# special name to identify value of default
|
|
43
48
|
GLOBAL_DEFAULT_KEYWORD = 'GLOBAL'
|
|
44
|
-
CONF_PLUGIN_SYM = :config # Plugins::Config.name.split('::').last.downcase.to_sym
|
|
45
49
|
CONF_GLOBAL_SYM = :config
|
|
46
50
|
# folder containing custom plugins in user's config folder
|
|
47
51
|
ASPERA_PLUGINS_FOLDERNAME = 'plugins'
|
|
48
52
|
PERSISTENCY_FOLDER = 'persist_store'
|
|
49
|
-
RUBY_FILE_EXT = '.rb'
|
|
50
53
|
ASPERA = 'aspera'
|
|
51
54
|
SERVER_COMMAND = 'server'
|
|
52
55
|
APP_NAME_SDK = 'sdk'
|
|
53
56
|
CONNECT_WEB_URL = 'https://d3gcli72yxqn2z.cloudfront.net/connect'
|
|
54
57
|
CONNECT_VERSIONS = 'connectversions.js' # cspell: disable-line
|
|
55
58
|
TRANSFER_SDK_ARCHIVE_URL = 'https://ibm.biz/aspera_transfer_sdk'
|
|
56
|
-
|
|
57
|
-
|
|
59
|
+
DEMO_SERVER = 'demo'
|
|
60
|
+
DEMO_PRESET = 'demoserver' # cspell: disable-line
|
|
58
61
|
EMAIL_TEST_TEMPLATE = <<~END_OF_TEMPLATE
|
|
59
62
|
From: <%=from_name%> <<%=from_email%>>
|
|
60
63
|
To: <<%=to%>>
|
|
@@ -77,14 +80,13 @@ module Aspera
|
|
|
77
80
|
private_constant :DEFAULT_CONFIG_FILENAME,
|
|
78
81
|
:CONF_PRESET_CONFIG,
|
|
79
82
|
:CONF_PRESET_VERSION,
|
|
80
|
-
:
|
|
83
|
+
:CONF_PRESET_DEFAULTS,
|
|
81
84
|
:CONF_PRESET_GLOBAL,
|
|
82
85
|
:ASPERA_PLUGINS_FOLDERNAME,
|
|
83
|
-
:RUBY_FILE_EXT,
|
|
84
86
|
:ASPERA,
|
|
85
|
-
:DEMO,
|
|
86
87
|
:TRANSFER_SDK_ARCHIVE_URL,
|
|
87
|
-
:
|
|
88
|
+
:DEMO_SERVER,
|
|
89
|
+
:DEMO_PRESET,
|
|
88
90
|
:EMAIL_TEST_TEMPLATE,
|
|
89
91
|
:EXTEND_PRESET,
|
|
90
92
|
:EXTEND_VAULT,
|
|
@@ -114,23 +116,11 @@ module Aspera
|
|
|
114
116
|
File.dirname(File.expand_path(__FILE__))
|
|
115
117
|
end
|
|
116
118
|
|
|
117
|
-
# name of englobing module
|
|
118
|
-
# @return "Aspera::Cli::Plugins"
|
|
119
|
-
def module_full_name
|
|
120
|
-
return Module.nesting[2].to_s
|
|
121
|
-
end
|
|
122
|
-
|
|
123
119
|
# @return main folder where code is, i.e. .../lib
|
|
124
120
|
# go up as many times as englobing modules (not counting class, as it is a file)
|
|
125
121
|
def gem_src_root
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
# instantiate a plugin
|
|
130
|
-
# plugins must be Capitalized
|
|
131
|
-
def plugin_class(plugin_name_sym)
|
|
132
|
-
# Module.nesting[2] is Aspera::Cli::Plugins
|
|
133
|
-
return Object.const_get("#{module_full_name}::#{plugin_name_sym.to_s.capitalize}")
|
|
122
|
+
# Module.nesting[2] is Cli::Plugins
|
|
123
|
+
File.expand_path(Module.nesting[2].to_s.gsub('::', '/').gsub(%r{[^/]+}, '..'), gem_plugins_folder)
|
|
134
124
|
end
|
|
135
125
|
|
|
136
126
|
# deep clone hash so that it does not get modified in case of display and secret hide
|
|
@@ -141,25 +131,25 @@ module Aspera
|
|
|
141
131
|
# return product family folder (~/.aspera)
|
|
142
132
|
def module_family_folder
|
|
143
133
|
user_home_folder = Dir.home
|
|
144
|
-
|
|
134
|
+
Aspera.assert(Dir.exist?(user_home_folder), exception_class: Cli::Error){"Home folder does not exist: #{user_home_folder}. Check your user environment."}
|
|
145
135
|
return File.join(user_home_folder, ASPERA_HOME_FOLDER_NAME)
|
|
146
136
|
end
|
|
147
137
|
|
|
148
138
|
# return product config folder (~/.aspera/<name>)
|
|
149
139
|
def default_app_main_folder(app_name:)
|
|
150
|
-
|
|
140
|
+
Aspera.assert_type(app_name, String)
|
|
141
|
+
Aspera.assert(!app_name.empty?)
|
|
151
142
|
return File.join(module_family_folder, app_name)
|
|
152
143
|
end
|
|
153
144
|
end # self
|
|
154
145
|
|
|
155
|
-
def initialize(env
|
|
156
|
-
raise 'Internal Error: env and params must be Hash' unless env.is_a?(Hash) && params.is_a?(Hash)
|
|
157
|
-
raise 'Internal Error: missing param' unless %i[gem help name version].eql?(params.keys.sort)
|
|
146
|
+
def initialize(gem:, name:, help:, version:, **env)
|
|
158
147
|
# we need to defer parsing of options until we have the config file, so we can use @extend with @preset
|
|
159
|
-
super(env)
|
|
160
|
-
@
|
|
161
|
-
@
|
|
162
|
-
@
|
|
148
|
+
super(**env)
|
|
149
|
+
@gem = gem
|
|
150
|
+
@name = name
|
|
151
|
+
@help = help
|
|
152
|
+
@version = version
|
|
163
153
|
@use_plugin_defaults = true
|
|
164
154
|
@config_presets = nil
|
|
165
155
|
@config_checksum_on_disk = nil
|
|
@@ -168,6 +158,7 @@ module Aspera
|
|
|
168
158
|
@pac_exec = nil
|
|
169
159
|
@sdk_default_location = false
|
|
170
160
|
@option_insecure = false
|
|
161
|
+
@option_warn_insecure_cert = true
|
|
171
162
|
@option_ignore_cert_host_port = []
|
|
172
163
|
@option_http_options = {}
|
|
173
164
|
@ssl_warned_urls = []
|
|
@@ -175,7 +166,9 @@ module Aspera
|
|
|
175
166
|
@proxy_credentials = nil
|
|
176
167
|
@main_folder = nil
|
|
177
168
|
@option_config_file = nil
|
|
169
|
+
# store is used for ruby https
|
|
178
170
|
@certificate_store = nil
|
|
171
|
+
# paths are used for ascp
|
|
179
172
|
@certificate_paths = nil
|
|
180
173
|
@progress_bar = nil
|
|
181
174
|
# option to set main folder
|
|
@@ -183,14 +176,14 @@ module Aspera
|
|
|
183
176
|
:home, 'Home folder for tool',
|
|
184
177
|
handler: {o: self, m: :main_folder},
|
|
185
178
|
types: String,
|
|
186
|
-
default: self.class.default_app_main_folder(app_name: @
|
|
179
|
+
default: self.class.default_app_main_folder(app_name: @name))
|
|
187
180
|
options.parse_options!
|
|
188
|
-
Log.log.debug{"#{@
|
|
189
|
-
# data persistency manager
|
|
190
|
-
|
|
181
|
+
Log.log.debug{"#{@name} folder: #{@main_folder}"}
|
|
182
|
+
# data persistency manager, created by config plugin
|
|
183
|
+
@persistency = PersistencyFolder.new(File.join(@main_folder, PERSISTENCY_FOLDER))
|
|
191
184
|
# set folders for plugin lookup
|
|
192
|
-
|
|
193
|
-
|
|
185
|
+
PluginFactory.instance.add_lookup_folder(self.class.gem_plugins_folder)
|
|
186
|
+
PluginFactory.instance.add_lookup_folder(File.join(@main_folder, ASPERA_PLUGINS_FOLDERNAME))
|
|
194
187
|
# option to set config file
|
|
195
188
|
options.declare(
|
|
196
189
|
:config_file, 'Path to YAML file with preset configuration',
|
|
@@ -222,10 +215,10 @@ module Aspera
|
|
|
222
215
|
options.declare(:test_mode, 'Wizard: skip private key check step', values: :bool, default: false)
|
|
223
216
|
options.declare(:key_path, 'Wizard: path to private key for JWT')
|
|
224
217
|
# Transfer SDK options
|
|
225
|
-
options.declare(:ascp_path, 'Path to ascp', handler: {o:
|
|
218
|
+
options.declare(:ascp_path, 'Path to ascp', handler: {o: Ascp::Installation.instance, m: :ascp_path})
|
|
226
219
|
options.declare(:use_product, 'Use ascp from specified product', handler: {o: self, m: :option_use_product})
|
|
227
220
|
options.declare(:sdk_url, 'URL to get SDK', default: TRANSFER_SDK_ARCHIVE_URL)
|
|
228
|
-
options.declare(:sdk_folder, 'SDK folder path', handler: {o:
|
|
221
|
+
options.declare(:sdk_folder, 'SDK folder path', handler: {o: Ascp::Installation.instance, m: :sdk_folder})
|
|
229
222
|
options.declare(:progress_bar, 'Display progress bar', values: :bool, default: Environment.terminal?)
|
|
230
223
|
# email options
|
|
231
224
|
options.declare(:smtp, 'SMTP configuration', types: Hash)
|
|
@@ -233,16 +226,17 @@ module Aspera
|
|
|
233
226
|
options.declare(:notify_template, 'Email ERB template for notification of transfers')
|
|
234
227
|
# HTTP options
|
|
235
228
|
options.declare(:insecure, 'Do not validate any HTTPS certificate', values: :bool, handler: {o: self, m: :option_insecure}, default: :no)
|
|
236
|
-
options.declare(:ignore_certificate, '
|
|
229
|
+
options.declare(:ignore_certificate, 'Do not validate HTTPS certificate for these URLs', types: Array, handler: {o: self, m: :option_ignore_cert_host_port})
|
|
230
|
+
options.declare(:silent_insecure, 'Issue a warning if certificate is ignored', values: :bool, handler: {o: self, m: :option_warn_insecure_cert}, default: :yes)
|
|
237
231
|
options.declare(:cert_stores, 'List of folder with trusted certificates', types: [Array, String], handler: {o: self, m: :trusted_cert_locations})
|
|
238
232
|
options.declare(:http_options, 'Options for HTTP/S socket', types: Hash, handler: {o: self, m: :option_http_options}, default: {})
|
|
239
|
-
options.declare(:cache_tokens, 'Save and reuse
|
|
233
|
+
options.declare(:cache_tokens, 'Save and reuse OAuth tokens', values: :bool, handler: {o: self, m: :option_cache_tokens})
|
|
240
234
|
options.declare(:fpac, 'Proxy auto configuration script')
|
|
241
235
|
options.declare(:proxy_credentials, 'HTTP proxy credentials (user and password)', types: Array)
|
|
242
236
|
options.parse_options!
|
|
243
237
|
@progress_bar = TransferProgress.new if options.get_option(:progress_bar)
|
|
244
238
|
# Check SDK folder is set or not, for compatibility, we check in two places
|
|
245
|
-
sdk_folder =
|
|
239
|
+
sdk_folder = Ascp::Installation.instance.sdk_folder rescue nil
|
|
246
240
|
if sdk_folder.nil?
|
|
247
241
|
@sdk_default_location = true
|
|
248
242
|
Log.log.debug('SDK folder is not set, checking default')
|
|
@@ -252,19 +246,19 @@ module Aspera
|
|
|
252
246
|
if !Dir.exist?(sdk_folder)
|
|
253
247
|
Log.log.debug{"not exists: #{sdk_folder}"}
|
|
254
248
|
# former location
|
|
255
|
-
former_sdk_folder = File.join(self.class.default_app_main_folder(app_name: @
|
|
249
|
+
former_sdk_folder = File.join(self.class.default_app_main_folder(app_name: @name), APP_NAME_SDK)
|
|
256
250
|
Log.log.debug{"checking: #{former_sdk_folder}"}
|
|
257
251
|
sdk_folder = former_sdk_folder if Dir.exist?(former_sdk_folder)
|
|
258
252
|
end
|
|
259
253
|
Log.log.debug{"using: #{sdk_folder}"}
|
|
260
|
-
|
|
254
|
+
Ascp::Installation.instance.sdk_folder = sdk_folder
|
|
261
255
|
end
|
|
262
256
|
pac_script = options.get_option(:fpac)
|
|
263
257
|
# create PAC executor
|
|
264
|
-
@pac_exec =
|
|
258
|
+
@pac_exec = ProxyAutoConfig.new(pac_script).register_uri_generic unless pac_script.nil?
|
|
265
259
|
proxy_user_pass = options.get_option(:proxy_credentials)
|
|
266
260
|
if !proxy_user_pass.nil?
|
|
267
|
-
|
|
261
|
+
Aspera.assert(proxy_user_pass.length.eql?(2), exception_class: Cli::BadArgument){"proxy_credentials shall have two elements (#{proxy_user_pass.length})"}
|
|
268
262
|
@proxy_credentials = {user: proxy_user_pass[0], pass: proxy_user_pass[1]}
|
|
269
263
|
@pac_exec.proxy_user = @proxy_credentials[:user]
|
|
270
264
|
@pac_exec.proxy_pass = @proxy_credentials[:pass]
|
|
@@ -273,34 +267,36 @@ module Aspera
|
|
|
273
267
|
user_agent: PROGRAM_NAME,
|
|
274
268
|
session_cb: lambda{|http_session|update_http_session(http_session)},
|
|
275
269
|
progress_bar: @progress_bar)
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
270
|
+
OAuth::Factory.instance.persist_mgr = persistency if @option_cache_tokens
|
|
271
|
+
Transfer::Parameters.file_list_folder = File.join(@main_folder, 'filelists') # cspell: disable-line
|
|
272
|
+
RestErrorAnalyzer.instance.log_file = File.join(@main_folder, 'rest_exceptions.log')
|
|
279
273
|
# register aspera REST call error handlers
|
|
280
|
-
|
|
274
|
+
RestErrorsAspera.register_handlers
|
|
281
275
|
end
|
|
282
276
|
|
|
283
|
-
attr_accessor :main_folder, :option_cache_tokens, :option_insecure, :option_http_options
|
|
277
|
+
attr_accessor :main_folder, :option_cache_tokens, :option_insecure, :option_warn_insecure_cert, :option_http_options
|
|
284
278
|
attr_reader :option_ignore_cert_host_port, :progress_bar
|
|
285
279
|
|
|
280
|
+
# add files, folders or default locations to the certificate store
|
|
286
281
|
def trusted_cert_locations=(path_list)
|
|
287
282
|
path_list = [path_list] unless path_list.is_a?(Array)
|
|
283
|
+
Aspera.assert_type(path_list, Array){'cert locations'}
|
|
288
284
|
if @certificate_store.nil?
|
|
289
285
|
Log.log.debug('Creating SSL Cert store')
|
|
290
286
|
@certificate_store = OpenSSL::X509::Store.new
|
|
291
|
-
@certificate_store.set_default_paths
|
|
292
287
|
@certificate_paths = []
|
|
293
288
|
end
|
|
294
289
|
|
|
295
290
|
path_list.each do |path|
|
|
296
|
-
|
|
297
|
-
|
|
291
|
+
Aspera.assert_type(path, String){'Expecting a String for certificate location'}
|
|
292
|
+
paths_to_add = [path]
|
|
293
|
+
Log.log.debug{"Adding cert location: #{path}"}
|
|
298
294
|
if path.eql?(ExtendedValue::DEF)
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
295
|
+
@certificate_store.set_default_paths
|
|
296
|
+
paths_to_add = [
|
|
297
|
+
OpenSSL::X509::DEFAULT_CERT_DIR,
|
|
298
|
+
OpenSSL::X509::DEFAULT_CERT_FILE
|
|
299
|
+
].select{|f|File.exist?(f)}
|
|
304
300
|
elsif File.file?(path)
|
|
305
301
|
@certificate_store.add_file(path)
|
|
306
302
|
elsif File.directory?(path)
|
|
@@ -308,39 +304,57 @@ module Aspera
|
|
|
308
304
|
else
|
|
309
305
|
raise "No such file or folder: #{path}"
|
|
310
306
|
end
|
|
311
|
-
|
|
307
|
+
paths_to_add.each do |p|
|
|
308
|
+
pp = [File.realpath(p)]
|
|
309
|
+
if File.directory?(p)
|
|
310
|
+
pp = Dir.entries(p)
|
|
311
|
+
.map{|e|File.realpath(File.join(p, e))}
|
|
312
|
+
.select{|entry|File.file?(entry)}
|
|
313
|
+
end
|
|
314
|
+
@certificate_paths.concat(pp)
|
|
315
|
+
end
|
|
312
316
|
end
|
|
317
|
+
@certificate_paths.uniq!
|
|
313
318
|
end
|
|
314
319
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
+
# returns only files
|
|
321
|
+
def trusted_cert_locations
|
|
322
|
+
locations = @certificate_paths
|
|
323
|
+
if locations.nil?
|
|
324
|
+
# compute default locations
|
|
325
|
+
self.trusted_cert_locations = ExtendedValue::DEF
|
|
326
|
+
locations = @certificate_paths
|
|
327
|
+
# restore defaults
|
|
328
|
+
@certificate_paths = @certificate_store = nil
|
|
320
329
|
end
|
|
321
|
-
locations = locations.select{|f|File.file?(f)} if files_only
|
|
322
330
|
return locations
|
|
323
331
|
end
|
|
324
332
|
|
|
325
333
|
def option_ignore_cert_host_port=(url_list)
|
|
326
334
|
url_list.each do |url|
|
|
327
335
|
uri = URI.parse(url)
|
|
336
|
+
raise "Expecting https scheme: #{url}" unless uri.scheme.eql?('https')
|
|
328
337
|
@option_ignore_cert_host_port.push([uri.host, uri.port].freeze)
|
|
329
338
|
end
|
|
330
339
|
end
|
|
331
340
|
|
|
332
341
|
def ignore_cert?(address, port)
|
|
333
342
|
endpoint = [address, port].freeze
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
343
|
+
ignore_cert = false
|
|
344
|
+
if @option_insecure || @option_ignore_cert_host_port.any?(endpoint)
|
|
345
|
+
ignore_cert = true
|
|
346
|
+
if @option_warn_insecure_cert
|
|
347
|
+
base_url = "https://#{address}:#{port}"
|
|
348
|
+
if !@ssl_warned_urls.include?(base_url)
|
|
349
|
+
formatter.display_message(
|
|
350
|
+
:error,
|
|
351
|
+
"#{Formatter::WARNING_FLASH} Ignoring certificate for: #{base_url}. Do not deactivate certificate verification in production.")
|
|
352
|
+
@ssl_warned_urls.push(base_url)
|
|
353
|
+
end
|
|
354
|
+
end
|
|
342
355
|
end
|
|
343
|
-
|
|
356
|
+
Log.log.debug{"ignore cert? #{endpoint} -> #{ignore_cert}"}
|
|
357
|
+
return ignore_cert
|
|
344
358
|
end
|
|
345
359
|
|
|
346
360
|
# called every time a new REST HTTP session is opened to set user-provided options
|
|
@@ -370,7 +384,7 @@ module Aspera
|
|
|
370
384
|
def check_gem_version
|
|
371
385
|
latest_version =
|
|
372
386
|
begin
|
|
373
|
-
Rest.new(base_url: 'https://rubygems.org/api/v1').read("versions/#{@
|
|
387
|
+
Rest.new(base_url: 'https://rubygems.org/api/v1').read("versions/#{@gem}/latest.json")[:data]['version']
|
|
374
388
|
rescue StandardError
|
|
375
389
|
Log.log.warn('Could not retrieve latest gem version on rubygems.')
|
|
376
390
|
'0'
|
|
@@ -382,10 +396,10 @@ module Aspera
|
|
|
382
396
|
end
|
|
383
397
|
end
|
|
384
398
|
return {
|
|
385
|
-
name: @
|
|
386
|
-
current:
|
|
399
|
+
name: @gem,
|
|
400
|
+
current: Cli::VERSION,
|
|
387
401
|
latest: latest_version,
|
|
388
|
-
need_update: Gem::Version.new(
|
|
402
|
+
need_update: Gem::Version.new(Cli::VERSION) < Gem::Version.new(latest_version)
|
|
389
403
|
}
|
|
390
404
|
end
|
|
391
405
|
|
|
@@ -418,8 +432,8 @@ module Aspera
|
|
|
418
432
|
# retrieve structure from cloud (CDN) with all versions available
|
|
419
433
|
def connect_versions
|
|
420
434
|
if @connect_versions.nil?
|
|
421
|
-
api_connect_cdn = Rest.new(
|
|
422
|
-
javascript = api_connect_cdn.call(
|
|
435
|
+
api_connect_cdn = Rest.new(base_url: CONNECT_WEB_URL)
|
|
436
|
+
javascript = api_connect_cdn.call(operation: 'GET', subpath: CONNECT_VERSIONS)
|
|
423
437
|
# get result on one line
|
|
424
438
|
connect_versions_javascript = javascript[:http].body.gsub(/\r?\n\s*/, '')
|
|
425
439
|
Log.log.debug{"javascript=[\n#{connect_versions_javascript}\n]"}
|
|
@@ -443,25 +457,25 @@ module Aspera
|
|
|
443
457
|
return nil
|
|
444
458
|
end
|
|
445
459
|
|
|
446
|
-
# get the default global preset, or
|
|
460
|
+
# get the default global preset, or set default one
|
|
447
461
|
def global_default_preset
|
|
448
|
-
|
|
449
|
-
if
|
|
450
|
-
|
|
451
|
-
set_preset_key(
|
|
462
|
+
result = get_plugin_default_config_name(CONF_GLOBAL_SYM)
|
|
463
|
+
if result.nil?
|
|
464
|
+
result = CONF_PRESET_GLOBAL
|
|
465
|
+
set_preset_key(CONF_PRESET_DEFAULTS, CONF_GLOBAL_SYM, result)
|
|
452
466
|
end
|
|
453
|
-
return
|
|
467
|
+
return result
|
|
454
468
|
end
|
|
455
469
|
|
|
456
470
|
def set_preset_key(preset, param_name, param_value)
|
|
457
|
-
|
|
471
|
+
Aspera.assert_values(param_name.class, [String, Symbol]){'parameter'}
|
|
458
472
|
param_name = param_name.to_s
|
|
459
473
|
selected_preset = @config_presets[preset]
|
|
460
474
|
if selected_preset.nil?
|
|
461
475
|
Log.log.debug{"No such preset name: #{preset}, initializing"}
|
|
462
476
|
selected_preset = @config_presets[preset] = {}
|
|
463
477
|
end
|
|
464
|
-
|
|
478
|
+
Aspera.assert_type(selected_preset, Hash){"#{preset}.#{param_name}"}
|
|
465
479
|
if selected_preset.key?(param_name)
|
|
466
480
|
if selected_preset[param_name].eql?(param_value)
|
|
467
481
|
Log.log.warn{"keeping same value for #{preset}: #{param_name}: #{param_value}"}
|
|
@@ -482,7 +496,7 @@ module Aspera
|
|
|
482
496
|
end
|
|
483
497
|
|
|
484
498
|
# $HOME/.aspera/`program_name`
|
|
485
|
-
attr_reader :gem_url
|
|
499
|
+
attr_reader :gem_url
|
|
486
500
|
attr_accessor :option_config_file
|
|
487
501
|
|
|
488
502
|
# @return the hash from name (also expands possible includes)
|
|
@@ -493,7 +507,7 @@ module Aspera
|
|
|
493
507
|
include_path = include_path.clone # avoid messing up if there are multiple branches
|
|
494
508
|
current = @config_presets
|
|
495
509
|
config_name.split(PRESET_DIG_SEPARATOR).each do |name|
|
|
496
|
-
|
|
510
|
+
Aspera.assert_type(current, Hash, exception_class: Cli::Error){"sub key: #{include_path}"}
|
|
497
511
|
include_path.push(name)
|
|
498
512
|
current = current[name]
|
|
499
513
|
raise Cli::Error, "No such config preset: #{include_path}" if current.nil?
|
|
@@ -503,7 +517,7 @@ module Aspera
|
|
|
503
517
|
end
|
|
504
518
|
|
|
505
519
|
def option_use_product=(value)
|
|
506
|
-
|
|
520
|
+
Ascp::Installation.instance.use_ascp_from_product(value)
|
|
507
521
|
end
|
|
508
522
|
|
|
509
523
|
def option_use_product
|
|
@@ -511,15 +525,14 @@ module Aspera
|
|
|
511
525
|
end
|
|
512
526
|
|
|
513
527
|
def option_plugin_folder=(value)
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
end
|
|
528
|
+
Aspera.assert_values(value.class, [String, Array]){'plugin folder'}
|
|
529
|
+
value = [value] if value.is_a?(String)
|
|
530
|
+
Aspera.assert(value.all?(String)){'plugin folder'}
|
|
531
|
+
value.each{|f|PluginFactory.instance.add_lookup_folder(f)}
|
|
519
532
|
end
|
|
520
533
|
|
|
521
534
|
def option_plugin_folder
|
|
522
|
-
return
|
|
535
|
+
return PluginFactory.instance.lookup_folders
|
|
523
536
|
end
|
|
524
537
|
|
|
525
538
|
def option_preset; 'write-only option'; end
|
|
@@ -558,18 +571,18 @@ module Aspera
|
|
|
558
571
|
end
|
|
559
572
|
files_to_copy = []
|
|
560
573
|
Log.log.debug{Log.dump('Available_presets', @config_presets)}
|
|
561
|
-
|
|
574
|
+
Aspera.assert_type(@config_presets, Hash){'config file YAML'}
|
|
562
575
|
# check there is at least the config section
|
|
563
|
-
|
|
576
|
+
Aspera.assert(@config_presets.key?(CONF_PRESET_CONFIG)){"Cannot find key: #{CONF_PRESET_CONFIG}"}
|
|
564
577
|
version = @config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION]
|
|
565
578
|
raise 'No version found in config section.' if version.nil?
|
|
566
579
|
Log.log.debug{"conf version: #{version}"}
|
|
567
580
|
# VVV if there are any conversion needed, those happen here.
|
|
568
581
|
# fix bug in 4.4 (creating key "true" in "default" preset)
|
|
569
|
-
@config_presets[
|
|
582
|
+
@config_presets[CONF_PRESET_DEFAULTS].delete(true) if @config_presets[CONF_PRESET_DEFAULTS].is_a?(Hash)
|
|
570
583
|
# ^^^ Place new compatibility code before this line
|
|
571
584
|
# set version to current
|
|
572
|
-
@config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION] = @
|
|
585
|
+
@config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION] = @version
|
|
573
586
|
unless files_to_copy.empty?
|
|
574
587
|
Log.log.warn('Copying referenced files')
|
|
575
588
|
files_to_copy.each do |file|
|
|
@@ -584,7 +597,7 @@ module Aspera
|
|
|
584
597
|
Log.log.debug{"-> #{e.class.name} : #{e}"}
|
|
585
598
|
if File.exist?(@option_config_file)
|
|
586
599
|
# then there is a problem with that file.
|
|
587
|
-
new_name = "#{@option_config_file}.pre#{@
|
|
600
|
+
new_name = "#{@option_config_file}.pre#{@version}.manual_conversion_needed"
|
|
588
601
|
File.rename(@option_config_file, new_name)
|
|
589
602
|
Log.log.warn{"Renamed config file to #{new_name}."}
|
|
590
603
|
Log.log.warn('Manual Conversion is required. Next time, a new empty file will be created.')
|
|
@@ -592,33 +605,6 @@ module Aspera
|
|
|
592
605
|
raise Cli::Error, e.to_s
|
|
593
606
|
end
|
|
594
607
|
|
|
595
|
-
# find plugins in defined paths
|
|
596
|
-
def add_plugins_from_lookup_folders
|
|
597
|
-
@plugin_lookup_folders.each do |folder|
|
|
598
|
-
next unless File.directory?(folder)
|
|
599
|
-
# TODO: add gem root to load path ? and require short folder ?
|
|
600
|
-
# $LOAD_PATH.push(folder) if i[:add_path]
|
|
601
|
-
Dir.entries(folder).select{|file|file.end_with?(RUBY_FILE_EXT)}.each do |source|
|
|
602
|
-
add_plugin_info(File.join(folder, source))
|
|
603
|
-
end
|
|
604
|
-
end
|
|
605
|
-
end
|
|
606
|
-
|
|
607
|
-
def add_plugin_lookup_folder(folder)
|
|
608
|
-
@plugin_lookup_folders.unshift(folder)
|
|
609
|
-
end
|
|
610
|
-
|
|
611
|
-
def add_plugin_info(path)
|
|
612
|
-
raise "ERROR: plugin path must end with #{RUBY_FILE_EXT}" if !path.end_with?(RUBY_FILE_EXT)
|
|
613
|
-
plugin_symbol = File.basename(path, RUBY_FILE_EXT).to_sym
|
|
614
|
-
req = path.gsub(/#{RUBY_FILE_EXT}$/o, '')
|
|
615
|
-
if @plugins.key?(plugin_symbol)
|
|
616
|
-
Log.log.warn{"skipping plugin already registered: #{plugin_symbol}"}
|
|
617
|
-
return
|
|
618
|
-
end
|
|
619
|
-
@plugins[plugin_symbol] = {source: path, require_stanza: req}
|
|
620
|
-
end
|
|
621
|
-
|
|
622
608
|
# Find a plugin, and issue the "require"
|
|
623
609
|
# @return [Hash] plugin info: { product: , url:, version: }
|
|
624
610
|
def identify_plugins_for_url
|
|
@@ -626,33 +612,36 @@ module Aspera
|
|
|
626
612
|
check_only = options.get_next_argument('plugin name', mandatory: false)
|
|
627
613
|
check_only = check_only.to_sym unless check_only.nil?
|
|
628
614
|
found_apps = []
|
|
629
|
-
|
|
615
|
+
my_self_plugin_sym = self.class.name.split('::').last.downcase.to_sym
|
|
616
|
+
PluginFactory.instance.plugins.each do |plugin_name_sym, plugin_info|
|
|
630
617
|
# no detection for internal plugin
|
|
631
|
-
next if plugin_name_sym.eql?(
|
|
618
|
+
next if plugin_name_sym.eql?(my_self_plugin_sym)
|
|
632
619
|
next if check_only && !check_only.eql?(plugin_name_sym)
|
|
633
620
|
# load plugin class
|
|
634
621
|
require plugin_info[:require_stanza]
|
|
635
|
-
detect_plugin_class =
|
|
622
|
+
detect_plugin_class = PluginFactory.plugin_class(plugin_name_sym)
|
|
636
623
|
# requires detection method
|
|
637
624
|
next unless detect_plugin_class.respond_to?(:detect)
|
|
638
625
|
detection_info = nil
|
|
639
626
|
begin
|
|
627
|
+
Log.log.debug{"detecting #{plugin_name_sym} at #{app_url}"}
|
|
640
628
|
detection_info = detect_plugin_class.detect(app_url)
|
|
641
629
|
rescue OpenSSL::SSL::SSLError => e
|
|
642
630
|
Log.log.warn(e.message)
|
|
643
631
|
Log.log.warn('Use option --insecure=yes to allow unchecked certificate') if e.message.include?('cert')
|
|
644
632
|
rescue StandardError => e
|
|
645
|
-
Log.log.debug{"detect error: #{e}"}
|
|
633
|
+
Log.log.debug{"detect error: [#{e.class}] #{e}"}
|
|
646
634
|
next
|
|
647
635
|
end
|
|
648
636
|
next if detection_info.nil?
|
|
649
|
-
|
|
637
|
+
Aspera.assert_type(detection_info, Hash)
|
|
638
|
+
Aspera.assert_type(detection_info[:url], String) if detection_info.key?(:url)
|
|
650
639
|
app_name = detect_plugin_class.respond_to?(:application_name) ? detect_plugin_class.application_name : detect_plugin_class.name.split('::').last
|
|
651
640
|
# if there is a redirect, then the detector can override the url.
|
|
652
641
|
found_apps.push({product: plugin_name_sym, name: app_name, url: app_url, version: 'unknown'}.merge(detection_info))
|
|
653
642
|
end # loop
|
|
654
643
|
raise "No known application found at #{app_url}" if found_apps.empty?
|
|
655
|
-
|
|
644
|
+
Aspera.assert(found_apps.all?{|a|a.keys.all?(Symbol)})
|
|
656
645
|
return found_apps
|
|
657
646
|
end
|
|
658
647
|
|
|
@@ -666,10 +655,10 @@ module Aspera
|
|
|
666
655
|
case command
|
|
667
656
|
when :list
|
|
668
657
|
return {type: :object_list, data: connect_versions, fields: %w[id title version]}
|
|
669
|
-
when :info
|
|
658
|
+
when :info
|
|
670
659
|
one_res.delete('links')
|
|
671
660
|
return {type: :single_object, data: one_res}
|
|
672
|
-
when :version
|
|
661
|
+
when :version
|
|
673
662
|
all_links = one_res['links']
|
|
674
663
|
command = options.get_next_command(%i[list download open])
|
|
675
664
|
if %i[download open].include?(command)
|
|
@@ -678,15 +667,15 @@ module Aspera
|
|
|
678
667
|
raise 'no such value' if one_link.nil?
|
|
679
668
|
end
|
|
680
669
|
case command
|
|
681
|
-
when :list
|
|
670
|
+
when :list
|
|
682
671
|
return {type: :object_list, data: all_links}
|
|
683
672
|
when :download
|
|
684
|
-
folder_dest = transfer.destination_folder(
|
|
673
|
+
folder_dest = transfer.destination_folder(Transfer::Spec::DIRECTION_RECEIVE)
|
|
685
674
|
# folder_dest=self.options.get_next_argument('destination folder')
|
|
686
|
-
api_connect_cdn = Rest.new(
|
|
675
|
+
api_connect_cdn = Rest.new(base_url: CONNECT_WEB_URL)
|
|
687
676
|
file_url = one_link['href']
|
|
688
677
|
filename = file_url.gsub(%r{.*/}, '')
|
|
689
|
-
api_connect_cdn.call(
|
|
678
|
+
api_connect_cdn.call(operation: 'GET', subpath: file_url, save_to_file: File.join(folder_dest, filename))
|
|
690
679
|
return Main.result_status("Downloaded: #{filename}")
|
|
691
680
|
when :open
|
|
692
681
|
OpenApplication.instance.uri(one_link['href'])
|
|
@@ -702,79 +691,47 @@ module Aspera
|
|
|
702
691
|
return execute_connect_action
|
|
703
692
|
when :use
|
|
704
693
|
ascp_path = options.get_next_argument('path to ascp')
|
|
705
|
-
ascp_version =
|
|
694
|
+
ascp_version = Ascp::Installation.instance.get_ascp_version(ascp_path)
|
|
706
695
|
formatter.display_status("ascp version: #{ascp_version}")
|
|
707
696
|
set_global_default(:ascp_path, ascp_path)
|
|
708
697
|
return Main.result_nothing
|
|
709
|
-
when :show
|
|
710
|
-
return {type: :status, data:
|
|
711
|
-
when :info
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
last_line = ''
|
|
716
|
-
while (line = stderr.gets)
|
|
717
|
-
line.chomp!
|
|
718
|
-
last_line = line
|
|
719
|
-
case line
|
|
720
|
-
when /^DBG Path ([^ ]+) (dir|file) +: (.*)$/
|
|
721
|
-
data[Regexp.last_match(1)] = Regexp.last_match(3)
|
|
722
|
-
when /^DBG Added module group:"(?<module>[^"]+)" name:"(?<scheme>[^"]+)", version:"(?<version>[^"]+)" interface:"(?<interface>[^"]+)"$/
|
|
723
|
-
c = Regexp.last_match.named_captures.symbolize_keys
|
|
724
|
-
data[c[:interface]] ||= {}
|
|
725
|
-
data[c[:interface]][c[:module]] ||= []
|
|
726
|
-
data[c[:interface]][c[:module]].push("#{c[:scheme]} v#{c[:version]}")
|
|
727
|
-
when %r{^DBG License result \(/license/(\S+)\): (.+)$}
|
|
728
|
-
data[Regexp.last_match(1)] = Regexp.last_match(2)
|
|
729
|
-
when /^LOG (.+) version ([0-9.]+)$/
|
|
730
|
-
data['product_name'] = Regexp.last_match(1)
|
|
731
|
-
data['product_version'] = Regexp.last_match(2)
|
|
732
|
-
when /^LOG Initializing FASP version ([^,]+),/
|
|
733
|
-
data['ascp_version'] = Regexp.last_match(1)
|
|
734
|
-
end
|
|
735
|
-
end
|
|
736
|
-
if !thread.value.exitstatus.eql?(1) && !data.key?('root')
|
|
737
|
-
raise last_line
|
|
738
|
-
end
|
|
739
|
-
end
|
|
740
|
-
# ascp's openssl directory
|
|
741
|
-
ascp_file = data['ascp']
|
|
742
|
-
File.binread(ascp_file).scan(/[\x20-\x7E]{4,}/) do |match|
|
|
743
|
-
if (m = match.match(/OPENSSLDIR.*"(.*)"/))
|
|
744
|
-
data['openssldir'] = m[1]
|
|
745
|
-
end
|
|
746
|
-
end if File.file?(ascp_file)
|
|
747
|
-
data['uuid'] = Fasp::Installation.instance.ssh_cert_uuid
|
|
748
|
-
# log is "-" no need to display
|
|
749
|
-
data.delete('log')
|
|
750
|
-
# show command line transfer spec
|
|
698
|
+
when :show
|
|
699
|
+
return {type: :status, data: Ascp::Installation.instance.path(:ascp)}
|
|
700
|
+
when :info
|
|
701
|
+
# collect info from ascp executable
|
|
702
|
+
data = Ascp::Installation.instance.ascp_info
|
|
703
|
+
# add command line transfer spec
|
|
751
704
|
data['ts'] = transfer.updated_ts
|
|
705
|
+
# add keys
|
|
706
|
+
DataRepository::ELEMENTS.each_with_object(data){|i, h|h[i.to_s] = DataRepository.instance.item(i)}
|
|
707
|
+
# declare those as secrets
|
|
708
|
+
SecretHider::ADDITIONAL_KEYS_TO_HIDE.push(*DataRepository::ELEMENTS.map(&:to_s))
|
|
752
709
|
return {type: :single_object, data: data}
|
|
753
710
|
when :products
|
|
754
711
|
command = options.get_next_command(%i[list use])
|
|
755
712
|
case command
|
|
756
713
|
when :list
|
|
757
|
-
return {type: :object_list, data:
|
|
714
|
+
return {type: :object_list, data: Ascp::Products.installed_products, fields: %w[name app_root]}
|
|
758
715
|
when :use
|
|
759
716
|
default_product = options.get_next_argument('product name')
|
|
760
|
-
|
|
761
|
-
set_global_default(:ascp_path,
|
|
717
|
+
Ascp::Installation.instance.use_ascp_from_product(default_product)
|
|
718
|
+
set_global_default(:ascp_path, Ascp::Installation.instance.path(:ascp))
|
|
762
719
|
return Main.result_nothing
|
|
763
720
|
end
|
|
764
721
|
when :install
|
|
765
722
|
# reset to default location, if older default was used
|
|
766
|
-
|
|
767
|
-
v =
|
|
723
|
+
Ascp::Installation.instance.sdk_folder = self.class.default_app_main_folder(app_name: APP_NAME_SDK) if @sdk_default_location
|
|
724
|
+
v = Ascp::Installation.instance.install_sdk(options.get_option(:sdk_url, mandatory: true))
|
|
768
725
|
return Main.result_status("Installed version #{v}")
|
|
769
726
|
when :spec
|
|
770
727
|
return {
|
|
771
728
|
type: :object_list,
|
|
772
|
-
data:
|
|
773
|
-
fields: [%w[name type],
|
|
729
|
+
data: Transfer::Parameters.man_table,
|
|
730
|
+
fields: [%w[name type], Transfer::Parameters::SUPPORTED_AGENTS_SHORT.map(&:to_s), %w[description]].flatten.freeze
|
|
774
731
|
}
|
|
775
732
|
when :errors
|
|
776
733
|
error_data = []
|
|
777
|
-
|
|
734
|
+
Transfer::ERROR_INFO.each_pair do |code, prop|
|
|
778
735
|
error_data.push(code: code, mnemonic: prop[:c], retry: prop[:r], info: prop[:a])
|
|
779
736
|
end
|
|
780
737
|
return {type: :object_list, data: error_data}
|
|
@@ -887,6 +844,7 @@ module Aspera
|
|
|
887
844
|
open
|
|
888
845
|
documentation
|
|
889
846
|
genkey
|
|
847
|
+
pubkey
|
|
890
848
|
remote_certificate
|
|
891
849
|
gem
|
|
892
850
|
plugins
|
|
@@ -918,36 +876,45 @@ module Aspera
|
|
|
918
876
|
when :documentation
|
|
919
877
|
section = options.get_next_argument('private key file path', mandatory: false)
|
|
920
878
|
section = "##{section}" unless section.nil?
|
|
921
|
-
OpenApplication.instance.uri("#{@
|
|
879
|
+
OpenApplication.instance.uri("#{@help}#{section}")
|
|
922
880
|
return Main.result_nothing
|
|
923
881
|
when :genkey # generate new rsa key
|
|
924
882
|
private_key_path = options.get_next_argument('private key file path')
|
|
925
883
|
private_key_length = options.get_next_argument('size in bits', mandatory: false, type: Integer, default: DEFAULT_PRIV_KEY_LENGTH)
|
|
926
884
|
self.class.generate_rsa_private_key(path: private_key_path, length: private_key_length)
|
|
927
885
|
return Main.result_status("Generated #{private_key_length} bit RSA key: #{private_key_path}")
|
|
886
|
+
when :pubkey # get pub key
|
|
887
|
+
private_key_pem = options.get_next_argument('private key PEM value')
|
|
888
|
+
return Main.result_status(OpenSSL::PKey::RSA.new(private_key_pem).public_key.to_s)
|
|
928
889
|
when :remote_certificate
|
|
890
|
+
cert_action = options.get_next_command(%i[chain only name])
|
|
929
891
|
remote_url = options.get_next_argument('remote URL')
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
892
|
+
remote_chain = Rest.remote_certificate_chain(remote_url, as_string: false)
|
|
893
|
+
raise "No certificate found for #{remote_url}" unless remote_chain&.first
|
|
894
|
+
case cert_action
|
|
895
|
+
when :chain
|
|
896
|
+
return Main.result_status(remote_chain.map(&:to_pem).join("\n"))
|
|
897
|
+
when :only
|
|
898
|
+
return Main.result_status(remote_chain.first.to_pem)
|
|
899
|
+
when :name
|
|
900
|
+
return Main.result_status(remote_chain.first.subject.to_a.find { |name, _, _| name == 'CN' }[1])
|
|
901
|
+
end
|
|
935
902
|
when :echo # display the content of a value given on command line
|
|
936
903
|
return Formatter.auto_type(options.get_next_argument('value'))
|
|
937
904
|
when :flush_tokens
|
|
938
|
-
deleted_files =
|
|
905
|
+
deleted_files = OAuth::Factory.instance.flush_tokens
|
|
939
906
|
return {type: :value_list, data: deleted_files, name: 'file'}
|
|
940
907
|
when :plugins
|
|
941
908
|
case options.get_next_command(%i[list create])
|
|
942
909
|
when :list
|
|
943
910
|
result = []
|
|
944
|
-
|
|
911
|
+
PluginFactory.instance.plugins.each do |name, info|
|
|
945
912
|
require info[:require_stanza]
|
|
946
|
-
|
|
913
|
+
plugin_klass = PluginFactory.plugin_class(name)
|
|
947
914
|
result.push({
|
|
948
915
|
plugin: name,
|
|
949
|
-
detect: Formatter.tick(
|
|
950
|
-
wizard: Formatter.tick(
|
|
916
|
+
detect: Formatter.tick(plugin_klass.respond_to?(:detect)),
|
|
917
|
+
wizard: Formatter.tick(plugin_klass.respond_to?(:wizard)),
|
|
951
918
|
path: info[:source]
|
|
952
919
|
})
|
|
953
920
|
end
|
|
@@ -984,8 +951,7 @@ module Aspera
|
|
|
984
951
|
return wizard_find(apps)
|
|
985
952
|
when :coffee
|
|
986
953
|
if OpenApplication.instance.url_method.eql?(:text)
|
|
987
|
-
|
|
988
|
-
return Main.result_status(Preview::Terminal.build(Rest.new(base_url: COFFEE_IMAGE).read('')[:http].body))
|
|
954
|
+
return Main.result_picture_in_terminal(options, Rest.new(base_url: COFFEE_IMAGE).read('')[:http].body)
|
|
989
955
|
end
|
|
990
956
|
OpenApplication.instance.uri(COFFEE_IMAGE)
|
|
991
957
|
return Main.result_nothing
|
|
@@ -994,8 +960,8 @@ module Aspera
|
|
|
994
960
|
when :gem
|
|
995
961
|
case options.get_next_command(%i[path version name])
|
|
996
962
|
when :path then return Main.result_status(self.class.gem_src_root)
|
|
997
|
-
when :version then return Main.result_status(
|
|
998
|
-
when :name then return Main.result_status(@
|
|
963
|
+
when :version then return Main.result_status(Cli::VERSION)
|
|
964
|
+
when :name then return Main.result_status(@gem)
|
|
999
965
|
end
|
|
1000
966
|
when :folder
|
|
1001
967
|
return Main.result_status(@main_folder)
|
|
@@ -1014,24 +980,24 @@ module Aspera
|
|
|
1014
980
|
when :check_update
|
|
1015
981
|
return {type: :single_object, data: check_gem_version}
|
|
1016
982
|
when :initdemo
|
|
1017
|
-
if @config_presets.key?(
|
|
1018
|
-
Log.log.warn{"Demo server preset already present: #{
|
|
983
|
+
if @config_presets.key?(DEMO_PRESET)
|
|
984
|
+
Log.log.warn{"Demo server preset already present: #{DEMO_PRESET}"}
|
|
1019
985
|
else
|
|
1020
|
-
Log.log.info{"Creating Demo server preset: #{
|
|
1021
|
-
@config_presets[
|
|
1022
|
-
'url' => "ssh://#{
|
|
986
|
+
Log.log.info{"Creating Demo server preset: #{DEMO_PRESET}"}
|
|
987
|
+
@config_presets[DEMO_PRESET] = {
|
|
988
|
+
'url' => "ssh://#{DEMO_SERVER}.asperasoft.com:33001",
|
|
1023
989
|
'username' => ASPERA,
|
|
1024
|
-
'ssAP'.downcase.reverse + 'drow'.reverse =>
|
|
990
|
+
'ssAP'.downcase.reverse + 'drow'.reverse => DEMO_SERVER + ASPERA # cspell:disable-line
|
|
1025
991
|
}
|
|
1026
992
|
end
|
|
1027
|
-
@config_presets[
|
|
1028
|
-
if @config_presets[
|
|
1029
|
-
Log.log.warn{"Server default preset already set to: #{@config_presets[
|
|
1030
|
-
Log.log.warn{"Use #{
|
|
1031
|
-
|
|
993
|
+
@config_presets[CONF_PRESET_DEFAULTS] ||= {}
|
|
994
|
+
if @config_presets[CONF_PRESET_DEFAULTS].key?(SERVER_COMMAND)
|
|
995
|
+
Log.log.warn{"Server default preset already set to: #{@config_presets[CONF_PRESET_DEFAULTS][SERVER_COMMAND]}"}
|
|
996
|
+
Log.log.warn{"Use #{DEMO_PRESET} for demo: -P#{DEMO_PRESET}"} unless
|
|
997
|
+
DEMO_PRESET.eql?(@config_presets[CONF_PRESET_DEFAULTS][SERVER_COMMAND])
|
|
1032
998
|
else
|
|
1033
|
-
@config_presets[
|
|
1034
|
-
Log.log.info{"Setting server default preset to : #{
|
|
999
|
+
@config_presets[CONF_PRESET_DEFAULTS][SERVER_COMMAND] = DEMO_PRESET
|
|
1000
|
+
Log.log.info{"Setting server default preset to : #{DEMO_PRESET}"}
|
|
1035
1001
|
end
|
|
1036
1002
|
return Main.result_status('Done')
|
|
1037
1003
|
when :vault then execute_vault
|
|
@@ -1041,9 +1007,9 @@ module Aspera
|
|
|
1041
1007
|
exception_class_name = options.get_next_argument('exception class name', mandatory: true)
|
|
1042
1008
|
exception_text = options.get_next_argument('exception text', mandatory: true)
|
|
1043
1009
|
exception_class = Object.const_get(exception_class_name)
|
|
1044
|
-
|
|
1010
|
+
Aspera.assert(exception_class <= Exception){"#{exception_class} is not an exception: #{exception_class.class}"}
|
|
1045
1011
|
raise exception_class, exception_text
|
|
1046
|
-
else
|
|
1012
|
+
else Aspera.error_unreachable_line
|
|
1047
1013
|
end
|
|
1048
1014
|
end
|
|
1049
1015
|
|
|
@@ -1058,15 +1024,17 @@ module Aspera
|
|
|
1058
1024
|
apps.find{|a|a[:product].eql?(answer)}
|
|
1059
1025
|
end
|
|
1060
1026
|
wiz_url = identification[:url]
|
|
1061
|
-
Log.log.debug{Log.dump(:identification, identification
|
|
1027
|
+
Log.log.debug{Log.dump(:identification, identification)}
|
|
1062
1028
|
formatter.display_status("Using: #{identification[:name]} at #{wiz_url}".bold)
|
|
1063
1029
|
# set url for instantiation of plugin
|
|
1064
1030
|
options.add_option_preset({url: wiz_url})
|
|
1065
1031
|
# instantiate plugin: command line options will be known and wizard can be called
|
|
1066
|
-
wiz_plugin_class =
|
|
1067
|
-
|
|
1032
|
+
wiz_plugin_class = PluginFactory.plugin_class(identification[:product])
|
|
1033
|
+
Aspera.assert(wiz_plugin_class.respond_to?(:wizard), exception_class: Cli::BadArgument) do
|
|
1034
|
+
"Detected: #{identification[:product]}, but this application has no wizard"
|
|
1035
|
+
end
|
|
1068
1036
|
# instantiate plugin: command line options will be known, e.g. private_key
|
|
1069
|
-
plugin_instance = wiz_plugin_class.new(
|
|
1037
|
+
plugin_instance = wiz_plugin_class.new(**init_params)
|
|
1070
1038
|
wiz_params = {
|
|
1071
1039
|
object: plugin_instance
|
|
1072
1040
|
}
|
|
@@ -1089,7 +1057,7 @@ module Aspera
|
|
|
1089
1057
|
formatter.display_status('Using existing key:')
|
|
1090
1058
|
else
|
|
1091
1059
|
formatter.display_status("Generating #{DEFAULT_PRIV_KEY_LENGTH} bit RSA key...")
|
|
1092
|
-
|
|
1060
|
+
self.class.generate_rsa_private_key(path: private_key_path)
|
|
1093
1061
|
formatter.display_status('Created key:')
|
|
1094
1062
|
end
|
|
1095
1063
|
formatter.display_status(private_key_path)
|
|
@@ -1102,7 +1070,7 @@ module Aspera
|
|
|
1102
1070
|
# finally, call the wizard
|
|
1103
1071
|
wizard_result = wiz_plugin_class.wizard(**wiz_params)
|
|
1104
1072
|
Log.log.debug{"wizard result: #{wizard_result}"}
|
|
1105
|
-
|
|
1073
|
+
Aspera.assert(WIZARD_RESULT_KEYS.eql?(wizard_result.keys.sort)){"missing or extra keys in wizard result: #{wizard_result.keys}"}
|
|
1106
1074
|
# get preset name from user or default
|
|
1107
1075
|
wiz_preset_name = options.get_option(:id)
|
|
1108
1076
|
if wiz_preset_name.nil?
|
|
@@ -1118,22 +1086,22 @@ module Aspera
|
|
|
1118
1086
|
# Write configuration file
|
|
1119
1087
|
formatter.display_status("Preparing preset: #{wiz_preset_name}")
|
|
1120
1088
|
# init defaults if necessary
|
|
1121
|
-
@config_presets[
|
|
1089
|
+
@config_presets[CONF_PRESET_DEFAULTS] ||= {}
|
|
1122
1090
|
option_override = options.get_option(:override, mandatory: true)
|
|
1123
1091
|
raise Cli::Error, "A default configuration already exists for plugin '#{identification[:product]}' (use --override=yes or --default=no)" \
|
|
1124
|
-
if !option_override && options.get_option(:default, mandatory: true) && @config_presets[
|
|
1092
|
+
if !option_override && options.get_option(:default, mandatory: true) && @config_presets[CONF_PRESET_DEFAULTS].key?(identification[:product])
|
|
1125
1093
|
raise Cli::Error, "Preset already exists: #{wiz_preset_name} (use --override=yes or --id=<name>)" \
|
|
1126
1094
|
if !option_override && @config_presets.key?(wiz_preset_name)
|
|
1127
1095
|
@config_presets[wiz_preset_name] = wizard_result[:preset_value].stringify_keys
|
|
1128
1096
|
test_args = wizard_result[:test_args]
|
|
1129
1097
|
if options.get_option(:default, mandatory: true)
|
|
1130
1098
|
formatter.display_status("Setting config preset as default for #{identification[:product]}")
|
|
1131
|
-
@config_presets[
|
|
1099
|
+
@config_presets[CONF_PRESET_DEFAULTS][identification[:product].to_s] = wiz_preset_name
|
|
1132
1100
|
else
|
|
1133
1101
|
test_args = "-P#{wiz_preset_name} #{test_args}"
|
|
1134
1102
|
end
|
|
1135
1103
|
# TODO: actually test the command
|
|
1136
|
-
return Main.result_status("You can test with:\n#{@
|
|
1104
|
+
return Main.result_status("You can test with:\n#{@name} #{identification[:product]} #{test_args}")
|
|
1137
1105
|
end
|
|
1138
1106
|
|
|
1139
1107
|
# @return [Hash] email server setting with defaults if not defined
|
|
@@ -1151,11 +1119,11 @@ module Aspera
|
|
|
1151
1119
|
25
|
|
1152
1120
|
end
|
|
1153
1121
|
smtp[:from_email] ||= smtp[:username] if smtp.key?(:username)
|
|
1154
|
-
smtp[:from_name] ||= smtp[:from_email].
|
|
1155
|
-
smtp[:domain] ||= smtp[:from_email].
|
|
1122
|
+
smtp[:from_name] ||= smtp[:from_email].sub(/@.*$/, '').gsub(/[^a-zA-Z]/, ' ').capitalize if smtp.key?(:username)
|
|
1123
|
+
smtp[:domain] ||= smtp[:from_email].sub(/^.*@/, '') if smtp.key?(:from_email)
|
|
1156
1124
|
# check minimum required
|
|
1157
1125
|
%i[server port domain].each do |n|
|
|
1158
|
-
|
|
1126
|
+
Aspera.assert(smtp.key?(n)){"Missing mandatory smtp parameter: #{n}"}
|
|
1159
1127
|
end
|
|
1160
1128
|
Log.log.debug{"smtp=#{smtp}"}
|
|
1161
1129
|
return smtp
|
|
@@ -1169,7 +1137,7 @@ module Aspera
|
|
|
1169
1137
|
values[:from_name] ||= mail_conf[:from_name]
|
|
1170
1138
|
values[:from_email] ||= mail_conf[:from_email]
|
|
1171
1139
|
%i[from_name from_email].each do |n|
|
|
1172
|
-
|
|
1140
|
+
Aspera.assert(values.key?(n)){"Missing email parameter: #{n}"}
|
|
1173
1141
|
end
|
|
1174
1142
|
start_options = [mail_conf[:domain]]
|
|
1175
1143
|
start_options.push(mail_conf[:username], mail_conf[:password], :login) if mail_conf.key?(:username) && mail_conf.key?(:password)
|
|
@@ -1177,7 +1145,7 @@ module Aspera
|
|
|
1177
1145
|
template_binding = Environment.empty_binding
|
|
1178
1146
|
# add variables to binding
|
|
1179
1147
|
values.each do |k, v|
|
|
1180
|
-
|
|
1148
|
+
Aspera.assert_type(k, Symbol)
|
|
1181
1149
|
template_binding.local_variable_set(k, v)
|
|
1182
1150
|
end
|
|
1183
1151
|
# execute template
|
|
@@ -1211,19 +1179,19 @@ module Aspera
|
|
|
1211
1179
|
# returns [String] name if config_presets has default
|
|
1212
1180
|
# returns nil if there is no config or bypass default params
|
|
1213
1181
|
def get_plugin_default_config_name(plugin_name_sym)
|
|
1214
|
-
|
|
1182
|
+
Aspera.assert(!@config_presets.nil?){'config_presets shall be defined'}
|
|
1215
1183
|
if !@use_plugin_defaults
|
|
1216
1184
|
Log.log.debug('skip default config')
|
|
1217
1185
|
return nil
|
|
1218
1186
|
end
|
|
1219
|
-
if @config_presets.key?(
|
|
1220
|
-
@config_presets[
|
|
1221
|
-
default_config_name = @config_presets[
|
|
1187
|
+
if @config_presets.key?(CONF_PRESET_DEFAULTS) &&
|
|
1188
|
+
@config_presets[CONF_PRESET_DEFAULTS].key?(plugin_name_sym.to_s)
|
|
1189
|
+
default_config_name = @config_presets[CONF_PRESET_DEFAULTS][plugin_name_sym.to_s]
|
|
1222
1190
|
if !@config_presets.key?(default_config_name)
|
|
1223
1191
|
Log.log.error do
|
|
1224
1192
|
"Default config name [#{default_config_name}] specified for plugin [#{plugin_name_sym}], but it does not exist in config file.\n" \
|
|
1225
1193
|
'Please fix the issue: either create preset with one parameter: ' \
|
|
1226
|
-
"(#{@
|
|
1194
|
+
"(#{@name} config id #{default_config_name} init @json:'{}') or remove default (#{@name} config id default remove #{plugin_name_sym})."
|
|
1227
1195
|
end
|
|
1228
1196
|
end
|
|
1229
1197
|
raise Cli::Error, "Config name [#{default_config_name}] must be a hash, check config file." if !@config_presets[default_config_name].is_a?(Hash)
|
|
@@ -1235,16 +1203,17 @@ module Aspera
|
|
|
1235
1203
|
# TODO: delete: ALLOWED_KEYS = %i[password username description].freeze
|
|
1236
1204
|
# @return [Hash] result of execution of vault command
|
|
1237
1205
|
def execute_vault
|
|
1238
|
-
command = options.get_next_command(%i[list show create delete password])
|
|
1206
|
+
command = options.get_next_command(%i[info list show create delete password])
|
|
1239
1207
|
case command
|
|
1208
|
+
when :info
|
|
1209
|
+
return {type: :single_object, data: vault_info}
|
|
1240
1210
|
when :list
|
|
1241
1211
|
return {type: :object_list, data: vault.list}
|
|
1242
1212
|
when :show
|
|
1243
1213
|
return {type: :single_object, data: vault.get(label: options.get_next_argument('label'))}
|
|
1244
1214
|
when :create
|
|
1245
|
-
label = options.get_next_argument('label')
|
|
1246
|
-
info = options.get_next_argument('info Hash
|
|
1247
|
-
raise 'info must be Hash' unless info.is_a?(Hash)
|
|
1215
|
+
label = options.get_next_argument('label', type: String)
|
|
1216
|
+
info = options.get_next_argument('info', type: Hash)
|
|
1248
1217
|
info = info.symbolize_keys
|
|
1249
1218
|
info[:label] = label
|
|
1250
1219
|
vault.set(info)
|
|
@@ -1253,7 +1222,7 @@ module Aspera
|
|
|
1253
1222
|
vault.delete(label: options.get_next_argument('label'))
|
|
1254
1223
|
return Main.result_status('Password deleted')
|
|
1255
1224
|
when :password
|
|
1256
|
-
|
|
1225
|
+
Aspera.assert(vault.respond_to?(:password=)){'Vault does not support password change'}
|
|
1257
1226
|
new_password = options.get_next_argument('new_password')
|
|
1258
1227
|
vault.password = new_password
|
|
1259
1228
|
vault.save
|
|
@@ -1263,36 +1232,45 @@ module Aspera
|
|
|
1263
1232
|
|
|
1264
1233
|
# @return [String] value from vault matching <name>.<param>
|
|
1265
1234
|
def vault_value(name)
|
|
1266
|
-
m = name.
|
|
1267
|
-
raise 'vault name shall match <name>.<param>'
|
|
1235
|
+
m = name.split('.')
|
|
1236
|
+
raise 'vault name shall match <name>.<param>' unless m.length.eql?(2)
|
|
1268
1237
|
# this raise exception if label not found:
|
|
1269
|
-
info = vault.get(label: m[
|
|
1270
|
-
value = info[m[
|
|
1271
|
-
raise "no such entry value: #{m[
|
|
1238
|
+
info = vault.get(label: m[0])
|
|
1239
|
+
value = info[m[1].to_sym]
|
|
1240
|
+
raise "no such entry value: #{m[1]}" if value.nil?
|
|
1272
1241
|
return value
|
|
1273
1242
|
end
|
|
1274
1243
|
|
|
1244
|
+
def vault_info
|
|
1245
|
+
info = options.get_option(:vault) || {}
|
|
1246
|
+
info = info.symbolize_keys
|
|
1247
|
+
info[:type] ||= 'file'
|
|
1248
|
+
info[:name] ||= (info[:type].eql?('file') ? DEFAULT_VAULT_FILENAME : PROGRAM_NAME)
|
|
1249
|
+
Aspera.assert(info.keys.sort == %i[name type]) {"vault info shall have exactly keys 'type' and 'name'"}
|
|
1250
|
+
Aspera.assert(info.values.all?(String)){'vault info shall have only string values'}
|
|
1251
|
+
info[:password] = options.get_option(:vault_password, mandatory: true)
|
|
1252
|
+
return info
|
|
1253
|
+
end
|
|
1254
|
+
|
|
1275
1255
|
# @return [Object] vault, from options or cache
|
|
1276
1256
|
def vault
|
|
1277
1257
|
if @vault.nil?
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
vault_type = vault_info['type'] || 'file'
|
|
1281
|
-
vault_name = vault_info['name'] || (vault_type.eql?('file') ? 'vault.bin' : PROGRAM_NAME)
|
|
1282
|
-
case vault_type
|
|
1258
|
+
info = vault_info
|
|
1259
|
+
case info[:type]
|
|
1283
1260
|
when 'file'
|
|
1284
1261
|
# absolute_path? introduced in ruby 2.7
|
|
1285
|
-
|
|
1286
|
-
|
|
1262
|
+
@vault = Keychain::EncryptedHash.new(
|
|
1263
|
+
info[:name].eql?(File.absolute_path(info[:name])) ? info[:name] : File.join(@main_folder, info[:name]),
|
|
1264
|
+
info[:password])
|
|
1287
1265
|
when 'system'
|
|
1288
1266
|
case Environment.os
|
|
1289
1267
|
when Environment::OS_X
|
|
1290
|
-
@vault = Keychain::MacosSystem.new(
|
|
1268
|
+
@vault = Keychain::MacosSystem.new(info[:name], info[:password])
|
|
1291
1269
|
else
|
|
1292
1270
|
raise 'not implemented for this OS'
|
|
1293
1271
|
end
|
|
1294
1272
|
else
|
|
1295
|
-
raise Cli::BadArgument, "Unknown vault type: #{
|
|
1273
|
+
raise Cli::BadArgument, "Unknown vault type: #{info[:type]}"
|
|
1296
1274
|
end
|
|
1297
1275
|
end
|
|
1298
1276
|
raise 'No vault defined' if @vault.nil?
|
|
@@ -1301,14 +1279,14 @@ module Aspera
|
|
|
1301
1279
|
|
|
1302
1280
|
# version of URL without trailing "/" and removing default port
|
|
1303
1281
|
def canonical_url(url)
|
|
1304
|
-
url.
|
|
1282
|
+
url.sub(%r{/+$}, '').sub(%r{^(https://[^/]+):443$}, '\1')
|
|
1305
1283
|
end
|
|
1306
1284
|
|
|
1307
1285
|
def lookup_preset(url:, username:)
|
|
1308
1286
|
# remove extra info to maximize match
|
|
1309
1287
|
url = canonical_url(url)
|
|
1310
1288
|
Log.log.debug{"Lookup preset for #{username}@#{url}"}
|
|
1311
|
-
@config_presets.
|
|
1289
|
+
@config_presets.each_value do |v|
|
|
1312
1290
|
next unless v.is_a?(Hash)
|
|
1313
1291
|
conf_url = v['url'].is_a?(String) ? canonical_url(v['url']) : nil
|
|
1314
1292
|
return self.class.protect_presets(v) if conf_url.eql?(url) && v['username'].eql?(username)
|