rails-auth 2.1.3 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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 +51 -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 -8
  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 +2 -0
  33. data/lib/rails/auth/x509/matcher.rb +2 -0
  34. data/lib/rails/auth/x509/middleware.rb +11 -31
  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 +15 -37
  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 +51 -13
  58. metadata +14 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 04accd9068297df63d222180e00d66bb5a3cdc24
4
- data.tar.gz: 36dba8c9eee4957f1defe679ae9d98ceba53393f
2
+ SHA256:
3
+ metadata.gz: 9f5669f564b62464b0d3078ecfa58fe3732735e44c63bed361061a9f1a663249
4
+ data.tar.gz: cbee05f42e189e543b059d961d1b926d763d84e07c93a3637165f95eba0fe776
5
5
  SHA512:
6
- metadata.gz: 790da2f08086cee1fd8719fff050e18e7cfc1301fb12483c327d117c0875bdc945fe404d7040a184f28dd69c352803b525acd720f94b8f7920f550776d950371
7
- data.tar.gz: 4f6d90c4d94195cc5b42cd0f783d64168aa045178bea6ac6e646cbf80e221bc0668a9400358271449e570fe8358592ae7ae2d84897771da583c2a45592325426
6
+ metadata.gz: 0be32c7166ed406dda136608370f059443a56219696c8d13a56f3978f9eca3b37b99ccf0885d4c42d13c660860be52530891d9317a2d2562f7f265d7d751ccd0
7
+ data.tar.gz: e1ada71b12c7732fe2aced6bb98abd11cb7b8fa665093f9faa5808b9c21bef12dd99e3070fcd2ee343acc4b377626ae885098388f85d7d9027f37e1d08d60890
@@ -1,12 +1,16 @@
1
1
  AllCops:
2
2
  DisplayCopNames: true
3
+ TargetRubyVersion: 2.3
3
4
 
4
5
  Style/StringLiterals:
5
6
  EnforcedStyle: double_quotes
6
7
 
7
- Style/ModuleFunction:
8
+ Layout/HashAlignment:
8
9
  Enabled: false
9
10
 
11
+ Metrics/BlockLength:
12
+ ExcludedMethods: ['describe', 'context']
13
+
10
14
  Metrics/ParameterLists:
11
15
  Max: 5
12
16
  CountKeywordArgs: false
@@ -22,3 +26,12 @@ Metrics/AbcSize:
22
26
 
23
27
  Metrics/CyclomaticComplexity:
24
28
  Max: 8
29
+
30
+ Naming/MethodParameterName:
31
+ MinNameLength: 2
32
+
33
+ Style/ModuleFunction:
34
+ Enabled: false
35
+
36
+ Style/SafeNavigation:
37
+ Enabled: false
@@ -10,12 +10,15 @@ before_install:
10
10
  bundler_args: --without development
11
11
 
12
12
  rvm:
13
- - 2.0.0
14
- - 2.1.10
15
- - 2.2.4
16
- - 2.3.0
13
+ - 2.4
14
+ - 2.5
15
+ - 2.6
17
16
  matrix:
18
17
  include:
19
- - rvm: jruby-9.0.5.0
18
+ - rvm: jruby
19
+ jdk: openjdk8
20
+ env: JRUBY_OPTS="--debug" # for simplecov
21
+ - rvm: jruby
22
+ jdk: openjdk11
20
23
  env: JRUBY_OPTS="--debug" # for simplecov
21
24
  fast_finish: true
@@ -1,9 +1,9 @@
1
- Break me and win a prize!
2
- =========================
1
+ Serious about security
2
+ ======================
3
3
 
4
4
  Square recognizes the important contributions the security research community
5
5
  can make. We therefore encourage reporting security issues with the code
6
6
  contained in this repository.
7
7
 
8
8
  If you believe you have discovered a security vulnerability, please follow the
