diff options
author | elijah <elijah@riseup.net> | 2016-08-31 14:54:46 -0700 |
---|---|---|
committer | elijah <elijah@riseup.net> | 2016-09-01 10:49:22 -0700 |
commit | 8116e007cfd4dbee8282247348cf45473dcde45e (patch) | |
tree | ecf8cfbc790ef57c3519c947a1fa76d0c1a4e5a2 /lib/leap_cli/acme.rb | |
parent | d679399af0898b959b8b84a8e8d1e2e03c4e21b5 (diff) |
added support for Let's Encrypt
Diffstat (limited to 'lib/leap_cli/acme.rb')
-rw-r--r-- | lib/leap_cli/acme.rb | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/lib/leap_cli/acme.rb b/lib/leap_cli/acme.rb new file mode 100644 index 00000000..6c7dbe98 --- /dev/null +++ b/lib/leap_cli/acme.rb @@ -0,0 +1,101 @@ +require 'openssl' +require 'acme-client' + +# +# A little bit of sugar around gem acme-client +# + +module LeapCli + class Acme + + if ENV['ACME_STAGING'] + ENDPOINT = 'https://acme-staging.api.letsencrypt.org/' + puts "using endpoint " + ENDPOINT + else + ENDPOINT = 'https://acme-v01.api.letsencrypt.org/' + end + + def initialize(domain: nil, key:) + @client = ::Acme::Client.new( + private_key: key, + endpoint: ENDPOINT, + connection_options: {request: {open_timeout: 5, timeout: 5}} + ) + @domain = domain + end + + # + # static methods + # + + def self.new_private_key + return OpenSSL::PKey::RSA.new(4096) + end + + def self.load_private_key(pem_encoded_key) + return OpenSSL::PKey::RSA.new(pem_encoded_key) + end + + def self.load_csr(pem_encoded_csr) + return OpenSSL::X509::Request.new(pem_encoded_csr) + end + + # + # instance methods + # + + # + # register a new account key with CA + # + def register(contact) + registration = @client.register(contact: 'mailto:' + contact) + if registration && registration.agree_terms + return registration + else + return false + end + end + + # + # authorize account key for domain + # + def authorize + authorization = @client.authorize(domain: @domain) + challenge = nil + begin + while true + if authorization.status == 'pending' + challenge = authorization.http01 + yield challenge + challenge.request_verification + sleep 1 + authorization.verify_status + if challenge.error + return 'error', challenge.error + end + elsif authorization.status == 'invalid' + challenge_msg = (challenge.nil? ? '' : challenge.error) + return 'error', 'Something bad happened. %s' % challenge_msg + elsif authorization.status == 'valid' + return 'valid', nil + else + challenge_msg = (challenge.nil? ? '' : challenge.error) + return 'error', 'status: %s, response message: %s' % [authorization.status, challenge_msg] + end + end + rescue Interrupt + return 'error', 'interrupted' + end + rescue ::Acme::Client::Error::Unauthorized => exc + return 'unauthorized', exc.to_s + end + + # + # get new certificate + # + def get_certificate(csr) + return @client.new_certificate(csr) + end + + end +end
\ No newline at end of file |