Project

General

Profile

Bug #15384 ยป unify-certification-bundler.patch

hsbt (Hiroshi SHIBATA), 03/14/2019 02:47 AM

View differences:

lib/bundler/fetcher.rb
require "bundler/vendored_persistent"
require "cgi"
require "rbconfig"
require "securerandom"
require "zlib"
......
end
else
store.set_default_paths
certs = File.expand_path("../ssl_certs/*/*.pem", __FILE__)
rubygems_certs_dir = File.expand_path("../../rubygems/ssl_certs", __FILE__)
unless File.exists?(rubygems_certs_dir)
rubygems_certs_dir = File.join(RbConfig::CONFIG["rubylibdir"], "rubygems", "ssl_certs")
end
certs = File.join(rubygems_certs_dir, "*", "*.pem")
Dir.glob(certs).each {|c| store.add_file c }
end
store
/dev/null
# Ignore all files in this directory
/dev/null
# frozen_string_literal: true
require "bundler/vendored_fileutils"
require "net/https"
require "openssl"
module Bundler
module SSLCerts
class CertificateManager
attr_reader :bundler_cert_path, :bundler_certs, :rubygems_certs
def self.update_from!(rubygems_path)
new(rubygems_path).update!
end
def initialize(rubygems_path = nil)
if rubygems_path
rubygems_cert_path = File.join(rubygems_path, "lib/rubygems/ssl_certs")
@rubygems_certs = certificates_in(rubygems_cert_path)
end
@bundler_cert_path = File.expand_path("..", __FILE__)
@bundler_certs = certificates_in(bundler_cert_path)
end
def up_to_date?
rubygems_certs.all? do |rc|
bundler_certs.find do |bc|
File.basename(bc) == File.basename(rc) && FileUtils.compare_file(bc, rc)
end
end
end
def update!
return if up_to_date?
FileUtils.rm bundler_certs
FileUtils.cp rubygems_certs, bundler_cert_path
end
def connect_to(host)
http = Net::HTTP.new(host, 443)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.cert_store = store
http.head("/")
end
private
def certificates_in(path)
Dir[File.join(path, "**/*.pem")].sort
end
def store
@store ||= begin
store = OpenSSL::X509::Store.new
bundler_certs.each do |cert|
store.add_file cert
end
store
end
end
end
end
end
/dev/null
-----BEGIN CERTIFICATE-----
MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
-----END CERTIFICATE-----
/dev/null
-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
+OkuE6N36B9K
-----END CERTIFICATE-----
/dev/null
-----BEGIN CERTIFICATE-----
MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU
MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs
IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290
MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux
FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h
bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v
dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt
H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9
uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX
mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX
a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN
E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0
WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD
VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0
Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU
cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx
IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN
AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH
YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC
Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX
c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
-----END CERTIFICATE-----
/dev/null
# frozen_string_literal: true
require "bundler/ssl_certs/certificate_manager"
RSpec.describe Bundler::SSLCerts::CertificateManager do
let(:rubygems_path) { root }
let(:stub_cert) { File.join(root.to_s, "lib", "rubygems", "ssl_certs", "rubygems.org", "ssl-cert.pem") }
let(:rubygems_certs_dir) { File.join(root.to_s, "lib", "rubygems", "ssl_certs", "rubygems.org") }
subject { described_class.new(rubygems_path) }
# Pretend bundler root is rubygems root
before do
# Backing up rubygems ceriticates
FileUtils.mv(rubygems_certs_dir, rubygems_certs_dir + ".back") if ruby_core?
FileUtils.mkdir_p(rubygems_certs_dir)
FileUtils.touch(stub_cert)
end
after do
FileUtils.rm_rf(rubygems_certs_dir)
# Restore rubygems certificates
FileUtils.mv(rubygems_certs_dir + ".back", rubygems_certs_dir) if ruby_core?
end
describe "#update_from" do
let(:cert_manager) { double(:cert_manager) }
before { allow(described_class).to receive(:new).with(rubygems_path).and_return(cert_manager) }
it "should update the certs through a new certificate manager" do
allow(cert_manager).to receive(:update!)
expect(described_class.update_from!(rubygems_path)).to be_nil
end
end
describe "#initialize" do
it "should set bundler_cert_path as path of the subdir with bundler ssl certs" do
expect(subject.bundler_cert_path).to eq(File.join(root, "lib/bundler/ssl_certs"))
end
it "should set bundler_certs as the paths of the bundler ssl certs" do
expect(subject.bundler_certs).to include(File.join(root, "lib/bundler/ssl_certs/rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem"))
expect(subject.bundler_certs).to include(File.join(root, "lib/bundler/ssl_certs/index.rubygems.org/GlobalSignRootCA.pem"))
end
context "when rubygems_path is not nil" do
it "should set rubygems_certs" do
expect(subject.rubygems_certs).to include(File.join(root, "lib", "rubygems", "ssl_certs", "rubygems.org", "ssl-cert.pem"))
end
end
end
describe "#up_to_date?" do
context "when bundler certs and rubygems certs are the same" do
before do
bundler_certs = Dir[File.join(root.to_s, "lib", "bundler", "ssl_certs", "**", "*.pem")]
FileUtils.rm(stub_cert)
FileUtils.cp(bundler_certs, rubygems_certs_dir)
end
it "should return true" do
expect(subject).to be_up_to_date
end
end
context "when bundler certs and rubygems certs are not the same" do
it "should return false" do
expect(subject).to_not be_up_to_date
end
end
end
describe "#update!" do
context "when certificate manager is not up to date" do
before do
allow(subject).to receive(:up_to_date?).and_return(false)
allow(bundler_fileutils).to receive(:rm)
allow(bundler_fileutils).to receive(:cp)
end
it "should remove the current bundler certs" do
expect(bundler_fileutils).to receive(:rm).with(subject.bundler_certs)
subject.update!
end
it "should copy the rubygems certs into bundler certs" do
expect(bundler_fileutils).to receive(:cp).with(subject.rubygems_certs, subject.bundler_cert_path)
subject.update!
end
it "should return nil" do
expect(subject.update!).to be_nil
end
end
context "when certificate manager is up to date" do
before { allow(subject).to receive(:up_to_date?).and_return(true) }
it "should return nil" do
expect(subject.update!).to be_nil
end
end
end
describe "#connect_to" do
let(:host) { "http://www.host.com" }
let(:http) { Net::HTTP.new(host, 443) }
let(:cert_store) { OpenSSL::X509::Store.new }
let(:http_header_response) { double(:http_header_response) }
before do
allow(Net::HTTP).to receive(:new).with(host, 443).and_return(http)
allow(OpenSSL::X509::Store).to receive(:new).and_return(cert_store)
allow(http).to receive(:head).with("/").and_return(http_header_response)
end
it "should use ssl for the http request" do
expect(http).to receive(:use_ssl=).with(true)
subject.connect_to(host)
end
it "use verify peer mode" do
expect(http).to receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_PEER)
subject.connect_to(host)
end
it "set its cert store as a OpenSSL::X509::Store populated with bundler certs" do
expect(cert_store).to receive(:add_file).at_least(:once)
expect(http).to receive(:cert_store=).with(cert_store)
subject.connect_to(host)
end
it "return the headers of the request response" do
expect(subject.connect_to(host)).to eq(http_header_response)
end
end
end
/dev/null
# frozen_string_literal: true
require "bundler/ssl_certs/certificate_manager"
RSpec.describe "SSL Certificates", :rubygems_master do
hosts = %w[
rubygems.org
index.rubygems.org
rubygems.global.ssl.fastly.net
staging.rubygems.org
]
hosts.each do |host|
it "can securely connect to #{host}", :realworld do
Bundler::SSLCerts::CertificateManager.new.connect_to(host)
end
end
end
spec/bundler/quality_spec.rb
end
it "has no malformed whitespace" do
exempt = /\.gitmodules|\.marshal|fixtures|vendor|ssl_certs|LICENSE|vcr_cassettes/
exempt = /\.gitmodules|\.marshal|fixtures|vendor|LICENSE|vcr_cassettes/
error_messages = []
Dir.chdir(root) do
lib_files = ruby_core? ? `git ls-files -z -- lib/bundler lib/bundler.rb spec/bundler` : `git ls-files -z -- lib`
    (1-1/1)