aspera-cli 4.12.0 → 4.14.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.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +45 -5
  4. data/CONTRIBUTING.md +113 -22
  5. data/README.md +1289 -754
  6. data/bin/ascli +3 -3
  7. data/examples/dascli +1 -1
  8. data/examples/rubyc +24 -0
  9. data/lib/aspera/aoc.rb +63 -74
  10. data/lib/aspera/ascmd.rb +5 -3
  11. data/lib/aspera/cli/basic_auth_plugin.rb +6 -6
  12. data/lib/aspera/cli/extended_value.rb +24 -37
  13. data/lib/aspera/cli/formatter.rb +23 -25
  14. data/lib/aspera/cli/info.rb +2 -4
  15. data/lib/aspera/cli/main.rb +27 -27
  16. data/lib/aspera/cli/manager.rb +143 -120
  17. data/lib/aspera/cli/plugin.rb +88 -43
  18. data/lib/aspera/cli/plugins/alee.rb +2 -2
  19. data/lib/aspera/cli/plugins/aoc.rb +235 -104
  20. data/lib/aspera/cli/plugins/ats.rb +16 -18
  21. data/lib/aspera/cli/plugins/bss.rb +3 -3
  22. data/lib/aspera/cli/plugins/config.rb +190 -373
  23. data/lib/aspera/cli/plugins/console.rb +4 -6
  24. data/lib/aspera/cli/plugins/cos.rb +12 -13
  25. data/lib/aspera/cli/plugins/faspex.rb +21 -21
  26. data/lib/aspera/cli/plugins/faspex5.rb +399 -150
  27. data/lib/aspera/cli/plugins/node.rb +260 -174
  28. data/lib/aspera/cli/plugins/orchestrator.rb +15 -18
  29. data/lib/aspera/cli/plugins/preview.rb +40 -62
  30. data/lib/aspera/cli/plugins/server.rb +33 -16
  31. data/lib/aspera/cli/plugins/shares.rb +24 -33
  32. data/lib/aspera/cli/plugins/sync.rb +6 -6
  33. data/lib/aspera/cli/transfer_agent.rb +47 -30
  34. data/lib/aspera/cli/version.rb +2 -1
  35. data/lib/aspera/colors.rb +9 -7
  36. data/lib/aspera/command_line_builder.rb +2 -1
  37. data/lib/aspera/cos_node.rb +1 -1
  38. data/lib/aspera/data/6 +0 -0
  39. data/lib/aspera/environment.rb +7 -3
  40. data/lib/aspera/fasp/agent_connect.rb +6 -1
  41. data/lib/aspera/fasp/agent_direct.rb +17 -17
  42. data/lib/aspera/fasp/agent_httpgw.rb +138 -60
  43. data/lib/aspera/fasp/agent_node.rb +14 -4
  44. data/lib/aspera/fasp/agent_trsdk.rb +2 -0
  45. data/lib/aspera/fasp/error_info.rb +2 -0
  46. data/lib/aspera/fasp/installation.rb +19 -19
  47. data/lib/aspera/fasp/parameters.rb +29 -20
  48. data/lib/aspera/fasp/parameters.yaml +5 -2
  49. data/lib/aspera/fasp/resume_policy.rb +3 -3
  50. data/lib/aspera/fasp/transfer_spec.rb +8 -5
  51. data/lib/aspera/fasp/uri.rb +23 -21
  52. data/lib/aspera/faspex_gw.rb +1 -0
  53. data/lib/aspera/faspex_postproc.rb +3 -3
  54. data/lib/aspera/hash_ext.rb +12 -2
  55. data/lib/aspera/keychain/macos_security.rb +13 -13
  56. data/lib/aspera/log.rb +1 -0
  57. data/lib/aspera/node.rb +73 -84
  58. data/lib/aspera/oauth.rb +4 -3
  59. data/lib/aspera/persistency_action_once.rb +1 -1
  60. data/lib/aspera/preview/file_types.rb +8 -6
  61. data/lib/aspera/preview/generator.rb +23 -11
  62. data/lib/aspera/preview/options.rb +3 -2
  63. data/lib/aspera/preview/terminal.rb +80 -0
  64. data/lib/aspera/preview/utils.rb +11 -11
  65. data/lib/aspera/proxy_auto_config.js +2 -2
  66. data/lib/aspera/rest.rb +42 -4
  67. data/lib/aspera/rest_call_error.rb +3 -1
  68. data/lib/aspera/secret_hider.rb +10 -5
  69. data/lib/aspera/ssh.rb +1 -1
  70. data/lib/aspera/sync.rb +41 -33
  71. data/lib/aspera/web_server_simple.rb +22 -18
  72. data.tar.gz.sig +0 -0
  73. metadata +40 -48
  74. metadata.gz.sig +0 -0
  75. data/docs/test_env.conf +0 -179
  76. data/examples/aoc.rb +0 -30
  77. data/examples/faspex4.rb +0 -94
  78. data/examples/node.rb +0 -96
  79. data/examples/server.rb +0 -93
  80. data/lib/aspera/data/7 +0 -0
@@ -40,19 +40,15 @@ module Aspera
40
40
  CONF_PRESET_GLOBAL = 'global_common_defaults'
41
41
  CONF_PLUGIN_SYM = :config # Plugins::Config.name.split('::').last.downcase.to_sym
42
42
  CONF_GLOBAL_SYM = :config
43
- # old tool name
44
- PROGRAM_NAME_V1 = 'aslmcli'
45
- PROGRAM_NAME_V2 = 'mlia'
46
43
  # default redirect for AoC web auth
47
44
  DEFAULT_REDIRECT = 'http://localhost:12345'
48
45
  # folder containing custom plugins in user's config folder
49
46
  ASPERA_PLUGINS_FOLDERNAME = 'plugins'
50
47
  RUBY_FILE_EXT = '.rb'
51
- AOC_COMMAND_V1 = 'files'
52
- AOC_COMMAND_V2 = 'aspera'
53
- AOC_COMMAND_V3 = 'aoc'
54
- AOC_COMMAND_CURRENT = AOC_COMMAND_V3
48
+ ASPERA = 'aspera'
49
+ AOC_COMMAND = 'aoc'
55
50
  SERVER_COMMAND = 'server'
51
+ APP_NAME_SDK = 'sdk'
56
52
  CONNECT_WEB_URL = 'https://d3gcli72yxqn2z.cloudfront.net/connect'
57
53
  CONNECT_VERSIONS = 'connectversions.js'
58
54
  TRANSFER_SDK_ARCHIVE_URL = 'https://ibm.biz/aspera_transfer_sdk'
@@ -74,20 +70,17 @@ module Aspera
74
70
  DEFAULT_CHECK_NEW_VERSION_DAYS = 7
75
71
  DEFAULT_PRIV_KEY_FILENAME = 'aspera_aoc_key' # pragma: allowlist secret
76
72
  DEFAULT_PRIVKEY_LENGTH = 4096
73
+ COFFEE_IMAGE = 'https://enjoyjava.com/wp-content/uploads/2018/01/How-to-make-strong-coffee.jpg'
77
74
  private_constant :DEFAULT_CONFIG_FILENAME,
