Class: Aspera::WebServerSimple

Inherits:
WEBrick::HTTPServer
  • Object
show all
Defined in:
lib/aspera/web_server_simple.rb

Overview

Simple WEBrick server with HTTPS support

Direct Known Subclasses

WebAuth

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(uri, certificate: nil) ⇒ WebServerSimple



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
72
73
74
75
76
77
78
79
80
# File 'lib/aspera/web_server_simple.rb', line 41

def initialize(uri, certificate: nil)
  @url = uri
  # see https://www.rubydoc.info/stdlib/webrick/WEBrick/Config
  webrick_options = {
    BindAddress: uri.host,
    Port:        uri.port,
    Logger:      Log.log,
    AccessLog:   [[self, WEBrick::AccessLog::COMMON_LOG_FORMAT]] # replace default access log to call local method "<<" below
  }
  case uri.scheme
  when 'http'
    Log.log.debug('HTTP mode')
  when 'https'
    webrick_options[:SSLEnable] = true
    if certificate.nil?
      webrick_options[:SSLCertName] = [['CN', WEBrick::Utils.getservername]]
    else
      Aspera.assert_type(certificate, Hash)
      certificate = certificate.symbolize_keys
      raise "unexpected key in certificate config: only: #{CERT_PARAMETERS.join(', ')}" if certificate.keys.any?{|key|!CERT_PARAMETERS.include?(key)}
      webrick_options[:SSLPrivateKey] = if certificate.key?(:key)
        OpenSSL::PKey::RSA.new(File.read(certificate[:key]))
      else
        OpenSSL::PKey::RSA.new(4096)
      end
      if certificate.key?(:cert)
        webrick_options[:SSLCertificate] = OpenSSL::X509::Certificate.new(File.read(certificate[:cert]))
      else
        webrick_options[:SSLCertificate] = OpenSSL::X509::Certificate.new
        self.class.fill_self_signed_cert(webrick_options[:SSLCertificate], webrick_options[:SSLPrivateKey])
      end
      if certificate.key?(:chain)
        webrick_options[:SSLExtraChainCert] = [OpenSSL::X509::Certificate.new(File.read(certificate[:chain]))]
      end
    end
  end
  # call constructor of parent class, but capture STDERR
  # self signed certificate generates characters on STDERR, see create_self_signed_cert in webrick/ssl.rb
  Log.capture_stderr { super(webrick_options) }
end

Class Method Details

.fill_self_signed_cert(cert, key, digest = 'SHA256') ⇒ Object

generates and adds self signed cert to provided webrick options



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/aspera/web_server_simple.rb', line 20

def fill_self_signed_cert(cert, key, digest = 'SHA256')
  cert.subject = cert.issuer = OpenSSL::X509::Name.parse(GENERIC_ISSUER)
  cert.not_before = cert.not_after = Time.now
  cert.not_after += ONE_YEAR_SECONDS
  cert.public_key = key.public_key
  cert.serial = 0x0
  cert.version = 2
  ef = OpenSSL::X509::ExtensionFactory.new
  ef.issuer_certificate = cert
  ef.subject_certificate = cert
  cert.extensions = [
    ef.create_extension('basicConstraints', 'CA:TRUE', true),
    ef.create_extension('subjectKeyIdentifier', 'hash')
    # ef.create_extension('keyUsage', 'cRLSign,keyCertSign', true),
  ]
  cert.add_extension(ef.create_extension('authorityKeyIdentifier', 'keyid:always,issuer:always'))
  cert.sign(key, OpenSSL::Digest.new(digest))
end

Instance Method Details

#<<(access_log) ⇒ Object

log web server access ( option AccessLog )



91
92
93
# File 'lib/aspera/web_server_simple.rb', line 91

def <<(access_log)
  Log.log.debug{"webrick log #{access_log.chomp}"}
end

#startObject

blocking



83
84
85
86
87
88
# File 'lib/aspera/web_server_simple.rb', line 83

def start
  Log.log.info{"Listening on #{@url}"}
  # kill -HUP for graceful shutdown
  Kernel.trap('HUP') { shutdown }
  super
end