rails-auth 2.1.2 → 2.2.2

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.
Files changed (58) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +14 -1
  3. data/.travis.yml +8 -5
  4. data/BUG-BOUNTY.md +3 -3
  5. data/CHANGES.md +45 -2
  6. data/CONTRIBUTING.md +11 -10
  7. data/Gemfile +6 -5
  8. data/Guardfile +2 -0
  9. data/Rakefile +3 -1
  10. data/lib/rails/auth/acl.rb +4 -0
  11. data/lib/rails/auth/acl/matchers/allow_all.rb +3 -0
  12. data/lib/rails/auth/acl/middleware.rb +3 -0
  13. data/lib/rails/auth/acl/resource.rb +7 -5
  14. data/lib/rails/auth/config_builder.rb +5 -1
  15. data/lib/rails/auth/controller_methods.rb +4 -0
  16. data/lib/rails/auth/credentials.rb +3 -1
  17. data/lib/rails/auth/credentials/injector_middleware.rb +6 -2
  18. data/lib/rails/auth/env.rb +4 -3
  19. data/lib/rails/auth/error_page/debug_middleware.rb +1 -1
  20. data/lib/rails/auth/error_page/middleware.rb +3 -0
  21. data/lib/rails/auth/exceptions.rb +2 -0
  22. data/lib/rails/auth/helpers.rb +3 -1
  23. data/lib/rails/auth/installed_constraint.rb +2 -0
  24. data/lib/rails/auth/monitor/middleware.rb +2 -0
  25. data/lib/rails/auth/rack.rb +1 -0
  26. data/lib/rails/auth/rspec.rb +2 -0
  27. data/lib/rails/auth/rspec/helper_methods.rb +6 -5
  28. data/lib/rails/auth/rspec/matchers/acl_matchers.rb +4 -2
  29. data/lib/rails/auth/version.rb +1 -1
  30. data/lib/rails/auth/x509/certificate.rb +35 -5
  31. data/lib/rails/auth/x509/filter/java.rb +4 -12
  32. data/lib/rails/auth/x509/filter/pem.rb +10 -1
  33. data/lib/rails/auth/x509/matcher.rb +2 -0
  34. data/lib/rails/auth/x509/middleware.rb +11 -9
  35. data/lib/rails/auth/x509/subject_alt_name_extension.rb +29 -0
  36. data/rails-auth.gemspec +5 -4
  37. data/spec/rails/auth/acl/matchers/allow_all_spec.rb +2 -0
  38. data/spec/rails/auth/acl/middleware_spec.rb +2 -0
  39. data/spec/rails/auth/acl/resource_spec.rb +2 -0
  40. data/spec/rails/auth/acl_spec.rb +2 -0
  41. data/spec/rails/auth/controller_methods_spec.rb +2 -0
  42. data/spec/rails/auth/credentials/injector_middleware_spec.rb +15 -0
  43. data/spec/rails/auth/credentials_spec.rb +2 -0
  44. data/spec/rails/auth/env_spec.rb +2 -0
  45. data/spec/rails/auth/error_page/debug_middleware_spec.rb +2 -0
  46. data/spec/rails/auth/error_page/middleware_spec.rb +2 -0
  47. data/spec/rails/auth/monitor/middleware_spec.rb +2 -0
  48. data/spec/rails/auth/rspec/helper_methods_spec.rb +2 -0
  49. data/spec/rails/auth/rspec/matchers/acl_matchers_spec.rb +12 -1
  50. data/spec/rails/auth/x509/certificate_spec.rb +103 -20
  51. data/spec/rails/auth/x509/matcher_spec.rb +2 -0
  52. data/spec/rails/auth/x509/middleware_spec.rb +13 -2
  53. data/spec/rails/auth/x509/subject_alt_name_extension_spec.rb +39 -0
  54. data/spec/rails/auth_spec.rb +2 -0
  55. data/spec/spec_helper.rb +5 -3
  56. data/spec/support/claims_matcher.rb +2 -0
  57. data/spec/support/create_certs.rb +57 -2
  58. metadata +14 -7
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  RSpec.describe Rails::Auth::X509::Matcher do
2
4
  let(:example_cert) { OpenSSL::X509::Certificate.new(cert_path("valid.crt").read) }