78
75
  :CONF_PRESET_CONFIG,
79
76
  :CONF_PRESET_VERSION,
80
77
  :CONF_PRESET_DEFAULT,
81
78
  :CONF_PRESET_GLOBAL,
82
- :PROGRAM_NAME_V1,
83
- :PROGRAM_NAME_V2,
84
79
  :DEFAULT_REDIRECT,
85
80
  :ASPERA_PLUGINS_FOLDERNAME,
86
81
  :RUBY_FILE_EXT,
87
- :AOC_COMMAND_V1,
88
- :AOC_COMMAND_V2,
89
- :AOC_COMMAND_V3,
90
- :AOC_COMMAND_CURRENT,
82
+ :ASPERA,
83
+ :AOC_COMMAND,
91
84
  :DEMO,
92
85
  :TRANSFER_SDK_ARCHIVE_URL,
93
86
  :AOC_PATH_API_CLIENTS,
@@ -99,7 +92,8 @@ module Aspera
99
92
  :DEFAULT_CHECK_NEW_VERSION_DAYS,
100
93
  :DEFAULT_PRIV_KEY_FILENAME,
101
94
  :SERVER_COMMAND,
102
- :PRESET_DIG_SEPARATOR
95
+ :PRESET_DIG_SEPARATOR,
96
+ :COFFEE_IMAGE
103
97
  def initialize(env, params)
104
98
  raise 'env and params must be Hash' unless env.is_a?(Hash) && params.is_a?(Hash)
105
99
  raise 'missing param' unless %i[name help version gem].sort.eql?(params.keys.sort)
@@ -115,57 +109,63 @@ module Aspera
115
109
  @conf_file_default = File.join(@main_folder, DEFAULT_CONFIG_FILENAME)
116
110
  @option_config_file = @conf_file_default
117
111
  @pac_exec = nil
112
+ @sdk_default_location = false
118
113
  Log.log.debug{"#{@info[:name]} folder: #{@main_folder}"}
119
114
  # set folder for FASP SDK
120
115
  add_plugin_lookup_folder(self.class.gem_plugins_folder)
121
116
  add_plugin_lookup_folder(File.join(@main_folder, ASPERA_PLUGINS_FOLDERNAME))
122
117
  # do file parameter first
123
- options.set_obj_attr(:config_file, self, :option_config_file)
124
- options.add_opt_simple(:config_file, "read parameters from file in YAML format, current=#{@option_config_file}")
118
+ options.declare(:config_file, "Read parameters from file in YAML format, current=#{@option_config_file}", handler: {o: self, m: :option_config_file})
125
119
  options.parse_options!
126
120
  # read correct file (set @config_presets)
127
121
  read_config_file
128
122
  # add preset handler (needed for smtp)
129
- ExtendedValue.instance.set_handler(EXTV_PRESET, :reader, lambda{|v|preset_by_name(v)})
130
- ExtendedValue.instance.set_handler(EXTV_INCLUDE_PRESETS, :decoder, lambda{|v|expanded_with_preset_includes(v)})
131
- ExtendedValue.instance.set_handler(EXTV_VAULT, :decoder, lambda{|v|vault_value(v)})
123
+ ExtendedValue.instance.set_handler(EXTV_PRESET, lambda{|v|preset_by_name(v)})
124
+ ExtendedValue.instance.set_handler(EXTV_INCLUDE_PRESETS, lambda{|v|expanded_with_preset_includes(v)})
125
+ ExtendedValue.instance.set_handler(EXTV_VAULT, lambda{|v|vault_value(v)})
132
126
  # load defaults before it can be overridden
133
127
  add_plugin_default_preset(CONF_GLOBAL_SYM)
134
128
  options.parse_options!
135
- options.set_obj_attr(:ascp_path, Fasp::Installation.instance, :ascp_path)
136
- options.set_obj_attr(:sdk_folder, Fasp::Installation.instance, :sdk_folder)
137
- options.set_obj_attr(:use_product, self, :option_use_product)
138
- options.set_obj_attr(:preset, self, :option_preset)
139
- options.set_obj_attr(:plugin_folder, self, :option_plugin_folder)
140
- options.add_opt_switch(:no_default, '-N', 'do not load default configuration for plugin') { @use_plugin_defaults = false }
141
- options.add_opt_boolean(:override, 'Wizard: override existing value')
142
- options.add_opt_boolean(:use_generic_client, 'Wizard: AoC: use global or org specific jwt client id')
143
- options.add_opt_boolean(:default, 'Wizard: set as default configuration for specified plugin (also: update)')
144
- options.add_opt_boolean(:test_mode, 'Wizard: skip private key check step')
145
- options.add_opt_simple(:preset, '-PVALUE', 'load the named option preset from current config file')
146
- options.add_opt_simple(:pkeypath, 'Wizard: path to private key for JWT')
147
- options.add_opt_simple(:ascp_path, 'Path to ascp')
148
- options.add_opt_simple(:use_product, 'Use ascp from specified product')
149
- options.add_opt_simple(:smtp, 'SMTP configuration (extended value: hash)')
150
- options.add_opt_simple(:fpac, 'Proxy auto configuration script')
151
- options.add_opt_simple(:proxy_credentials, 'HTTP proxy credentials (Array with user and password)')
152
- options.add_opt_simple(:secret, 'Secret for access keys')
153
- options.add_opt_simple(:vault, 'Vault for secrets')
154
- options.add_opt_simple(:vault_password, 'Vault password')
155
- options.add_opt_simple(:sdk_url, 'URL to get SDK')
156
- options.add_opt_simple(:sdk_folder, 'SDK folder path')
157
- options.add_opt_simple(:notif_to, 'Email recipient for notification of transfers')
158
- options.add_opt_simple(:notif_template, 'Email ERB template for notification of transfers')
159
- options.add_opt_simple(:version_check_days, Integer, 'Period in days to check new version (zero to disable)')
160
- options.add_opt_simple(:plugin_folder, 'Folder where to find additional plugins')
161
- options.set_option(:use_generic_client, true)
162
- options.set_option(:test_mode, false)
163
- options.set_option(:default, true)
164
- options.set_option(:version_check_days, DEFAULT_CHECK_NEW_VERSION_DAYS)
165
- options.set_option(:sdk_url, TRANSFER_SDK_ARCHIVE_URL)
166
- options.set_option(:sdk_folder, File.join(@main_folder, 'sdk'))
167
- options.set_option(:override, :no)
129
+ options.declare(:no_default, 'Do not load default configuration for plugin', values: :none, short: 'N') { @use_plugin_defaults = false }
130
+ options.declare(:override, 'Wizard: override existing value', values: :bool, default: :no)
131
+ options.declare(:use_generic_client, 'Wizard: AoC: use global or org specific jwt client id', values: :bool, default: true)
132
+ options.declare(:default, 'Wizard: set as default configuration for specified plugin (also: update)', values: :bool, default: true)
133
+ options.declare(:test_mode, 'Wizard: skip private key check step', values: :bool, default: false)
134
+ options.declare(:preset, 'Load the named option preset from current config file', short: 'P', handler: {o: self, m: :option_preset})
135
+ options.declare(:pkeypath, 'Wizard: path to private key for JWT')
136
+ options.declare(:ascp_path, 'Path to ascp', handler: {o: Fasp::Installation.instance, m: :ascp_path})
137
+ options.declare(:use_product, 'Use ascp from specified product', handler: {o: self, m: :option_use_product})
138
+ options.declare(:smtp, 'SMTP configuration', types: Hash)
139
+ options.declare(:fpac, 'Proxy auto configuration script')
140
+ options.declare(:proxy_credentials, 'HTTP proxy credentials (Array with user and password)')
141
+ options.declare(:secret, 'Secret for access keys')
142
+ options.declare(:vault, 'Vault for secrets')
143
+ options.declare(:vault_password, 'Vault password')
144
+ options.declare(:sdk_url, 'URL to get SDK', default: TRANSFER_SDK_ARCHIVE_URL)
145
+ options.declare(:sdk_folder, 'SDK folder path', handler: {o: Fasp::Installation.instance, m: :sdk_folder})
146
+ options.declare(:notif_to, 'Email recipient for notification of transfers')
147
+ options.declare(:notif_template, 'Email ERB template for notification of transfers')
148
+ options.declare(:version_check_days, 'Period in days to check new version (zero to disable)', coerce: Integer, default: DEFAULT_CHECK_NEW_VERSION_DAYS)
149
+ options.declare(:plugin_folder, 'Folder where to find additional plugins', handler: {o: self, m: :option_plugin_folder})
168
150
  options.parse_options!
