Class: Aspera::CosNode

Inherits:
Node show all
Defined in:
lib/aspera/cos_node.rb

Constant Summary collapse

IBM_CLOUD_TOKEN_URL =
'https://iam.cloud.ibm.com/identity'
TOKEN_FIELD =
'delegated_refresh_token'

Constants inherited from Node

Node::ACCESS_LEVELS, Node::HEADER_X_ASPERA_ACCESS_KEY, Node::MATCH_EXEC_PREFIX, Node::PATH_SEPARATOR, Node::TS_FIELDS_TO_COPY

Constants inherited from Rest

Rest::ENTITY_NOT_FOUND

Instance Attribute Summary

Attributes inherited from Node

#app_info

Attributes inherited from Rest

#params

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Node

#add_tspec_info, file_matcher, #find_files, #node_id_to_node, #process_folder_tree, #refreshed_transfer_token, #resolve_api_fid, #transfer_spec_gen4

Methods inherited from Rest

array_params, basic_creds, #build_request, build_uri, #call, #cancel, #create, #delete, #lookup_by_name, #oauth, #oauth_token, #read, start_http_session, #update

Constructor Details

#initialize(bucket_name, storage_endpoint, instance_id, api_key, auth_url = IBM_CLOUD_TOKEN_URL) ⇒ CosNode

Returns a new instance of CosNode.



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/aspera/cos_node.rb', line 32

def initialize(bucket_name, storage_endpoint, instance_id, api_key, auth_url= IBM_CLOUD_TOKEN_URL)
  @auth_url = auth_url
  @api_key = api_key
  s3_api = Aspera::Rest.new({
    base_url:       storage_endpoint,
    not_auth_codes: %w[401 403], # error codes when not authorized
    headers:        {'ibm-service-instance-id' => instance_id},
    auth:           {
      type:         :oauth2,
      base_url:     @auth_url,
      grant_method: :generic,
      generic:      {
        grant_type:    'urn:ibm:params:oauth:grant-type:apikey',
        response_type: 'cloud_iam',
        apikey:        @api_key
      }}})
  # read FASP connection information for bucket
  xml_result_text = s3_api.call(
    operation: 'GET',
    subpath: bucket_name,
    headers: {'Accept' => 'application/xml'},
    url_params: {'faspConnectionInfo' => nil}
  )[:http].body
  ats_info = XmlSimple.xml_in(xml_result_text, {'ForceArray' => false})
  Aspera::Log.dump('ats_info', ats_info)
  @storage_credentials = {
    'type'  => 'token',
    'token' => {TOKEN_FIELD => nil}
  }
  super(
    params: {
      base_url: ats_info['ATSEndpoint'],
      auth:     {
        type:     :basic,
        username: ats_info['AccessKey']['Id'],
        password: ats_info['AccessKey']['Secret']}},
    add_tspec: {'tags'=>{Fasp::TransferSpec::TAG_RESERVED=>{'node'=>{'storage_credentials'=>@storage_credentials}}}})
  # update storage_credentials AND Rest params
  generate_token
end

Class Method Details

.parameters_from_svc_creds(service_credentials, bucket_region) ⇒ Object



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/aspera/cos_node.rb', line 10

def parameters_from_svc_creds(service_credentials, bucket_region)
  # check necessary contents
  raise 'service_credentials must be a Hash' unless service_credentials.is_a?(Hash)
  %w[apikey resource_instance_id endpoints].each do |field|
    raise "service_credentials must have a field: #{field}" unless service_credentials.key?(field)
  end
  Aspera::Log.dump('service_credentials', service_credentials)
  # read endpoints from service provided in service credentials
  endpoints = Aspera::Rest.new({base_url: service_credentials['endpoints']}).read('')[:data]
  Aspera::Log.dump('endpoints', endpoints)
  storage_endpoint = endpoints.dig('service-endpoints', 'regional', bucket_region, 'public', bucket_region)
  raise "no such region: #{bucket_region}" if storage_endpoint.nil?
  return {
    instance_id:      service_credentials['resource_instance_id'],
    service_api_key:  service_credentials['apikey'],
    storage_endpoint: "https://#{storage_endpoint}"
  }
end

Instance Method Details

#generate_tokenObject

potentially call this if delegated token is expired



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/aspera/cos_node.rb', line 74

def generate_token
  # OAuth API to get delegated token
  delegated_oauth = Oauth.new({
    type:         :oauth2,
    base_url:     @auth_url,
    token_field:  TOKEN_FIELD,
    grant_method: :generic,
    generic:      {
      grant_type:          'urn:ibm:params:oauth:grant-type:apikey',
      response_type:       'delegated_refresh_token',
      apikey:              @api_key,
      receiver_client_ids: 'aspera_ats'
    }})
  # get delegated token to be placed in rest call header and in transfer tags
  @storage_credentials['token'][TOKEN_FIELD] = delegated_oauth.get_authorization.gsub(/^Bearer /, '')
  @params[:headers] = {'X-Aspera-Storage-Credentials' => JSON.generate(@storage_credentials)}
end