aspera-cli 4.8.0 → 4.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/README.md +445 -160
- data/docs/test_env.conf +1 -5
- data/examples/dascli +1 -4
- data/examples/{transfer.rb → node.rb} +17 -46
- data/examples/server.rb +93 -0
- data/lib/aspera/aoc.rb +4 -2
- data/lib/aspera/ats_api.rb +3 -1
- data/lib/aspera/cli/extended_value.rb +1 -0
- data/lib/aspera/cli/formater.rb +3 -1
- data/lib/aspera/cli/info.rb +1 -1
- data/lib/aspera/cli/main.rb +14 -11
- data/lib/aspera/cli/manager.rb +4 -4
- data/lib/aspera/cli/plugin.rb +50 -9
- data/lib/aspera/cli/plugins/aoc.rb +88 -52
- data/lib/aspera/cli/plugins/config.rb +5 -0
- data/lib/aspera/cli/plugins/faspex.rb +5 -4
- data/lib/aspera/cli/plugins/node.rb +3 -2
- data/lib/aspera/cli/plugins/server.rb +7 -108
- data/lib/aspera/cli/plugins/shares.rb +21 -1
- data/lib/aspera/cli/transfer_agent.rb +21 -14
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/environment.rb +15 -2
- data/lib/aspera/fasp/agent_base.rb +9 -7
- data/lib/aspera/fasp/installation.rb +15 -19
- data/lib/aspera/fasp/parameters.rb +38 -30
- data/lib/aspera/fasp/parameters.yaml +69 -17
- data/lib/aspera/hash_ext.rb +14 -2
- data/lib/aspera/id_generator.rb +12 -10
- data/lib/aspera/keychain/encrypted_hash.rb +3 -3
- data/lib/aspera/log.rb +1 -1
- data/lib/aspera/nagios.rb +26 -19
- data/lib/aspera/oauth.rb +4 -4
- data/lib/aspera/open_application.rb +21 -19
- data/lib/aspera/persistency_folder.rb +3 -0
- data/lib/aspera/preview/image_error.png +0 -0
- data/lib/aspera/preview/video_error.png +0 -0
- data/lib/aspera/proxy_auto_config.rb +6 -4
- data/lib/aspera/rest_error_analyzer.rb +15 -13
- data/lib/aspera/rest_errors_aspera.rb +42 -40
- data/lib/aspera/secret_hider.rb +11 -5
- data/lib/aspera/ssh.rb +1 -0
- data/lib/aspera/uri_reader.rb +15 -13
- data.tar.gz.sig +0 -0
- metadata +4 -3
- metadata.gz.sig +0 -0
data/lib/aspera/oauth.rb
CHANGED
@@ -56,7 +56,7 @@ module Aspera
|
|
56
56
|
Log.log.debug('Not using persistency') # (use Aspera::Oauth.persist_mgr=Aspera::PersistencyFolder.new)
|
57
57
|
# create NULL persistency class
|
58
58
|
@persist = Class.new do
|
59
|
-
def get(_x);nil;end;def delete(_x);nil;end;def put(_x,_y);nil;end;def garbage_collect(_x,_y);nil;end
|
59
|
+
def get(_x);nil;end;def delete(_x);nil;end;def put(_x,_y);nil;end;def garbage_collect(_x,_y);nil;end # rubocop:disable Layout/EmptyLineBetweenDefs
|
60
60
|
end.new
|
61
61
|
end
|
62
62
|
return @persist
|
@@ -121,9 +121,9 @@ module Aspera
|
|
121
121
|
|
122
122
|
# Authentication using Web browser
|
123
123
|
register_token_creator :web,lambda { |oauth|
|
124
|
-
|
124
|
+
random_state = SecureRandom.uuid # used to check later
|
125
125
|
login_page_url = Rest.build_uri("#{oauth.api[:base_url]}/#{oauth.sparams[:path_authorize]}",
|
126
|
-
oauth.optional_scope_client_id.merge(response_type: 'code', redirect_uri: oauth.sparams[:redirect_uri], state:
|
126
|
+
oauth.optional_scope_client_id.merge(response_type: 'code', redirect_uri: oauth.sparams[:redirect_uri], state: random_state))
|
127
127
|
# here, we need a human to authorize on a web page
|
128
128
|
Log.log.info("login_page_url=#{login_page_url}".bg_red.gray)
|
129
129
|
# start a web server to receive request code
|
@@ -132,7 +132,7 @@ module Aspera
|
|
132
132
|
OpenApplication.instance.uri(login_page_url)
|
133
133
|
# wait for code in request
|
134
134
|
received_params = webserver.received_request
|
135
|
-
raise '
|
135
|
+
raise 'wrong received state' unless random_state.eql?(received_params['state'])
|
136
136
|
# exchange code for token
|
137
137
|
return oauth.create_token(oauth.optional_scope_client_id(add_secret: true).merge(
|
138
138
|
grant_type: 'authorization_code',
|
@@ -11,27 +11,29 @@ module Aspera
|
|
11
11
|
# if method is "graphical", then the URL will be opened with the default browser.
|
12
12
|
class OpenApplication
|
13
13
|
include Singleton
|
14
|
-
|
15
|
-
|
14
|
+
class << self
|
15
|
+
# User Interfaces
|
16
|
+
def user_interfaces; %i[text graphical]; end
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
def default_gui_mode
|
19
|
+
return :graphical if [Aspera::Environment::OS_WINDOWS,Aspera::Environment::OS_X].include?(Aspera::Environment.os)
|
20
|
+
# unix family
|
21
|
+
return :graphical if ENV.has_key?('DISPLAY') && !ENV['DISPLAY'].empty?
|
22
|
+
return :text
|
23
|
+
end
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
25
|
+
# command must be non blocking
|
26
|
+
def uri_graphical(uri)
|
27
|
+
case Aspera::Environment.os
|
28
|
+
when Aspera::Environment::OS_X
|
29
|
+
return system('open',uri.to_s)
|
30
|
+
when Aspera::Environment::OS_WINDOWS
|
31
|
+
return system('start explorer "' + uri.to_s + '"')
|
32
|
+
when Aspera::Environment::OS_LINUX
|
33
|
+
return system("xdg-open '#{uri}'")
|
34
|
+
else
|
35
|
+
raise "no graphical open method for #{Aspera::Environment.os}"
|
36
|
+
end
|
35
37
|
end
|
36
38
|
end
|
37
39
|
|
@@ -36,7 +36,9 @@ module Aspera
|
|
36
36
|
raise 'value: only String supported' unless value.is_a?(String)
|
37
37
|
persist_filepath = id_to_filepath(object_id)
|
38
38
|
Log.log.debug("persistency saving: #{persist_filepath}")
|
39
|
+
File.delete(persist_filepath) if File.exist?(persist_filepath)
|
39
40
|
File.write(persist_filepath,value)
|
41
|
+
File.chmod(0400,persist_filepath)
|
40
42
|
@cache[object_id] = value
|
41
43
|
end
|
42
44
|
|
@@ -66,6 +68,7 @@ module Aspera
|
|
66
68
|
def id_to_filepath(object_id)
|
67
69
|
raise 'object_id: only String supported' unless object_id.is_a?(String)
|
68
70
|
FileUtils.mkdir_p(@folder)
|
71
|
+
File.chmod(0700,@folder)
|
69
72
|
return File.join(@folder,"#{object_id}#{FILE_SUFFIX}")
|
70
73
|
#.gsub(/[^a-z]+/,FILE_FIELD_SEPARATOR)
|
71
74
|
end
|
Binary file
|
Binary file
|
@@ -7,10 +7,12 @@ module URI
|
|
7
7
|
class Generic
|
8
8
|
# save original method that finds proxy in URI::Generic, it uses env var http_proxy
|
9
9
|
alias_method :find_proxy_orig, :find_proxy
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
class << self
|
11
|
+
def register_proxy_finder
|
12
|
+
raise 'mandatory block missing' unless Kernel.block_given?
|
13
|
+
# overload the method in URI : call user's provided block and fallback to original method
|
14
|
+
define_method(:find_proxy) {|envars=ENV| yield(to_s) || find_proxy_orig(envars)}
|
15
|
+
end
|
14
16
|
end
|
15
17
|
end
|
16
18
|
end
|
@@ -80,19 +80,21 @@ module Aspera
|
|
80
80
|
end
|
81
81
|
end # add_simple_handler
|
82
82
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
call_context
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
"#{
|
83
|
+
class << self
|
84
|
+
# used by handler to add an error description to list of errors
|
85
|
+
# for logging and tracing : collect error descriptions (create file to activate)
|
86
|
+
# @param call_context a Hash containing the result call_context, provided to handler
|
87
|
+
# @param type a string describing type of exception, for logging purpose
|
88
|
+
# @param msg one error message to add to list
|
89
|
+
def add_error(call_context,type,msg)
|
90
|
+
call_context[:messages].push(msg)
|
91
|
+
logfile = instance.log_file
|
92
|
+
# log error for further analysis (file must exist to activate)
|
93
|
+
return if logfile.nil? || !File.exist?(logfile)
|
94
|
+
File.open(logfile,'a+') do |f|
|
95
|
+
f.write("\n=#{type}=====\n#{call_context[:request].method} #{call_context[:request].path}\n#{call_context[:response].code}\n"\
|
96
|
+
"#{JSON.generate(call_context[:data])}\n#{call_context[:messages].join("\n")}")
|
97
|
+
end
|
96
98
|
end
|
97
99
|
end
|
98
100
|
end
|
@@ -6,55 +6,57 @@ require 'aspera/log'
|
|
6
6
|
module Aspera
|
7
7
|
# REST error handlers for various Aspera REST APIs
|
8
8
|
class RestErrorsAspera
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
call_context[:data]['errors'].
|
24
|
-
|
9
|
+
class << self
|
10
|
+
# handlers should probably be defined by plugins for modularity
|
11
|
+
def register_handlers
|
12
|
+
Log.log.debug('registering Aspera REST error handlers')
|
13
|
+
# Faspex 4: both user_message and internal_message, and code 200
|
14
|
+
# example: missing meta data on package creation
|
15
|
+
RestErrorAnalyzer.instance.add_simple_handler('Type 1: error:user_message','error','user_message',true)
|
16
|
+
RestErrorAnalyzer.instance.add_simple_handler('Type 2: error:description','error','description')
|
17
|
+
RestErrorAnalyzer.instance.add_simple_handler('Type 3: error:internal_message','error','internal_message')
|
18
|
+
# AoC Automation
|
19
|
+
RestErrorAnalyzer.instance.add_simple_handler('AoC Automation','error')
|
20
|
+
RestErrorAnalyzer.instance.add_simple_handler('Type 5','error_description')
|
21
|
+
RestErrorAnalyzer.instance.add_simple_handler('Type 6','message')
|
22
|
+
RestErrorAnalyzer.instance.add_handler('Type 7: errors[]') do |name,call_context|
|
23
|
+
if call_context[:data].is_a?(Hash) && call_context[:data]['errors'].is_a?(Hash)
|
24
|
+
call_context[:data]['errors'].each do |k,v|
|
25
|
+
RestErrorAnalyzer.add_error(call_context,name,"#{k}: #{v}")
|
26
|
+
end
|
25
27
|
end
|
26
28
|
end
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
29
|
+
# call to upload_setup and download_setup of node api
|
30
|
+
RestErrorAnalyzer.instance.add_handler('T8:node: *_setup') do |type,call_context|
|
31
|
+
if call_context[:data].is_a?(Hash)
|
32
|
+
d_t_s = call_context[:data]['transfer_specs']
|
33
|
+
if d_t_s.is_a?(Array)
|
34
|
+
d_t_s.each do |res|
|
35
|
+
#r_err=res['transfer_spec']['error']
|
36
|
+
r_err = res['error']
|
37
|
+
if r_err.is_a?(Hash)
|
38
|
+
RestErrorAnalyzer.add_error(call_context,type,"#{r_err['code']}: #{r_err['reason']}: #{r_err['user_message']}")
|
39
|
+
end
|
38
40
|
end
|
39
41
|
end
|
40
42
|
end
|
41
43
|
end
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
44
|
+
RestErrorAnalyzer.instance.add_simple_handler('T9:IBM cloud IAM','errorMessage')
|
45
|
+
RestErrorAnalyzer.instance.add_simple_handler('T10:faspex v4','user_message')
|
46
|
+
RestErrorAnalyzer.instance.add_handler('bss graphql') do |type,call_context|
|
47
|
+
if call_context[:data].is_a?(Hash)
|
48
|
+
d_t_s = call_context[:data]['errors']
|
49
|
+
if d_t_s.is_a?(Array)
|
50
|
+
d_t_s.each do |res|
|
51
|
+
r_err = res['message']
|
52
|
+
if r_err.is_a?(String)
|
53
|
+
RestErrorAnalyzer.add_error(call_context,type,r_err)
|
54
|
+
end
|
53
55
|
end
|
54
56
|
end
|
55
57
|
end
|
56
58
|
end
|
57
|
-
end
|
58
|
-
end
|
59
|
+
end # register_handlers
|
60
|
+
end
|
59
61
|
end
|
60
62
|
end
|
data/lib/aspera/secret_hider.rb
CHANGED
@@ -8,11 +8,17 @@ module Aspera
|
|
8
8
|
# display string for hidden secrets
|
9
9
|
HIDDEN_PASSWORD = '🔑'
|
10
10
|
# keys in hash that contain secrets
|
11
|
-
|
11
|
+
ASCP_SECRETS=%w[ASPERA_SCP_PASS ASPERA_SCP_KEY ASPERA_SCP_FILEPASS ASPERA_PROXY_PASS].freeze
|
12
|
+
KEY_SECRETS =%w[password secret private_key passphrase].freeze
|
13
|
+
ALL_SECRETS =[ASCP_SECRETS,KEY_SECRETS].flatten.freeze
|
12
14
|
# regex that define namec captures :begin and :end
|
13
15
|
REGEX_LOG_REPLACES=[
|
14
|
-
#
|
15
|
-
/(?<begin>[
|
16
|
+
# CLI manager get/set options
|
17
|
+
/(?<begin>[sg]et (#{KEY_SECRETS.join('|')})=).*(?<end>)/,
|
18
|
+
# env var ascp exec
|
19
|
+
/(?<begin> (#{ASCP_SECRETS.join('|')})=)[^ ]*(?<end> )/,
|
20
|
+
# rendered JSON
|
21
|
+
/(?<begin>["':][^"]*(#{ALL_SECRETS.join('|')})[^"]*["']?[=>: ]+")[^"]+(?<end>")/,
|
16
22
|
# option "secret"
|
17
23
|
/(?<begin>"[^"]*(secret)[^"]*"=>{)[^}]+(?<end>})/,
|
18
24
|
# option "secrets"
|
@@ -20,7 +26,7 @@ module Aspera
|
|
20
26
|
# private key values
|
21
27
|
/(?<begin>--+BEGIN .+ KEY--+)[[:ascii:]]+?(?<end>--+?END .+ KEY--+)/
|
22
28
|
].freeze
|
23
|
-
private_constant :HIDDEN_PASSWORD,:
|
29
|
+
private_constant :HIDDEN_PASSWORD,:ASCP_SECRETS,:KEY_SECRETS,:ALL_SECRETS,:REGEX_LOG_REPLACES
|
24
30
|
@log_secrets = false
|
25
31
|
class << self
|
26
32
|
attr_accessor :log_secrets
|
@@ -40,7 +46,7 @@ module Aspera
|
|
40
46
|
def secret?(keyword,value)
|
41
47
|
keyword=keyword.to_s if keyword.is_a?(Symbol)
|
42
48
|
# only Strings can be secrets, not booleans, or hash, arrays
|
43
|
-
keyword.is_a?(String) &&
|
49
|
+
keyword.is_a?(String) && ALL_SECRETS.any?{|kw|keyword.include?(kw)} && value.is_a?(String)
|
44
50
|
end
|
45
51
|
|
46
52
|
def deep_remove_secret(obj,is_name_value: false)
|
data/lib/aspera/ssh.rb
CHANGED
@@ -17,6 +17,7 @@ module Aspera
|
|
17
17
|
# see: https://net-ssh.github.io/net-ssh/classes/Net/SSH.html#method-c-start
|
18
18
|
def initialize(host,username,ssh_options)
|
19
19
|
Log.log.debug("ssh:#{username}@#{host}")
|
20
|
+
Log.log.debug("ssh_options:#{ssh_options}")
|
20
21
|
@host = host
|
21
22
|
@username = username
|
22
23
|
@ssh_options = ssh_options
|
data/lib/aspera/uri_reader.rb
CHANGED
@@ -5,19 +5,21 @@ require 'aspera/rest'
|
|
5
5
|
|
6
6
|
module Aspera
|
7
7
|
module UriReader
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
8
|
+
class << self
|
9
|
+
# read some content from some URI, support file: , http: and https: schemes
|
10
|
+
def read(uri_to_read)
|
11
|
+
proxy_uri = URI.parse(uri_to_read)
|
12
|
+
case proxy_uri.scheme
|
13
|
+
when 'http','https'
|
14
|
+
return Rest.new(base_url: uri_to_read,redirect_max: 5).call(operation: 'GET', subpath: '', headers: {'Accept' => 'text/plain'})[:data]
|
15
|
+
when 'file',NilClass
|
16
|
+
local_file_path = proxy_uri.path
|
17
|
+
raise 'URL shall have a path, check syntax' if local_file_path.nil?
|
18
|
+
local_file_path = File.expand_path(local_file_path.gsub(/^\//,'')) if /^\/(~|.|..)\//.match?(local_file_path)
|
19
|
+
return File.read(local_file_path)
|
20
|
+
else
|
21
|
+
raise "unknown scheme: [#{proxy_uri.scheme}] for [#{uri_to_read}]"
|
22
|
+
end
|
21
23
|
end
|
22
24
|
end
|
23
25
|
end
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aspera-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Laurent Martin
|
@@ -35,7 +35,7 @@ cert_chain:
|
|
35
35
|
ZjkOWbUc1aLIsfaQFHWyNfisY9X2RgkFHjX0p5493wnoA7aWh52MUhc145npFh8z
|
36
36
|
v4P9xwkT02Shkert4B4iwNvVjoAUGk+J4090svZCroAyXBjon5LV7MJ4fyw=
|
37
37
|
-----END CERTIFICATE-----
|
38
|
-
date: 2022-
|
38
|
+
date: 2022-09-14 00:00:00.000000000 Z
|
39
39
|
dependencies:
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
41
|
name: execjs
|
@@ -395,8 +395,9 @@ files:
|
|
395
395
|
- examples/aoc.rb
|
396
396
|
- examples/dascli
|
397
397
|
- examples/faspex4.rb
|
398
|
+
- examples/node.rb
|
398
399
|
- examples/proxy.pac
|
399
|
-
- examples/
|
400
|
+
- examples/server.rb
|
400
401
|
- lib/aspera/aoc.rb
|
401
402
|
- lib/aspera/ascmd.rb
|
402
403
|
- lib/aspera/ats_api.rb
|
metadata.gz.sig
CHANGED
Binary file
|