151
+ # Check SDK folder is set or not, for compatibility, we check in two places
152
+ sdk_folder = Fasp::Installation.instance.sdk_folder rescue nil
153
+ if sdk_folder.nil?
154
+ @sdk_default_location = true
155
+ Log.log.debug('SDK folder is not set, checking default')
156
+ # new location
157
+ sdk_folder = default_app_main_folder(app_name: APP_NAME_SDK)
158
+ Log.log.debug{"checking: #{sdk_folder}"}
159
+ if !Dir.exist?(sdk_folder)
160
+ Log.log.debug{"not exists: #{sdk_folder}"}
161
+ # former location
162
+ former_sdk_folder = File.join(default_app_main_folder, APP_NAME_SDK)
163
+ Log.log.debug{"checking: #{former_sdk_folder}"}
164
+ sdk_folder = former_sdk_folder if Dir.exist?(former_sdk_folder)
165
+ end
166
+ Log.log.debug{"using: #{sdk_folder}"}
167
+ Fasp::Installation.instance.sdk_folder = sdk_folder
168
+ end
169
169
  pac_script = options.get_option(:fpac)
170
170
  # create PAC executor
171
171
  @pac_exec = Aspera::ProxyAutoConfig.new(pac_script).register_uri_generic unless pac_script.nil?
@@ -184,15 +184,20 @@ module Aspera
184
184
  return "#{@info[:name]}_home".upcase
185
185
  end
186
186
 
187
- def default_app_main_folder
187
+ # return product family folder (~/.aspera)
188
+ def module_family_folder
189
+ user_home_folder = Dir.home
190
+ raise CliError, "Home folder does not exist: #{user_home_folder}. Check your user environment." unless Dir.exist?(user_home_folder)
191
+ return File.join(user_home_folder, ASPERA_HOME_FOLDER_NAME)
192
+ end
193
+
194
+ # return product config folder (~/.aspera/<name>)
195
+ def default_app_main_folder(app_name: nil)
196
+ app_name = @info[:name] if app_name.nil?
188
197
  # find out application main folder
189
198
  app_folder = ENV[conf_dir_env_var]
190
199
  # if env var undefined or empty
191
- if app_folder.nil? || app_folder.empty?
192
- user_home_folder = Dir.home
193
- raise CliError, "Home folder does not exist: #{user_home_folder}. Check your user environment or use #{conf_dir_env_var}." unless Dir.exist?(user_home_folder)
194
- app_folder = File.join(user_home_folder, ASPERA_HOME_FOLDER_NAME, @info[:name])
195
- end
200
+ app_folder = File.join(module_family_folder, app_name) if app_folder.nil? || app_folder.empty?
196
201
  return app_folder
197
202
  end
198
203
 
@@ -220,7 +225,7 @@ module Aspera
220
225
 
221
226
  def periodic_check_newer_gem_version
222
227
  # get verification period
223
- delay_days = options.get_option(:version_check_days, is_type: :mandatory)
228
+ delay_days = options.get_option(:version_check_days, mandatory: true)
224
229
  Log.log.info{"check days: #{delay_days}"}
225
230
  # check only if not zero day
226
231
  return if delay_days.eql?(0)
@@ -281,17 +286,17 @@ module Aspera
281
286
 
282
287
  private
283
288
 
284
- def generate_rsa_private_key(private_key_path, length)
285
- require 'openssl'
286
- priv_key = OpenSSL::PKey::RSA.new(length)
287
- File.write(private_key_path, priv_key.to_s)
288
- File.write(private_key_path + '.pub', priv_key.public_key.to_s)
289
- Environment.restrict_file_access(private_key_path)
290
- Environment.restrict_file_access(private_key_path + '.pub')
291
- nil
292
- end
293
-
294
289
  class << self
290
+ def generate_rsa_private_key(path:, length: DEFAULT_PRIVKEY_LENGTH)
291
+ require 'openssl'
292
+ priv_key = OpenSSL::PKey::RSA.new(length)
293
+ File.write(path, priv_key.to_s)
294
+ File.write(path + '.pub', priv_key.public_key.to_s)
295
+ Environment.restrict_file_access(path)
296
+ Environment.restrict_file_access(path + '.pub')
297
+ nil
298
+ end
299
+
295
300
  # folder containing plugins in the gem's main folder
296
301
  def gem_plugins_folder
297
302
  File.dirname(File.expand_path(__FILE__))
@@ -350,7 +355,7 @@ module Aspera
350
355
  include_path = include_path.clone # avoid messing up if there are multiple branches
351
356
  current = @config_presets
352
357
  config_name.split(PRESET_DIG_SEPARATOR).each do |name|
353
- raise CliError, "Expecting Hash for subkey: #{include_path} (#{current.class})" unless current.is_a?(Hash)
358
+ raise CliError, "Expecting Hash for sub key: #{include_path} (#{current.class})" unless current.is_a?(Hash)
354
359
  include_path.push(name)
355
360
  current = current[name]
356
361
  raise CliError, "No such config preset: #{include_path}" if current.nil?
@@ -415,43 +420,15 @@ module Aspera
415
420
  end
416
421
  end
417
422
 
