Allow to load ECDSA certificates for pages domains
Just replace RSA.new with PKey.read
This commit is contained in:
parent
7920ff1147
commit
8c3d0703ed
|
@ -17,7 +17,7 @@ class PagesDomain < ApplicationRecord
|
||||||
validates :certificate, certificate: true, if: ->(domain) { domain.certificate.present? }
|
validates :certificate, certificate: true, if: ->(domain) { domain.certificate.present? }
|
||||||
validates :key, presence: { message: 'must be present if HTTPS-only is enabled' },
|
validates :key, presence: { message: 'must be present if HTTPS-only is enabled' },
|
||||||
if: :certificate_should_be_present?
|
if: :certificate_should_be_present?
|
||||||
validates :key, certificate_key: true, if: ->(domain) { domain.key.present? }
|
validates :key, certificate_key: true, named_ecdsa_key: true, if: ->(domain) { domain.key.present? }
|
||||||
validates :verification_code, presence: true, allow_blank: false
|
validates :verification_code, presence: true, allow_blank: false
|
||||||
|
|
||||||
validate :validate_pages_domain
|
validate :validate_pages_domain
|
||||||
|
@ -247,7 +247,7 @@ class PagesDomain < ApplicationRecord
|
||||||
def pkey
|
def pkey
|
||||||
return unless key
|
return unless key
|
||||||
|
|
||||||
@pkey ||= OpenSSL::PKey::RSA.new(key)
|
@pkey ||= OpenSSL::PKey.read(key)
|
||||||
rescue OpenSSL::PKey::PKeyError, OpenSSL::Cipher::CipherError
|
rescue OpenSSL::PKey::PKeyError, OpenSSL::Cipher::CipherError
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# UrlValidator
|
# CertificateKeyValidator
|
||||||
#
|
#
|
||||||
# Custom validator for private keys.
|
# Custom validator for private keys.
|
||||||
#
|
#
|
||||||
|
@ -20,7 +20,7 @@ class CertificateKeyValidator < ActiveModel::EachValidator
|
||||||
def valid_private_key_pem?(value)
|
def valid_private_key_pem?(value)
|
||||||
return false unless value
|
return false unless value
|
||||||
|
|
||||||
pkey = OpenSSL::PKey::RSA.new(value)
|
pkey = OpenSSL::PKey.read(value)
|
||||||
pkey.private?
|
pkey.private?
|
||||||
rescue OpenSSL::PKey::PKeyError
|
rescue OpenSSL::PKey::PKeyError
|
||||||
false
|
false
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# NamedEcdsaKeyValidator
|
||||||
|
#
|
||||||
|
# Custom validator for ecdsa private keys.
|
||||||
|
# Golang currently doesn't support explicit curves for ECDSA certificates
|
||||||
|
# This validator checks if curve is set by name, not by parameters
|
||||||
|
#
|
||||||
|
# class Project < ActiveRecord::Base
|
||||||
|
# validates :certificate_key, named_ecdsa_key: true
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
class NamedEcdsaKeyValidator < ActiveModel::EachValidator
|
||||||
|
def validate_each(record, attribute, value)
|
||||||
|
if explicit_ec?(value)
|
||||||
|
record.errors.add(attribute, "ECDSA keys with explicit curves are not supported")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
UNNAMED_CURVE = "UNDEF"
|
||||||
|
|
||||||
|
def explicit_ec?(value)
|
||||||
|
return false unless value
|
||||||
|
|
||||||
|
pkey = OpenSSL::PKey.read(value)
|
||||||
|
return false unless pkey.is_a?(OpenSSL::PKey::EC)
|
||||||
|
|
||||||
|
pkey.group.curve_name == UNNAMED_CURVE
|
||||||
|
rescue OpenSSL::PKey::PKeyError
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Allow ECDSA certificates for pages domains
|
||||||
|
merge_request: 32393
|
||||||
|
author:
|
||||||
|
type: added
|
|
@ -271,5 +271,88 @@ ZDXgrA==
|
||||||
auto_ssl_enabled { true }
|
auto_ssl_enabled { true }
|
||||||
certificate_source { :gitlab_provided }
|
certificate_source { :gitlab_provided }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
trait :explicit_ecdsa do
|
||||||
|
certificate '-----BEGIN CERTIFICATE-----
|
||||||
|
MIID1zCCAzkCCQDatOIwBlktwjAKBggqhkjOPQQDAjBPMQswCQYDVQQGEwJVUzEL
|
||||||
|
MAkGA1UECAwCTlkxCzAJBgNVBAcMAk5ZMQswCQYDVQQLDAJJVDEZMBcGA1UEAwwQ
|
||||||
|
dGVzdC1jZXJ0aWZpY2F0ZTAeFw0xOTA4MjkxMTE1NDBaFw0yMTA4MjgxMTE1NDBa
|
||||||
|
ME8xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJOWTELMAkGA1UEBwwCTlkxCzAJBgNV
|
||||||
|
BAsMAklUMRkwFwYDVQQDDBB0ZXN0LWNlcnRpZmljYXRlMIICXDCCAc8GByqGSM49
|
||||||
|
AgEwggHCAgEBME0GByqGSM49AQECQgH/////////////////////////////////
|
||||||
|
/////////////////////////////////////////////////////zCBngRCAf//
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
///////////////////8BEFRlT65YY4cmh+SmiGgtoVA7qLacluZsxXzuLSJkY7x
|
||||||
|
CeFWGTlR7H6TexZSwL07sb8HNXPfiD0sNPHvRR/Ua1A/AAMVANCeiAApHLhTlsxn
|
||||||
|
FzkyhKqg2mS6BIGFBADGhY4GtwQE6c2ePstmI5W0QpxkgTkFP7Uh+CivYGtNPbqh
|
||||||
|
S1537+dZKP4dwSei/6jeM0izwYVqQpv5fn4xwuW9ZgEYOSlqeJo7wARcil+0LH0b
|
||||||
|
2Zj1RElXm0RoF6+9Fyc+ZiyX7nKZXvQmQMVQuQE/rQdhNTxwhqJywkCIvpR2n9Fm
|
||||||
|
UAJCAf//////////////////////////////////////////+lGGh4O/L5Zrf8wB
|
||||||
|
SPcJpdA7tcm4iZxHrrtvtx6ROGQJAgEBA4GGAAQBVG/4c/hgl36toHj+eGL4pqv7
|
||||||
|
l7M+ZKQJ4vz0Y9E6xIx+gvfVaZ58krmbBAP53ikwneQbFdcvw3L/ACPEib/qWjkB
|
||||||
|
ogykguy3OwHtKLYNnDWIsfiLumEjElhcBMZVXiXhb5txf11uXAWn5n6Qhey5YKPM
|
||||||
|
NjLLqDqaG19efCLCd21A0TcwCgYIKoZIzj0EAwIDgYsAMIGHAkEm68kYFVnN1c2N
|
||||||
|
OjSJpIDdFWGVYJHyMDI5WgQyhm4hAioXJ0T22Zab8Wmq+hBYRJNcHoaV894blfqR
|
||||||
|
V3ZJgam8EQJCAcnPpJQ0IqoT1pAQkaL3+Ka8ZaaCd6/8RnoDtGvWljisuyH65SRu
|
||||||
|
kmYv87bZe1KqOZDoaDBdfVsoxcGbik19lBPV
|
||||||
|
-----END CERTIFICATE-----'
|
||||||
|
|
||||||
|
key '-----BEGIN EC PARAMETERS-----
|
||||||
|
MIIBwgIBATBNBgcqhkjOPQEBAkIB////////////////////////////////////
|
||||||
|
//////////////////////////////////////////////////8wgZ4EQgH/////
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
/////////////////ARBUZU+uWGOHJofkpohoLaFQO6i2nJbmbMV87i0iZGO8Qnh
|
||||||
|
Vhk5Uex+k3sWUsC9O7G/BzVz34g9LDTx70Uf1GtQPwADFQDQnogAKRy4U5bMZxc5
|
||||||
|
MoSqoNpkugSBhQQAxoWOBrcEBOnNnj7LZiOVtEKcZIE5BT+1Ifgor2BrTT26oUte
|
||||||
|
d+/nWSj+HcEnov+o3jNIs8GFakKb+X5+McLlvWYBGDkpaniaO8AEXIpftCx9G9mY
|
||||||
|
9URJV5tEaBevvRcnPmYsl+5ymV70JkDFULkBP60HYTU8cIaicsJAiL6Udp/RZlAC
|
||||||
|
QgH///////////////////////////////////////////pRhoeDvy+Wa3/MAUj3
|
||||||
|
CaXQO7XJuImcR667b7cekThkCQIBAQ==
|
||||||
|
-----END EC PARAMETERS-----
|
||||||
|
-----BEGIN EC PRIVATE KEY-----
|
||||||
|
MIICnQIBAQRCAZZRG4FJO+OK29ygycrNzjxQDB+dp+QPo1Pk6RAl5PcraohyhFnI
|
||||||
|
MGUL4ba1efZUxCbAWxjVRSi7QEUNYCCdUPAtoIIBxjCCAcICAQEwTQYHKoZIzj0B
|
||||||
|
AQJCAf//////////////////////////////////////////////////////////
|
||||||
|
////////////////////////////MIGeBEIB////////////////////////////
|
||||||
|
//////////////////////////////////////////////////////////wEQVGV
|
||||||
|
PrlhjhyaH5KaIaC2hUDuotpyW5mzFfO4tImRjvEJ4VYZOVHsfpN7FlLAvTuxvwc1
|
||||||
|
c9+IPSw08e9FH9RrUD8AAxUA0J6IACkcuFOWzGcXOTKEqqDaZLoEgYUEAMaFjga3
|
||||||
|
BATpzZ4+y2YjlbRCnGSBOQU/tSH4KK9ga009uqFLXnfv51ko/h3BJ6L/qN4zSLPB
|
||||||
|
hWpCm/l+fjHC5b1mARg5KWp4mjvABFyKX7QsfRvZmPVESVebRGgXr70XJz5mLJfu
|
||||||
|
cple9CZAxVC5AT+tB2E1PHCGonLCQIi+lHaf0WZQAkIB////////////////////
|
||||||
|
///////////////////////6UYaHg78vlmt/zAFI9wml0Du1ybiJnEeuu2+3HpE4
|
||||||
|
ZAkCAQGhgYkDgYYABAFUb/hz+GCXfq2geP54Yvimq/uXsz5kpAni/PRj0TrEjH6C
|
||||||
|
99VpnnySuZsEA/neKTCd5BsV1y/Dcv8AI8SJv+paOQGiDKSC7Lc7Ae0otg2cNYix
|
||||||
|
+Iu6YSMSWFwExlVeJeFvm3F/XW5cBafmfpCF7Llgo8w2MsuoOpobX158IsJ3bUDR
|
||||||
|
Nw==
|
||||||
|
-----END EC PRIVATE KEY-----'
|
||||||
|
end
|
||||||
|
|
||||||
|
trait :ecdsa do
|
||||||
|
certificate '-----BEGIN CERTIFICATE-----
|
||||||
|
MIIB8zCCAVUCCQCGKuPQ6SBxUTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJVUzEL
|
||||||
|
MAkGA1UECAwCVVMxCzAJBgNVBAcMAlVTMRUwEwYDVQQDDAxzaHVzaGxpbi5kZXYw
|
||||||
|
HhcNMTkwOTAyMDkyMDUxWhcNMjEwOTAxMDkyMDUxWjA+MQswCQYDVQQGEwJVUzEL
|
||||||
|
MAkGA1UECAwCVVMxCzAJBgNVBAcMAlVTMRUwEwYDVQQDDAxzaHVzaGxpbi5kZXYw
|
||||||
|
gZswEAYHKoZIzj0CAQYFK4EEACMDgYYABAH9Jd7ZWnTasgltZRbIMreihycOh/G4
|
||||||
|
TXpkp8tTtEsuD+sh8au3Jywsi89RSZ6vgVoCY7//DQ2vamYnyBZqbL+cTQBsQ7wD
|
||||||
|
UEaSyP0R3P4b6Ox347pYzXwSdSOra9Cm4TMQe+prVMesxulqIm7G7CTI+9J8LHlJ
|
||||||
|
z0wUDQz/o+tUSYwv6zAKBggqhkjOPQQDAgOBiwAwgYcCQUOlTnn2QP/uYSh1dUSl
|
||||||
|
R9WYUg5+PQMg7kS+4K/5+5gonWCvaMcP+2P7hltUcvq41l3uMKKCZRU/x60/FMHc
|
||||||
|
1ZXdAkIBuVtm9RJXziNOKS4TcpH9os/FuREW8YQlpec58LDZdlivcHnikHZ4LCri
|
||||||
|
T7zu3VY6Rq+V/IKpsQwQjmoTJ0IpCM8=
|
||||||
|
-----END CERTIFICATE-----'
|
||||||
|
|
||||||
|
key '-----BEGIN EC PARAMETERS-----
|
||||||
|
BgUrgQQAIw==
|
||||||
|
-----END EC PARAMETERS-----
|
||||||
|
-----BEGIN EC PRIVATE KEY-----
|
||||||
|
MIHbAgEBBEFa72+eREW25IHbke0TiWFdW1R1ad9Nyqaz7CDtv5Kqdgd6Kcl8V2az
|
||||||
|
Lr6z1PS+JSERWzRP+fps7kdFRrtqy/ECpKAHBgUrgQQAI6GBiQOBhgAEAf0l3tla
|
||||||
|
dNqyCW1lFsgyt6KHJw6H8bhNemSny1O0Sy4P6yHxq7cnLCyLz1FJnq+BWgJjv/8N
|
||||||
|
Da9qZifIFmpsv5xNAGxDvANQRpLI/RHc/hvo7HfjuljNfBJ1I6tr0KbhMxB76mtU
|
||||||
|
x6zG6WoibsbsJMj70nwseUnPTBQNDP+j61RJjC/r
|
||||||
|
-----END EC PRIVATE KEY-----'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -151,6 +151,24 @@ describe PagesDomain do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with ecdsa certificate' do
|
||||||
|
it "is valid" do
|
||||||
|
domain = build(:pages_domain, :ecdsa)
|
||||||
|
|
||||||
|
expect(domain).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when curve is set explicitly by parameters' do
|
||||||
|
it 'adds errors to private key' do
|
||||||
|
domain = build(:pages_domain, :explicit_ecdsa)
|
||||||
|
|
||||||
|
expect(domain).to be_invalid
|
||||||
|
|
||||||
|
expect(domain.errors[:key]).not_to be_empty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'validations' do
|
describe 'validations' do
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe NamedEcdsaKeyValidator do
|
||||||
|
let(:validator) { described_class.new(attributes: [:key]) }
|
||||||
|
let!(:domain) { build(:pages_domain) }
|
||||||
|
|
||||||
|
subject { validator.validate_each(domain, :key, value) }
|
||||||
|
|
||||||
|
context 'with empty value' do
|
||||||
|
let(:value) { nil }
|
||||||
|
|
||||||
|
it 'does not add any error if value is empty' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(domain.errors).to be_empty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_examples 'does not add any error' do
|
||||||
|
it 'does not add any error' do
|
||||||
|
expect(value).to be_present
|
||||||
|
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(domain.errors).to be_empty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when key is not EC' do
|
||||||
|
let(:value) { attributes_for(:pages_domain)[:key] }
|
||||||
|
|
||||||
|
include_examples 'does not add any error'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with ECDSA certificate with named curve' do
|
||||||
|
let(:value) { attributes_for(:pages_domain, :ecdsa)[:key] }
|
||||||
|
|
||||||
|
include_examples 'does not add any error'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with ECDSA certificate with explicit curve params' do
|
||||||
|
let(:value) { attributes_for(:pages_domain, :explicit_ecdsa)[:key] }
|
||||||
|
|
||||||
|
it 'adds errors' do
|
||||||
|
expect(value).to be_present
|
||||||
|
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(domain.errors[:key]).not_to be_empty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue