aspera-cli 4.13.0 → 4.14.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/CHANGELOG.md +28 -5
- data/CONTRIBUTING.md +17 -1
- data/README.md +782 -401
- data/examples/dascli +1 -1
- data/examples/rubyc +24 -0
- data/lib/aspera/aoc.rb +21 -32
- data/lib/aspera/ascmd.rb +1 -0
- data/lib/aspera/cli/basic_auth_plugin.rb +6 -6
- data/lib/aspera/cli/formatter.rb +17 -25
- data/lib/aspera/cli/main.rb +21 -27
- data/lib/aspera/cli/manager.rb +128 -114
- data/lib/aspera/cli/plugin.rb +87 -38
- data/lib/aspera/cli/plugins/alee.rb +2 -2
- data/lib/aspera/cli/plugins/aoc.rb +216 -102
- data/lib/aspera/cli/plugins/ats.rb +16 -18
- data/lib/aspera/cli/plugins/bss.rb +3 -3
- data/lib/aspera/cli/plugins/config.rb +177 -367
- data/lib/aspera/cli/plugins/console.rb +4 -6
- data/lib/aspera/cli/plugins/cos.rb +12 -13
- data/lib/aspera/cli/plugins/faspex.rb +17 -18
- data/lib/aspera/cli/plugins/faspex5.rb +332 -216
- data/lib/aspera/cli/plugins/node.rb +171 -142
- data/lib/aspera/cli/plugins/orchestrator.rb +15 -18
- data/lib/aspera/cli/plugins/preview.rb +38 -60
- data/lib/aspera/cli/plugins/server.rb +22 -15
- data/lib/aspera/cli/plugins/shares.rb +24 -33
- data/lib/aspera/cli/plugins/sync.rb +3 -3
- data/lib/aspera/cli/transfer_agent.rb +29 -26
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/colors.rb +9 -7
- data/lib/aspera/data/6 +0 -0
- data/lib/aspera/environment.rb +7 -3
- data/lib/aspera/fasp/agent_connect.rb +5 -0
- data/lib/aspera/fasp/agent_direct.rb +5 -5
- data/lib/aspera/fasp/agent_httpgw.rb +138 -60
- data/lib/aspera/fasp/agent_trsdk.rb +2 -0
- data/lib/aspera/fasp/error_info.rb +2 -0
- data/lib/aspera/fasp/installation.rb +18 -19
- data/lib/aspera/fasp/parameters.rb +18 -17
- data/lib/aspera/fasp/parameters.yaml +2 -1
- data/lib/aspera/fasp/resume_policy.rb +3 -3
- data/lib/aspera/fasp/transfer_spec.rb +6 -5
- data/lib/aspera/fasp/uri.rb +23 -21
- data/lib/aspera/faspex_postproc.rb +1 -1
- data/lib/aspera/hash_ext.rb +12 -2
- data/lib/aspera/keychain/macos_security.rb +13 -13
- data/lib/aspera/log.rb +1 -0
- data/lib/aspera/node.rb +62 -80
- data/lib/aspera/oauth.rb +1 -1
- data/lib/aspera/persistency_action_once.rb +1 -1
- data/lib/aspera/preview/terminal.rb +61 -15
- data/lib/aspera/preview/utils.rb +3 -3
- data/lib/aspera/proxy_auto_config.js +2 -2
- data/lib/aspera/rest.rb +37 -0
- data/lib/aspera/secret_hider.rb +6 -1
- data/lib/aspera/ssh.rb +1 -1
- data/lib/aspera/sync.rb +2 -0
- data.tar.gz.sig +0 -0
- metadata +3 -4
- metadata.gz.sig +0 -0
- data/docs/test_env.conf +0 -186
- data/lib/aspera/data/7 +0 -0
@@ -23,7 +23,10 @@ module Aspera
|
|
23
23
|
# either in standard domain, or product name in page
|
24
24
|
if URI.parse(base_url).host.end_with?(Aspera::AoC::PROD_DOMAIN) ||
|
25
25
|
api.call({operation: 'GET', redirect_max: 1, headers: {'Accept' => 'text/html'}})[:http].body.include?(Aspera::AoC::PRODUCT_NAME)
|
26
|
-
return {
|
26
|
+
return {
|
27
|
+
version: 'SaaS',
|
28
|
+
name: 'Aspera on Cloud'
|
29
|
+
}
|
27
30
|
end
|
28
31
|
return nil
|
29
32
|
end
|
@@ -50,6 +53,7 @@ module Aspera
|
|
50
53
|
client_registration_token
|
51
54
|
client_access_key
|
52
55
|
kms_profile].freeze
|
56
|
+
# TODO: remove this and use %name: instead
|
53
57
|
ENTITY_NAME_SPECIFIER = 'name'
|
54
58
|
PACKAGE_QUERY_DEFAULT = {'archived' => false, 'exclude_dropbox_packages' => true, 'has_content' => true, 'received' => true}.freeze
|
55
59
|
|
@@ -58,28 +62,23 @@ module Aspera
|
|
58
62
|
@cache_workspace_info = nil
|
59
63
|
@cache_home_node_file = nil
|
60
64
|
@cache_api_aoc = nil
|
61
|
-
options.
|
62
|
-
options.
|
63
|
-
options.
|
64
|
-
options.
|
65
|
-
options.
|
66
|
-
options.
|
67
|
-
options.
|
68
|
-
options.
|
69
|
-
options.
|
70
|
-
|
71
|
-
options.
|
72
|
-
options.
|
73
|
-
options.
|
74
|
-
options.
|
75
|
-
options.
|
76
|
-
options.set_option(:operation, :push)
|
77
|
-
options.set_option(:auth, :jwt)
|
78
|
-
options.set_option(:scope, AoC::SCOPE_FILES_USER)
|
79
|
-
options.set_option(:private_key, '@file:' + env[:private_key_path]) if env[:private_key_path].is_a?(String)
|
80
|
-
options.set_option(:workspace, :default)
|
65
|
+
options.declare(:auth, 'OAuth type of authentication', values: Oauth::STD_AUTH_TYPES, default: :jwt)
|
66
|
+
options.declare(:operation, 'Client operation for transfers', values: %i[push pull], default: :push)
|
67
|
+
options.declare(:client_id, 'OAuth API client identifier')
|
68
|
+
options.declare(:client_secret, 'OAuth API client secret')
|
69
|
+
options.declare(:redirect_uri, 'OAuth API client redirect URI')
|
70
|
+
options.declare(:private_key, 'OAuth JWT RSA private key PEM value (prefix file path with @file:)')
|
71
|
+
options.declare(:scope, 'OAuth scope for AoC API calls', default: AoC::SCOPE_FILES_USER)
|
72
|
+
options.declare(:passphrase, 'RSA private key passphrase')
|
73
|
+
options.declare(:workspace, 'Name of workspace', default: :default)
|
74
|
+
# TODO: remove this and use %name: instead
|
75
|
+
options.declare(:name, "Resource name (prefer to use keyword #{ENTITY_NAME_SPECIFIER})")
|
76
|
+
options.declare(:link, 'Public link to shared resource')
|
77
|
+
options.declare(:new_user_option, 'New user creation option for unknown package recipients')
|
78
|
+
options.declare(:from_folder, 'Source folder for Folder-to-Folder transfer')
|
79
|
+
options.declare(:validate_metadata, 'Validate shared inbox metadata', values: :bool, default: true)
|
81
80
|
options.parse_options!
|
82
|
-
# add node plugin options
|
81
|
+
# add node plugin options (TODO: check needed ? if yes, tell why)
|
83
82
|
Node.new(env.merge({man_only: true, skip_basic_auth_options: true}))
|
84
83
|
end
|
85
84
|
|
@@ -114,7 +113,7 @@ module Aspera
|
|
114
113
|
Log.log.debug('Using default workspace'.green)
|
115
114
|
raise CliError, 'No default workspace defined for user, please specify workspace' if default_workspace_id.nil?
|
116
115
|
default_workspace_id
|
117
|
-
when String then aoc_api.
|
116
|
+
when String then aoc_api.lookup_by_name('workspaces', ws_name)['id']
|
118
117
|
when NilClass then nil
|
119
118
|
else raise CliError, 'unexpected value type for workspace'
|
120
119
|
end
|
@@ -164,11 +163,11 @@ module Aspera
|
|
164
163
|
l_res_name = options.get_option(:name)
|
165
164
|
raise 'Provide either option id or name, not both' unless l_res_id.nil? || l_res_name.nil?
|
166
165
|
# try to find item by name (single partial match or exact match)
|
167
|
-
l_res_id = aoc_api.
|
166
|
+
l_res_id = aoc_api.lookup_by_name(resource_class_path, l_res_name)['id'] unless l_res_name.nil?
|
168
167
|
# if no name or id option, taken on command line (after command)
|
169
168
|
if l_res_id.nil?
|
170
169
|
l_res_id = options.get_next_argument('identifier')
|
171
|
-
l_res_id = aoc_api.
|
170
|
+
l_res_id = aoc_api.lookup_by_name(resource_class_path, options.get_next_argument('identifier'))['id'] if l_res_id.eql?(ENTITY_NAME_SPECIFIER)
|
172
171
|
end
|
173
172
|
return l_res_id
|
174
173
|
end
|
@@ -240,15 +239,15 @@ module Aspera
|
|
240
239
|
# server side is protocol server
|
241
240
|
# in same workspace
|
242
241
|
# default is push
|
243
|
-
case options.get_option(:operation,
|
242
|
+
case options.get_option(:operation, mandatory: true)
|
244
243
|
when :push
|
245
244
|
client_direction = Fasp::TransferSpec::DIRECTION_SEND
|
246
|
-
client_folder = options.get_option(:from_folder,
|
245
|
+
client_folder = options.get_option(:from_folder, mandatory: true)
|
247
246
|
server_folder = transfer.destination_folder(client_direction)
|
248
247
|
when :pull
|
249
248
|
client_direction = Fasp::TransferSpec::DIRECTION_RECEIVE
|
250
249
|
client_folder = transfer.destination_folder(client_direction)
|
251
|
-
server_folder = options.get_option(:from_folder,
|
250
|
+
server_folder = options.get_option(:from_folder, mandatory: true)
|
252
251
|
end
|
253
252
|
client_apfid = top_node_api.resolve_api_fid(file_id, client_folder)
|
254
253
|
server_apfid = top_node_api.resolve_api_fid(file_id, server_folder)
|
@@ -371,12 +370,12 @@ module Aspera
|
|
371
370
|
filter = options.get_option(:query) || {}
|
372
371
|
raise 'query must be Hash' unless filter.is_a?(Hash)
|
373
372
|
filter['limit'] ||= 100
|
374
|
-
if options.get_option(:once_only,
|
373
|
+
if options.get_option(:once_only, mandatory: true)
|
375
374
|
saved_date = []
|
376
375
|
start_date_persistency = PersistencyActionOnce.new(
|
377
376
|
manager: @agents[:persistency],
|
378
377
|
data: saved_date,
|
379
|
-
ids: IdGenerator.from_list(['aoc_ana_date', options.get_option(:url,
|
378
|
+
ids: IdGenerator.from_list(['aoc_ana_date', options.get_option(:url, mandatory: true), current_workspace_info['name']].push(
|
380
379
|
filter_resource,
|
381
380
|
filter_id)))
|
382
381
|
start_date_time = saved_date.first
|
@@ -387,7 +386,7 @@ module Aspera
|
|
387
386
|
filter['start_time'] = start_date_time unless start_date_time.nil?
|
388
387
|
filter['stop_time'] = stop_date_time
|
389
388
|
end
|
390
|
-
events = analytics_api.read("#{filter_resource}/#{filter_id}/#{event_type}",
|
389
|
+
events = analytics_api.read("#{filter_resource}/#{filter_id}/#{event_type}", query_read_delete(default: filter))[:data][event_type]
|
391
390
|
start_date_persistency&.save
|
392
391
|
if !options.get_option(:notif_to).nil?
|
393
392
|
events.each do |tr_event|
|
@@ -451,7 +450,7 @@ module Aspera
|
|
451
450
|
when :group_membership then default_fields.push(*%w[group_id member_type member_id])
|
452
451
|
when :workspace_membership then default_fields.push(*%w[workspace_id member_type member_id])
|
453
452
|
end
|
454
|
-
items = read_with_paging(resource_class_path,
|
453
|
+
items = read_with_paging(resource_class_path, query_read_delete(default: default_query))
|
455
454
|
formatter.display_item_count(items[:list].length, items[:total])
|
456
455
|
return {type: :object_list, data: items[:list], fields: default_fields}
|
457
456
|
when :show
|
@@ -491,7 +490,7 @@ module Aspera
|
|
491
490
|
case command
|
492
491
|
when :reminder
|
493
492
|
# send an email reminder with list of orgs
|
494
|
-
user_email = options.get_option(:username,
|
493
|
+
user_email = options.get_option(:username, mandatory: true)
|
495
494
|
Rest.new(base_url: "#{AoC.api_base_url}/#{AoC::API_V1}").create('organization_reminders', {email: user_email})[:data]
|
496
495
|
return Main.result_status("List of organizations user is member of, has been sent by e-mail to #{user_email}")
|
497
496
|
when :servers
|
@@ -528,7 +527,7 @@ module Aspera
|
|
528
527
|
when :shared_inboxes
|
529
528
|
case options.get_next_command(%i[list show])
|
530
529
|
when :list
|
531
|
-
query =
|
530
|
+
query = query_read_delete
|
532
531
|
if query.nil?
|
533
532
|
query = {'embed[]' => 'dropbox', 'aggregate_permissions_by_dropbox' => true, 'sort' => 'dropbox_name'}
|
534
533
|
query['workspace_id'] = current_workspace_info['id'] unless current_workspace_info['id'].eql?(:undefined)
|
@@ -538,8 +537,7 @@ module Aspera
|
|
538
537
|
return {type: :single_object, data: aoc_api.read(get_resource_path_from_args('dropboxes'), query)[:data]}
|
539
538
|
end
|
540
539
|
when :send
|
541
|
-
package_data =
|
542
|
-
raise CliBadArgument, 'value must be hash, refer to doc' unless package_data.is_a?(Hash)
|
540
|
+
package_data = value_create_modify(command: package_command, type: Hash)
|
543
541
|
new_user_option = options.get_option(:new_user_option)
|
544
542
|
option_validate = options.get_option(:validate_metadata)
|
545
543
|
# works for both normal usr auth and link auth
|
@@ -567,20 +565,20 @@ module Aspera
|
|
567
565
|
ids_to_download = instance_identifier
|
568
566
|
skip_ids_data = []
|
569
567
|
skip_ids_persistency = nil
|
570
|
-
if options.get_option(:once_only,
|
568
|
+
if options.get_option(:once_only, mandatory: true)
|
571
569
|
skip_ids_persistency = PersistencyActionOnce.new(
|
572
570
|
manager: @agents[:persistency],
|
573
571
|
data: skip_ids_data,
|
574
|
-
id: IdGenerator.from_list(['aoc_recv', options.get_option(:url,
|
572
|
+
id: IdGenerator.from_list(['aoc_recv', options.get_option(:url, mandatory: true),
|
575
573
|
current_workspace_info['id']].concat(aoc_api.additional_persistence_ids)))
|
576
574
|
end
|
577
575
|
if VAL_ALL.eql?(ids_to_download)
|
578
|
-
query =
|
576
|
+
query = query_read_delete(default: PACKAGE_QUERY_DEFAULT)
|
579
577
|
raise 'option query must be Hash' unless query.is_a?(Hash)
|
580
578
|
if query.key?('dropbox_name')
|
581
579
|
# convenience: specify name instead of id
|
582
580
|
raise 'not both dropbox_name and dropbox_id' if query.key?('dropbox_id')
|
583
|
-
query['dropbox_id'] = aoc_api.
|
581
|
+
query['dropbox_id'] = aoc_api.lookup_by_name('dropboxes', query['dropbox_name'])['id']
|
584
582
|
query.delete('dropbox_name')
|
585
583
|
end
|
586
584
|
query['workspace_id'] ||= current_workspace_info['id'] unless current_workspace_info['id'].eql?(:undefined)
|
@@ -623,12 +621,12 @@ module Aspera
|
|
623
621
|
return { type: :single_object, data: package_info }
|
624
622
|
when :list
|
625
623
|
display_fields = %w[id name bytes_transferred]
|
626
|
-
query =
|
624
|
+
query = query_read_delete(default: PACKAGE_QUERY_DEFAULT)
|
627
625
|
raise 'option query must be Hash' unless query.is_a?(Hash)
|
628
626
|
if query.key?('dropbox_name')
|
629
627
|
# convenience: specify name instead of id
|
630
628
|
raise 'not both dropbox_name and dropbox_id' if query.key?('dropbox_id')
|
631
|
-
query['dropbox_id'] = aoc_api.
|
629
|
+
query['dropbox_id'] = aoc_api.lookup_by_name('dropboxes', query['dropbox_name'])['id']
|
632
630
|
query.delete('dropbox_name')
|
633
631
|
end
|
634
632
|
if current_workspace_info['id'].eql?(:undefined)
|
@@ -655,75 +653,111 @@ module Aspera
|
|
655
653
|
when *NODE4_EXT_COMMANDS
|
656
654
|
return execute_nodegen4_command(command_repo, home_info[:node_id], file_id: home_info[:file_id], scope: AoC::SCOPE_NODE_USER)
|
657
655
|
when :short_link
|
658
|
-
#
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
656
|
+
# execute action on AoC API
|
657
|
+
short_link_command = options.get_next_command(%i[create delete list])
|
658
|
+
folder_dest = options.get_next_argument('path')
|
659
|
+
link_type = options.get_next_argument('link type', expected: %i[public private])
|
660
|
+
home_node_api = aoc_api.node_api_from(
|
661
|
+
node_id: home_info[:node_id],
|
662
|
+
workspace_id: current_workspace_info['id'],
|
663
|
+
workspace_name: current_workspace_info['name'])
|
664
|
+
shared_apfid = home_node_api.resolve_api_fid(home_info[:file_id], folder_dest)
|
665
|
+
folder_info = {
|
666
|
+
node_id: shared_apfid[:api].app_info[:node_info]['id'],
|
667
|
+
file_id: shared_apfid[:file_id],
|
668
|
+
workspace_id: current_workspace_info['id']
|
669
|
+
}
|
670
|
+
purpose = case link_type
|
671
|
+
when :public then 'token_auth_redirection'
|
672
|
+
when :private then 'shared_folder_auth_link'
|
673
|
+
else raise 'internal error'
|
666
674
|
end
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
shared_apfid = home_node_api.resolve_api_fid(home_info[:file_id], folder_dest)
|
675
|
-
create_params = {
|
676
|
-
file_id: shared_apfid[:file_id],
|
677
|
-
node_id: shared_apfid[:api].app_info[:node_info]['id'],
|
678
|
-
workspace_id: current_workspace_info['id']
|
675
|
+
case short_link_command
|
676
|
+
when :delete
|
677
|
+
one_id = instance_identifier
|
678
|
+
folder_info.delete(:workspace_id)
|
679
|
+
delete_params = {
|
680
|
+
edit_access: true,
|
681
|
+
json_query: folder_info.to_json
|
679
682
|
}
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
683
|
+
aoc_api.delete("short_links/#{one_id}", delete_params)
|
684
|
+
if link_type.eql?(:public)
|
685
|
+
# TODO: get permission id..
|
686
|
+
# shared_apfid[:api].delete('permissions', {ids: })[:data]
|
687
|
+
end
|
688
|
+
return Main.result_status('deleted')
|
689
|
+
when :list
|
690
|
+
query = if link_type.eql?(:private)
|
691
|
+
folder_info
|
692
|
+
else
|
693
|
+
{
|
694
|
+
url_token_data: {
|
695
|
+
data: folder_info,
|
696
|
+
purpose: 'view_shared_file'
|
697
|
+
}
|
698
|
+
}
|
699
|
+
end
|
700
|
+
list_params = {
|
701
|
+
json_query: query.to_json,
|
702
|
+
edit_access: true,
|
703
|
+
purpose: purpose,
|
704
|
+
# embed: 'updated_by_user',
|
705
|
+
sort: '-created_at'
|
706
|
+
}
|
707
|
+
result = aoc_api.read('short_links', list_params)[:data]
|
708
|
+
result.each{|i|i.delete('data')}
|
709
|
+
return {type: :object_list, data: result}
|
710
|
+
when :create
|
711
|
+
creation_params = {
|
712
|
+
purpose: purpose,
|
713
|
+
user_selected_name: nil
|
714
|
+
}
|
715
|
+
case link_type
|
716
|
+
when :private
|
717
|
+
creation_params[:data] = folder_info
|
718
|
+
when :public
|
719
|
+
creation_params[:expires_at] = nil
|
720
|
+
creation_params[:password_enabled] = false
|
721
|
+
folder_info[:name] = ''
|
722
|
+
creation_params[:data] = {
|
689
723
|
aoc: true,
|
690
724
|
url_token_data: {
|
691
|
-
data:
|
725
|
+
data: folder_info,
|
692
726
|
purpose: 'view_shared_file'
|
693
727
|
}
|
694
728
|
}
|
695
|
-
value_option['user_selected_name'] = nil
|
696
|
-
else
|
697
|
-
raise 'purpose must be one of: token_auth_redirection or shared_folder_auth_link'
|
698
729
|
end
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
'
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
730
|
+
result_create_short_link = aoc_api.create('short_links', creation_params)[:data]
|
731
|
+
# public: Creation: permission on node
|
732
|
+
if link_type.eql?(:public)
|
733
|
+
# TODO: merge with node permissions ?
|
734
|
+
# TODO: access level as arg
|
735
|
+
access_levels = Aspera::Node::ACCESS_LEVELS # ['delete','list','mkdir','preview','read','rename','write']
|
736
|
+
folder_name = File.basename(folder_dest)
|
737
|
+
perm_data = {
|
738
|
+
'file_id' => shared_apfid[:file_id],
|
739
|
+
'access_id' => result_create_short_link['resource_id'],
|
740
|
+
'access_type' => 'user',
|
741
|
+
'access_levels' => access_levels,
|
742
|
+
'tags' => {
|
743
|
+
'url_token' => true,
|
744
|
+
'workspace_id' => current_workspace_info['id'],
|
745
|
+
'workspace_name' => current_workspace_info['name'],
|
746
|
+
'folder_name' => folder_name,
|
747
|
+
'created_by_name' => aoc_api.current_user_info['name'],
|
748
|
+
'created_by_email' => aoc_api.current_user_info['email'],
|
749
|
+
'access_key' => shared_apfid[:api].app_info[:node_info]['access_key'],
|
750
|
+
'node' => shared_apfid[:api].app_info[:node_info]['host']
|
751
|
+
}
|
719
752
|
}
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
753
|
+
created_data = shared_apfid[:api].create('permissions', perm_data)[:data]
|
754
|
+
aoc_api.permissions_send_event(created_data: created_data, app_info: shared_apfid[:api].app_info)
|
755
|
+
# TODO: event ?
|
756
|
+
end
|
757
|
+
return {type: :single_object, data: result_create_short_link}
|
758
|
+
end # short_link command
|
725
759
|
end # files command
|
726
|
-
|
760
|
+
raise 'Error: shall not reach this line'
|
727
761
|
when :automation
|
728
762
|
Log.log.warn('BETA: work under progress')
|
729
763
|
# automation api is not in the same place
|
@@ -760,7 +794,7 @@ module Aspera
|
|
760
794
|
return execute_admin_action
|
761
795
|
when :gateway
|
762
796
|
require 'aspera/faspex_gw'
|
763
|
-
url =
|
797
|
+
url = value_create_modify(type: String)
|
764
798
|
uri = URI.parse(url)
|
765
799
|
server = WebServerSimple.new(uri)
|
766
800
|
server.mount(uri.path, Faspex4GWServlet, aoc_api, current_workspace_info['id'])
|
@@ -776,6 +810,86 @@ module Aspera
|
|
776
810
|
raise 'internal error: command shall return'
|
777
811
|
end
|
778
812
|
|
813
|
+
# @param [Hash] params : plugin_sym, instance_url
|
814
|
+
# @return [Hash] :preset_value, :test_args
|
815
|
+
def wizard(params)
|
816
|
+
if params[:prepare]
|
817
|
+
organization = AoC.parse_url(params[:instance_url]).first
|
818
|
+
# if not defined by user, generate name
|
819
|
+
params[:preset_name] ||= [params[:plugin_sym], organization].join('_')
|
820
|
+
params[:need_private_key] = true
|
821
|
+
return
|
822
|
+
end
|
823
|
+
options.set_option(:private_key, '@file:' + params[:private_key_path])
|
824
|
+
# make username mandatory for jwt, this triggers interactive input
|
825
|
+
options.get_option(:username, mandatory: true)
|
826
|
+
auto_set_pub_key = false
|
827
|
+
auto_set_jwt = false
|
828
|
+
use_browser_authentication = false
|
829
|
+
if options.get_option(:use_generic_client)
|
830
|
+
formatter.display_status('Using global client_id.')
|
831
|
+
formatter.display_status('Please Login to your Aspera on Cloud instance.'.red)
|
832
|
+
formatter.display_status('Navigate to your "Account Settings"'.red)
|
833
|
+
formatter.display_status('Check or update the value of "Public Key" to be:'.red.blink)
|
834
|
+
formatter.display_status(params[:pub_key_pem])
|
835
|
+
if !options.get_option(:test_mode)
|
836
|
+
formatter.display_status('Once updated or validated, press enter.')
|
837
|
+
OpenApplication.instance.uri(params[:instance_url])
|
838
|
+
$stdin.gets
|
839
|
+
end
|
840
|
+
else
|
841
|
+
formatter.display_status('Using organization specific client_id.')
|
842
|
+
if options.get_option(:client_id).nil? || options.get_option(:client_secret).nil?
|
843
|
+
formatter.display_status('Please login to your Aspera on Cloud instance.'.red)
|
844
|
+
formatter.display_status('Go to: Apps->Admin->Organization->Integrations')
|
845
|
+
formatter.display_status('Create or check if there is an existing integration named:')
|
846
|
+
formatter.display_status("- name: #{@info[:name]}")
|
847
|
+
formatter.display_status("- redirect uri: #{DEFAULT_REDIRECT}")
|
848
|
+
formatter.display_status('- origin: localhost')
|
849
|
+
formatter.display_status('Once created or identified,')
|
850
|
+
formatter.display_status('Please enter:'.red)
|
851
|
+
end
|
852
|
+
OpenApplication.instance.uri("#{params[:instance_url]}/#{AOC_PATH_API_CLIENTS}")
|
853
|
+
options.get_option(:client_id, mandatory: true)
|
854
|
+
options.get_option(:client_secret, mandatory: true)
|
855
|
+
use_browser_authentication = true
|
856
|
+
end
|
857
|
+
if use_browser_authentication
|
858
|
+
formatter.display_status('We will use web authentication to bootstrap.')
|
859
|
+
auto_set_pub_key = true
|
860
|
+
auto_set_jwt = true
|
861
|
+
aoc_api.oauth.generic_parameters[:grant_method] = :web
|
862
|
+
aoc_api.oauth.generic_parameters[:scope] = AoC::SCOPE_FILES_ADMIN
|
863
|
+
aoc_api.oauth.specific_parameters[:redirect_uri] = DEFAULT_REDIRECT
|
864
|
+
end
|
865
|
+
myself = aoc_api.read('self')[:data]
|
866
|
+
if auto_set_pub_key
|
867
|
+
raise CliError, 'Public key is already set in profile (use --override=yes)' unless myself['public_key'].empty? || option_override
|
868
|
+
formatter.display_status('Updating profile with new key')
|
869
|
+
aoc_api.update("users/#{myself['id']}", {'public_key' => params[:pub_key_pem]})
|
870
|
+
end
|
871
|
+
if auto_set_jwt
|
872
|
+
formatter.display_status('Enabling JWT for client')
|
873
|
+
aoc_api.update("clients/#{options.get_option(:client_id)}", {'jwt_grant_enabled' => true, 'explicit_authorization_required' => false})
|
874
|
+
end
|
875
|
+
formatter.display_status("Creating new config preset: #{params[:preset_name]}")
|
876
|
+
preset_result = {
|
877
|
+
url: params[:instance_url],
|
878
|
+
username: myself['email'],
|
879
|
+
auth: :jwt.to_s,
|
880
|
+
private_key: '@file:' + params[:private_key_path]
|
881
|
+
}.stringify_keys
|
882
|
+
# set only if non nil
|
883
|
+
%i[client_id client_secret].each do |s|
|
884
|
+
o = options.get_option(s)
|
885
|
+
preset_result[s.to_s] = o unless o.nil?
|
886
|
+
end
|
887
|
+
return {
|
888
|
+
preset_value: preset_result,
|
889
|
+
test_args: "#{params[:plugin_sym]} user profile show"
|
890
|
+
}
|
891
|
+
end
|
892
|
+
|
779
893
|
private :aoc_params,
|
780
894
|
:home_info,
|
781
895
|
:assert_public_link_types,
|
@@ -7,25 +7,24 @@ module Aspera
|
|
7
7
|
module Cli
|
8
8
|
module Plugins
|
9
9
|
# Access Aspera Transfer Service
|
10
|
-
# https://52.44.83.163/docs/
|
11
10
|
# https://developer.ibm.com/aspera/docs/ats-api-reference/creating-ats-api-keys/
|
12
11
|
class Ats < Aspera::Cli::Plugin
|
13
12
|
def initialize(env)
|
14
13
|
super(env)
|
15
|
-
options.
|
16
|
-
options.
|
17
|
-
options.
|
18
|
-
options.
|
19
|
-
options.
|
20
|
-
options.
|
21
|
-
options.
|
14
|
+
options.declare(:ibm_api_key, 'IBM API key, see https://cloud.ibm.com/iam/apikeys')
|
15
|
+
options.declare(:instance, 'ATS instance in ibm cloud')
|
16
|
+
options.declare(:ats_key, 'ATS key identifier (ats_xxx)')
|
17
|
+
options.declare(:ats_secret, 'ATS key secret')
|
18
|
+
options.declare(:params, 'Parameters access key creation (@json:)')
|
19
|
+
options.declare(:cloud, 'Cloud provider')
|
20
|
+
options.declare(:region, 'Cloud region')
|
22
21
|
options.parse_options!
|
23
22
|
end
|
24
23
|
|
25
24
|
def server_by_cloud_region
|
26
25
|
# TODO: provide list ?
|
27
|
-
cloud = options.get_option(:cloud,
|
28
|
-
region = options.get_option(:region,
|
26
|
+
cloud = options.get_option(:cloud, mandatory: true).upcase
|
27
|
+
region = options.get_option(:region, mandatory: true)
|
29
28
|
return @ats_api_pub.read("servers/#{cloud}/#{region}")[:data]
|
30
29
|
end
|
31
30
|
|
@@ -36,8 +35,8 @@ module Aspera
|
|
36
35
|
base_url: AtsApi.base_url + '/pub/v1',
|
37
36
|
auth: {
|
38
37
|
type: :basic,
|
39
|
-
username: options.get_option(:ats_key,
|
40
|
-
password: options.get_option(:ats_secret,
|
38
|
+
username: options.get_option(:ats_key, mandatory: true),
|
39
|
+
password: options.get_option(:ats_secret, mandatory: true)}
|
41
40
|
})
|
42
41
|
end
|
43
42
|
|
@@ -90,7 +89,7 @@ module Aspera
|
|
90
89
|
res = ats_api_pub_v1.read("access_keys/#{access_key_id}")
|
91
90
|
return {type: :single_object, data: res[:data]}
|
92
91
|
when :modify
|
93
|
-
params =
|
92
|
+
params = value_create_modify(command: command, type: Hash)
|
94
93
|
params['id'] = access_key_id
|
95
94
|
ats_api_pub_v1.update("access_keys/#{access_key_id}", params)
|
96
95
|
return Main.result_status('modified')
|
@@ -138,7 +137,7 @@ module Aspera
|
|
138
137
|
when :list
|
139
138
|
return {type: :object_list, data: @ats_api_pub.all_servers, fields: %w[id cloud region]}
|
140
139
|
when :show
|
141
|
-
if options.get_option(:cloud) || options.get_option(:region
|
140
|
+
if options.get_option(:cloud) || options.get_option(:region)
|
142
141
|
server_data = server_by_cloud_region
|
143
142
|
else
|
144
143
|
server_id = instance_identifier
|
@@ -161,7 +160,7 @@ module Aspera
|
|
161
160
|
generic: {
|
162
161
|
grant_type: 'urn:ibm:params:oauth:grant-type:apikey',
|
163
162
|
response_type: 'cloud_iam',
|
164
|
-
apikey: options.get_option(:ibm_api_key,
|
163
|
+
apikey: options.get_option(:ibm_api_key, mandatory: true)
|
165
164
|
}}})
|
166
165
|
end
|
167
166
|
|
@@ -187,8 +186,7 @@ module Aspera
|
|
187
186
|
Log.log.warn{"more instances remaining: #{instances['remaining']}"} unless instances['remaining'].to_i.eql?(0)
|
188
187
|
return {type: :value_list, data: instances['data'], name: 'instance'}
|
189
188
|
when :create
|
190
|
-
|
191
|
-
created_key = ats_ibm_api.create('api_keys', create_value)[:data]
|
189
|
+
created_key = ats_ibm_api.create('api_keys', value_create_modify(command: command, default: {}, type: Hash))[:data]
|
192
190
|
return {type: :single_object, data: created_key}
|
193
191
|
when :list # list known api keys in ATS (this require an api_key ...)
|
194
192
|
res = ats_ibm_api.read('api_keys', {'offset' => 0, 'max_results' => 1000})
|
@@ -221,7 +219,7 @@ module Aspera
|
|
221
219
|
when :api_key # manage credential to access ATS API
|
222
220
|
return execute_action_api_key
|
223
221
|
when :aws_trust_policy
|
224
|
-
res = ats_api_pub_v1.read('aws/trustpolicy', {region: options.get_option(:region,
|
222
|
+
res = ats_api_pub_v1.read('aws/trustpolicy', {region: options.get_option(:region, mandatory: true)})[:data]
|
225
223
|
return {type: :single_object, data: res}
|
226
224
|
else raise 'ERROR'
|
227
225
|
end
|
@@ -23,7 +23,7 @@ module Aspera
|
|
23
23
|
|
24
24
|
def execute_action
|
25
25
|
if @api_bss.nil?
|
26
|
-
key = options.get_option(:password,
|
26
|
+
key = options.get_option(:password, mandatory: true)
|
27
27
|
@api_bss = Rest.new(
|
28
28
|
base_url: 'https://dashboard.bss.asperasoft.com/platform',
|
29
29
|
headers: {cookie: "_dashboard_key=#{key}"})
|
@@ -35,8 +35,8 @@ module Aspera
|
|
35
35
|
object = 'bssSubscriptions'
|
36
36
|
case command
|
37
37
|
when :find
|
38
|
-
query = options.get_option(:query,
|
39
|
-
value =
|
38
|
+
query = options.get_option(:query, mandatory: true) # AOC_ORGANIZATION_QUERY AOC_USER_EMAIL
|
39
|
+
value = value_create_modify(command: command)
|
40
40
|
request = {
|
41
41
|
'variables' => {'filter' => {'key' => query, 'value' => value}},
|
42
42
|
'query' => "query($filter: BssSubscriptionFilter!) {#{object}(filter: $filter) { #{all_fields('bssSubscriptions')} } }"
|