418
- def convert_preset_path(old_name, new_name, files_to_copy)
419
- old_subpath = File.join('', ASPERA_HOME_FOLDER_NAME, old_name, '')
420
- new_subpath = File.join('', ASPERA_HOME_FOLDER_NAME, new_name, '')
421
- # convert possible keys located in config folder
422
- @config_presets.values.select{|p|p.is_a?(Hash)}.each do |preset|
423
- preset.values.select{|v|v.is_a?(String) && v.include?(old_subpath)}.each do |value|
424
- old_val = value.clone
425
- included_path = File.expand_path(old_val.gsub(/^@file:/, ''))
426
- files_to_copy.push(included_path) unless files_to_copy.include?(included_path) || !File.exist?(included_path)
427
- value.gsub!(old_subpath, new_subpath)
428
- Log.log.warn{"Converted config value: #{old_val} -> #{value}"}
429
- end
430
- end
431
- end
432
-
433
- def convert_preset_plugin_name(old_name, new_name)
434
- default_preset = @config_presets[CONF_PRESET_DEFAULT]
435
- return unless default_preset.is_a?(Hash) && default_preset.key?(old_name)
436
- default_preset[new_name] = default_preset[old_name]
437
- default_preset.delete(old_name)
438
- Log.log.warn{"Converted plugin default: #{old_name} -> #{new_name}"}
439
- end
440
-
441
423
  # read config file and validate format
442
- # tries to convert from older version if possible and required
443
424
  def read_config_file
444
425
  Log.log.debug{"config file is: #{@option_config_file}".red}
445
- conf_file_v1 = File.join(Dir.home, ASPERA_HOME_FOLDER_NAME, PROGRAM_NAME_V1, DEFAULT_CONFIG_FILENAME)
446
- conf_file_v2 = File.join(Dir.home, ASPERA_HOME_FOLDER_NAME, PROGRAM_NAME_V2, DEFAULT_CONFIG_FILENAME)
447
426
  # files search for configuration, by default the one given by user
448
427
  search_files = [@option_config_file]
449
- # if default file, then also look for older versions
450
- search_files.push(conf_file_v2, conf_file_v1) if @option_config_file.eql?(@conf_file_default)
451
428
  # find first existing file (or nil)
452
429
  conf_file_to_load = search_files.find{|f| File.exist?(f)}
453
430
  # require save if old version of file
454
- save_required = !@option_config_file.eql?(conf_file_to_load)
431
+ save_required = false
455
432
  # if no file found, create default config
456
433
  if conf_file_to_load.nil?
457
434
  Log.log.warn{"No config file found. Creating empty configuration file: #{@option_config_file}"}
@@ -471,32 +448,8 @@ module Aspera
471
448
  if version.nil?
472
449
  raise 'No version found in config section.'
473
450
  end
474
- # oldest compatible conf file format, update to latest version when an incompatible change is made
475
- # check compatibility of version of conf file
476
- config_tested_version = '0.4.5'
477
- if Gem::Version.new(version) < Gem::Version.new(config_tested_version)
478
- raise "Unsupported config file version #{version}. Expecting min version #{config_tested_version}"
479
- end
480
- config_tested_version = '0.6.15'
481
- if Gem::Version.new(version) < Gem::Version.new(config_tested_version)
482
- convert_preset_plugin_name(AOC_COMMAND_V1, AOC_COMMAND_V2)
483
- version = @config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION] = config_tested_version
484
- save_required = true
485
- end
486
- config_tested_version = '0.8.10'
487
- if Gem::Version.new(version) <= Gem::Version.new(config_tested_version)
488
- convert_preset_path(PROGRAM_NAME_V1, PROGRAM_NAME_V2, files_to_copy)
489
- version = @config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION] = config_tested_version
490
- save_required = true
491
- end
492
- config_tested_version = '1.0'
493
- if Gem::Version.new(version) <= Gem::Version.new(config_tested_version)
494
- convert_preset_plugin_name(AOC_COMMAND_V2, AOC_COMMAND_V3)
495
- convert_preset_path(PROGRAM_NAME_V2, @info[:name], files_to_copy)
496
- version = @config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION] = config_tested_version
497
- save_required = true
498
- end
499
451
  Log.log.debug{"conf version: #{version}"}
452
+ # if there are any conversion needed, those happen here.
500
453
  # Place new compatibility code here
501
454
  if save_required
502
455
  Log.log.warn('Saving automatic conversion.')
@@ -550,13 +503,18 @@ module Aspera
550
503
  @plugins[plugin_symbol] = {source: path, require_stanza: req}
551
504
  end
552
505
 
553
- def identify_plugin_for_url(url)
506
+ # Find a plugin, and issue the "require"
507
+ # @return [Hash] plugin info: { product: , url:, version: }
508
+ def identify_plugin_for_url(url, check_only: nil)
509
+ check_only = check_only.to_sym unless check_only.nil?
554
510
  plugins.each do |plugin_name_sym, plugin_info|
555
511
  # no detection for internal plugin
556
512
  next if plugin_name_sym.eql?(CONF_PLUGIN_SYM)
513
+ next if check_only && !check_only.eql?(plugin_name_sym)
557
514
  # load plugin class
558
515
  require plugin_info[:require_stanza]
559
516
  c = self.class.plugin_class(plugin_name_sym)
517
+ # requires detection method
560
518
  next unless c.respond_to?(:detect)
561
519
  current_url = url
562
520
  detection_info = nil
@@ -565,7 +523,7 @@ module Aspera
565
523
  detection_info = c.detect(current_url)
566
524
  rescue OpenSSL::SSL::SSLError => e
567
525
  Log.log.warn(e.message)
568
- Log.log.warn('Use option --insecure=yes to ignore certificate') if e.message.include?('cert')
526
+ Log.log.warn('Use option --insecure=yes to allow unchecked certificate') if e.message.include?('cert')
569
527
  rescue StandardError => e
570
528
  Log.log.debug{"Cannot detect #{plugin_name_sym} : #{e.class}/#{e.message}"}
571
529
  end
@@ -674,6 +632,10 @@ module Aspera
674
632
  end
675
633
  end
676
634
  data['keypass'] = Fasp::Installation.instance.bypass_pass
635
+ # log is "-" no need to display
636
+ data.delete('log')
637
+ # show command line transfer spec
638
+ data['ts'] = transfer.updated_ts
677
639
  return {type: :single_object, data: data}
678
640
  when :products
679
641
  command = options.get_next_command(%i[list use])
@@ -687,7 +649,9 @@ module Aspera
687
649
  return Main.result_status("Saved to default global preset #{preset_name}")
688
650
  end
689
651
  when :install
690
- v = Fasp::Installation.instance.install_sdk(options.get_option(:sdk_url, is_type: :mandatory))
652
+ # reset to default location, if older default was used
653
+ Fasp::Installation.instance.sdk_folder = default_app_main_folder(app_name: APP_NAME_SDK) if @sdk_default_location
654
+ v = Fasp::Installation.instance.install_sdk(options.get_option(:sdk_url, mandatory: true))
691
655
  return Main.result_status("Installed version #{v}")
692
656
  when :spec
