summaryrefslogtreecommitdiff
path: root/lib/leap_cli/acme.rb
diff options
context:
space:
mode:
authorelijah <elijah@riseup.net>2016-08-31 14:54:46 -0700
committerelijah <elijah@riseup.net>2016-09-01 10:49:22 -0700
commit8116e007cfd4dbee8282247348cf45473dcde45e (patch)
treeecf8cfbc790ef57c3519c947a1fa76d0c1a4e5a2 /lib/leap_cli/acme.rb
parentd679399af0898b959b8b84a8e8d1e2e03c4e21b5 (diff)
added support for Let's Encrypt
Diffstat (limited to 'lib/leap_cli/acme.rb')
-rw-r--r--lib/leap_cli/acme.rb101
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