Class: Docker::API::Transport::Tls

Inherits:
Tcp
  • Object
show all
Defined in:
lib/docker/api/transport/tls.rb

Overview

A daemon reached over TLS, as DOCKER_CERT_PATH configures.

The handshake happens here rather than in Net::HTTP. That is deliberate: the layer above receives an already-encrypted socket and does not need to know whether TLS is in play, which keeps one code path for every transport.

Instance Attribute Summary

Attributes inherited from Tcp

#host, #port

Instance Method Summary collapse

Methods inherited from Tcp

#host_header

Methods inherited from Base

#host_header

Constructor Details

#initialize(host:, port:, ca_file: nil, cert_file: nil, key_file: nil, verify: true, open_timeout: 10) ⇒ Tls

Returns a new instance of Tls.

Parameters:

  • host (String)

    the host to dial

  • port (Integer)

    the port to dial

  • ca_file (String, nil) (defaults to: nil)

    path to the CA bundle

  • cert_file (String, nil) (defaults to: nil)

    path to the client certificate

  • key_file (String, nil) (defaults to: nil)

    path to the client key

  • verify (Boolean) (defaults to: true)

    whether to verify the daemon's certificate

  • open_timeout (Numeric) (defaults to: 10)

    seconds to wait for the connection



23
24
25
26
27
28
29
30
# File 'lib/docker/api/transport/tls.rb', line 23

def initialize(host:, port:, ca_file: nil, cert_file: nil, key_file: nil,
  verify: true, open_timeout: 10)
  super(host: host, port: port, open_timeout: open_timeout)
  @ca_file = ca_file
  @cert_file = cert_file
  @key_file = key_file
  @verify = verify
end

Instance Method Details

#connectOpenSSL::SSL::SSLSocket

Returns a connected, handshaken socket.

Returns:

  • (OpenSSL::SSL::SSLSocket)

    a connected, handshaken socket

Raises:



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/docker/api/transport/tls.rb', line 34

def connect
  dial("https://#{host}:#{port}") do
    # The raw socket is closed by hand if anything between here and a
    # completed handshake raises. sync_close only ties the two together
    # once an SSLSocket exists and owns it, so an expired certificate,
    # a hostname mismatch or an untrusted CA used to leave the
    # descriptor open until GC got to it -- and a retry loop waiting for
    # a daemon to come up exhausts descriptors rather than failing.
    raw = super_socket
    begin
      socket = OpenSSL::SSL::SSLSocket.new(raw, ssl_context)
      socket.hostname = host # SNI, which some proxies in front of a daemon require
      socket.sync_close = true
      socket.connect
      socket
    rescue StandardError
      raw.close unless raw.closed?
      raise
    end
  end
end

#to_sString Also known as: inspect

Returns:

  • (String)


57
58
59
# File 'lib/docker/api/transport/tls.rb', line 57

def to_s
  "#<Docker::API::Transport::Tls host=#{host} port=#{port} verify=#{@verify}>"
end