Module: CertChecker

Extended by:
CertChecker
Included in:
CertChecker
Defined in:
lib/cert_checker.rb,
lib/cert_checker/version.rb

Defined Under Namespace

Classes: Error

Constant Summary collapse

DEFAULT_TIMEOUT =
5
ONE_DAY =
3600.0 * 24
VERSION =
"0.1.2"

Instance Method Summary collapse

Instance Method Details

#cert_storeObject



69
70
71
72
73
# File 'lib/cert_checker.rb', line 69

def cert_store
  @cert_store ||= OpenSSL::X509::Store.new.tap do |store|
    store.set_default_paths
  end
end

#check(host, *args) ⇒ status_symbol, ...

Returns:

  • (status_symbol, host, issuer, expired_at, desc)


48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/cert_checker.rb', line 48

def check(host, *args)
  cert, verify_result, _cert_chain, err_str = verify(host, *args)
  return [:failed, host, nil, nil, nil] unless cert
  status_sym = :unverifiable unless verify_result

  issuer = get_cert_issuer_name(cert)
  expired_at = cert.not_after
  valid_days = ((cert.not_after - Time.now) / ONE_DAY).floor
  valid_days = 0 if valid_days < 0
  desc = err_str || valid_days

  status_sym ||= :not_match unless verify_cert_dns(host, cert)
  status_sym ||= if expired_at <= Time.now then :expired
  elsif expired_at <= Time.now + 15 * ONE_DAY then :urgent
  elsif expired_at <= Time.now + 30 * ONE_DAY then :warning
  else :ok
  end

  [status_sym, host, issuer, expired_at, desc]
end

#get_cert(host, port = 443, timeout: DEFAULT_TIMEOUT) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/cert_checker.rb', line 16

def get_cert(host, port = 443, timeout: DEFAULT_TIMEOUT)
  tcp_client = Socket.tcp(host, port, connect_timeout: timeout)
  ssl_client = OpenSSL::SSL::SSLSocket.new(tcp_client)
  ssl_client.hostname = host

  begin
    ssl_client.connect_nonblock
  rescue IO::WaitReadable
    retry if IO.select([ssl_client], nil, nil, timeout)
  rescue IO::WaitWritable
    retry if IO.select(nil, [ssl_client], nil, timeout)
  end

  [ssl_client.peer_cert, ssl_client.peer_cert_chain].tap do
    ssl_client.close
    tcp_client.close
  end
rescue SocketError, SystemCallError, OpenSSL::SSL::SSLError => e
  raise CertChecker::Error.new("Failed to get cert of #{host}:#{port}. #{e.inspect}")
end

#verify(host, *args) ⇒ cert, ...

Returns:

  • (cert, verify_result, cert_chain, err_str)


38
39
40
41
42
43
44
45
# File 'lib/cert_checker.rb', line 38

def verify(host, *args)
  cert, cert_chain = get_cert(host, *args)
  if cert
    err = nil
    result = cert_store.verify(cert, cert_chain) { |r, s| err = s.error_string unless r; r }
    [cert, result, cert_chain, err]
  end
end