aspera-cli 4.5.0 → 4.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +1 -0
- data/README.md +1894 -1574
- data/bin/ascli +21 -1
- data/bin/asession +38 -34
- data/docs/test_env.conf +14 -3
- data/examples/aoc.rb +17 -15
- data/examples/dascli +26 -0
- data/examples/faspex4.rb +42 -35
- data/examples/proxy.pac +1 -1
- data/examples/transfer.rb +38 -37
- data/lib/aspera/aoc.rb +245 -205
- data/lib/aspera/ascmd.rb +111 -90
- data/lib/aspera/ats_api.rb +16 -14
- data/lib/aspera/cli/basic_auth_plugin.rb +19 -18
- data/lib/aspera/cli/extended_value.rb +50 -39
- data/lib/aspera/cli/formater.rb +161 -135
- data/lib/aspera/cli/info.rb +18 -0
- data/lib/aspera/cli/listener/line_dump.rb +4 -2
- data/lib/aspera/cli/listener/logger.rb +3 -1
- data/lib/aspera/cli/listener/progress.rb +20 -21
- data/lib/aspera/cli/listener/progress_multi.rb +29 -31
- data/lib/aspera/cli/main.rb +194 -183
- data/lib/aspera/cli/manager.rb +213 -206
- data/lib/aspera/cli/plugin.rb +71 -49
- data/lib/aspera/cli/plugins/alee.rb +8 -7
- data/lib/aspera/cli/plugins/aoc.rb +675 -558
- data/lib/aspera/cli/plugins/ats.rb +116 -109
- data/lib/aspera/cli/plugins/bss.rb +35 -34
- data/lib/aspera/cli/plugins/config.rb +722 -542
- data/lib/aspera/cli/plugins/console.rb +28 -22
- data/lib/aspera/cli/plugins/cos.rb +28 -37
- data/lib/aspera/cli/plugins/faspex.rb +281 -227
- data/lib/aspera/cli/plugins/faspex5.rb +129 -84
- data/lib/aspera/cli/plugins/node.rb +426 -232
- data/lib/aspera/cli/plugins/orchestrator.rb +106 -98
- data/lib/aspera/cli/plugins/preview.rb +196 -191
- data/lib/aspera/cli/plugins/server.rb +131 -126
- data/lib/aspera/cli/plugins/shares.rb +49 -36
- data/lib/aspera/cli/plugins/sync.rb +27 -28
- data/lib/aspera/cli/transfer_agent.rb +84 -79
- data/lib/aspera/cli/version.rb +3 -1
- data/lib/aspera/colors.rb +37 -28
- data/lib/aspera/command_line_builder.rb +84 -63
- data/lib/aspera/cos_node.rb +68 -34
- data/lib/aspera/data_repository.rb +4 -2
- data/lib/aspera/environment.rb +61 -46
- data/lib/aspera/fasp/agent_base.rb +36 -31
- data/lib/aspera/fasp/agent_connect.rb +44 -37
- data/lib/aspera/fasp/agent_direct.rb +101 -104
- data/lib/aspera/fasp/agent_httpgw.rb +91 -90
- data/lib/aspera/fasp/agent_node.rb +36 -33
- data/lib/aspera/fasp/agent_trsdk.rb +28 -31
- data/lib/aspera/fasp/error.rb +3 -1
- data/lib/aspera/fasp/error_info.rb +81 -54
- data/lib/aspera/fasp/installation.rb +171 -151
- data/lib/aspera/fasp/listener.rb +2 -0
- data/lib/aspera/fasp/parameters.rb +105 -111
- data/lib/aspera/fasp/parameters.yaml +305 -249
- data/lib/aspera/fasp/resume_policy.rb +20 -20
- data/lib/aspera/fasp/transfer_spec.rb +27 -0
- data/lib/aspera/fasp/uri.rb +31 -29
- data/lib/aspera/faspex_gw.rb +95 -118
- data/lib/aspera/hash_ext.rb +12 -13
- data/lib/aspera/id_generator.rb +11 -9
- data/lib/aspera/keychain/encrypted_hash.rb +73 -57
- data/lib/aspera/keychain/macos_security.rb +27 -29
- data/lib/aspera/log.rb +40 -39
- data/lib/aspera/nagios.rb +24 -22
- data/lib/aspera/node.rb +38 -30
- data/lib/aspera/oauth.rb +217 -248
- data/lib/aspera/open_application.rb +9 -7
- data/lib/aspera/persistency_action_once.rb +15 -14
- data/lib/aspera/persistency_folder.rb +15 -18
- data/lib/aspera/preview/file_types.rb +266 -270
- data/lib/aspera/preview/generator.rb +94 -92
- data/lib/aspera/preview/image_error.png +0 -0
- data/lib/aspera/preview/options.rb +20 -17
- data/lib/aspera/preview/utils.rb +99 -102
- data/lib/aspera/preview/video_error.png +0 -0
- data/lib/aspera/{proxy_auto_config.erb.js → proxy_auto_config.js} +23 -31
- data/lib/aspera/proxy_auto_config.rb +114 -21
- data/lib/aspera/rest.rb +144 -142
- data/lib/aspera/rest_call_error.rb +3 -2
- data/lib/aspera/rest_error_analyzer.rb +31 -31
- data/lib/aspera/rest_errors_aspera.rb +18 -16
- data/lib/aspera/secret_hider.rb +68 -0
- data/lib/aspera/ssh.rb +20 -16
- data/lib/aspera/sync.rb +57 -54
- data/lib/aspera/temp_file_manager.rb +20 -14
- data/lib/aspera/timer_limiter.rb +10 -8
- data/lib/aspera/uri_reader.rb +14 -15
- data/lib/aspera/web_auth.rb +85 -80
- data.tar.gz.sig +0 -0
- metadata +169 -40
- metadata.gz.sig +2 -0
- data/bin/dascli +0 -13
- data/docs/Makefile +0 -63
- data/docs/README.erb.md +0 -4221
- data/docs/README.md +0 -13
- data/docs/diagrams.txt +0 -49
- data/docs/doc_tools.rb +0 -58
- data/lib/aspera/cli/plugins/shares2.rb +0 -114
- data/lib/aspera/fasp/default.rb +0 -17
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'singleton'
|
2
4
|
require 'aspera/log'
|
3
5
|
|
@@ -5,27 +7,23 @@ module Aspera
|
|
5
7
|
module Fasp
|
6
8
|
# implements a simple resume policy
|
7
9
|
class ResumePolicy
|
8
|
-
|
9
10
|
# list of supported parameters and default values
|
10
|
-
DEFAULTS={
|
11
|
-
:
|
12
|
-
:
|
13
|
-
:
|
14
|
-
:
|
15
|
-
}
|
11
|
+
DEFAULTS = {
|
12
|
+
iter_max: 7,
|
13
|
+
sleep_initial: 2,
|
14
|
+
sleep_factor: 2,
|
15
|
+
sleep_max: 60
|
16
|
+
}.freeze
|
16
17
|
|
17
18
|
# @param params see DEFAULTS
|
18
19
|
def initialize(params=nil)
|
19
|
-
@parameters=DEFAULTS.
|
20
|
+
@parameters = DEFAULTS.dup
|
20
21
|
if !params.nil?
|
21
22
|
raise "expecting Hash (or nil), but have #{params.class}" unless params.is_a?(Hash)
|
22
23
|
params.each do |k,v|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
else
|
27
|
-
raise "unknown resume parameter: #{k}, expect one of #{DEFAULTS.keys.map{|i|i.to_s}.join(",")}"
|
28
|
-
end
|
24
|
+
raise "unknown resume parameter: #{k}, expect one of #{DEFAULTS.keys.map(&:to_s).join(',')}" unless DEFAULTS.has_key?(k)
|
25
|
+
raise "#{k} must be Integer" unless v.is_a?(Integer)
|
26
|
+
@parameters[k] = v
|
29
27
|
end
|
30
28
|
end
|
31
29
|
Log.log.debug("resume params=#{@parameters}")
|
@@ -33,7 +31,8 @@ module Aspera
|
|
33
31
|
|
34
32
|
# calls block a number of times (resumes) until success or limit reached
|
35
33
|
# this is re-entrant, one resumer can handle multiple transfers in //
|
36
|
-
def
|
34
|
+
def execute_with_resume
|
35
|
+
raise 'block manndatory' unless block_given?
|
37
36
|
# maximum of retry
|
38
37
|
remaining_resumes = @parameters[:iter_max]
|
39
38
|
sleep_seconds = @parameters[:sleep_initial]
|
@@ -42,12 +41,13 @@ module Aspera
|
|
42
41
|
loop do
|
43
42
|
Log.log.debug('transfer starting');
|
44
43
|
begin
|
45
|
-
block
|
44
|
+
# call provided block
|
45
|
+
yield
|
46
46
|
break
|
47
47
|
rescue Fasp::Error => e
|
48
|
-
Log.log.warn("An error occured: #{e.message}"
|
48
|
+
Log.log.warn("An error occured: #{e.message}");
|
49
49
|
# failure in ascp
|
50
|
-
if e.retryable?
|
50
|
+
if e.retryable?
|
51
51
|
# exit if we exceed the max number of retry
|
52
52
|
raise Fasp::Error,'Maximum number of retry reached' if remaining_resumes <= 0
|
53
53
|
else
|
@@ -60,8 +60,8 @@ module Aspera
|
|
60
60
|
end
|
61
61
|
|
62
62
|
# take this retry in account
|
63
|
-
remaining_resumes-=1
|
64
|
-
Log.log.warn(
|
63
|
+
remaining_resumes -= 1
|
64
|
+
Log.log.warn("resuming in #{sleep_seconds} seconds (retry left:#{remaining_resumes})");
|
65
65
|
|
66
66
|
# wait a bit before retrying, maybe network condition will be better
|
67
67
|
sleep(sleep_seconds)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'aspera/fasp/parameters'
|
4
|
+
|
5
|
+
module Aspera
|
6
|
+
module Fasp
|
7
|
+
# parameters for Transfer Spec
|
8
|
+
class TransferSpec
|
9
|
+
# default transfer username for access key based transfers
|
10
|
+
ACCESS_KEY_TRANSFER_USER = 'xfer'
|
11
|
+
SSH_PORT = 33_001
|
12
|
+
UDP_PORT = 33_001
|
13
|
+
AK_TSPEC_BASE = {
|
14
|
+
'remote_user' => ACCESS_KEY_TRANSFER_USER,
|
15
|
+
'ssh_port' => SSH_PORT,
|
16
|
+
'fasp_port' => UDP_PORT
|
17
|
+
}.freeze
|
18
|
+
# define constants for enums of parameters: <paramater>_<enum>, e.g. CIPHER_AES_128
|
19
|
+
Aspera::Fasp::Parameters.description.each do |k,v|
|
20
|
+
next unless v[:enum].is_a?(Array)
|
21
|
+
v[:enum].each do |enum|
|
22
|
+
TransferSpec.const_set("#{k.to_s.upcase}_#{enum.upcase.gsub(/[^A-Z0-9]/,'_')}", enum.freeze)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/aspera/fasp/uri.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'aspera/log'
|
2
4
|
require 'aspera/command_line_builder'
|
3
5
|
|
@@ -6,42 +8,42 @@ module Aspera
|
|
6
8
|
# translates a "faspe:" URI (used in Faspex) into transfer spec hash
|
7
9
|
class Uri
|
8
10
|
def initialize(fasplink)
|
9
|
-
@fasp_uri=URI.parse(fasplink.gsub(' ','%20'))
|
11
|
+
@fasp_uri = URI.parse(fasplink.gsub(' ','%20'))
|
10
12
|
# TODO: check scheme is faspe
|
11
13
|
end
|
12
14
|
|
13
15
|
def transfer_spec
|
14
|
-
result_ts={}
|
15
|
-
result_ts['remote_host']
|
16
|
-
result_ts['remote_user']
|
17
|
-
result_ts['ssh_port']
|
18
|
-
result_ts['paths']=[{
|
16
|
+
result_ts = {}
|
17
|
+
result_ts['remote_host'] = @fasp_uri.host
|
18
|
+
result_ts['remote_user'] = @fasp_uri.user
|
19
|
+
result_ts['ssh_port'] = @fasp_uri.port
|
20
|
+
result_ts['paths'] = [{'source' => URI.decode_www_form_component(@fasp_uri.path)}]
|
19
21
|
# faspex does not encode trailing base64 encoded tags, fix that
|
20
|
-
fixed_query = @fasp_uri.query.gsub(/(=+)$/){|x|'%3D'*x.length}
|
22
|
+
fixed_query = @fasp_uri.query.gsub(/(=+)$/){|x|'%3D' * x.length}
|
21
23
|
|
22
|
-
URI
|
23
|
-
name=i[0]
|
24
|
-
value=i[1]
|
24
|
+
URI.decode_www_form(fixed_query).each do |i|
|
25
|
+
name = i[0]
|
26
|
+
value = i[1]
|
25
27
|
case name
|
26
|
-
when 'cookie'
|
27
|
-
when 'token'
|
28
|
-
when '
|
29
|
-
when '
|
30
|
-
when '
|
31
|
-
when '
|
32
|
-
when '
|
33
|
-
when '
|
34
|
-
when '
|
35
|
-
when '
|
36
|
-
when '
|
37
|
-
when '
|
38
|
-
when '
|
39
|
-
when '
|
40
|
-
when '
|
41
|
-
when 'auth'
|
42
|
-
when 'v'
|
43
|
-
when 'protect'
|
44
|
-
else Log.log.
|
28
|
+
when 'cookie' then result_ts['cookie'] = value
|
29
|
+
when 'token' then result_ts['token'] = value
|
30
|
+
when 'sshfp' then result_ts['sshfp'] = value
|
31
|
+
when 'policy' then result_ts['rate_policy'] = value
|
32
|
+
when 'httpport' then result_ts['http_fallback_port'] = value.to_i
|
33
|
+
when 'targetrate' then result_ts['target_rate_kbps'] = value.to_i
|
34
|
+
when 'minrate' then result_ts['min_rate_kbps'] = value.to_i
|
35
|
+
when 'port' then result_ts['fasp_port'] = value.to_i
|
36
|
+
when 'bwcap' then result_ts['target_rate_cap_kbps'] = value.to_i
|
37
|
+
when 'enc' then result_ts['cipher'] = value.gsub(/^aes/,'aes-').gsub(/cfb$/,'-cfb').gsub(/gcm$/,'-gcm').gsub(/--/,'-')
|
38
|
+
when 'tags64' then result_ts['tags'] = JSON.parse(Base64.strict_decode64(value))
|
39
|
+
when 'createpath' then result_ts['create_dir'] = CommandLineBuilder.yes_to_true(value)
|
40
|
+
when 'fallback' then result_ts['http_fallback'] = CommandLineBuilder.yes_to_true(value)
|
41
|
+
when 'lockpolicy' then result_ts['lock_rate_policy'] = CommandLineBuilder.yes_to_true(value)
|
42
|
+
when 'lockminrate' then result_ts['lock_min_rate'] = CommandLineBuilder.yes_to_true(value)
|
43
|
+
when 'auth' then Log.log.debug("ignoring auth #{name}=#{value}") # TODO: translate into transfer spec ? yes/no
|
44
|
+
when 'v' then Log.log.debug("ignoring v #{name}=#{value}") # TODO: translate into transfer spec ? 2
|
45
|
+
when 'protect' then Log.log.debug("ignoring protect #{name}=#{value}") # TODO: translate into transfer spec ?
|
46
|
+
else Log.log.warn("URI parameter ignored: #{name} = #{value}")
|
45
47
|
end
|
46
48
|
end
|
47
49
|
return result_ts
|
data/lib/aspera/faspex_gw.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'aspera/log'
|
2
4
|
require 'aspera/aoc'
|
3
|
-
require 'aspera/fasp/
|
5
|
+
require 'aspera/fasp/transfer_spec'
|
4
6
|
require 'aspera/cli/main'
|
5
7
|
require 'webrick'
|
6
8
|
require 'webrick/https'
|
@@ -12,13 +14,14 @@ module Aspera
|
|
12
14
|
# this class answers the Faspex /send API and creates a package on Aspera on Cloud
|
13
15
|
class FaspexGW
|
14
16
|
class FxGwServlet < WEBrick::HTTPServlet::AbstractServlet
|
15
|
-
def initialize(
|
16
|
-
|
17
|
-
@
|
17
|
+
def initialize(_server, a_aoc_api_user, a_workspace_id)
|
18
|
+
super
|
19
|
+
@aoc_api_user = a_aoc_api_user
|
20
|
+
@aoc_workspace_id = a_workspace_id
|
18
21
|
end
|
19
22
|
|
20
23
|
# parameters from user to Faspex API call
|
21
|
-
#{"delivery":{"use_encryption_at_rest":false,"note":"note","sources":[{"paths":["file1"]}],"title":"my title","recipients":["email1"],"send_upload_result":true}}
|
24
|
+
# {"delivery":{"use_encryption_at_rest":false,"note":"note","sources":[{"paths":["file1"]}],"title":"my title","recipients":["email1"],"send_upload_result":true}}
|
22
25
|
# {
|
23
26
|
# "delivery"=>{
|
24
27
|
# "use_encryption_at_rest"=>false,
|
@@ -30,164 +33,138 @@ module Aspera
|
|
30
33
|
# }
|
31
34
|
# }
|
32
35
|
def process_faspex_send(request, response)
|
33
|
-
raise
|
34
|
-
|
35
|
-
|
36
|
-
|
36
|
+
raise 'no payload' if request.body.nil?
|
37
|
+
|
38
|
+
faspex_pkg_parameters = JSON.parse(request.body)
|
39
|
+
faspex_pkg_delivery = faspex_pkg_parameters['delivery']
|
40
|
+
Log.log.debug("faspex pkg create parameters=#{faspex_pkg_parameters}")
|
37
41
|
|
38
42
|
# get recipient ids
|
39
|
-
files_pkg_recipients=[]
|
43
|
+
files_pkg_recipients = []
|
40
44
|
faspex_pkg_delivery['recipients'].each do |recipient_email|
|
41
|
-
user_lookup
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
+
user_lookup = @aoc_api_user.read('contacts',
|
46
|
+
{ 'current_workspace_id' => @aoc_workspace_id, 'q' => recipient_email })[:data]
|
47
|
+
raise StandardError,
|
48
|
+
"no such unique user: #{recipient_email} / #{user_lookup}" unless !user_lookup.nil? && user_lookup.length.eql?(1)
|
49
|
+
|
50
|
+
recipient_user_info = user_lookup.first
|
51
|
+
files_pkg_recipients.push({
|
52
|
+
'id' => recipient_user_info['source_id'],
|
53
|
+
'type' => recipient_user_info['source_type']
|
54
|
+
})
|
45
55
|
end
|
46
56
|
|
47
57
|
# create a new package with one file
|
48
|
-
the_package
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
58
|
+
the_package = @aoc_api_user.create('packages', {
|
59
|
+
'file_names' => faspex_pkg_delivery['sources'][0]['paths'],
|
60
|
+
'name' => faspex_pkg_delivery['title'],
|
61
|
+
'note' => faspex_pkg_delivery['note'],
|
62
|
+
'recipients' => files_pkg_recipients,
|
63
|
+
'workspace_id' => @aoc_workspace_id
|
64
|
+
})[:data]
|
54
65
|
|
55
66
|
# get node information for the node on which package must be created
|
56
|
-
node_info
|
67
|
+
node_info = @aoc_api_user.read("nodes/#{the_package['node_id']}")[:data]
|
57
68
|
|
58
69
|
# get transfer token (for node)
|
59
|
-
node_auth_bearer_token
|
70
|
+
node_auth_bearer_token = @aoc_api_user.oauth_token(scope: AoC.node_scope(node_info['access_key'],
|
71
|
+
AoC::SCOPE_NODE_USER))
|
60
72
|
|
61
73
|
# tell Files what to expect in package: 1 transfer (can also be done after transfer)
|
62
|
-
@aoc_api_user.update("packages/#{the_package['id']}",{
|
74
|
+
@aoc_api_user.update("packages/#{the_package['id']}", { 'sent' => true, 'transfers_expected' => 1 })
|
75
|
+
|
76
|
+
# to return an error:
|
77
|
+
# response.status=400
|
78
|
+
# return 'ERROR HERE'
|
63
79
|
|
64
|
-
if false
|
65
|
-
response.status=400
|
66
|
-
return "ERROR HERE"
|
67
|
-
end
|
68
80
|
# TODO: check about xfer_*
|
69
|
-
ts_tags={
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
81
|
+
ts_tags = {
|
82
|
+
'aspera' => {
|
83
|
+
'files' => { 'package_id' => the_package['id'], 'package_operation' => 'upload' },
|
84
|
+
'node' => { 'access_key' => node_info['access_key'], 'file_id' => the_package['contents_file_id'] },
|
85
|
+
'xfer_id' => SecureRandom.uuid,
|
86
|
+
'xfer_retry' => 3600
|
87
|
+
}
|
88
|
+
}
|
75
89
|
# this transfer spec is for transfer to AoC
|
76
|
-
faspex_transfer_spec={
|
77
|
-
'direction'
|
78
|
-
'remote_host'
|
79
|
-
'remote_user'
|
80
|
-
'ssh_port'
|
81
|
-
'fasp_port'
|
82
|
-
'tags'
|
83
|
-
'token'
|
84
|
-
'paths'
|
85
|
-
'cookie'
|
86
|
-
'create_dir'
|
87
|
-
'rate_policy'
|
88
|
-
'rate_policy_allowed'
|
89
|
-
'min_rate_cap_kbps'
|
90
|
-
'min_rate_kbps'
|
90
|
+
faspex_transfer_spec = {
|
91
|
+
'direction' => 'send',
|
92
|
+
'remote_host' => node_info['host'],
|
93
|
+
'remote_user' => Fasp::TransferSpec::ACCESS_KEY_TRANSFER_USER,
|
94
|
+
'ssh_port' => Fasp::TransferSpec::SSH_PORT,
|
95
|
+
'fasp_port' => Fasp::TransferSpec::UDP_PORT,
|
96
|
+
'tags' => ts_tags,
|
97
|
+
'token' => node_auth_bearer_token,
|
98
|
+
'paths' => [{ 'destination' => '/' }],
|
99
|
+
'cookie' => 'unused',
|
100
|
+
'create_dir' => true,
|
101
|
+
'rate_policy' => 'fair',
|
102
|
+
'rate_policy_allowed' => 'fixed',
|
103
|
+
'min_rate_cap_kbps' => nil,
|
104
|
+
'min_rate_kbps' => 0,
|
91
105
|
'target_rate_percentage' => nil,
|
92
|
-
'lock_target_rate'
|
93
|
-
'fasp_url'
|
94
|
-
'lock_min_rate'
|
95
|
-
'lock_rate_policy'
|
96
|
-
'source_root'
|
97
|
-
'content_protection'
|
98
|
-
'target_rate_cap_kbps'
|
99
|
-
'target_rate_kbps'
|
100
|
-
'cipher'
|
101
|
-
'cipher_allowed'
|
102
|
-
'http_fallback'
|
103
|
-
'http_fallback_port'
|
104
|
-
'https_fallback_port'
|
105
|
-
'destination_root'
|
106
|
+
'lock_target_rate' => nil,
|
107
|
+
'fasp_url' => 'unused',
|
108
|
+
'lock_min_rate' => true,
|
109
|
+
'lock_rate_policy' => true,
|
110
|
+
'source_root' => '',
|
111
|
+
'content_protection' => nil,
|
112
|
+
'target_rate_cap_kbps' => 20_000, # TODO: is this value useful ?
|
113
|
+
'target_rate_kbps' => 10_000, # TODO: get from where?
|
114
|
+
'cipher' => 'aes-128',
|
115
|
+
'cipher_allowed' => nil,
|
116
|
+
'http_fallback' => false,
|
117
|
+
'http_fallback_port' => nil,
|
118
|
+
'https_fallback_port' => nil,
|
119
|
+
'destination_root' => '/'
|
106
120
|
}
|
107
121
|
# but we place it in a Faspex package creation response
|
108
|
-
faspex_package_create_result={
|
109
|
-
'links'
|
122
|
+
faspex_package_create_result = {
|
123
|
+
'links' => { 'status' => 'unused' },
|
110
124
|
'xfer_sessions' => [faspex_transfer_spec]
|
111
125
|
}
|
112
126
|
Log.log.info("faspex_package_create_result=#{faspex_package_create_result}")
|
113
|
-
response.status=200
|
114
|
-
response.content_type =
|
115
|
-
response.body=JSON.generate(faspex_package_create_result)
|
127
|
+
response.status = 200
|
128
|
+
response.content_type = 'application/json'
|
129
|
+
response.body = JSON.generate(faspex_package_create_result)
|
116
130
|
end
|
117
131
|
|
118
|
-
def do_GET
|
132
|
+
def do_GET(request, response)
|
119
133
|
case request.path
|
120
134
|
when '/aspera/faspex/send'
|
121
135
|
process_faspex_send(request, response)
|
122
136
|
else
|
123
|
-
response.status=400
|
124
|
-
|
125
|
-
raise "unsupported path: #{request.path}"
|
137
|
+
response.status = 400
|
138
|
+
'ERROR HERE'
|
126
139
|
end
|
127
140
|
end
|
128
141
|
end # FxGwServlet
|
129
142
|
|
130
143
|
class NewUserServlet < WEBrick::HTTPServlet::AbstractServlet
|
131
|
-
def do_GET
|
144
|
+
def do_GET(request, response)
|
132
145
|
case request.path
|
133
146
|
when '/newuser'
|
134
|
-
response.status=200
|
135
|
-
response.content_type =
|
136
|
-
response.body='<html><body>hello world</body></html>'
|
147
|
+
response.status = 200
|
148
|
+
response.content_type = 'text/html'
|
149
|
+
response.body = '<html><body>hello world</body></html>'
|
137
150
|
else
|
138
151
|
raise "unsupported path: [#{request.path}]"
|
139
152
|
end
|
140
153
|
end
|
141
154
|
end
|
142
155
|
|
143
|
-
def
|
144
|
-
key = OpenSSL::PKey::RSA.new(4096)
|
145
|
-
cert = OpenSSL::X509::Certificate.new
|
146
|
-
cert.subject = cert.issuer = OpenSSL::X509::Name.parse("/C=FR/O=Test/OU=Test/CN=Test")
|
147
|
-
cert.not_before = Time.now
|
148
|
-
cert.not_after = Time.now + 365 * 24 * 60 * 60
|
149
|
-
cert.public_key = key.public_key
|
150
|
-
cert.serial = 0x0
|
151
|
-
cert.version = 2
|
152
|
-
ef = OpenSSL::X509::ExtensionFactory.new
|
153
|
-
ef.issuer_certificate = cert
|
154
|
-
ef.subject_certificate = cert
|
155
|
-
cert.extensions = [
|
156
|
-
ef.create_extension("basicConstraints","CA:TRUE", true),
|
157
|
-
ef.create_extension("subjectKeyIdentifier", "hash"),
|
158
|
-
# ef.create_extension("keyUsage", "cRLSign,keyCertSign", true),
|
159
|
-
]
|
160
|
-
cert.add_extension(ef.create_extension("authorityKeyIdentifier","keyid:always,issuer:always"))
|
161
|
-
cert.sign(key, OpenSSL::Digest::SHA256.new)
|
162
|
-
options[:SSLPrivateKey] = key
|
163
|
-
options[:SSLCertificate] = cert
|
164
|
-
end
|
165
|
-
|
166
|
-
def initialize(a_aoc_api_user,a_workspace_id)
|
156
|
+
def initialize(a_aoc_api_user, a_workspace_id)
|
167
157
|
webrick_options = {
|
168
|
-
:
|
169
|
-
:
|
170
|
-
:
|
171
|
-
|
172
|
-
:SSLEnable => true,
|
173
|
-
:SSLVerifyClient => OpenSSL::SSL::VERIFY_NONE,
|
158
|
+
Port: 9443,
|
159
|
+
Logger: Log.log,
|
160
|
+
SSLEnable: true,
|
161
|
+
SSLCertName: [['CN', WEBrick::Utils.getservername]]
|
174
162
|
}
|
175
|
-
case 2
|
176
|
-
when 0
|
177
|
-
# generate self signed cert
|
178
|
-
webrick_options[:SSLCertName] = [ [ 'CN',WEBrick::Utils::getservername ] ]
|
179
|
-
Log.log.error(">>>#{webrick_options[:SSLCertName]}")
|
180
|
-
when 1
|
181
|
-
fill_self_signed_cert(webrick_options)
|
182
|
-
when 2
|
183
|
-
webrick_options[:SSLPrivateKey] =OpenSSL::PKey::RSA.new(File.read('/Users/laurent/workspace/Tools/certificate/myserver.key'))
|
184
|
-
webrick_options[:SSLCertificate] = OpenSSL::X509::Certificate.new(File.read('/Users/laurent/workspace/Tools/certificate/myserver.crt'))
|
185
|
-
end
|
186
163
|
Log.log.info("Server started on port #{webrick_options[:Port]}")
|
187
164
|
@server = WEBrick::HTTPServer.new(webrick_options)
|
188
|
-
@server.mount('/aspera/faspex', FxGwServlet,a_aoc_api_user,a_workspace_id)
|
165
|
+
@server.mount('/aspera/faspex', FxGwServlet, a_aoc_api_user, a_workspace_id)
|
189
166
|
@server.mount('/newuser', NewUserServlet)
|
190
|
-
trap('INT') {@server.shutdown}
|
167
|
+
trap('INT') { @server.shutdown }
|
191
168
|
end
|
192
169
|
|
193
170
|
def start_server
|
data/lib/aspera/hash_ext.rb
CHANGED
@@ -1,28 +1,27 @@
|
|
1
|
-
#
|
2
|
-
unless Hash.method_defined?(:dig)
|
3
|
-
class Hash
|
4
|
-
def dig(*path)
|
5
|
-
path.inject(self) do |location, key|
|
6
|
-
location.respond_to?(:keys) ? location[key] : nil
|
7
|
-
end
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
1
|
+
# frozen_string_literal: true
|
11
2
|
|
12
3
|
class ::Hash
|
13
4
|
def deep_merge(second)
|
14
|
-
|
5
|
+
merge(second){|_key,v1,v2|Hash === v1 && Hash === v2 ? v1.deep_merge(v2) : v2}
|
15
6
|
end
|
16
7
|
|
17
8
|
def deep_merge!(second)
|
18
|
-
|
9
|
+
merge!(second){|_key,v1,v2|Hash === v1 && Hash === v2 ? v1.deep_merge!(v2) : v2}
|
19
10
|
end
|
20
11
|
end
|
21
12
|
|
22
13
|
unless Hash.method_defined?(:symbolize_keys)
|
23
14
|
class Hash
|
24
15
|
def symbolize_keys
|
25
|
-
return
|
16
|
+
return each_with_object({}){|(k,v),memo| memo[k.to_sym] = v; }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
unless Hash.method_defined?(:stringify_keys)
|
22
|
+
class Hash
|
23
|
+
def stringify_keys
|
24
|
+
return each_with_object({}){|(k,v),memo| memo[k.to_s] = v }
|
26
25
|
end
|
27
26
|
end
|
28
27
|
end
|
data/lib/aspera/id_generator.rb
CHANGED
@@ -1,22 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'uri'
|
2
4
|
|
3
5
|
module Aspera
|
4
6
|
class IdGenerator
|
5
|
-
ID_SEPARATOR='_'
|
6
|
-
WINDOWS_PROTECTED_CHAR
|
7
|
-
PROTECTED_CHAR_REPLACE='_'
|
7
|
+
ID_SEPARATOR = '_'
|
8
|
+
WINDOWS_PROTECTED_CHAR = %r{[/:"<>\\*?]}.freeze
|
9
|
+
PROTECTED_CHAR_REPLACE = '_'
|
8
10
|
private_constant :ID_SEPARATOR,:PROTECTED_CHAR_REPLACE,:WINDOWS_PROTECTED_CHAR
|
9
11
|
def self.from_list(object_id)
|
10
12
|
if object_id.is_a?(Array)
|
11
|
-
object_id=object_id.
|
12
|
-
|
13
|
+
object_id = object_id.compact.map do |i|
|
14
|
+
i.is_a?(String) && i.start_with?('https://') ? URI.parse(i).host : i.to_s
|
13
15
|
end.join(ID_SEPARATOR)
|
14
16
|
end
|
15
|
-
raise
|
17
|
+
raise 'id must be a String' unless object_id.is_a?(String)
|
16
18
|
return object_id.
|
17
|
-
|
18
|
-
|
19
|
-
|
19
|
+
gsub(WINDOWS_PROTECTED_CHAR,PROTECTED_CHAR_REPLACE). # remove windows forbidden chars
|
20
|
+
gsub('.',PROTECTED_CHAR_REPLACE). # keep dot for extension only (nicer)
|
21
|
+
downcase
|
20
22
|
end
|
21
23
|
end
|
22
24
|
end
|