rails-auth 2.2.2 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|