Bug #15384 ยป unify-certification-bundler.patch
lib/bundler/fetcher.rb | ||
---|---|---|
2 | 2 | |
3 | 3 |
require "bundler/vendored_persistent" |
4 | 4 |
require "cgi" |
5 |
require "rbconfig" |
|
5 | 6 |
require "securerandom" |
6 | 7 |
require "zlib" |
7 | 8 | |
... | ... | |
293 | 294 |
end |
294 | 295 |
else |
295 | 296 |
store.set_default_paths |
296 |
certs = File.expand_path("../ssl_certs/*/*.pem", __FILE__) |
|
297 | ||
298 |
rubygems_certs_dir = File.expand_path("../../rubygems/ssl_certs", __FILE__) |
|
299 |
unless File.exists?(rubygems_certs_dir) |
|
300 |
rubygems_certs_dir = File.join(RbConfig::CONFIG["rubylibdir"], "rubygems", "ssl_certs") |
|
301 |
end |
|
302 |
certs = File.join(rubygems_certs_dir, "*", "*.pem") |
|
303 | ||
297 | 304 |
Dir.glob(certs).each {|c| store.add_file c } |
298 | 305 |
end |
299 | 306 |
store |
/dev/null | ||
---|---|---|
1 |
# Ignore all files in this directory |
/dev/null | ||
---|---|---|
1 |
# frozen_string_literal: true |
|
2 | ||
3 |
require "bundler/vendored_fileutils" |
|
4 |
require "net/https" |
|
5 |
require "openssl" |
|
6 | ||
7 |
module Bundler |
|
8 |
module SSLCerts |
|
9 |
class CertificateManager |
|
10 |
attr_reader :bundler_cert_path, :bundler_certs, :rubygems_certs |
|
11 | ||
12 |
def self.update_from!(rubygems_path) |
|
13 |
new(rubygems_path).update! |
|
14 |
end |
|
15 | ||
16 |
def initialize(rubygems_path = nil) |
|
17 |
if rubygems_path |
|
18 |
rubygems_cert_path = File.join(rubygems_path, "lib/rubygems/ssl_certs") |
|
19 |
@rubygems_certs = certificates_in(rubygems_cert_path) |
|
20 |
end |
|
21 | ||
22 |
@bundler_cert_path = File.expand_path("..", __FILE__) |
|
23 |
@bundler_certs = certificates_in(bundler_cert_path) |
|
24 |
end |
|
25 | ||
26 |
def up_to_date? |
|
27 |
rubygems_certs.all? do |rc| |
|
28 |
bundler_certs.find do |bc| |
|
29 |
File.basename(bc) == File.basename(rc) && FileUtils.compare_file(bc, rc) |
|
30 |
end |
|
31 |
end |
|
32 |
end |
|
33 | ||
34 |
def update! |
|
35 |
return if up_to_date? |
|
36 | ||
37 |
FileUtils.rm bundler_certs |
|
38 |
FileUtils.cp rubygems_certs, bundler_cert_path |
|
39 |
end |
|
40 | ||
41 |
def connect_to(host) |
|
42 |
http = Net::HTTP.new(host, 443) |
|
43 |
http.use_ssl = true |
|
44 |
http.verify_mode = OpenSSL::SSL::VERIFY_PEER |
|
45 |
http.cert_store = store |
|
46 |
http.head("/") |
|
47 |
end |
|
48 | ||
49 |
private |
|
50 | ||
51 |
def certificates_in(path) |
|
52 |
Dir[File.join(path, "**/*.pem")].sort |
|
53 |
end |
|
54 | ||
55 |
def store |
|
56 |
@store ||= begin |
|
57 |
store = OpenSSL::X509::Store.new |
|
58 |
bundler_certs.each do |cert| |
|
59 |
store.add_file cert |
|
60 |
end |
|
61 |
store |
|
62 |
end |
|
63 |
end |
|
64 |
end |
|
65 |
end |
|
66 |
end |
/dev/null | ||
---|---|---|
1 |
-----BEGIN CERTIFICATE----- |
|
2 |
MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG |
|
3 |
A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv |
|
4 |
b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw |
|
5 |
MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i |
|
6 |
YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT |
|
7 |
aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ |
|
8 |
jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp |
|
9 |
xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp |
|
10 |
1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG |
|
11 |
snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ |
|
12 |
U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 |
|
13 |
9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E |
|
14 |
BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B |
|
15 |
AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz |
|
16 |
yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE |
|
17 |
38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP |
|
18 |
AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad |
|
19 |
DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME |
|
20 |
HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== |
|
21 |
-----END CERTIFICATE----- |
/dev/null | ||
---|---|---|
1 |
-----BEGIN CERTIFICATE----- |
|
2 |
MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs |
|
3 |
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 |
|
4 |
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j |
|
5 |
ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL |
|
6 |
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 |
|
7 |
LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug |
|
8 |
RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm |
|
9 |
+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW |
|
10 |
PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM |
|
11 |
xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB |
|
12 |
Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 |
|
13 |
hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg |
|
14 |
EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF |
|
15 |
MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA |
|
16 |
FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec |
|
17 |
nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z |
|
18 |
eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF |
|
19 |
hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 |
|
20 |
Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe |
|
21 |
vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep |
|
22 |
+OkuE6N36B9K |
|
23 |
-----END CERTIFICATE----- |
/dev/null | ||
---|---|---|
1 |
-----BEGIN CERTIFICATE----- |
|
2 |
MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU |
|
3 |
MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs |
|
4 |
IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 |
|
5 |
MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux |
|
6 |
FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h |
|
7 |
bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v |
|
8 |
dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt |
|
9 |
H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 |
|
10 |
uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX |
|
11 |
mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX |
|
12 |
a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN |
|
13 |
E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 |
|
14 |
WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD |
|
15 |
VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 |
|
16 |
Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU |
|
17 |
cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx |
|
18 |
IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN |
|
19 |
AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH |
|
20 |
YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 |
|
21 |
6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC |
|
22 |
Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX |
|
23 |
c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a |
|
24 |
mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= |
|
25 |
-----END CERTIFICATE----- |
/dev/null | ||
---|---|---|
1 |
# frozen_string_literal: true |
|
2 | ||
3 |
require "bundler/ssl_certs/certificate_manager" |
|
4 | ||
5 |
RSpec.describe Bundler::SSLCerts::CertificateManager do |
|
6 |
let(:rubygems_path) { root } |
|
7 |
let(:stub_cert) { File.join(root.to_s, "lib", "rubygems", "ssl_certs", "rubygems.org", "ssl-cert.pem") } |
|
8 |
let(:rubygems_certs_dir) { File.join(root.to_s, "lib", "rubygems", "ssl_certs", "rubygems.org") } |
|
9 | ||
10 |
subject { described_class.new(rubygems_path) } |
|
11 | ||
12 |
# Pretend bundler root is rubygems root |
|
13 |
before do |
|
14 |
# Backing up rubygems ceriticates |
|
15 |
FileUtils.mv(rubygems_certs_dir, rubygems_certs_dir + ".back") if ruby_core? |
|
16 | ||
17 |
FileUtils.mkdir_p(rubygems_certs_dir) |
|
18 |
FileUtils.touch(stub_cert) |
|
19 |
end |
|
20 | ||
21 |
after do |
|
22 |
FileUtils.rm_rf(rubygems_certs_dir) |
|
23 | ||
24 |
# Restore rubygems certificates |
|
25 |
FileUtils.mv(rubygems_certs_dir + ".back", rubygems_certs_dir) if ruby_core? |
|
26 |
end |
|
27 | ||
28 |
describe "#update_from" do |
|
29 |
let(:cert_manager) { double(:cert_manager) } |
|
30 | ||
31 |
before { allow(described_class).to receive(:new).with(rubygems_path).and_return(cert_manager) } |
|
32 | ||
33 |
it "should update the certs through a new certificate manager" do |
|
34 |
allow(cert_manager).to receive(:update!) |
|
35 |
expect(described_class.update_from!(rubygems_path)).to be_nil |
|
36 |
end |
|
37 |
end |
|
38 | ||
39 |
describe "#initialize" do |
|
40 |
it "should set bundler_cert_path as path of the subdir with bundler ssl certs" do |
|
41 |
expect(subject.bundler_cert_path).to eq(File.join(root, "lib/bundler/ssl_certs")) |
|
42 |
end |
|
43 | ||
44 |
it "should set bundler_certs as the paths of the bundler ssl certs" do |
|
45 |
expect(subject.bundler_certs).to include(File.join(root, "lib/bundler/ssl_certs/rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem")) |
|
46 |
expect(subject.bundler_certs).to include(File.join(root, "lib/bundler/ssl_certs/index.rubygems.org/GlobalSignRootCA.pem")) |
|
47 |
end |
|
48 | ||
49 |
context "when rubygems_path is not nil" do |
|
50 |
it "should set rubygems_certs" do |
|
51 |
expect(subject.rubygems_certs).to include(File.join(root, "lib", "rubygems", "ssl_certs", "rubygems.org", "ssl-cert.pem")) |
|
52 |
end |
|
53 |
end |
|
54 |
end |
|
55 | ||
56 |
describe "#up_to_date?" do |
|
57 |
context "when bundler certs and rubygems certs are the same" do |
|
58 |
before do |
|
59 |
bundler_certs = Dir[File.join(root.to_s, "lib", "bundler", "ssl_certs", "**", "*.pem")] |
|
60 |
FileUtils.rm(stub_cert) |
|
61 |
FileUtils.cp(bundler_certs, rubygems_certs_dir) |
|
62 |
end |
|
63 | ||
64 |
it "should return true" do |
|
65 |
expect(subject).to be_up_to_date |
|
66 |
end |
|
67 |
end |
|
68 | ||
69 |
context "when bundler certs and rubygems certs are not the same" do |
|
70 |
it "should return false" do |
|
71 |
expect(subject).to_not be_up_to_date |
|
72 |
end |
|
73 |
end |
|
74 |
end |
|
75 | ||
76 |
describe "#update!" do |
|
77 |
context "when certificate manager is not up to date" do |
|
78 |
before do |
|
79 |
allow(subject).to receive(:up_to_date?).and_return(false) |
|
80 |
allow(bundler_fileutils).to receive(:rm) |
|
81 |
allow(bundler_fileutils).to receive(:cp) |
|
82 |
end |
|
83 | ||
84 |
it "should remove the current bundler certs" do |
|
85 |
expect(bundler_fileutils).to receive(:rm).with(subject.bundler_certs) |
|
86 |
subject.update! |
|
87 |
end |
|
88 | ||
89 |
it "should copy the rubygems certs into bundler certs" do |
|
90 |
expect(bundler_fileutils).to receive(:cp).with(subject.rubygems_certs, subject.bundler_cert_path) |
|
91 |
subject.update! |
|
92 |
end |
|
93 | ||
94 |
it "should return nil" do |
|
95 |
expect(subject.update!).to be_nil |
|
96 |
end |
|
97 |
end |
|
98 | ||
99 |
context "when certificate manager is up to date" do |
|
100 |
before { allow(subject).to receive(:up_to_date?).and_return(true) } |
|
101 | ||
102 |
it "should return nil" do |
|
103 |
expect(subject.update!).to be_nil |
|
104 |
end |
|
105 |
end |
|
106 |
end |
|
107 | ||
108 |
describe "#connect_to" do |
|
109 |
let(:host) { "http://www.host.com" } |
|
110 |
let(:http) { Net::HTTP.new(host, 443) } |
|
111 |
let(:cert_store) { OpenSSL::X509::Store.new } |
|
112 |
let(:http_header_response) { double(:http_header_response) } |
|
113 | ||
114 |
before do |
|
115 |
allow(Net::HTTP).to receive(:new).with(host, 443).and_return(http) |
|
116 |
allow(OpenSSL::X509::Store).to receive(:new).and_return(cert_store) |
|
117 |
allow(http).to receive(:head).with("/").and_return(http_header_response) |
|
118 |
end |
|
119 | ||
120 |
it "should use ssl for the http request" do |
|
121 |
expect(http).to receive(:use_ssl=).with(true) |
|
122 |
subject.connect_to(host) |
|
123 |
end |
|
124 | ||
125 |
it "use verify peer mode" do |
|
126 |
expect(http).to receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_PEER) |
|
127 |
subject.connect_to(host) |
|
128 |
end |
|
129 | ||
130 |
it "set its cert store as a OpenSSL::X509::Store populated with bundler certs" do |
|
131 |
expect(cert_store).to receive(:add_file).at_least(:once) |
|
132 |
expect(http).to receive(:cert_store=).with(cert_store) |
|
133 |
subject.connect_to(host) |
|
134 |
end |
|
135 | ||
136 |
it "return the headers of the request response" do |
|
137 |
expect(subject.connect_to(host)).to eq(http_header_response) |
|
138 |
end |
|
139 |
end |
|
140 |
end |
/dev/null | ||
---|---|---|
1 |
# frozen_string_literal: true |
|
2 | ||
3 |
require "bundler/ssl_certs/certificate_manager" |
|
4 | ||
5 |
RSpec.describe "SSL Certificates", :rubygems_master do |
|
6 |
hosts = %w[ |
|
7 |
rubygems.org |
|
8 |
index.rubygems.org |
|
9 |
rubygems.global.ssl.fastly.net |
|
10 |
staging.rubygems.org |
|
11 |
] |
|
12 | ||
13 |
hosts.each do |host| |
|
14 |
it "can securely connect to #{host}", :realworld do |
|
15 |
Bundler::SSLCerts::CertificateManager.new.connect_to(host) |
|
16 |
end |
|
17 |
end |
|
18 |
end |
spec/bundler/quality_spec.rb | ||
---|---|---|
105 | 105 |
end |
106 | 106 | |
107 | 107 |
it "has no malformed whitespace" do |
108 |
exempt = /\.gitmodules|\.marshal|fixtures|vendor|ssl_certs|LICENSE|vcr_cassettes/
|
|
108 |
exempt = /\.gitmodules|\.marshal|fixtures|vendor|LICENSE|vcr_cassettes/ |
|
109 | 109 |
error_messages = [] |
110 | 110 |
Dir.chdir(root) do |
111 | 111 |
lib_files = ruby_core? ? `git ls-files -z -- lib/bundler lib/bundler.rb spec/bundler` : `git ls-files -z -- lib` |