rails-auth 2.2.2 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +12 -0
- data/lib/rails/auth/config_builder.rb +0 -7
- data/lib/rails/auth/version.rb +1 -1
- data/lib/rails/auth/x509/middleware.rb +7 -29
- data/spec/rails/auth/x509/middleware_spec.rb +9 -35
- data/spec/support/create_certs.rb +0 -17
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9f5669f564b62464b0d3078ecfa58fe3732735e44c63bed361061a9f1a663249
|
4
|
+
data.tar.gz: cbee05f42e189e543b059d961d1b926d763d84e07c93a3637165f95eba0fe776
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0be32c7166ed406dda136608370f059443a56219696c8d13a56f3978f9eca3b37b99ccf0885d4c42d13c660860be52530891d9317a2d2562f7f265d7d751ccd0
|
7
|
+
data.tar.gz: e1ada71b12c7732fe2aced6bb98abd11cb7b8fa665093f9faa5808b9c21bef12dd99e3070fcd2ee343acc4b377626ae885098388f85d7d9027f37e1d08d60890
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
### 3.0.0 (2020-08-10)
|
2
|
+
|
3
|
+
* [#68](https://github.com/square/rails-auth/pull/68)
|
4
|
+
Remove `ca_file` and `require_cert` options to the config builder as we no
|
5
|
+
longer verify the certificate chain.
|
6
|
+
([@drcapulet])
|
7
|
+
|
8
|
+
* [#67](https://github.com/square/rails-auth/pull/67)
|
9
|
+
Remove `ca_file`, `require_cert`, and `truststore` options to X509 middleware
|
10
|
+
as we no longer verify the certificate chain.
|
11
|
+
([@drcapulet])
|
12
|
+
|
1
13
|
### 2.2.2 (2020-07-02)
|
2
14
|
|
3
15
|
* [#65](https://github.com/square/rails-auth/pull/65)
|
@@ -31,22 +31,15 @@ module Rails
|
|
31
31
|
def production(
|
32
32
|
config,
|
33
33
|
cert_filters: nil,
|
34
|
-
require_cert: false,
|
35
|
-
ca_file: nil,
|
36
34
|
error_page: Rails.root.join("public/403.html"),
|
37
35
|
monitor: nil
|
38
36
|
)
|
39
|
-
raise ArgumentError, "no cert_filters given but require_cert is true" if require_cert && !cert_filters
|
40
|
-
raise ArgumentError, "no ca_file given but cert_filters were set" if cert_filters && !ca_file
|
41
|
-
|
42
37
|
error_page_middleware(config, error_page)
|
43
38
|
|
44
39
|
if cert_filters
|
45
40
|
config.middleware.insert_before Rails::Auth::ACL::Middleware,
|
46
41
|
Rails::Auth::X509::Middleware,
|
47
|
-
require_cert: require_cert,
|
48
42
|
cert_filters: cert_filters,
|
49
|
-
ca_file: ca_file,
|
50
43
|
logger: Rails.logger
|
51
44
|
end
|
52
45
|
|
data/lib/rails/auth/version.rb
CHANGED
@@ -3,30 +3,20 @@
|
|
3
3
|
module Rails
|
4
4
|
module Auth
|
5
5
|
module X509
|
6
|
-
#
|
7
|
-
|
8
|
-
|
9
|
-
# Validates X.509 client certificates and adds credential objects for valid
|
10
|
-
# clients to the rack environment as env["rails-auth.credentials"]["x509"]
|
6
|
+
# Extracts X.509 client certificates and adds credential objects to the
|
7
|
+
# rack environment as env["rails-auth.credentials"]["x509"]
|
11
8
|
class Middleware
|
12
9
|
# Create a new X.509 Middleware object
|
13
10
|
#
|
14
|
-
# @param [Object]
|
15
|
-
# @param [
|
16
|
-
# @param [
|
17
|
-
# @param [Logger] logger place to log verification successes & failures
|
18
|
-
# @param [Boolean] require_cert causes middleware to raise if certs are unverified
|
19
|
-
# @param [OpenSSL::X509::Store] truststore (optional) provide your own truststore (for e.g. CRLs)
|
11
|
+
# @param [Object] app next app in the Rack middleware chain
|
12
|
+
# @param [Hash] cert_filters maps Rack environment names to cert extractors
|
13
|
+
# @param [Logger] logger place to log certificate extraction issues
|
20
14
|
#
|
21
15
|
# @return [Rails::Auth::X509::Middleware] new X509 middleware instance
|
22
|
-
def initialize(app,
|
23
|
-
raise ArgumentError, "no ca_file or truststore given" unless ca_file || truststore
|
24
|
-
|
16
|
+
def initialize(app, cert_filters: {}, logger: nil)
|
25
17
|
@app = app
|
26
18
|
@cert_filters = cert_filters
|
27
19
|
@logger = logger
|
28
|
-
@require_cert = require_cert
|
29
|
-
@truststore = truststore || OpenSSL::X509::Store.new.add_file(ca_file)
|
30
20
|
|
31
21
|
@cert_filters.each do |key, filter|
|
32
22
|
next unless filter.is_a?(Symbol)
|
@@ -53,17 +43,9 @@ module Rails
|
|
53
43
|
cert = extract_certificate_with_filter(filter, env[key])
|
54
44
|
next unless cert
|
55
45
|
|
56
|
-
|
57
|
-
log("Verified", cert)
|
58
|
-
return Rails::Auth::X509::Certificate.new(cert)
|
59
|
-
else
|
60
|
-
log("Verify FAILED", cert)
|
61
|
-
raise CertificateVerifyFailed, "verify failed: #{subject(cert)}" if @require_cert
|
62
|
-
end
|
46
|
+
return Rails::Auth::X509::Certificate.new(cert)
|
63
47
|
end
|
64
48
|
|
65
|
-
raise CertificateVerifyFailed, "no client certificate in request" if @require_cert
|
66
|
-
|
67
49
|
nil
|
68
50
|
end
|
69
51
|
|
@@ -79,10 +61,6 @@ module Rails
|
|
79
61
|
nil
|
80
62
|
end
|
81
63
|
|
82
|
-
def log(message, cert)
|
83
|
-
@logger.debug("rails-auth: #{message} (#{subject(cert)})") if @logger
|
84
|
-
end
|
85
|
-
|
86
64
|
def subject(cert)
|
87
65
|
cert.subject.to_a.map { |attr, data| "#{attr}=#{data}" }.join(",")
|
88
66
|
end
|
@@ -3,41 +3,32 @@
|
|
3
3
|
require "logger"
|
4
4
|
|
5
5
|
RSpec.describe Rails::Auth::X509::Middleware do
|
6
|
-
let(:request) { Rack::MockRequest.env_for("https://www.example.com") }
|
7
6
|
let(:app) { ->(env) { [200, env, "Hello, world!"] } }
|
7
|
+
let(:request) { Rack::MockRequest.env_for("https://www.example.com") }
|
8
8
|
|
9
|
-
let(:
|
10
|
-
let(:
|
11
|
-
let(:
|
12
|
-
let(:cert_filter) { :pem }
|
13
|
-
let(:example_key) { "X-SSL-Client-Cert" }
|
9
|
+
let(:cert_filter) { :pem }
|
10
|
+
let(:cert_pem) { cert_path("valid.crt").read }
|
11
|
+
let(:example_key) { "X-SSL-Client-Cert" }
|
14
12
|
|
15
13
|
let(:middleware) do
|
16
14
|
described_class.new(
|
17
15
|
app,
|
18
|
-
logger: Logger.new(STDERR),
|
19
|
-
ca_file: cert_path("ca.crt").to_s,
|
20
16
|
cert_filters: { example_key => cert_filter },
|
21
|
-
|
17
|
+
logger: Logger.new(STDERR)
|
22
18
|
)
|
23
19
|
end
|
24
20
|
|
25
21
|
context "certificate types" do
|
26
22
|
describe "PEM certificates" do
|
27
23
|
it "extracts Rails::Auth::X509::Certificate from a PEM certificate in the Rack environment" do
|
28
|
-
_response, env = middleware.call(request.merge(example_key =>
|
24
|
+
_response, env = middleware.call(request.merge(example_key => cert_pem))
|
29
25
|
|
30
26
|
credential = Rails::Auth.credentials(env).fetch("x509")
|
31
27
|
expect(credential).to be_a Rails::Auth::X509::Certificate
|
32
28
|
end
|
33
29
|
|
34
|
-
it "ignores unverified certificates" do
|
35
|
-
_response, env = middleware.call(request.merge(example_key => bad_cert_pem))
|
36
|
-
expect(Rails::Auth.credentials(env)).to be_empty
|
37
|
-
end
|
38
|
-
|
39
30
|
it "normalizes abnormal whitespace" do
|
40
|
-
_response, env = middleware.call(request.merge(example_key =>
|
31
|
+
_response, env = middleware.call(request.merge(example_key => cert_pem.tr("\n", "\t")))
|
41
32
|
|
42
33
|
credential = Rails::Auth.credentials(env).fetch("x509")
|
43
34
|
expect(credential).to be_a Rails::Auth::X509::Certificate
|
@@ -46,11 +37,11 @@ RSpec.describe Rails::Auth::X509::Middleware do
|
|
46
37
|
|
47
38
|
# :nocov:
|
48
39
|
describe "Java certificates" do
|
49
|
-
let(:example_key) { "javax.servlet.request.X509Certificate" }
|
50
40
|
let(:cert_filter) { :java }
|
41
|
+
let(:example_key) { "javax.servlet.request.X509Certificate" }
|
51
42
|
|
52
43
|
let(:java_cert) do
|
53
|
-
ruby_cert = OpenSSL::X509::Certificate.new(
|
44
|
+
ruby_cert = OpenSSL::X509::Certificate.new(cert_pem)
|
54
45
|
input_stream = Java::JavaIO::ByteArrayInputStream.new(ruby_cert.to_der.to_java_bytes)
|
55
46
|
java_cert_klass = Java::JavaSecurityCert::CertificateFactory.getInstance("X.509")
|
56
47
|
java_cert_klass.generateCertificate(input_stream)
|
@@ -67,21 +58,4 @@ RSpec.describe Rails::Auth::X509::Middleware do
|
|
67
58
|
end
|
68
59
|
# :nocov:
|
69
60
|
end
|
70
|
-
|
71
|
-
describe "require_cert: true" do
|
72
|
-
let(:cert_required) { true }
|
73
|
-
|
74
|
-
it "functions normally for valid certificates" do
|
75
|
-
_response, env = middleware.call(request.merge(example_key => valid_cert_pem))
|
76
|
-
|
77
|
-
credential = Rails::Auth.credentials(env).fetch("x509")
|
78
|
-
expect(credential).to be_a Rails::Auth::X509::Certificate
|
79
|
-
end
|
80
|
-
|
81
|
-
it "raises Rails::Auth::X509::CertificateVerifyFailed for unverified certificates" do
|
82
|
-
expect do
|
83
|
-
middleware.call(request.merge(example_key => bad_cert_pem))
|
84
|
-
end.to raise_error Rails::Auth::X509::CertificateVerifyFailed
|
85
|
-
end
|
86
|
-
end
|
87
61
|
end
|
@@ -95,20 +95,3 @@ valid_key_with_ext_path = File.join(cert_path, "valid_with_ext.key")
|
|
95
95
|
|
96
96
|
File.write valid_cert_with_ext_path, valid_cert_with_ext.to_pem
|
97
97
|
File.write valid_key_with_ext_path, valid_cert_with_ext.key_material.private_key.to_pem
|
98
|
-
|
99
|
-
#
|
100
|
-
# Create evil MitM self-signed certificate
|
101
|
-
#
|
102
|
-
|
103
|
-
self_signed_cert = CertificateAuthority::Certificate.new
|
104
|
-
self_signed_cert.subject.common_name = "127.0.0.1"
|
105
|
-
self_signed_cert.subject.organizational_unit = "ponycopter"
|
106
|
-
self_signed_cert.serial_number.number = 2
|
107
|
-
self_signed_cert.key_material.generate_key
|
108
|
-
self_signed_cert.sign!
|
109
|
-
|
110
|
-
self_signed_cert_path = File.join(cert_path, "invalid.crt")
|
111
|
-
self_signed_key_path = File.join(cert_path, "invalid.key")
|
112
|
-
|
113
|
-
File.write self_signed_cert_path, self_signed_cert.to_pem
|
114
|
-
File.write self_signed_key_path, self_signed_cert.key_material.private_key.to_pem
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails-auth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tony Arcieri
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-08-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|