From: Tom Hughes Date: Fri, 26 Jan 2018 15:22:34 +0000 (+0000) Subject: Check all hosts for shared certificates X-Git-Url: https://git.openstreetmap.org./chef.git/commitdiff_plain/90a99a9591ff08a70463403ad1dba1a2d7939881 Check all hosts for shared certificates --- diff --git a/cookbooks/letsencrypt/files/default/bin/check-certificate b/cookbooks/letsencrypt/files/default/bin/check-certificate index 303314fca..35fbbed1f 100755 --- a/cookbooks/letsencrypt/files/default/bin/check-certificate +++ b/cookbooks/letsencrypt/files/default/bin/check-certificate @@ -1,36 +1,52 @@ #!/usr/bin/ruby -require "net/http" +require "socket" +require "openssl" -domain = ARGV.first +host = ARGV.shift +address = ARGV.shift +domains = ARGV + +context = OpenSSL::SSL::SSLContext.new +context.verify_mode = OpenSSL::SSL::VERIFY_NONE begin - connection = Net::HTTP.start(domain, :use_ssl => true) - certificate = connection.peer_cert + socket = TCPSocket.new(address, 443) - if Time.now < certificate.not_before - puts "Certificate #{domain} not valid until #{certificate.not_before}" - elsif certificate.not_after - Time.now < 21 * 86400 - puts "Certificate #{domain} expires at #{certificate.not_after}" - else - subject_alt_name = certificate.extensions.find { |e| e.oid == "subjectAltName" } + ssl = OpenSSL::SSL::SSLSocket.new(socket, context) + ssl.sync_close = true + ssl.hostname = domains.first + ssl.connect +rescue StandardError => error + puts "Error connecting to #{host}: #{error.message}" +end - if subject_alt_name.nil? - puts "Certificate #{domain} has no subjectAltName" - else - alt_names = subject_alt_name.value.split(/\s*,\s*/).sort +certificate = ssl.peer_cert - ARGV.sort.each do |expected| - puts "Certificate #{domain} is missing subjectAltName #{expected}" unless alt_names.shift == "DNS:#{expected}" - end +if Time.now < certificate.not_before + puts "Certificate #{domains.first} on #{host} not valid until #{certificate.not_before}" +elsif certificate.not_after - Time.now < 21 * 86400 + puts "Certificate #{domains.first} on #{host} expires at #{certificate.not_after}" +else + subject_alt_name = certificate.extensions.find { |e| e.oid == "subjectAltName" } + + if subject_alt_name.nil? + puts "Certificate #{domains.first} on #{host} has no subjectAltName" + else + alt_names = subject_alt_name.value.split(/\s*,\s*/).map { |n| n.sub(/^DNS:/, "") } - alt_names.each do |name| - puts "Certificate #{domain} has unexpected subjectAltName #{name}" + domains.each do |domain| + if alt_names.include?(domain) + alt_names.delete(domain) + else + puts "Certificate #{domains.first} on #{host} is missing subjectAltName #{domain}" end end - end - connection.finish -rescue StandardError => error - puts "Error connecting to #{domain}: #{error.message}" + alt_names.each do |name| + puts "Certificate #{domains.first} on #{host} has unexpected subjectAltName #{name}" + end + end end + +ssl.close diff --git a/cookbooks/letsencrypt/recipes/default.rb b/cookbooks/letsencrypt/recipes/default.rb index a2c42e1c5..34e9be8f7 100644 --- a/cookbooks/letsencrypt/recipes/default.rb +++ b/cookbooks/letsencrypt/recipes/default.rb @@ -121,7 +121,11 @@ directory "/srv/acme.openstreetmap.org/requests" do end certificates = search(:node, "letsencrypt:certificates").each_with_object({}) do |n, c| - c.merge!(n[:letsencrypt][:certificates]) + n[:letsencrypt][:certificates].each do |name, details| + c[name] ||= details.merge(:nodes => []) + + c[name][:nodes] << { :name => n[:fqdn], :address => n[:ipaddress] } + end end certificates.each do |name, details| diff --git a/cookbooks/letsencrypt/templates/default/check-certificates.erb b/cookbooks/letsencrypt/templates/default/check-certificates.erb index d03e98a4d..d07bacf5c 100644 --- a/cookbooks/letsencrypt/templates/default/check-certificates.erb +++ b/cookbooks/letsencrypt/templates/default/check-certificates.erb @@ -1,5 +1,7 @@ #!/bin/sh <% @certificates.each_value do |certificate| -%> -/srv/acme.openstreetmap.org/bin/check-certificate <%= certificate[:domains].join(" ") %> +<% certificate[:nodes].each do |host| -%> +/srv/acme.openstreetmap.org/bin/check-certificate <%= host[:name] %> <%= host[:address] %> <%= certificate[:domains].join(" ") %> +<% end -%> <% end -%>