class Uninterruptible::TLSServerFactory

Wraps a bound TCP server with an OpenSSL::SSL::SSLServer according to the Uninterruptible::Configuration for this server.

Attributes

configuration[R]

Public Class Methods

new(configuration) click to toggle source

@param [Uninterruptible::Configuration] configuration Object with valid TLS configuration options

@raise [Uninterruptible::ConfigurationError] Correct options are not set for TLS

# File lib/uninterruptible/tls_server_factory.rb, line 24
def initialize(configuration)
  @configuration = configuration
  check_configuration!
end

Public Instance Methods

wrap_with_tls(tcp_server) click to toggle source

Accepts a TCP server, gives it a nice friendly SSLServer wrapper and returns the SSLServer

@param [TCPServer] tcp_server Server to be wrapped

@return [OpenSSL::SSL::SSLServer] tcp_server with a TLS layer

# File lib/uninterruptible/tls_server_factory.rb, line 34
def wrap_with_tls(tcp_server)
  server = OpenSSL::SSL::SSLServer.new(tcp_server, ssl_context)
  server.start_immediately = false
  server
end

Private Instance Methods

check_configuration!() click to toggle source

Check the configuration parameters for TLS are correct

@raise [Uninterruptible::ConfigurationError] Correct options are not set for TLS

# File lib/uninterruptible/tls_server_factory.rb, line 66
def check_configuration!
  raise ConfigurationError, "TLS can only be used on TCP servers" unless configuration.bind.start_with?('tcp://')

  empty = %i[tls_certificate tls_key].any? { |config_param| configuration.send(config_param).nil? }
  raise ConfigurationError, "tls_certificate and tls_key must be set to use TLS" if empty
end
ssl_context() click to toggle source

Build an OpenSSL::SSL::SSLContext object from the configuration passed to the initializer

@return [OpenSSL::SSL::SSLContext] SSL context for the server config

# File lib/uninterruptible/tls_server_factory.rb, line 45
def ssl_context
  context = OpenSSL::SSL::SSLContext.new

  certificates = CertificateChain.new(configuration.tls_certificate).to_a
  context.cert = certificates.shift
  context.extra_chain_cert = certificates # Remaining certificataes that aren't the primary. Could be empty.

  context.key = OpenSSL::PKey::RSA.new(configuration.tls_key)
  context.ssl_version = configuration.tls_version.to_sym

  if configuration.verify_client_tls_certificate?
    context.verify_mode = OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
  end
  context.ca_file = configuration.client_tls_certificate_ca if configuration.client_tls_certificate_ca

  context
end