tls-checker 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ab14c3e081bec34c6623b35ee52b0e26e544242b21ff50a484c9780d73940585
4
- data.tar.gz: 1de5b2c8fae2bb03564a23d751ac04240ea64003a7022cf7d5779d6f61b478e5
3
+ metadata.gz: 1cdde3a84021818453f8783a575370df091b421bc8ec46b9f37eea6afea7c68d
4
+ data.tar.gz: f197dbf9cf67fccb5e6f5d757929ea6f145d5fbff77f0ed6adb311b362154e11
5
5
  SHA512:
6
- metadata.gz: f14c9c95cb25b5e36f5b8a1e1799cc18900e31f66790456704a4c866a65c47f165247a64d5795f9e22de3d87a6d89701d8726a3c4639f5fe5bc0d9bf4ccb07d3
7
- data.tar.gz: 413fc601fb7b4d410f6dc8f6518d982056b06f4144625e2d900a1f3c0b300d8b58c8ed039d533d13872b21d8cc7cd92ec73b13e35c651e374203d953c111dddc
6
+ metadata.gz: 59c569e106f22433b88cfd2480a8aad515b6cecedc1e50eaa533b907bb09711e7e90f58f4ed8ec7ecdb6781e17910eee527a72f903a187bb0f125ec1788314be
7
+ data.tar.gz: 4771ef041e39cb1da7aaae82f5508fc528dd3980a3f4fab0fa8907e89395f0c788e951d15fb8c0bb9d38b2108760b635661a9dfb4c393da2ea233614089f71be
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  language: ruby
3
3
  rvm:
4
+ - 2.3
4
5
  - 2.4
5
6
  - 2.5
6
7
  - 2.6
@@ -0,0 +1,16 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.1.0]
9
+
10
+ ### Added
11
+
12
+ - Make it possible to test services using an IP address;
13
+ - Report validity of certificates when a TLSA record is found in the DNS.
14
+
15
+ [Unreleased]: https://github.com/smortex/tls-checker/compare/v1.1.0...HEAD
16
+ [1.1.0]: https://github.com/smortex/tls-checker/compare/v1.0.0...v1.1.0
@@ -3,3 +3,5 @@
3
3
  require 'tls-checker/certificate_checker'
4
4
  require 'tls-checker/certificate_checker_factory'
5
5
  require 'tls-checker/line_oriented_socket'
6
+ require 'tls-checker/tlsa_checker'
7
+ require 'tls-checker/tlsa_checker_factory'
@@ -6,8 +6,6 @@ require 'internet_security_event'
6
6
 
7
7
  module TLSChecker
8
8
  class CertificateChecker
9
- include ActionView::Helpers::DateHelper
10
-
11
9
  def initialize(hostname, address, port, starttls)
12
10
  @hostname = hostname
13
11
  @address = address
@@ -31,7 +29,7 @@ module TLSChecker
31
29
  }
32
30
  end.merge(
33
31
  service: service,
34
- ttl: 3600 * 12,
32
+ ttl: 12.hours,
35
33
  tags: ['tls-checker'],
36
34
  )
37
35
  end
@@ -40,10 +38,16 @@ module TLSChecker
40
38
  description
41
39
  end
42
40
 
43
- private
41
+ def certificate
42
+ @certificate = OpenSSL::X509::Certificate.new(tls_socket.peer_cert) if @certificate.nil?
43
+ @certificate
44
+ rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT, SocketRecvTimeout => e
45
+ @certificate_failure = e.message
46
+ @certificate = false
47
+ end
44
48
 
45
49
  def service
46
- format('X.509/%<hostname>s/%<address>s:%<port>d', hostname: hostname, address: humanized_address, port: port)
50
+ "X.509/#{hostname}/#{humanized_address}:#{port}"
47
51
  end
48
52
 
49
53
  def humanized_address
@@ -54,13 +58,7 @@ module TLSChecker
54
58
  end
55
59
  end
56
60
 
57
- def certificate
58
- @certificate = OpenSSL::X509::Certificate.new(tls_socket.peer_cert) if @certificate.nil?
59
- @certificate
60
- rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT, SocketRecvTimeout => e
61
- @certificate_failure = e.message
62
- @certificate = false
63
- end
61
+ private
64
62
 
65
63
  def tls_socket
66
64
  @tls_socket ||= case starttls
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'ipaddr'
4
+
3
5
  module TLSChecker
4
6
  class CertificateCheckerFactory
5
7
  def initialize
@@ -14,7 +16,25 @@ module TLSChecker
14
16
 
15
17
  port ||= port_for(hostname)
16
18
  starttls ||= starttls_for(port)
