diff options
author | Vladimir Shushlin <vshushlin@gitlab.com> | 2019-05-16 09:32:25 +0000 |
---|---|---|
committer | Nick Thomas <nick@gitlab.com> | 2019-05-16 09:32:25 +0000 |
commit | 3c33724e2e182436a2d8b44ef71d0bdac37c585b (patch) | |
tree | ddf7bd94e5981ca34da591afd993cdaa5f45b283 /lib | |
parent | c841c8771b8d69034c1ceb6e452746d193865cb0 (diff) | |
download | gitlab-ce-3c33724e2e182436a2d8b44ef71d0bdac37c585b.tar.gz |
Add Let's Encrypt client
Part of adding Let's Encrypt certificates for pages domains
Add acme-client gem
Client is being initialized by private key stored in secrets.yml
Let's Encrypt account is being created lazily.
If it's already created, Acme::Client just gets account_kid by
calling new_account method
Make Let's Encrypt client an instance
Wrap order and challenge classes
Diffstat (limited to 'lib')
-rw-r--r-- | lib/gitlab/lets_encrypt/challenge.rb | 17 | ||||
-rw-r--r-- | lib/gitlab/lets_encrypt/client.rb | 74 | ||||
-rw-r--r-- | lib/gitlab/lets_encrypt/order.rb | 23 |
3 files changed, 114 insertions, 0 deletions
diff --git a/lib/gitlab/lets_encrypt/challenge.rb b/lib/gitlab/lets_encrypt/challenge.rb new file mode 100644 index 00000000000..6a7f5e965c5 --- /dev/null +++ b/lib/gitlab/lets_encrypt/challenge.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module Gitlab + module LetsEncrypt + class Challenge + def initialize(acme_challenge) + @acme_challenge = acme_challenge + end + + delegate :url, :token, :file_content, :status, :request_validation, to: :acme_challenge + + private + + attr_reader :acme_challenge + end + end +end diff --git a/lib/gitlab/lets_encrypt/client.rb b/lib/gitlab/lets_encrypt/client.rb new file mode 100644 index 00000000000..d7468b06767 --- /dev/null +++ b/lib/gitlab/lets_encrypt/client.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +module Gitlab + module LetsEncrypt + class Client + PRODUCTION_DIRECTORY_URL = 'https://acme-v02.api.letsencrypt.org/directory' + STAGING_DIRECTORY_URL = 'https://acme-staging-v02.api.letsencrypt.org/directory' + + def new_order(domain_name) + ensure_account + + acme_order = acme_client.new_order(identifiers: [domain_name]) + + ::Gitlab::LetsEncrypt::Order.new(acme_order) + end + + def load_order(url) + ensure_account + + # rubocop: disable CodeReuse/ActiveRecord + ::Gitlab::LetsEncrypt::Order.new(acme_client.order(url: url)) + # rubocop: enable CodeReuse/ActiveRecord + end + + def load_challenge(url) + ensure_account + + ::Gitlab::LetsEncrypt::Challenge.new(acme_client.challenge(url: url)) + end + + def terms_of_service_url + acme_client.terms_of_service + end + + def enabled? + return false unless Feature.enabled?(:pages_auto_ssl) + + Gitlab::CurrentSettings.lets_encrypt_terms_of_service_accepted + end + + private + + def acme_client + @acme_client ||= ::Acme::Client.new(private_key: private_key, directory: acme_api_directory_url) + end + + def private_key + @private_key ||= OpenSSL::PKey.read(Gitlab::Application.secrets.lets_encrypt_private_key) + end + + def admin_email + Gitlab::CurrentSettings.lets_encrypt_notification_email + end + + def contact + "mailto:#{admin_email}" + end + + def ensure_account + raise 'Acme integration is disabled' unless enabled? + + @acme_account ||= acme_client.new_account(contact: contact, terms_of_service_agreed: true) + end + + def acme_api_directory_url + if Rails.env.production? + PRODUCTION_DIRECTORY_URL + else + STAGING_DIRECTORY_URL + end + end + end + end +end diff --git a/lib/gitlab/lets_encrypt/order.rb b/lib/gitlab/lets_encrypt/order.rb new file mode 100644 index 00000000000..5109b5e9843 --- /dev/null +++ b/lib/gitlab/lets_encrypt/order.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module Gitlab + module LetsEncrypt + class Order + def initialize(acme_order) + @acme_order = acme_order + end + + def new_challenge + authorization = @acme_order.authorizations.first + challenge = authorization.http + ::Gitlab::LetsEncrypt::Challenge.new(challenge) + end + + delegate :url, :status, to: :acme_order + + private + + attr_reader :acme_order + end + end +end |