From 9ef69854ca19357f987088eb819bdfcfcf289635 Mon Sep 17 00:00:00 2001 From: Kyle Drake Date: Sat, 18 Jun 2016 12:46:00 -0700 Subject: [PATCH] simplify letsencrypt code for now, merge into single async worker --- environment.rb | 7 ----- models/site.rb | 22 ---------------- workers/create_ssl_cert_worker.rb | 17 ------------ workers/request_ssl_auth_worker.rb | 42 +++++++++++++++++++++++++++--- 4 files changed, 38 insertions(+), 50 deletions(-) delete mode 100644 workers/create_ssl_cert_worker.rb diff --git a/environment.rb b/environment.rb index ddb6f4b1..387685a6 100644 --- a/environment.rb +++ b/environment.rb @@ -152,10 +152,3 @@ end gandi_opts = {} gandi_opts[:env] = :test unless ENV['RACK_ENV'] == 'production' $gandi = Gandi::Session.new $config['gandi_api_key'], gandi_opts - -# Let's Encrypt - -$letsencrypt = Acme::Client.new( - private_key: OpenSSL::PKey::RSA.new(File.read($config['letsencrypt_key'])), - endpoint: $config['letsencrypt_endpoint'] -) \ No newline at end of file diff --git a/models/site.rb b/models/site.rb index d0d48903..6b5603cd 100644 --- a/models/site.rb +++ b/models/site.rb @@ -1330,28 +1330,6 @@ class Site < Sequel::Model sanitized.gsub(/(http|https):\/\//, '').gsub(/[^\w\s]/, '').downcase.split.uniq.select{|v| v.length < SiteFile::CLASSIFIER_WORD_LIMIT}.join(' ') end - def request_ssl_authorization - auth = $letsencrypt.authorize domain: domain - challenge = auth.http01 - FileUtils.mkdir_p File.join(base_files_path, File.dirname(challenge.filename)) - - File.write File.join(base_files_path, challenge.filename), challenge.file_content - - challenge.request_verification - - challenge - end - - # request_ssl_authorization must be run first! - def obtain_ssl_certificate - csr = Acme::Client::CertificateRequest.new names: [domain, "www.#{domain}"] - certificate = $letsencrypt.new_certificate csr - self.ssl_key = certificate.request.private_key.to_pem - self.ssl_cert = certificate.fullchain_to_pem - save_changes - FileUtils.rm_rf File.join(base_files_path, '.well-known') - end - # array of hashes: filename, tempfile, opts. def store_files(files, opts={}) results = [] diff --git a/workers/create_ssl_cert_worker.rb b/workers/create_ssl_cert_worker.rb deleted file mode 100644 index 7827bcd3..00000000 --- a/workers/create_ssl_cert_worker.rb +++ /dev/null @@ -1,17 +0,0 @@ -class CreateSSLCertWorker - include Sidekiq::Worker - sidekiq_options queue: :create_ssl_cert_worker, retry: 100, backtrace: true - - sidekiq_retry_in do |count| - 180 - end - - def perform(site_id, challenge) - site = Site[site_id] - - challenge = $letsencrypt.challenge_from_hash JSON.parse(challenge) - if challenge.verify_status == 'valid' - site.obtain_ssl_certificate - end - end -end diff --git a/workers/request_ssl_auth_worker.rb b/workers/request_ssl_auth_worker.rb index a5cf2b9f..ee6fbd2a 100644 --- a/workers/request_ssl_auth_worker.rb +++ b/workers/request_ssl_auth_worker.rb @@ -1,4 +1,6 @@ class RequestSSLAuthWorker + class NotAuthorizedYetError < StandardError; end + class VerificationTimeoutError < StandardError; end include Sidekiq::Worker sidekiq_options queue: :request_ssl_auth_worker, retry: 100, backtrace: true @@ -7,10 +9,42 @@ class RequestSSLAuthWorker end def perform(site_id) - site = Site[site_id] - return if site.domain.blank? - challenge = site.request_ssl_authorization + letsencrypt = Acme::Client.new( + private_key: OpenSSL::PKey::RSA.new(File.read($config['letsencrypt_key'])), + endpoint: $config['letsencrypt_endpoint'] + ) - CreateSSLCertWorker.perform_in 5.seconds, site_id, challenge.to_h.to_json + site = Site[site_id] + + return if site.domain.blank? || site.is_deleted || site.is_banned + + auth = letsencrypt.authorize domain: site.domain + + challenge = auth.http01 + + FileUtils.mkdir_p File.join(site.base_files_path, File.dirname(challenge.filename)) + File.write File.join(site.base_files_path, challenge.filename), challenge.file_content + + challenge.request_verification + + sleep 1 + + attempts = 0 + + begin + raise VerificationTimeoutError if attempts == 5 + raise NotAuthorizedYet if challenge.verify_status != 'valid' + rescue NotAuthorizedYet + sleep 5 + attempts += 1 + retry + end + + csr = Acme::Client::CertificateRequest.new names: [site.domain, "www.#{site.domain}"] + certificate = letsencrypt.new_certificate csr + site.ssl_key = certificate.request.private_key.to_pem + site.ssl_cert = certificate.fullchain_to_pem + site.save_changes validate: false + FileUtils.rm_rf File.join(site.base_files_path, '.well-known') end end