Commit ad07d1db authored by Vladimir Shushlin's avatar Vladimir Shushlin

Add Let's Encrypt errors to log

+specs
parent b8ff11ba
......@@ -37,7 +37,7 @@ module PagesDomains
save_certificate(acme_order.private_key, api_order)
acme_order.destroy!
when 'invalid'
save_order_error(acme_order)
save_order_error(acme_order, api_order)
end
end
......@@ -48,11 +48,27 @@ module PagesDomains
pages_domain.update!(gitlab_provided_key: private_key, gitlab_provided_certificate: certificate)
end
def save_order_error(acme_order)
def save_order_error(acme_order, api_order)
log_error(api_order)
return unless Feature.enabled?(:pages_letsencrypt_errors, pages_domain.project)
acme_order.pages_domain.update_column(:auto_ssl_failed, true)
pages_domain.assign_attributes(auto_ssl_failed: true)
pages_domain.save!(validate: false)
acme_order.destroy!
end
def log_error(api_order)
Gitlab::AppLogger.error(
message: "Failed to obtain Let's Encrypt certificate",
acme_error: api_order.challenge_error,
project_id: pages_domain.project_id,
pages_domain: pages_domain.domain
)
rescue => e
# getting authorizations is an additional network request which can raise errors
Gitlab::ErrorTracking.track_exception(e)
end
end
end
......@@ -7,7 +7,7 @@ module Gitlab
@acme_challenge = acme_challenge
end
delegate :token, :file_content, :status, :request_validation, to: :acme_challenge
delegate :token, :file_content, :status, :request_validation, :error, to: :acme_challenge
private
......
......@@ -8,7 +8,6 @@ module Gitlab
end
def new_challenge
authorization = @acme_order.authorizations.first
challenge = authorization.http
::Gitlab::LetsEncrypt::Challenge.new(challenge)
end
......@@ -22,11 +21,19 @@ module Gitlab
acme_order.finalize(csr: csr)
end
def challenge_error
authorization.challenges.first&.error
end
delegate :url, :status, :expires, :certificate, to: :acme_order
private
attr_reader :acme_order
def authorization
@acme_order.authorizations.first
end
end
end
end
......@@ -38,4 +38,23 @@ describe ::Gitlab::LetsEncrypt::Order do
order.request_certificate(domain: 'example.com', private_key: private_key)
end
end
describe '#challenge_error' do
it 'returns error if challenge has errors' do
challenge = acme_challenge_double
# error just to give an example
error = {
"type" => "urn:ietf:params:acme:error:dns",
"detail" => "No valid IP addresses found for test.example.com",
"status" => 400
}
allow(challenge).to receive(:error).and_return(error)
acme_order = acme_order_double(authorizations: [acme_authorization_double(challenge)])
expect(described_class.new(acme_order).challenge_error).to eq(error)
end
end
end
......@@ -11,7 +11,8 @@ module LetsEncryptHelpers
status: 'pending',
token: 'tokenvalue',
file_content: 'hereisfilecontent',
request_validation: true
request_validation: true,
error: nil
}.freeze
def stub_lets_encrypt_settings
......@@ -43,16 +44,17 @@ module LetsEncryptHelpers
challenge
end
def acme_authorization_double
def acme_authorization_double(challenge = acme_challenge_double)
authorization = instance_double('Acme::Client::Resources::Authorization')
allow(authorization).to receive(:http).and_return(acme_challenge_double)
allow(authorization).to receive(:http).and_return(challenge)
allow(authorization).to receive(:challenges).and_return([challenge])
authorization
end
def acme_order_double(attributes = {})
acme_order = instance_double('Acme::Client::Resources::Order')
allow(acme_order).to receive_messages(ACME_ORDER_METHODS.merge(attributes))
allow(acme_order).to receive(:authorizations).and_return([acme_authorization_double])
allow(acme_order).to receive(:authorizations).and_return([acme_authorization_double]) unless attributes[:authorizations]
allow(acme_order).to receive(:finalize)
acme_order
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment