aspera-cli 4.13.0 → 4.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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')} } }"
|