Class: Aspera::WebServerSimple
- Inherits:
-
WEBrick::HTTPServer
- Object
- WEBrick::HTTPServer
- Aspera::WebServerSimple
- Defined in:
- lib/aspera/web_server_simple.rb
Overview
Simple WEBrick server with HTTPS support
Direct Known Subclasses
Constant Summary collapse
- PARAMS =
%i[cert key chain].freeze
- DEFAULT_URL =
'http://localhost:8080'
Class Method Summary collapse
-
.read_chain_file(chain) ⇒ Array<OpenSSL::X509::Certificate>
List of Certificates from chain file.
-
.self_signed_cert(private_key, digest: 'SHA256') ⇒ Object
Generate or fill and self sign certificate.
Instance Method Summary collapse
-
#<<(access_log) ⇒ Object
log web server access ( option AccessLog ).
-
#initialize(uri, cert: nil, key: nil, chain: nil) ⇒ WebServerSimple
constructor
A new instance of WebServerSimple.
-
#start ⇒ Object
blocking.
Constructor Details
#initialize(uri, cert: nil, key: nil, chain: nil) ⇒ WebServerSimple
Returns a new instance of WebServerSimple.
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 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/aspera/web_server_simple.rb', line 53 def initialize(uri, cert: nil, key: nil, chain: nil) Aspera.assert_type(uri, URI) @uri = uri # see https://www.rubydoc.info/stdlib/webrick/WEBrick/Config = { 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' # Required lazily: webrick/ssl.rb reads OpenSSL::OPENSSL_VERSION at load time, # a constant CosmoRuby's OpenSSL shim does not define, so requiring it # unconditionally at file load would break any command in a Cosmo build # even when no HTTPS server is ever started. require 'webrick/https' [:SSLEnable] = true if cert.nil? && key.nil? [:SSLCertName] = [['CN', WEBrick::Utils.getservername]] elsif cert && PKCS12_EXT.include?(File.extname(cert).downcase) # PKCS12 Log.log.debug('Using PKCS12 certificate') Aspera.assert(!key.nil?, type: Error) { 'PKCS12 requires a key (password)' } pkcs12 = OpenSSL::PKCS12.new(File.read(cert), key) [:SSLCertificate] = pkcs12.certificate [:SSLPrivateKey] = pkcs12.key [:SSLExtraChainCert] = pkcs12.ca_certs else Log.log.debug('Using PEM certificate') [:SSLPrivateKey] = if key.nil? OpenSSL::PKey::RSA.new(4096) else OpenSSL::PKey::RSA.new(File.read(key)) end [:SSLCertificate] = if cert.nil? self.class.self_signed_cert([:SSLPrivateKey]) else OpenSSL::X509::Certificate.new(File.read(cert)) end [:SSLExtraChainCert] = read_chain_file(chain) unless chain.nil? Aspera.assert([:SSLCertificate].public_key.to_der == [:SSLPrivateKey].public_key.to_der, type: Error) { 'key and cert do not match' } 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() } end |
Class Method Details
.read_chain_file(chain) ⇒ Array<OpenSSL::X509::Certificate>
Returns list of Certificates from chain file.
44 45 46 |
# File 'lib/aspera/web_server_simple.rb', line 44 def read_chain_file(chain) File.read(chain).scan(/-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----/m).map { |i| OpenSSL::X509::Certificate.new(i) } end |
.self_signed_cert(private_key, digest: 'SHA256') ⇒ Object
Generate or fill and self sign certificate
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/aspera/web_server_simple.rb', line 22 def self_signed_cert(private_key, digest: 'SHA256') cert = OpenSSL::X509::Certificate.new cert.subject = cert.issuer = OpenSSL::X509::Name.parse(GENERIC_ISSUER) cert.not_before = Time.now - CLOCK_SKEW_OFFSET_SEC cert.not_after = cert.not_before + ONE_YEAR_SECONDS cert.public_key = private_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(private_key, OpenSSL::Digest.new(digest)) cert end |