693
657
  return {
@@ -747,6 +711,7 @@ module Aspera
747
711
  when :set
748
712
  param_name = options.get_next_argument('parameter name')
749
713
  param_value = options.get_next_argument('parameter value')
714
+ param_name = Manager.option_line_to_name(param_name)
750
715
  if !@config_presets.key?(name)
751
716
  Log.log.debug{"no such config name: #{name}, initializing"}
752
717
  selected_preset = @config_presets[name] = {}
@@ -786,8 +751,8 @@ module Aspera
786
751
  return Main.result_status("Updated: #{name}")
787
752
  when :lookup
788
753
  BasicAuthPlugin.register_options(@agents)
789
- url = options.get_option(:url, is_type: :mandatory)
790
- user = options.get_option(:username, is_type: :mandatory)
754
+ url = options.get_option(:url, mandatory: true)
755
+ user = options.get_option(:username, mandatory: true)
791
756
  result = lookup_preset(url: url, username: user)
792
757
  raise 'no such config found' if result.nil?
793
758
  return {type: :single_object, data: result}
@@ -820,7 +785,6 @@ module Aspera
820
785
  end
821
786
 
822
787
  ACTIONS = %i[
823
- id
824
788
  preset
825
789
  open
826
790
  documentation
@@ -830,7 +794,6 @@ module Aspera
830
794
  flush_tokens
831
795
  echo
832
796
  wizard
833
- export_to_cli
834
797
  detect
835
798
  coffee
836
799
  ascp
@@ -841,19 +804,12 @@ module Aspera
841
804
  file
842
805
  check_update
843
806
  initdemo
844
- vault].concat(PRESET_GBL_ACTIONS).freeze
807
+ vault].freeze
845
808
 
846
809
  # "config" plugin
847
810
  def execute_action
848
811
  action = options.get_next_command(ACTIONS)
849
812
  case action
850
- when *PRESET_GBL_ACTIONS # older syntax
851
- Log.log.warn{"This syntax is deprecated, use command: preset #{action}"}
852
- return execute_preset(action: action)
853
- when :id # older syntax
854
- identifier = options.get_next_argument('config name')
855
- Log.log.warn{"This syntax is deprecated, use command: preset <verb> #{identifier}"}
856
- return execute_preset(name: identifier)
857
813
  when :preset # newer syntax
858
814
  return execute_preset
859
815
  when :open
@@ -867,7 +823,7 @@ module Aspera
867
823
  when :genkey # generate new rsa key
868
824
  private_key_path = options.get_next_argument('private key file path')
869
825
  private_key_length = options.get_next_argument('size in bits', mandatory: false) || DEFAULT_PRIVKEY_LENGTH
870
- generate_rsa_private_key(private_key_path, private_key_length)
826
+ self.class.generate_rsa_private_key(path: private_key_path, length: private_key_length)
871
827
  return Main.result_status('Generated key: ' + private_key_path)
872
828
  when :echo # display the content of a value given on command line
873
829
  result = {type: :other_struct, data: options.get_next_argument('value')}
@@ -909,72 +865,89 @@ module Aspera
909
865
  BasicAuthPlugin.register_options(@agents)
910
866
  params = {}
911
867
  # get from option, or ask
