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 +4 -4
- data/.travis.yml +1 -0
- data/CHANGELOG.md +16 -0
- data/lib/tls-checker.rb +2 -0
- data/lib/tls-checker/certificate_checker.rb +10 -12
- data/lib/tls-checker/certificate_checker_factory.rb +21 -1
- data/lib/tls-checker/tlsa_checker.rb +24 -0
- data/lib/tls-checker/tlsa_checker_factory.rb +52 -0
- data/lib/tls-checker/version.rb +1 -1
- data/tls-checker.gemspec +1 -1
- metadata +8 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1cdde3a84021818453f8783a575370df091b421bc8ec46b9f37eea6afea7c68d
|
4
|
+
data.tar.gz: f197dbf9cf67fccb5e6f5d757929ea6f145d5fbff77f0ed6adb311b362154e11
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 59c569e106f22433b88cfd2480a8aad515b6cecedc1e50eaa533b907bb09711e7e90f58f4ed8ec7ecdb6781e17910eee527a72f903a187bb0f125ec1788314be
|
7
|
+
data.tar.gz: 4771ef041e39cb1da7aaae82f5508fc528dd3980a3f4fab0fa8907e89395f0c788e951d15fb8c0bb9d38b2108760b635661a9dfb4c393da2ea233614089f71be
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
ADDED
@@ -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
|
data/lib/tls-checker.rb
CHANGED
@@ -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:
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
data/lib/tls-checker/version.rb
CHANGED
data/tls-checker.gemspec
CHANGED
@@ -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.
|
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.
|
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-
|
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.
|
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.
|
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
|
-
|
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
|