Class: Aspera::Cli::Http

Inherits:
Object
  • Object
show all
Defined in:
lib/aspera/cli/http.rb

Overview

Encapsulates all HTTP/S and TLS runtime configuration options. Extracted from Plugins::Config so it can be referenced independently via Context#http_config without coupling to the plugin machinery.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeHttp

Returns a new instance of Http.



26
27
28
29
30
31
32
33
34
# File 'lib/aspera/cli/http.rb', line 26

def initialize
  @insecure              = false
  @warn_insecure         = true
  @ignore_cert_host_port = []
  @http_options          = {}
  @ssl_warned_urls       = []
  @certificate_store     = nil
  @certificate_paths     = nil
end

Instance Attribute Details

#http_optionsObject

Returns the value of attribute http_options.



37
38
39
# File 'lib/aspera/cli/http.rb', line 37

def http_options
  @http_options
end

#ignore_cert_host_portObject

Returns the value of attribute ignore_cert_host_port.



37
38
39
# File 'lib/aspera/cli/http.rb', line 37

def ignore_cert_host_port
  @ignore_cert_host_port
end

#insecureObject

Returns the value of attribute insecure.



36
37
38
# File 'lib/aspera/cli/http.rb', line 36

def insecure
  @insecure
end

#warn_insecureObject

Returns the value of attribute warn_insecure.



36
37
38
# File 'lib/aspera/cli/http.rb', line 36

def warn_insecure
  @warn_insecure
end

Class Method Details

.declare_options(options) ⇒ nil

Declare all HTTP/S CLI options (metadata only - no handler binding yet). Called once from Config#initialize before this instance is available as a target. Handlers are bound in a second pass via bind_options once the instance exists.

Parameters:

  • CLI options manager to declare options into

Returns:



45
46
47
48
49
50
51
52
53
# File 'lib/aspera/cli/http.rb', line 45

def declare_options(options)
  options.declare(:insecure,           description: 'HTTP/S: Do not validate any certificate',                   allowed: Allowed::TYPES_BOOLEAN, default: false)
  options.declare(:ignore_certificate, description: 'HTTP/S: Do not validate certificate for these URLs',        allowed: [Array, NilClass])
  options.declare(:warn_insecure,      description: 'HTTP/S: Issue a warning if certificate is ignored',         allowed: Allowed::TYPES_BOOLEAN, default: true)
  options.declare(:cert_stores,        description: 'HTTP/S: List of folder with trusted certificates',          allowed: Allowed::TYPES_STRING_ARRAY)
  options.declare(:http_options,       schema: Schema::Registry::HTTP_OPTIONS)
  options.declare(:http_proxy,         description: 'HTTP/S: URL for proxy with optional credentials')
  nil
end

Instance Method Details

#bind_options(options) ⇒ nil

Bind all HTTP options to this instance using set_handler. Called from Config#initialize immediately after Http.new.

Parameters:

Returns:



60
61
62
63
64
65
66
67
# File 'lib/aspera/cli/http.rb', line 60

def bind_options(options)
  options.set_handler(:insecure,           object: self, method: :insecure)
  options.set_handler(:ignore_certificate, object: self, method: :ignore_cert_host_port)
  options.set_handler(:warn_insecure,      object: self, method: :warn_insecure)
  options.set_handler(:cert_stores,        object: self, method: :trusted_cert_locations)
  options.set_handler(:http_options,       object: self, method: :http_options)
  options.set_handler(:http_proxy,         object: self, method: :http_proxy)
end

#http_proxyObject


Proxy



100
101
102
# File 'lib/aspera/cli/http.rb', line 100

def http_proxy
  ENV['http_proxy']
end

#http_proxy=(value) ⇒ Object



104
105
106
107
# File 'lib/aspera/cli/http.rb', line 104

def http_proxy=(value)
  URI.parse(value)
  ENV['http_proxy'] = value
end