9
- guidelines at https://hackerone.com/square-open-source
9
+ guidelines at <https://bugcrowd.com/squareopensource>.
data/CHANGES.md CHANGED
@@ -1,3 +1,49 @@
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
+
13
+ ### 2.2.2 (2020-07-02)
14
+
15
+ * [#65](https://github.com/square/rails-auth/pull/65)
16
+ Fix error when passing `truststore` instead of `ca_file` to X509 middleware.
17
+ ([@drcapulet])
18
+
19
+ ### 2.2.1 (2020-01-08)
20
+
21
+ * [#63](https://github.com/square/rails-auth/pull/63)
22
+ Fix `FrozenError` in `permit` matcher description.
23
+ ([@drcapulet])
24
+
25
+ ### 2.2.0 (2019-12-05)
26
+
27
+ * [#55](https://github.com/square/rails-auth/pull/55)
28
+ Allow dynamic injection of credentials.
29
+ ([@drcapulet])
30
+
31
+ * [#59](https://github.com/square/rails-auth/pull/59)
32
+ Expose X.509 Subject Alternative Name extension
33
+ in the Rails::Auth::X509::Certificate and provide a convenience
34
+ method `spiffe_id` to expose [SPIFFE ID](https://spiffe.io).
35
+ ([@mbyczkowski])
36
+
37
+ * [#57](https://github.com/square/rails-auth/pull/57)
38
+ Add support for latest versions of Ruby, JRuby and Bundler 2.
39
+ ([@mbyczkowski])
40
+
41
+ ### 2.1.4 (2018-07-12)
42
+
43
+ * [#51](https://github.com/square/rails-auth/pull/51)
44
+ Fix bug in `permit` custom matcher so that a description is rendered.
45
+ ([@yellow-beard])
46
+
1
47
  ### 2.1.3 (2017-08-04)
2
48
 
3
49
  * [#44](https://github.com/square/rails-auth/pull/44)
@@ -178,6 +224,9 @@
178
224
  * Vaporware release to claim the "rails-auth" gem name
179
225
 
180
226
 
181
- [@tarcieri]: https://github.com/tarcieri
182
- [@ewr]: https://github.com/ewr
183
227
  [@drcapulet]: https://github.com/drcapulet
228
+ [@ewr]: https://github.com/ewr
229
+ [@mbyczkowski]: https://github.com/mbyczkowski
230
+ [@nerdrew]: https://github.com/nerdrew
231
+ [@tarcieri]: https://github.com/tarcieri
232
+ [@yellow-beard]: https://github.com/yellow-beard
@@ -1,14 +1,15 @@
1
- ### Sign the CLA
1
+ # Contributing
2
2
 
3
- Any contributors to the master *rails-auth* repository must sign the
4
- [Individual Contributor License Agreement (CLA)]. It's a short form that covers
5
- our bases and makes sure you're eligible to contribute.
3
+ If you would like to contribute code to *rails-auth* you can do so through GitHub by
4
+ forking the repository and sending a pull request.
6
5
 
7
- ### Submitting a Pull Request
6
+ When submitting code, please make every effort to follow existing conventions
7
+ and style in order to keep the code as readable as possible. Please also make
8
+ sure all tests pass by running `bundle exec rspec spec`, and format your code
9
+ according to `rubocop` rules.
8
10
 
9
- When you have a change you'd like to see in the master repository, send a
10
- [pull request]. Before we merge your request, we'll make sure you're in the list
11
- of people who have signed a CLA.
11
+ Before your code can be accepted into the project you must also sign the
12
+ Individual Contributor License Agreement. We use [cla-assistant.io][1] and you
13
+ will be prompted to sign once a pull request is opened.
12
14
 
13
- [Individual Contributor License Agreement (CLA)]: https://spreadsheets.google.com/spreadsheet/viewform?formkey=dDViT2xzUHAwRkI3X3k5Z0lQM091OGc6MQ&ndplr=1
14
- [pull request]: https://github.com/square/rails-auth/pulls
15
+ [1]: https://cla-assistant.io/
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source "https://rubygems.org"
2
4
 
3
5
  group :development do
@@ -5,15 +7,14 @@ group :development do
5
7
  end
6
8
 
7
9
  group :development, :test do
10
+ gem "activesupport", "~> 4"
11
+ gem "certificate_authority", require: false
12
+ gem "coveralls", require: false
8
13
  # Workaround for: https://github.com/bundler/bundler/pull/4650
9
14
  gem "rack", "~> 1.x"
10
- gem "activesupport", "~> 4"
11
-
12
15
  gem "rake"
13
16
  gem "rspec"
14
- gem "rubocop", "0.38.0"
15
- gem "coveralls", require: false
16
- gem "certificate_authority", require: false
17
+ gem "rubocop", "0.77.0"
17
18
  end
18
19
 
19
20
  gemspec
data/Guardfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  guard :rspec, cmd: "bundle exec rspec" do
2
4
  watch(%r{^spec/.+_spec\.rb$})
3
5
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "bundler/gem_tasks"
2
4
  require "rspec/core/rake_task"
3
5
  require "rubocop/rake_task"
@@ -5,4 +7,4 @@ require "rubocop/rake_task"
5
7
  RSpec::Core::RakeTask.new(:spec)
6
8
  RuboCop::RakeTask.new
7
9
 
8
- task default: %w(spec rubocop)
10
+ task default: %w[spec rubocop]
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Pull in default matchers
2
4
  require "rails/auth/acl/matchers/allow_all"
3
5
 
@@ -17,7 +19,9 @@ module Rails
17
19
  # @param [String] :yaml serialized YAML to load an ACL from
18
20
  def self.from_yaml(yaml, **args)
19
21
  require "yaml"
22
+ # rubocop:todo Security/YAMLLoad
20
23
  new(YAML.load(yaml), **args)
24
+ # rubocop:enable Security/YAMLLoad
21
25
  end
22
26
 
23
27
  # @param [Array<Hash>] :acl Access Control List configuration
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rails
2
4
  module Auth
3
5
  class ACL
@@ -7,6 +9,7 @@ module Rails
7
9
  class AllowAll
8
10
  def initialize(enabled)
9
11
  raise ArgumentError, "enabled must be true/false" unless [true, false].include?(enabled)
12
+
10
13
  @enabled = enabled
11
14
  end
12
15
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rails
2
4
  module Auth
3
5
  class ACL
@@ -25,6 +27,7 @@ module Rails
25
27
  unless Rails::Auth.authorized?(env)
26
28
  matcher_name = @acl.match(env)
27
29
  raise NotAuthorizedError, "unauthorized request" unless matcher_name
30
+
28
31
  Rails::Auth.set_allowed_by(env, "matcher:#{matcher_name}")
29
32
  end
30
33
 
@@ -8,10 +8,10 @@ module Rails
8
8
  attr_reader :http_methods, :path, :host, :matchers
9
9
 
10
10
  # Valid HTTP methods
11
- HTTP_METHODS = %w(GET HEAD PUT POST DELETE OPTIONS PATCH LINK UNLINK).freeze
11
+ HTTP_METHODS = %w[GET HEAD PUT POST DELETE OPTIONS PATCH LINK UNLINK].freeze
12
12
 
13
13
  # Options allowed for resource matchers
14
- VALID_OPTIONS = %w(method path host).freeze
14
+ VALID_OPTIONS = %w[method path host].freeze
15
15
 
16
16
  # @option :options [String] :method HTTP method allowed ("ALL" for all methods)
17
17
  # @option :options [String] :path path to the resource (regex syntax allowed)
@@ -46,6 +46,7 @@ module Rails
46
46
  #
47
47
  def match(env)
48
48
  return nil unless match!(env)
49
+
49
50
  name, = @matchers.find { |_name, matcher| matcher.match(env) }
50
51
  name
51
52
  end
@@ -58,9 +59,10 @@ module Rails
58
59
  # @return [Boolean] method and path *only* match the given environment
59
60
  #
60
61
  def match!(env)
61
- return false unless @http_methods.include?(env["REQUEST_METHOD".freeze])
62
- return false unless @path =~ env["PATH_INFO".freeze]
63
- return false unless @host.nil? || @host =~ env["HTTP_HOST".freeze]
62
+ return false unless @http_methods.include?(env["REQUEST_METHOD"])
63
+ return false unless @path =~ env["PATH_INFO"]
64
+ return false unless @host.nil? || @host =~ env["HTTP_HOST"]
65
+
64
66
  true
65
67
  end
66
68
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rails
2
4
  module Auth
3
5
  # Configures Rails::Auth middleware for use in a Rails application
@@ -11,7 +13,7 @@ module Rails
11
13
  matchers: matchers
12
14
  )
13
15
 
14
- config.middleware.use Rails::Auth::ACL::Middleware, acl: config.x.acl
16
+ config.middleware.use Rails::Auth::ACL::Middleware, acl: config.x.rails_auth.acl
15
17
  end
16
18
 
17
19
  # Development configuration (i.e. config/environments/development.rb)
@@ -29,26 +31,20 @@ module Rails
29
31
  def production(
30
32
  config,
31
33
  cert_filters: nil,
32
- require_cert: false,
33
- ca_file: nil,
34
34
  error_page: Rails.root.join("public/403.html"),
35
35
  monitor: nil
36
36
  )
37
- raise ArgumentError, "no cert_filters given but require_cert is true" if require_cert && !cert_filters
38
- raise ArgumentError, "no ca_file given but cert_filters were set" if cert_filters && !ca_file
39
-
40
37
  error_page_middleware(config, error_page)
41
38
 
42
39
  if cert_filters
43
40
  config.middleware.insert_before Rails::Auth::ACL::Middleware,
44
41
  Rails::Auth::X509::Middleware,
45
- require_cert: require_cert,
46
42
  cert_filters: cert_filters,
47
- ca_file: ca_file,
48
43
  logger: Rails.logger
49
44
  end
50
45
 
51
46
  return unless monitor
47
+
52
48
  config.middleware.insert_before Rails::Auth::ACL::Middleware,
53
49
  Rails::Auth::Monitor::Middleware,
54
50
  monitor
@@ -68,6 +64,7 @@ module Rails
68
64
  Rails::Auth::ErrorPage::Middleware,
69
65
  page_body: Pathname(error_page).read
70
66
  when FalseClass, NilClass
67
+ nil
71
68
  else raise TypeError, "bad error page mode: #{mode.inspect}"
72
69
  end
73
70
  end
@@ -1,5 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/hash_with_indifferent_access"
2
4
 
5
+ # rubocop:disable Naming/MemoizedInstanceVariableName
3
6
  module Rails
4
7
  module Auth
5
8
  # Convenience methods designed to be included in an ActionController::Base subclass
@@ -18,3 +21,4 @@ module Rails
18
21
  end
19
22
  end
20
23
  end
24
+ # rubocop:enable Naming/MemoizedInstanceVariableName
@@ -10,7 +10,7 @@ module Rails
10
10
  extend Forwardable
11
11
  include Enumerable
12
12
 
13
- def_delegators :@credentials, :fetch, :empty?, :key?, :each, :to_hash
13
+ def_delegators :@credentials, :fetch, :empty?, :key?, :each, :to_hash, :values
14
14
 
15
15
  def self.from_rack_env(env)
16
16
  new(env.fetch(Rails::Auth::Env::CREDENTIALS_ENV_KEY, {}))
@@ -18,6 +18,7 @@ module Rails
18
18
 
19
19
  def initialize(credentials = {})
20
20
  raise TypeError, "expected Hash, got #{credentials.class}" unless credentials.is_a?(Hash)
21
+
21
22
  @credentials = credentials
22
23
  end
23
24
 
@@ -25,6 +26,7 @@ module Rails
25
26
  return if @credentials.key?(type) && @credentials[type] == value
26
27
  raise TypeError, "expected String for type, got #{type.class}" unless type.is_a?(String)
27
28
  raise AlreadyAuthorizedError, "credential '#{type}' has already been set" if @credentials.key?(type)
29
+
28
30
  @credentials[type] = value
29
31
  end
30
32
 
@@ -1,9 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rails
2
4
  module Auth
3
5
  class Credentials
4
6
  # A middleware for injecting an arbitrary credentials hash into the Rack environment
5
7
  # This is intended for development and testing purposes where you would like to
6
- # simulate a given X.509 certificate being used in a request or user logged in
8
+ # simulate a given X.509 certificate being used in a request or user logged in.
9
+ # The credentials argument should either be a hash or a proc that returns one.
7
10
  class InjectorMiddleware
8
11
  def initialize(app, credentials)
9
12
  @app = app
@@ -11,7 +14,8 @@ module Rails
11
14
  end
12
15
 
13
16
  def call(env)
14
- env[Rails::Auth::Env::CREDENTIALS_ENV_KEY] = @credentials
17
+ credentials = @credentials.respond_to?(:call) ? @credentials.call(env) : @credentials
18
+ env[Rails::Auth::Env::CREDENTIALS_ENV_KEY] = credentials
15
19
  @app.call(env)
16
20
  end
17
21
  end
@@ -5,13 +5,13 @@ module Rails
5
5
  # Wrapper for Rack environments with Rails::Auth helpers
6
6
  class Env
7
7
  # Rack environment key for marking external authorization
8
- AUTHORIZED_ENV_KEY = "rails-auth.authorized".freeze
8
+ AUTHORIZED_ENV_KEY = "rails-auth.authorized"
9
9
 
10
10
  # Rack environment key for storing what allowed the request
11
- ALLOWED_BY_ENV_KEY = "rails-auth.allowed-by".freeze
11
+ ALLOWED_BY_ENV_KEY = "rails-auth.allowed-by"
12
12
 
13
13
  # Rack environment key for all rails-auth credentials
14
- CREDENTIALS_ENV_KEY = "rails-auth.credentials".freeze
14
+ CREDENTIALS_ENV_KEY = "rails-auth.credentials"
15
15
 
16
16
  attr_reader :allowed_by, :credentials
17
17
 
@@ -44,6 +44,7 @@ module Rails
44
44
  def allowed_by=(allowed_by)
45
45
  raise AlreadyAuthorizedError, "already allowed by #{@allowed_by.inspect}" if @allowed_by
46
46
  raise TypeError, "expected String for allowed_by, got #{allowed_by.class}" unless allowed_by.is_a?(String)
47
+
47
48
  @allowed_by = allowed_by
48
49
  end
49
50
 
@@ -26,7 +26,7 @@ module Rails
26
26
 
27
27
  @app = app
28
28
  @acl = acl
29
- @erb = ERB.new(File.read(File.expand_path("../debug_page.html.erb", __FILE__))).freeze
29
+ @erb = ERB.new(File.read(File.expand_path("debug_page.html.erb", __dir__))).freeze
30
30
  end
31
31
 
32
32
  def call(env)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rails
2
4
  module Auth
3
5
  module ErrorPage
@@ -32,6 +34,7 @@ module Rails
32
34
  accept_format = env["HTTP_ACCEPT"]
33
35
  return :json if accept_format && accept_format.downcase.start_with?("application/json")
34
36
  return :json if env["PATH_INFO"] && env["PATH_INFO"].end_with?(".json")
37
+
35
38
  nil
36
39
  end
37
40
  end