17
- @resolver.getaddresses(hostname).map { |ip| CertificateChecker.new(hostname, ip, port, starttls) }
19
+
20
+ begin
21
+ ip_in_hostname = IPAddr.new(hostname)
22
+
23
+ [
24
+ CertificateChecker.new(nil, ip_in_hostname, port, starttls),
25
+ ]
26
+ rescue IPAddr::InvalidAddressError
27
+ certificate_checkers = @resolver.getaddresses(hostname).map { |ip| CertificateChecker.new(hostname, ip, port, starttls) }
28
+
29
+ factory = TLSACheckerFactory.new
30
+
31
+ tlsa_checkers = []
32
+ certificate_checkers.each do |certificate_checker|
33
+ tlsa_checkers += factory.tlsa_checkers_for(certificate_checker)
34
+ end
35
+
36
+ certificate_checkers + tlsa_checkers
37
+ end
18
38
  end
19
39
 
20
40
  private
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TLSChecker
4
+ class TLSAChecker < InternetSecurityEvent::TLSAStatus
5
+ def initialize(record, certificate_checker)
6
+ super(record, certificate_checker.certificate)
7
+
8
+ @certificate_checker = certificate_checker
9
+ end
10
+
11
+ def to_e
12
+ super.merge(
13
+ service: service,
14
+ ttl: 12.hours,
15
+ )
16
+ end
17
+
18
+ private
19
+
20
+ def service
21
+ "#{@certificate_checker.service}/TLSA"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TLSChecker
4
+ class TLSACheckerFactory
5
+ def initialize
6
+ @resolver = Resolv::DNS.new
7
+ end
8
+
9
+ def tlsa_checkers_for(certificate_checker)
10
+ res = []
11
+
12
+ each_tlsa_end_entity_record(certificate_checker) do |record|
13
+ checker = TLSAChecker.new(record, certificate_checker)
14
+ # Since a single domain may have different certificates on different
15
+ # addresses, we are not interested in reporting failures here: a server
16
+ # with 3 certificates on 3 IP addresses is expected to have 3 TLSA
17
+ # records in the DNS, each one being valid for a different certificate.
18
+ #
19
+ # By adding only valid certificates, we can still detect problems when
20
+ # events expire.
21
+ next unless checker.certificate_match_tlsa_record?
22
+
23
+ res << checker
24
+ end
25
+
26
+ res
27
+ end
28
+
29
+ private
30
+
31
+ def each_tlsa_end_entity_record(certificate_checker)
32
+ each_tlsa_record(certificate_checker) do |record|
33
+ next unless record.end_entity?
34
+
35
+ yield(record)
36
+ end
37
+ end
38
+
39
+ def each_tlsa_record(certificate_checker)
40
+ resource = "_#{certificate_checker.port}._tcp.#{certificate_checker.hostname}."
41
+
42
+ @resolver.getresources(resource, Resolv::DNS::Resource::IN::ANY).each do |rr|
43
+ # XXX: Should we check the RRSIG here, or can we assume that the resolver
44
+ # should have failed if it could not verify the response?
45
+ next unless rr.class.name == 'Resolv::DNS::Resource::Generic::Type52_Class1'
46
+
47
+ record = Resolv::DNS::Resource::IN::TLSA.new(rr.data)
48
+ yield(record)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TlsChecker
4
- VERSION = '1.0.0'
4
+ VERSION = '1.1.0'
5
5
  end
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
23
23
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
24
  spec.require_paths = ['lib']
25
25
 
26
- spec.add_dependency 'internet_security_event', '~> 1.0'
26
+ spec.add_dependency 'internet_security_event', '~> 1.1'
27
27
 
28
28
  spec.add_development_dependency 'bundler'
29
29
  spec.add_development_dependency 'midi-smtp-server'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tls-checker
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Romain Tartière
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-02-19 00:00:00.000000000 Z
11
+ date: 2019-03-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: internet_security_event
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.0'
19
+ version: '1.1'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.0'
26
+ version: '1.1'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -105,6 +105,7 @@ files:
105
105
  - ".gitignore"
106
106
  - ".rspec"
107
107
  - ".travis.yml"
108
+ - CHANGELOG.md
108
109
  - CODE_OF_CONDUCT.md
109
110
  - Gemfile
110
111
  - LICENSE.txt
@@ -117,6 +118,8 @@ files:
117
118
  - lib/tls-checker/certificate_checker.rb
118
119
  - lib/tls-checker/certificate_checker_factory.rb
119
120
  - lib/tls-checker/line_oriented_socket.rb
121
+ - lib/tls-checker/tlsa_checker.rb
122
+ - lib/tls-checker/tlsa_checker_factory.rb
120
123
  - lib/tls-checker/version.rb
121
124
  - tls-checker.gemspec
122
125
  homepage: https://github.com/smortex/tls-checker
@@ -138,8 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
138
141
  - !ruby/object:Gem::Version
139
142
  version: '0'
140
143
  requirements: []
141
- rubyforge_project:
142
- rubygems_version: 2.7.8
144
+ rubygems_version: 3.0.2
143
145
  signing_key:
144
146
  specification_version: 4
145
147
  summary: Report expired/about to expires certificates used in TLS connexions