912
- params[:instance_url] = options.get_option(:url, is_type: :mandatory)
868
+ params[:instance_url] = options.get_option(:url, mandatory: true)
869
+ # check it is a well formatted url: starts with scheme
870
+ if !params[:instance_url].match?(%r{^[a-z]{1,6}://})
871
+ new_url = "https://#{params[:instance_url]}"
872
+ Log.log.warn("URL #{params[:instance_url]} does not start with a scheme, using #{new_url}")
873
+ params[:instance_url] = new_url
874
+ end
913
875
  # allow user to tell the preset name
914
876
  params[:preset_name] = options.get_option(:id)
915
- # allow user to specify type of application
916
- params[:application] = options.get_option(:value)
917
- params[:application] = params[:application].nil? ? identify_plugin_for_url(params[:instance_url])[:product] : params[:application].to_sym
918
- params[:plugin_name] = params[:application]
919
- params[:test_args] = '<replace per app>'
920
- case params[:application]
921
- when :faspex5
922
- wizard_faspex5(params)
923
- when :aoc
924
- wizard_aoc(params)
925
- else
926
- raise CliBadArgument, "Supports only: aoc. Detected: #{params[:application]}"
927
- end # product
928
- if params[:option_default]
929
- formatter.display_status("Setting config preset as default for #{params[:plugin_name]}")
930
- @config_presets[CONF_PRESET_DEFAULT][params[:plugin_name]] = params[:preset_name]
877
+ # allow user to specify type of application (symbol)
878
+ identification = identify_plugin_for_url(params[:instance_url], check_only: value_or_query(allowed_types: String))
879
+ Log.log.debug{"Detected: #{identification}"}
880
+ formatter.display_status("Detected: #{identification[:name]} at #{identification[:url]}".bold)
881
+ # we detected application (not set by user)
882
+ params[:plugin_sym] = identification[:product]
883
+ # update the url option
884
+ params[:instance_url] = identification[:url]
885
+ options.set_option(:url, params[:instance_url])
886
+ # instantiate plugin: command line options are known and wizard can be called
887
+ plugin_instance = self.class.plugin_class(params[:plugin_sym]).new(@agents.merge({skip_basic_auth_options: true}))
888
+ raise CliBadArgument, "Detected: #{params[:plugin_sym]}, no wizard available for this application" unless plugin_instance.respond_to?(:wizard)
889
+ # get default preset name if not set by user
890
+ params[:prepare] = true
891
+ plugin_instance.send(:wizard, params)
892
+ params[:prepare] = false
893
+
894
+ if params[:need_private_key]
895
+ # lets see if path to priv key is provided
896
+ private_key_path = options.get_option(:pkeypath)
897
+ # give a chance to provide
898
+ if private_key_path.nil?
899
+ formatter.display_status('Please provide path to your private RSA key, or empty to generate one:')
900
+ private_key_path = options.get_option(:pkeypath, mandatory: true).to_s
901
+ # private_key_path = File.expand_path(private_key_path)
902
+ end
903
+ # else generate path
904
+ if private_key_path.empty?
905
+ private_key_path = File.join(@main_folder, DEFAULT_PRIV_KEY_FILENAME)
906
+ end
907
+ if File.exist?(private_key_path)
908
+ formatter.display_status('Using existing key:')
909
+ else
910
+ formatter.display_status("Generating #{DEFAULT_PRIVKEY_LENGTH} bit RSA key...")
911
+ Config.generate_rsa_private_key(path: private_key_path)
912
+ formatter.display_status('Created key:')
913
+ end
914
+ formatter.display_status(private_key_path)
915
+ params[:pub_key_pem] = OpenSSL::PKey::RSA.new(File.read(private_key_path)).public_key.to_s
916
+ params[:private_key_path] = private_key_path
917
+ end
918
+
919
+ formatter.display_status("Preparing preset: #{params[:preset_name]}")
920
+ # init defaults if necessary
921
+ @config_presets[CONF_PRESET_DEFAULT] ||= {}
922
+ option_override = options.get_option(:override, mandatory: true)
923
+ raise CliError, "A default configuration already exists for plugin '#{params[:plugin_sym]}' (use --override=yes or --default=no)" \
924
+ if !option_override && options.get_option(:default, mandatory: true) && @config_presets[CONF_PRESET_DEFAULT].key?(params[:plugin_sym])
925
+ raise CliError, "Preset already exists: #{params[:preset_name]} (use --override=yes or --id=<name>)" \
926
+ if !option_override && @config_presets.key?(params[:preset_name])
927
+ wizard_result = plugin_instance.send(:wizard, params)
928
+ Log.log.debug{"wizard result: #{wizard_result}"}
929
+ raise "Internal error: missing keys in wizard result: #{wizard_result.keys}" unless %i[preset_value test_args].eql?(wizard_result.keys.sort)
930
+ @config_presets[params[:preset_name]] = wizard_result[:preset_value].stringify_keys
931
+ params[:test_args] = wizard_result[:test_args]
932
+ if options.get_option(:default, mandatory: true)
933
+ formatter.display_status("Setting config preset as default for #{params[:plugin_sym]}")
934
+ @config_presets[CONF_PRESET_DEFAULT][params[:plugin_sym].to_s] = params[:preset_name]
931
935
  else
932
936
  params[:test_args] = "-P#{params[:preset_name]} #{params[:test_args]}"
933
937
  end
934
938
  formatter.display_status('Saving config file.')
935
939
  save_presets_to_config_file
936
940
  return Main.result_status("Done.\nYou can test with:\n#{@info[:name]} #{params[:test_args]}")
937
- when :export_to_cli # this method shall be deprecated in the future: it was used to export configuration to "aspera.exe" CLI
938
- formatter.display_status('Exporting: Aspera on Cloud')
939
- require 'aspera/cli/plugins/aoc'
940
- # need url / username
941
- add_plugin_default_preset(AOC_COMMAND_V3.to_sym)
942
- # instantiate AoC plugin
943
- self.class.plugin_class(AOC_COMMAND_CURRENT).new(@agents) # TODO: is this line needed ? get options ?
944
- url = options.get_option(:url, is_type: :mandatory)
945
- cli_conf_file = Fasp::Installation.instance.cli_conf_file
946
- data = JSON.parse(File.read(cli_conf_file))
947
- organization, instance_domain = AoC.parse_url(url)
948
- key_basename = 'org_' + organization + '.pem'
949
- key_file = File.join(File.dirname(File.dirname(cli_conf_file)), 'etc', key_basename)
950
- File.write(key_file, options.get_option(:private_key, is_type: :mandatory))
951
- new_conf = {
952
- 'organization' => organization,
953
- 'hostname' => [organization, instance_domain].join('.'),
954
- 'privateKeyFilename' => key_basename,
955
- 'username' => options.get_option(:username, is_type: :mandatory)
956
- }
957
- new_conf['clientId'] = options.get_option(:client_id)
958
- new_conf['clientSecret'] = options.get_option(:client_secret)
959
- if new_conf['clientId'].nil?
960
- new_conf['clientId'], new_conf['clientSecret'] = AoC.get_client_info
961
- end
962
- entry = data['AoCAccounts'].find{|i|i['organization'].eql?(organization)}
963
- if entry.nil?
964
- data['AoCAccounts'].push(new_conf)
965
- formatter.display_status("Creating new aoc entry: #{organization}")
966
- else
967
- formatter.display_status("Updating existing aoc entry: #{organization}")
968
- entry.merge!(new_conf)
969
- end
970
- File.write(cli_conf_file, JSON.pretty_generate(data))
971
- return Main.result_status("Updated: #{cli_conf_file}")
972
941
  when :detect
973
942
  # need url / username
974
943
  BasicAuthPlugin.register_options(@agents)
975
- return {type: :single_object, data: identify_plugin_for_url(options.get_option(:url, is_type: :mandatory))}
944
+ return {type: :single_object, data: identify_plugin_for_url(options.get_option(:url, mandatory: true))}
976
945
  when :coffee
977
- OpenApplication.instance.uri('https://enjoyjava.com/wp-content/uploads/2018/01/How-to-make-strong-coffee.jpg')
946
+ if OpenApplication.instance.url_method.eql?(:text)
947
+ require 'aspera/preview/terminal'
948
+ return Main.result_status(Preview::Terminal.build(Rest.new(base_url: COFFEE_IMAGE).read('')[:http].body, reserved_lines: 3))
949
+ end
950
+ OpenApplication.instance.uri(COFFEE_IMAGE)
978
951
  return Main.result_nothing
979
952
  when :ascp
980
953
  execute_action_ascp
@@ -995,7 +968,7 @@ module Aspera
995
968
  return {type: :single_object, data: email_settings}
996
969
  when :proxy_check
997
970
  # ensure fpac was provided
998
- options.get_option(:fpac, is_type: :mandatory)
971
+ options.get_option(:fpac, mandatory: true)
999
972
  server_url = options.get_next_argument('server url')
1000
973
  return Main.result_status(@pac_exec.find_proxy_for_url(server_url))
1001
974
  when :check_update
@@ -1007,8 +980,8 @@ module Aspera
1007
980
  Log.log.info{"Creating Demo server preset: #{DEMO_SERVER_PRESET}"}
1008
981
  @config_presets[DEMO_SERVER_PRESET] = {
1009
982
  'url' => 'ssh://' + DEMO + '.asperasoft.com:33001',
1010
- 'username' => AOC_COMMAND_V2,
1011
- 'ssAP'.downcase.reverse + 'drow'.reverse => DEMO + AOC_COMMAND_V2
983
+ 'username' => ASPERA,
984
+ 'ssAP'.downcase.reverse + 'drow'.reverse => DEMO + ASPERA # cspell:disable-line
1012
985
  }
1013
986
  end
1014
987
  @config_presets[CONF_PRESET_DEFAULT] ||= {}
@@ -1029,18 +1002,24 @@ module Aspera
1029
1002
 
1030
1003
  # @return email server setting with defaults if not defined
1031
1004
  def email_settings
1032
- smtp = options.get_option(:smtp, is_type: :mandatory)
1005
+ smtp = options.get_option(:smtp, mandatory: true, allowed_types: [Hash])
1033
1006
  # change string keys into symbol keys
1034
- smtp = smtp.keys.each_with_object({}){|v, m|m[v.to_sym] = smtp[v]; }
1007
+ smtp = smtp.symbolize_keys
1035
1008
  # defaults
1036
- smtp[:tls] ||= true
1037
- smtp[:port] ||= smtp[:tls] ? 587 : 25
1009
+ smtp[:tls] = !smtp[:ssl] unless smtp.key?(:tls)
1010
+ smtp[:port] ||= if smtp[:tls]
1011
+ 587
1012
+ elsif smtp[:ssl]
1013
+ 465
1014
+ else
1015
+ 25
1016
+ end
1038
1017
  smtp[:from_email] ||= smtp[:username] if smtp.key?(:username)
1039
1018
  smtp[:from_name] ||= smtp[:from_email].gsub(/@.*$/, '').gsub(/[^a-zA-Z]/, ' ').capitalize if smtp.key?(:username)
1040
1019
  smtp[:domain] ||= smtp[:from_email].gsub(/^.*@/, '') if smtp.key?(:from_email)
1041
1020
  # check minimum required
1042
1021
  %i[server port domain].each do |n|
1043
- raise "Missing smtp parameter: #{n}" unless smtp.key?(n)
1022
+ raise "Missing mandatory smtp parameter: #{n}" unless smtp.key?(n)
1044
1023
  end
1045
1024
  Log.log.debug{"smtp=#{smtp}"}
1046
1025
  return smtp
@@ -1052,8 +1031,8 @@ module Aspera
1052
1031
  end
1053
1032
 
1054
1033
  def send_email_template(email_template_default: nil, values: {})
1055
- values[:to] ||= options.get_option(:notif_to, is_type: :mandatory)
1056
- notif_template = options.get_option(:notif_template, is_type: email_template_default.nil? ? :mandatory : :optional) || email_template_default
1034
+ values[:to] ||= options.get_option(:notif_to, mandatory: true)
1035
+ notif_template = options.get_option(:notif_template, mandatory: email_template_default.nil?) || email_template_default
1057
1036
  mail_conf = email_settings
1058
1037
  values[:from_name] ||= mail_conf[:from_name]
1059
1038
  values[:from_email] ||= mail_conf[:from_email]
@@ -1074,6 +1053,7 @@ module Aspera
1074
1053
  Log.dump(:msg_with_headers, msg_with_headers)
1075
1054
  smtp = Net::SMTP.new(mail_conf[:server], mail_conf[:port])
1076
1055
  smtp.enable_starttls if mail_conf[:tls]
1056
+ smtp.enable_tls if mail_conf[:ssl]
1077
1057
  smtp.start(*start_options) do |smtp_session|
1078
1058
  smtp_session.send_message(msg_with_headers, values[:from_email], values[:to])
1079
1059
  end
@@ -1090,20 +1070,20 @@ module Aspera
1090
1070
 
1091
1071
  # returns [String] name if config_presets has default
1092
1072
  # returns nil if there is no config or bypass default params
1093
- def get_plugin_default_config_name(plugin_sym)
1073
+ def get_plugin_default_config_name(plugin_name_sym)
1094
1074
  raise 'internal error: config_presets shall be defined' if @config_presets.nil?
1095
1075
  if !@use_plugin_defaults
1096
1076
  Log.log.debug('skip default config')
1097
1077
  return nil
1098
1078
  end
1099
1079
  if @config_presets.key?(CONF_PRESET_DEFAULT) &&
1100
- @config_presets[CONF_PRESET_DEFAULT].key?(plugin_sym.to_s)
1101
- default_config_name = @config_presets[CONF_PRESET_DEFAULT][plugin_sym.to_s]
1080
+ @config_presets[CONF_PRESET_DEFAULT].key?(plugin_name_sym.to_s)
1081
+ default_config_name = @config_presets[CONF_PRESET_DEFAULT][plugin_name_sym.to_s]
1102
1082
  if !@config_presets.key?(default_config_name)
1103
1083
  Log.log.error do
1104
- "Default config name [#{default_config_name}] specified for plugin [#{plugin_sym}], but it does not exist in config file.\n"\
1084
+ "Default config name [#{default_config_name}] specified for plugin [#{plugin_name_sym}], but it does not exist in config file.\n"\
1105
1085
  'Please fix the issue: either create preset with one parameter: '\
1106
- "(#{@info[:name]} config id #{default_config_name} init @json:'{}') or remove default (#{@info[:name]} config id default remove #{plugin_sym})."
1086
+ "(#{@info[:name]} config id #{default_config_name} init @json:'{}') or remove default (#{@info[:name]} config id default remove #{plugin_name_sym})."
1107
1087
  end
1108
1088
  end
1109
1089
  raise CliError, "Config name [#{default_config_name}] must be a hash, check config file." if !@config_presets[default_config_name].is_a?(Hash)
@@ -1153,7 +1133,7 @@ module Aspera
1153
1133
  def vault
1154
1134
  if @vault.nil?
1155
1135
  vault_info = options.get_option(:vault) || {'type' => 'file', 'name' => 'vault.bin'}
1156
- vault_password = options.get_option(:vault_password, is_type: :mandatory)
1136
+ vault_password = options.get_option(:vault_password, mandatory: true)
1157
1137
  raise 'vault must be Hash' unless vault_info.is_a?(Hash)
1158
1138
  vault_type = vault_info['type'] || 'file'
1159
1139
  vault_name = vault_info['name'] || (vault_type.eql?('file') ? 'vault.bin' : PROGRAM_NAME)
@@ -1207,169 +1187,6 @@ module Aspera
1207
1187
  end
1208
1188
  return secret
1209
1189
  end
1210
-
1211
- def wizard_aoc(params)
1212
- formatter.display_status('Detected: Aspera on Cloud'.bold)
1213
- params[:plugin_name] = AOC_COMMAND_CURRENT
1214
- organization = AoC.parse_url(params[:instance_url]).first
1215
- # if not defined by user, generate name
1216
- params[:preset_name] = [params[:application], organization].join('_') if params[:preset_name].nil?
1217
- formatter.display_status("Preparing preset: #{params[:preset_name]}")
1218
- # init defaults if necessary
1219
- @config_presets[CONF_PRESET_DEFAULT] ||= {}
1220
- option_override = options.get_option(:override, is_type: :mandatory)
1221
- params[:option_default] = options.get_option(:default, is_type: :mandatory)
1222
- Log.log.error{"override=#{option_override} -> #{option_override.class}"}
1223
- raise CliError, "A default configuration already exists for plugin '#{params[:plugin_name]}' (use --override=yes or --default=no)" \
1224
- if !option_override && params[:option_default] && @config_presets[CONF_PRESET_DEFAULT].key?(params[:plugin_name])
1225
- raise CliError, "Preset already exists: #{params[:preset_name]} (use --override=yes or --id=<name>)" \
1226
- if !option_override && @config_presets.key?(params[:preset_name])
1227
- # lets see if path to priv key is provided
1228
- private_key_path = options.get_option(:pkeypath)
1229
- # give a chance to provide
1230
- if private_key_path.nil?
1231
- formatter.display_status('Please provide path to your private RSA key, or empty to generate one:')
1232
- private_key_path = options.get_option(:pkeypath, is_type: :mandatory).to_s
1233
- end
1234
- # else generate path
1235
- if private_key_path.empty?
1236
- private_key_path = File.join(@main_folder, DEFAULT_PRIV_KEY_FILENAME)
1237
- end
1238
- if File.exist?(private_key_path)
1239
- formatter.display_status('Using existing key:')
1240
- else
1241
- formatter.display_status("Generating #{DEFAULT_PRIVKEY_LENGTH} bit RSA key...")
1242
- generate_rsa_private_key(private_key_path, DEFAULT_PRIVKEY_LENGTH)
1243
- formatter.display_status('Created:')
1244
- end
1245
- formatter.display_status(private_key_path)
1246
- pub_key_pem = OpenSSL::PKey::RSA.new(File.read(private_key_path)).public_key.to_s
1247
- # declare command line options for AoC
1248
- require 'aspera/cli/plugins/aoc'
1249
- # make username mandatory for jwt, this triggers interactive input
1250
- options.get_option(:username, is_type: :mandatory)
1251
- # instantiate AoC plugin, so that command line options are known
1252
- aoc_api = self.class.plugin_class(params[:plugin_name]).new(@agents.merge({skip_basic_auth_options: true, private_key_path: private_key_path})).aoc_api
1253
- auto_set_pub_key = false
1254
- auto_set_jwt = false
1255
- use_browser_authentication = false
1256
- if options.get_option(:use_generic_client)
1257
- formatter.display_status('Using global client_id.')
1258
- formatter.display_status('Please Login to your Aspera on Cloud instance.'.red)
1259
- formatter.display_status('Navigate to your "Account Settings"'.red)
1260
- formatter.display_status('Check or update the value of "Public Key" to be:'.red.blink)
1261
- formatter.display_status(pub_key_pem.to_s)
1262
- if !options.get_option(:test_mode)
1263
- formatter.display_status('Once updated or validated, press enter.')
1264
- OpenApplication.instance.uri(params[:instance_url])
1265
- $stdin.gets
1266
- end
1267
- else
1268
- formatter.display_status('Using organization specific client_id.')
1269
- if options.get_option(:client_id).nil? || options.get_option(:client_secret, is_type: :optional).nil?
1270
- formatter.display_status('Please login to your Aspera on Cloud instance.'.red)
1271
- formatter.display_status('Go to: Apps->Admin->Organization->Integrations')
1272
- formatter.display_status('Create or check if there is an existing integration named:')
1273
- formatter.display_status("- name: #{@info[:name]}")
1274
- formatter.display_status("- redirect uri: #{DEFAULT_REDIRECT}")
1275
- formatter.display_status('- origin: localhost')
1276
- formatter.display_status('Once created or identified,')
1277
- formatter.display_status('Please enter:'.red)
1278
- end
1279
- OpenApplication.instance.uri("#{params[:instance_url]}/#{AOC_PATH_API_CLIENTS}")
1280
- options.get_option(:client_id, is_type: :mandatory)
1281
- options.get_option(:client_secret, is_type: :mandatory)
1282
- use_browser_authentication = true
1283
- end
1284
- if use_browser_authentication
1285
- formatter.display_status('We will use web authentication to bootstrap.')
1286
- auto_set_pub_key = true
1287
- auto_set_jwt = true
1288
- aoc_api.oauth.generic_parameters[:grant_method] = :web
1289
- aoc_api.oauth.generic_parameters[:scope] = AoC::SCOPE_FILES_ADMIN
1290
- aoc_api.oauth.specific_parameters[:redirect_uri] = DEFAULT_REDIRECT
1291
- end
1292
- myself = aoc_api.read('self')[:data]
1293
- if auto_set_pub_key
1294
- raise CliError, 'Public key is already set in profile (use --override=yes)' unless myself['public_key'].empty? || option_override
1295
- formatter.display_status('Updating profile with new key')
1296
- aoc_api.update("users/#{myself['id']}", {'public_key' => pub_key_pem})
1297
- end
1298
- if auto_set_jwt
1299
- formatter.display_status('Enabling JWT for client')
1300
- aoc_api.update("clients/#{options.get_option(:client_id)}", {'jwt_grant_enabled' => true, 'explicit_authorization_required' => false})
1301
- end
1302
- formatter.display_status("Creating new config preset: #{params[:preset_name]}")
1303
- @config_presets[params[:preset_name]] = {
1304
- :url.to_s => options.get_option(:url),
1305
- :username.to_s => myself['email'],
1306
- :auth.to_s => :jwt.to_s,
1307
- :private_key.to_s => '@file:' + private_key_path
1308
- }
1309
- # set only if non nil
1310
- %i[client_id client_secret].each do |s|
1311
- o = options.get_option(s)
1312
- @config_presets[params[:preset_name]][s.to_s] = o unless o.nil?
1313
- end
1314
- params[:test_args] = "#{params[:plugin_name]} user profile show"
1315
- end
1316
-
1317
- def wizard_faspex5(params)
1318
- formatter.display_status('Detected: Faspex v5'.bold)
1319
- # if not defined by user, generate unique name
1320
- params[:preset_name] = [params[:application]].concat(URI.parse(params[:instance_url]).host.gsub(/[^a-z0-9.]/, '').split('.')).join('_') \
1321
- if params[:preset_name].nil?
1322
- formatter.display_status("Preparing preset: #{params[:preset_name]}")
1323
- # init defaults if necessary
1324
- @config_presets[CONF_PRESET_DEFAULT] ||= {}
1325
- option_override = options.get_option(:override, is_type: :mandatory)
1326
- params[:option_default] = options.get_option(:default, is_type: :mandatory)
1327
- Log.log.error{"override=#{option_override} -> #{option_override.class}"}
1328
- raise CliError, "A default configuration already exists for plugin '#{params[:plugin_name]}' (use --override=yes or --default=no)" \
1329
- if !option_override && params[:option_default] && @config_presets[CONF_PRESET_DEFAULT].key?(params[:plugin_name])
1330
- raise CliError, "Preset already exists: #{params[:preset_name]} (use --override=yes or --id=<name>)" \
1331
- if !option_override && @config_presets.key?(params[:preset_name])
1332
- # lets see if path to priv key is provided
1333
- private_key_path = options.get_option(:pkeypath)
1334
- # give a chance to provide
1335
- if private_key_path.nil?
1336
- formatter.display_status('Please provide path to your private RSA key, or empty to generate one:')
1337
- private_key_path = options.get_option(:pkeypath, is_type: :mandatory).to_s
1338
- end
1339
- # else generate path
1340
- if private_key_path.empty?
1341
- private_key_path = File.join(@main_folder, DEFAULT_PRIV_KEY_FILENAME)
1342
- end
1343
- if File.exist?(private_key_path)
1344
- formatter.display_status('Using existing key:')
1345
- else
1346
- formatter.display_status("Generating #{DEFAULT_PRIVKEY_LENGTH} bit RSA key...")
1347
- generate_rsa_private_key(private_key_path, DEFAULT_PRIVKEY_LENGTH)
1348
- formatter.display_status('Created:')
1349
- end
1350
- formatter.display_status(private_key_path)
1351
- pub_key_pem = OpenSSL::PKey::RSA.new(File.read(private_key_path)).public_key.to_s
1352
- # declare command line options for AoC
1353
- require 'aspera/cli/plugins/faspex5'
1354
- self.class.plugin_class(params[:plugin_name]).new(@agents.merge({skip_basic_auth_options: true}))
1355
- formatter.display_status('Please login to Faspex 5.'.red)
1356
- OpenApplication.instance.uri(params[:instance_url])
1357
- formatter.display_status('Navigate to: 𓃑 → Admin → Configurations → API clients')
1358
- formatter.display_status('Create a client with:')
1359
- formatter.display_status('- JWT enabled')
1360
- formatter.display_status('- The following public key:')
1361
- formatter.display_status(pub_key_pem.to_s)
1362
- formatter.display_status('Once created, copy the following parameters:')
1363
- @config_presets[params[:preset_name]] = {
1364
- :url.to_s => options.get_option(:url),
1365
- :username.to_s => options.get_option(:username),
1366
- :auth.to_s => :jwt.to_s,
1367
- :private_key.to_s => '@file:' + private_key_path,
1368
- :client_id.to_s => options.get_option(:client_id, is_type: :mandatory),
1369
- :client_secret.to_s => options.get_option(:client_secret, is_type: :mandatory)
1370
- }
1371
- params[:test_args] = "#{params[:plugin_name]} user profile show"
1372
- end
1373
1190
  end
1374
1191
  end
1375
1192
  end