3
5
  let(:example_certificate) { Rails::Auth::X509::Certificate.new(example_cert) }
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "logger"
2
4
 
3
5
  RSpec.describe Rails::Auth::X509::Middleware do
@@ -33,6 +35,13 @@ RSpec.describe Rails::Auth::X509::Middleware do
33
35
  _response, env = middleware.call(request.merge(example_key => bad_cert_pem))
34
36
  expect(Rails::Auth.credentials(env)).to be_empty
35
37
  end
38
+
39
+ it "normalizes abnormal whitespace" do
40
+ _response, env = middleware.call(request.merge(example_key => valid_cert_pem.tr("\n", "\t")))
41
+
42
+ credential = Rails::Auth.credentials(env).fetch("x509")
43
+ expect(credential).to be_a Rails::Auth::X509::Certificate
44
+ end
36
45
  end
37
46
 
38
47
  # :nocov:
@@ -42,10 +51,12 @@ RSpec.describe Rails::Auth::X509::Middleware do
42
51
 
43
52
  let(:java_cert) do
44
53
  ruby_cert = OpenSSL::X509::Certificate.new(valid_cert_pem)
45
- Java::SunSecurityX509::X509CertImpl.new(ruby_cert.to_der.to_java_bytes)
54
+ input_stream = Java::JavaIO::ByteArrayInputStream.new(ruby_cert.to_der.to_java_bytes)
55
+ java_cert_klass = Java::JavaSecurityCert::CertificateFactory.getInstance("X.509")
56
+ java_cert_klass.generateCertificate(input_stream)
46
57
  end
47
58
 
48
- it "extracts Rails::Auth::Credential::X509 from a Java::SunSecurityX509::X509CertImpl" do
59
+ it "extracts Rails::Auth::Credential::X509 from a java.security.cert.Certificate" do
49
60
  skip "JRuby only" unless defined?(JRUBY_VERSION)
50
61
 