#ignore_cert?(address, port) ⇒ Boolean

Should the certificate be ignored for this host/port? Also logs a warning the first time (if warn_insecure is set).

Returns:



123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/aspera/cli/http.rb', line 123

def ignore_cert?(address, port)
  endpoint    = [address, port].freeze
  ignore_cert = @insecure || @ignore_cert_host_port.any?(endpoint)
  if ignore_cert && @warn_insecure
    base_url = "https://#{address}:#{port}"
    unless @ssl_warned_urls.include?(base_url)
      Log.log.warn{"Ignoring certificate for: #{base_url}. Do not deactivate certificate verification in production."}
      @ssl_warned_urls.push(base_url)
    end
  end
  Log.log.debug{"ignore cert? #{endpoint} -> #{ignore_cert}"}
  ignore_cert
end

#trusted_cert_locationsObject

Return cert file paths (computes OS defaults lazily if never set).



183
184
185
186
187
188
189
190
191
192
# File 'lib/aspera/cli/http.rb', line 183

def trusted_cert_locations
  if @certificate_paths.nil?
    self.trusted_cert_locations = [SpecialValues::DEF]
    locations = @certificate_paths
    # Restore to "lazy" state so next call recomputes if store was reset
    @certificate_paths = @certificate_store = nil
    return locations
  end
  @certificate_paths
end

#trusted_cert_locations=(path_list) ⇒ nil

Add files, folders or the default OS locations to the cert store.

Parameters:

  • list of file/folder paths to add to the certificate store

Returns:



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/aspera/cli/http.rb', line 144

def trusted_cert_locations=(path_list)
  Aspera.assert_type(path_list, Array){'cert locations'}
  if @certificate_store.nil?
    Log.log.debug('Creating SSL Cert store')
    @certificate_store = OpenSSL::X509::Store.new
    @certificate_paths = []
  end
  path_list.each do |path|
    Aspera.assert_type(path, String){'Expecting a String for certificate location'}
    paths_to_add = [path]
    Log.log.debug{"Adding cert location: #{path}"}
    if path.eql?(SpecialValues::DEF)
      @certificate_store.set_default_paths
      paths_to_add = [OpenSSL::X509::DEFAULT_CERT_DIR]
      paths_to_add.push(OpenSSL::X509::DEFAULT_CERT_FILE) unless defined?(JRUBY_VERSION)
      paths_to_add.select!{ |f| File.exist?(f)}
    elsif File.file?(path)
      @certificate_store.add_file(path)
    elsif File.directory?(path)
      @certificate_store.add_path(path)
    else
      raise "No such file or folder: #{path}"
    end
    paths_to_add.each do |p|
      pp = [File.realpath(p)]
      if File.directory?(p)
        pp = Dir.entries(p)
          .map{ |e| File.realpath(File.join(p, e))}
          .select{ |entry| File.file?(entry)}
          .select{ |entry| CERT_EXT.any?{ |ext| entry.end_with?(ext)}}
      end
      @certificate_paths.concat(pp)
    end
  end
  @certificate_paths.uniq!
  nil
end

#update_session(http_session) ⇒ nil

Parameters:

  • HTTP session to configure

Returns:



201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/aspera/cli/http.rb', line 201

def update_session(http_session)
  http_session.set_debug_output(LineLogger.new(:trace2)) if Log.instance.logger.trace2?
  http_session.verify_mode = SELF_SIGNED_CERT if http_session.use_ssl? && ignore_cert?(http_session.address, http_session.port)
  http_session.cert_store = @certificate_store if @certificate_store
  Log.log.debug{"Using cert store #{http_session.cert_store} (#{@certificate_store})"} unless http_session.cert_store.nil?
  @http_options.each do |k, v|
    method = "#{k}=".to_sym
    if http_session.respond_to?(method)
      http_session.send(method, v)
    else
      Log.log.error{"Unknown HTTP session attribute: #{k}"}
    end
  end
  nil
end