Add a cron job to check SSL certificate validity
authorTom Hughes <tom@compton.nu>
Thu, 25 Jan 2018 00:08:44 +0000 (00:08 +0000)
committerTom Hughes <tom@compton.nu>
Thu, 25 Jan 2018 00:27:03 +0000 (00:27 +0000)
cookbooks/letsencrypt/files/default/bin/check-certificate [new file with mode: 0755]
cookbooks/letsencrypt/recipes/default.rb
cookbooks/letsencrypt/templates/default/check-certificates.erb [new file with mode: 0644]
cookbooks/letsencrypt/templates/default/cron.erb

diff --git a/cookbooks/letsencrypt/files/default/bin/check-certificate b/cookbooks/letsencrypt/files/default/bin/check-certificate
new file mode 100755 (executable)
index 0000000..46ca8e8
--- /dev/null
@@ -0,0 +1,36 @@
+#!/usr/bin/ruby
+
+require "net/http"
+
+domain = ARGV.first
+
+begin
+  connection = Net::HTTP.start(domain, :use_ssl => true)
+  certificate = connection.peer_cert
+
+  if Time.now < certificate.not_before
+    puts "Certificate #{domain} not valid until #{certificate.not_before}"
+  elsif certificate.not_after - Time.now < 14 * 86400
+    puts "Certificate #{domain} expires at #{certificate.not_after}"
+  else
+    subject_alt_name = certificate.extensions.find { |e| e.oid == "subjectAltName" }
+
+    if subject_alt_name.nil?
+      puts "Certificate #{domain} has no subject_alt_name"
+    else
+      alt_names = subject_alt_name.value.split(/\s*,\s*/).sort
+
+      ARGV.sort.each do |expected|
+        puts "Certificate #{domain} is missing subject_alt_name #{expected}" unless alt_names.shift == "DNS:#{expected}"
+      end
+
+      alt_names.each do |name|
+        puts "Certificate #{domain} has unexpected altName #{name}"
+      end
+    end
+  end
+
+  connection.finish
+rescue OpenSSL::SSL::SSLError => error
+  puts "Error connecting to #{domain}: #{error.message}"
+end
index 8f95644..a2c42e1 100644 (file)
@@ -143,6 +143,14 @@ certificates.each do |name, details|
   end
 end
 
+template "/srv/acme.openstreetmap.org/bin/check-certificates" do
+  source "check-certificates.erb"
+  owner "root"
+  group "root"
+  mode 0o755
+  variables :certificates => certificates
+end
+
 template "/etc/cron.d/letsencrypt" do
   source "cron.erb"
   owner "root"
diff --git a/cookbooks/letsencrypt/templates/default/check-certificates.erb b/cookbooks/letsencrypt/templates/default/check-certificates.erb
new file mode 100644 (file)
index 0000000..d03e98a
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+<% @certificates.each_value do |certificate| -%>
+/srv/acme.openstreetmap.org/bin/check-certificate <%= certificate[:domains].join(" ") %>
+<% end -%>
index fa89eda..74a8ee0 100644 (file)
@@ -2,4 +2,5 @@
 
 MAILTO=admins@openstreetmap.org
 
-0 */12 * * * letsencrypt /srv/acme.openstreetmap.org/bin/renew
+00 */12 * * * letsencrypt /srv/acme.openstreetmap.org/bin/renew
+30 */12 * * * letsencrypt /srv/acme.openstreetmap.org/bin/check-certificates