51
62
  _response, env = middleware.call(request.merge(example_key => [java_cert]))
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Rails::Auth::X509::SubjectAltNameExtension do
4
+ let(:example_cert) { OpenSSL::X509::Certificate.new(cert_path("valid.crt").read) }
5
+ let(:example_cert_with_extension) { OpenSSL::X509::Certificate.new(cert_path("valid_with_ext.crt").read) }
6
+ let(:extension_for_cert) { described_class.new(example_cert) }
7
+ let(:extension_for_cert_with_san) { described_class.new(example_cert_with_extension) }
8
+ let(:example_dns_names) { %w[example.com exemplar.com somethingelse.com] }
9
+ let(:example_ips) { %w[0.0.0.0 127.0.0.1 192.168.1.1] }
10
+ let(:example_uris) { %w[spiffe://example.com/exemplar https://www.example.com/page1 https://www.example.com/page2] }
11
+
12
+ describe "for cert without extensions" do
13
+ it "returns no DNS names" do
14
+ expect(extension_for_cert.dns_names).to be_empty
15
+ end
16
+
17
+ it "returns no IPs" do
18
+ expect(extension_for_cert.ips).to be_empty
19
+ end
20
+
21
+ it "returns no URIs" do
22
+ expect(extension_for_cert.uris).to be_empty
23
+ end
24
+ end
25
+
26
+ describe "for cert with extensions" do
27
+ it "knows its DNS names" do
28
+ expect(extension_for_cert_with_san.dns_names).to eq example_dns_names
29
+ end
30
+
31
+ it "knows its IPs" do
32
+ expect(extension_for_cert_with_san.ips).to eq example_ips
33
+ end
34
+
35
+ it "knows its URIs" do
36
+ expect(extension_for_cert_with_san.uris).to eq example_uris
37
+ end
38
+ end
39
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  RSpec.describe Rails::Auth do
2
4
  it "has a version number" do
3
5
  expect(Rails::Auth::VERSION).not_to be nil
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "coveralls"
2
4
  Coveralls.wear!
3
5
 
4
- $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
6
+ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
5
7
  require "rails/auth"
6
8
  require "rails/auth/rspec"
7
9
  require "support/create_certs"
@@ -11,11 +13,11 @@ require "pathname"
11
13
  RSpec.configure(&:disable_monkey_patching!)
12
14
 
13
15
  def cert_path(name)
14
- Pathname.new(File.expand_path("../../tmp/certs", __FILE__)).join(name)
16
+ Pathname.new(File.expand_path("../tmp/certs", __dir__)).join(name)
15
17
  end
16
18
 
17
19
  def fixture_path(*args)
18
- Pathname.new(File.expand_path("../fixtures", __FILE__)).join(*args)
20
+ Pathname.new(File.expand_path("fixtures", __dir__)).join(*args)
19
21
  end
20
22
 
21
23
  def env_for(method, path, host = "127.0.0.1")
@@ -1,4 +1,6 @@
1
1
  # A strawman matcher for claims-based credentials for use in tests
2
+ # frozen_string_literal: true
3
+
2
4
  class ClaimsMatcher
3
5
  def initialize(options)
4
6
  @options = options
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "certificate_authority"
2
4
  require "fileutils"
3
5
 
4
- cert_path = File.expand_path("../../../tmp/certs", __FILE__)
6
+ cert_path = File.expand_path("../../tmp/certs", __dir__)
5
7
  FileUtils.mkdir_p(cert_path)
6
8
 
7
9
  #
@@ -15,7 +17,7 @@ ca.serial_number.number = 1
15
17
  ca.key_material.generate_key
16
18
  ca.signing_entity = true
17
19
 
18
- ca.sign! "extensions" => { "keyUsage" => { "usage" => %w(critical keyCertSign) } }
20
+ ca.sign! "extensions" => { "keyUsage" => { "usage" => %w[critical keyCertSign] } }
19
21
 
20
22
  ca_cert_path = File.join(cert_path, "ca.crt")
21
23
  ca_key_path = File.join(cert_path, "ca.key")
@@ -41,6 +43,59 @@ valid_key_path = File.join(cert_path, "valid.key")
41
43
  File.write valid_cert_path, valid_cert.to_pem
42
44
  File.write valid_key_path, valid_cert.key_material.private_key.to_pem
43
45
 
46
+ #
47
+ # Valid client certificate with extensions
48
+ #
49
+
50
+ valid_cert_with_ext = CertificateAuthority::Certificate.new
51
+ valid_cert_with_ext.subject.common_name = "127.0.0.1"
52
+ valid_cert_with_ext.subject.organizational_unit = "ponycopter"
53
+ valid_cert_with_ext.serial_number.number = 3
54
+ valid_cert_with_ext.key_material.generate_key
55
+ signing_profile = {
56
+ "extensions" => {
57
+ "basicConstraints" => {
58
+ "ca" => false
59
+ },
60
+ "crlDistributionPoints" => {
61
+ "uri" => "http://notme.com/other.crl"
62
+ },
63
+ "subjectKeyIdentifier" => {},
64
+ "authorityKeyIdentifier" => {},
65
+ "authorityInfoAccess" => {
66
+ "ocsp" => %w[http://youFillThisOut/ocsp/]
67
+ },
68
+ "keyUsage" => {
69
+ "usage" => %w[digitalSignature keyEncipherment dataEncipherment]
70
+ },
71
+ "extendedKeyUsage" => {
72
+ "usage" => %w[serverAuth clientAuth]
73
+ },
74
+ "subjectAltName" => {
75
+ "uris" => %w[spiffe://example.com/exemplar https://www.example.com/page1 https://www.example.com/page2],
76
+ "ips" => %w[0.0.0.0 127.0.0.1 192.168.1.1],
77
+ "dns_names" => %w[example.com exemplar.com somethingelse.com]
78
+ },
79
+ "certificatePolicies" => {
80
+ "policy_identifier" => "1.3.5.8",
81
+ "cps_uris" => %w[http://my.host.name/ http://my.your.name/],
82
+ "user_notice" => {
83
+ "explicit_text" => "Explicit Text Here",
84
+ "organization" => "Organization name",
85
+ "notice_numbers" => "1,2,3,4"
86
+ }
87
+ }
88
+ }
89
+ }
90
+ valid_cert_with_ext.parent = ca
91
+ valid_cert_with_ext.sign!(signing_profile)
92
+
93
+ valid_cert_with_ext_path = File.join(cert_path, "valid_with_ext.crt")
94
+ valid_key_with_ext_path = File.join(cert_path, "valid_with_ext.key")
95
+
96
+ File.write valid_cert_with_ext_path, valid_cert_with_ext.to_pem
97
+ File.write valid_key_with_ext_path, valid_cert_with_ext.key_material.private_key.to_pem
98
+
44
99
  #
45
100
  # Create evil MitM self-signed certificate
46
101
  #
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: 2.1.2
4
+ version: 2.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tony Arcieri
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-01-27 00:00:00.000000000 Z
11
+ date: 2020-07-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -28,16 +28,22 @@ dependencies:
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '1.10'
34
+ - - "<"
35
+ - !ruby/object:Gem::Version
36
+ version: '3'
34
37
  type: :development
35
38
  prerelease: false
36
39
  version_requirements: !ruby/object:Gem::Requirement
37
40
  requirements:
38
- - - "~>"
41
+ - - ">="
39
42
  - !ruby/object:Gem::Version
40
43
  version: '1.10'
44
+ - - "<"
45
+ - !ruby/object:Gem::Version
46
+ version: '3'
41
47
  - !ruby/object:Gem::Dependency
42
48
  name: rake
43
49
  requirement: !ruby/object:Gem::Requirement
@@ -102,6 +108,7 @@ files:
102
108
  - lib/rails/auth/x509/filter/pem.rb
103
109
  - lib/rails/auth/x509/matcher.rb
104
110
  - lib/rails/auth/x509/middleware.rb
111
+ - lib/rails/auth/x509/subject_alt_name_extension.rb
105
112
  - rails-auth.gemspec
106
113
  - spec/fixtures/example_acl.yml
107
114
  - spec/rails/auth/acl/matchers/allow_all_spec.rb
@@ -120,6 +127,7 @@ files:
120
127
  - spec/rails/auth/x509/certificate_spec.rb
121
128
  - spec/rails/auth/x509/matcher_spec.rb
122
129
  - spec/rails/auth/x509/middleware_spec.rb
130
+ - spec/rails/auth/x509/subject_alt_name_extension_spec.rb
123
131
  - spec/rails/auth_spec.rb
124
132
  - spec/spec_helper.rb
125
133
  - spec/support/claims_matcher.rb
@@ -137,15 +145,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
137
145
  requirements:
138
146
  - - ">="
139
147
  - !ruby/object:Gem::Version
140
- version: 2.0.0
148
+ version: 2.3.0
141
149
  required_rubygems_version: !ruby/object:Gem::Requirement
142
150
  requirements:
143
151
  - - ">="
144
152
  - !ruby/object:Gem::Version
145
153
  version: '0'
146
154
  requirements: []
147
- rubyforge_project:
148
- rubygems_version: 2.6.8
155
+ rubygems_version: 3.0.3
149
156
  signing_key:
150
157
  specification_version: 4
151
158
  summary: Modular resource-oriented authentication and authorization for Rails/Rack