module AcmeNsupdate
Constants
- RENEWAL_THRESHOLD
- VERSION
Attributes
logger[R]
options[R]
Public Class Methods
new(options)
click to toggle source
# File lib/acme_nsupdate/client.rb, line 33 def initialize options @options = options @logger = Logger.new(STDOUT) @logger.level = Logger::INFO @logger.level = Logger::FATAL if @options[:quiet] @logger.level = Logger::DEBUG if @options[:verbose] @verification_strategy = Strategy.for(@options[:challenge]).new(self) end
Public Instance Methods
account_key()
click to toggle source
# File lib/acme_nsupdate/client.rb, line 81 def account_key @account_key ||= read_or_create_key account_key_path end
account_key_path()
click to toggle source
# File lib/acme_nsupdate/client.rb, line 73 def account_key_path @account_key_path ||= datadir.join ".#{@options[:contact]}.pem" end
archive_path()
click to toggle source
# File lib/acme_nsupdate/client.rb, line 135 def archive_path @archive_path ||= datadir.join("archive") .join(Time.now.strftime("%Y%m%d%H%M%S")) .join(@options[:domains].first) .tap(&:mkpath) end
build_nsupdate()
click to toggle source
# File lib/acme_nsupdate/client.rb, line 101 def build_nsupdate Nsupdate.new(logger).tap do |nsupdate| nsupdate.server @options[:master] if @options[:master] nsupdate.tsig(*@options[:tsig].split(":")) if @options[:tsig] end end
client()
click to toggle source
# File lib/acme_nsupdate/client.rb, line 67 def client @client ||= DebuggableClient.new(private_key: account_key, directory: @options[:endpoint]).tap do |client| client.logger = @logger if @options[:verbose] end end
csr()
click to toggle source
# File lib/acme_nsupdate/client.rb, line 118 def csr logger.debug "Generating CSR" Acme::Client::CertificateRequest.new(names: @options[:domains], private_key: private_key) end
datadir()
click to toggle source
# File lib/acme_nsupdate/client.rb, line 77 def datadir @datadir ||= Pathname.new(@options[:datadir]).tap(&:mkpath) end
fetch_certificate(order)
click to toggle source
# File lib/acme_nsupdate/client.rb, line 108 def fetch_certificate order order.finalize csr: csr while order.status == 'processing' sleep 3 order.reload end raise "Failed to fetch certificate, order failed." unless order.status == 'valid' order.certificate end
live_path()
click to toggle source
# File lib/acme_nsupdate/client.rb, line 131 def live_path @live_path ||= datadir.join("live").join(@options[:domains].first).tap(&:mkpath) end
outdated_certificates()
click to toggle source
# File lib/acme_nsupdate/client.rb, line 194 def outdated_certificates domain = @options[:domains].first @outdated_certificates ||= datadir .join("archive") .children .select {|dir| dir.join(domain, "fullchain.pem").exist? } .sort_by(&:basename) .map {|path| OpenSSL::X509::Certificate.new path.join(domain, "fullchain.pem").read } .tap(&:pop) # keep current .tap(&:pop) # keep previous end
private_key()
click to toggle source
# File lib/acme_nsupdate/client.rb, line 123 def private_key @private_key ||= read_or_create_key private_key_path end
private_key_path()
click to toggle source
# File lib/acme_nsupdate/client.rb, line 127 def private_key_path @private_key_path ||= live_path.join("privkey.pem") end
publish_tlsa_records(certificate_pem)
click to toggle source
# File lib/acme_nsupdate/client.rb, line 151 def publish_tlsa_records certificate_pem return if @options[:notlsa] certificate = OpenSSL::X509::Certificate.new certificate_pem logger.info "Publishing TLSA records" old_contents = outdated_certificates.map {|certificate| "3 1 1 #{OpenSSL::Digest::SHA256.hexdigest(certificate.public_key.to_der)}" }.uniq content = "3 1 1 #{OpenSSL::Digest::SHA256.hexdigest(certificate.public_key.to_der)}" old_contents.delete(content) @options[:domains].each do |domain| nsupdate = build_nsupdate @options[:tlsaports].each do |port| restriction, port = port.split(":") restriction, port = port, restriction unless port label = "_#{port}._tcp.#{domain}" if restriction restrictions = restriction.delete("[]").split(" ") unless restrictions.include? domain logger.debug "Not publishing TLSA record for #{label}, not one of #{restrictions.join(" ")}" next end end old_contents.each do |old_content| nsupdate.del label, "TLSA", old_content unless @options[:keep] end nsupdate.del label, "TLSA", content nsupdate.add label, "TLSA", content, @options[:tlsa_ttl] end begin nsupdate.send rescue Nsupdate::Error # Continue trying other zones, errors logged in Nsupdate end end end
read_or_create_key(path)
click to toggle source
# File lib/acme_nsupdate/client.rb, line 85 def read_or_create_key path logger.debug "Creating or reading #{path}" path.write OpenSSL::PKey::RSA.new @options[:keylength] unless path.exist? OpenSSL::PKey::RSA.new path.read end
register_account()
click to toggle source
# File lib/acme_nsupdate/client.rb, line 60 def register_account return if account_key_path.exist? logger.debug "No key found at #{account_key_path}, registering" client.new_account contact: "mailto:#{@options[:contact]}", terms_of_service_agreed: true end
renewal_needed?()
click to toggle source
# File lib/acme_nsupdate/client.rb, line 91 def renewal_needed? return true if @options[:force] cert_path = live_path.join("fullchain.pem") return true unless cert_path.exist? cert = OpenSSL::X509::Certificate.new(cert_path.read) (cert.not_after - Time.now) <= RENEWAL_THRESHOLD end
run()
click to toggle source
# File lib/acme_nsupdate/client.rb, line 42 def run unless renewal_needed? logger.info "Existing certificate is still valid long enough." return end register_account order, challenges = @verification_strategy.verify_domains logger.info "Requesting certificate" certificate = fetch_certificate order write_files live_path, certificate, private_key write_files archive_path, certificate, private_key @verification_strategy.cleanup challenges unless @options[:keep] publish_tlsa_records certificate rescue Nsupdate::Error abort "nsupdate failed." # detail logged in Nsupdate end
write_files(path, certificate, key)
click to toggle source
# File lib/acme_nsupdate/client.rb, line 142 def write_files path, certificate, key logger.info "Writing files to #{path}" logger.debug "Writing #{path.join("key.pem")}" path.join("privkey.pem").write key.to_pem path.join("privkey.pem").chmod(0600) logger.debug "Writing #{path.join("fullchain.pem")}" path.join("fullchain.pem").write certificate end