aspera-cli 4.12.0 → 4.14.0

Sign up to get free protection for your applications and to get access to all the features.
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