files/gitlab-cookbooks/letsencrypt/libraries/lets_encrypt.rb (53 lines of code) (raw):
# Copyright:: Copyright (c) 2018 GitLab Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require_relative '../../package/libraries/helpers/logging_helper'
class LetsEncrypt
class << self
def parse_variables
parse_enable
end
# Munge the enable parameter
#
# @return [void]
def parse_enable
# default for letsencrypt.enable is nil. If a user has specified anything
# else leave it alone.
return unless Gitlab['letsencrypt']['enable'].nil?
if should_auto_enable? && Gitlab['package']['generate_secrets_json_file'] == false
LoggingHelper.warning("Writing secrets to `gitlab-secrets.json` file is disabled. Hence, not automatically enabling Let's Encrypt integration.")
return
end
# We get to make a 'guess' as to if we should enable based on other parsed
# values
Gitlab['letsencrypt']['enable'] = should_auto_enable?
# Remember if we auto-enabled, for later runs. Persisted as a secret
Gitlab['letsencrypt']['auto_enabled'] = Gitlab['letsencrypt']['enable'] == true
end
def rails_listen_https?
Gitlab['gitlab_rails']['gitlab_https']
end
def nginx_enabled?
[
Gitlab['nginx']['enable'],
Gitlab[:node]['gitlab']['nginx']['enable'],
true
].find { |e| !e.nil? }
end
def nginx_listen_https?
Gitlab['nginx']['listen_https'].nil? || Gitlab['nginx']['listen_https']
end
def le_auto_enabled?
# We store value of this setting to gitlab-secrets.json file. This acts
# as a marker whether the certificate present is something we generated
# automatically in a previous run, or is something user brought.
Gitlab['letsencrypt']['auto_enabled']
end
def cert_files_present?
File.exist?(Gitlab['nginx']['ssl_certificate_key']) || File.exist?(Gitlab['nginx']['ssl_certificate'])
end
# Should we enable the recipe even if a user didn't specify it?
#
# @return [true, false]
def should_auto_enable?
# We automatically enable LE if all the following conditions are met
# 1. Rails component is listening to https
# 2. Nginx is enabled and is listening over https
# 3. At least one of the following is true
# a. LE was automatically enabled in a previous run
# b. No certificate/key files are present
# c. If certificate is present, and they are from LE, and is ready for renewal
# Note: The last condition here is a failsafe to ensure an expired
# certificate always gets renewed.
# Check https://gitlab.com/gitlab-org/omnibus-gitlab/issues/4244 for
# details. The downside is that when expired certificate issued by LE
# is encountered, omnibus-gitlab will attempt to renew it, irrespective
# of whether it was automatically generated by a previous reconfigure
# run or brought by the user.
rails_listen_https? && nginx_enabled? && nginx_listen_https? && (le_auto_enabled? || !cert_files_present? || needs_renewal?)
end
# Save secrets if they do not have letsencrypt.auto_enabled
#
# @return [void]
def save_auto_enabled
return unless Gitlab['letsencrypt']['auto_enabled']
secrets = SecretsHelper.load_gitlab_secrets
# Avoid writing if the attribute is there and true
return if secrets.dig('letsencrypt', 'auto_enabled')
SecretsHelper.write_to_gitlab_secrets
end
private
LETSENCRYPT_ISSUER = %r(/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X[1-4]).freeze
# Checks wheather the existing Let's Encrypt certificate is expired and needs renewal.
#
# @return [true, false]
def needs_renewal?
file_name = Gitlab['nginx']['ssl_certificate']
return false unless File.exist? file_name
cert = OpenSSL::X509::Certificate.new File.read(file_name)
cert.issuer.to_s =~ LETSENCRYPT_ISSUER && cert.not_after < Time.now
end
end
end