blouson 4.0.0 → 6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: debaa94dc33912dc0432b49d4f73e3b3753ad5a335d14d7aff5be862790f5aec
4
- data.tar.gz: 64ee1c8a595e0101e87c5316554a3b937188fd2d82cb9c5eb66aacf53b394496
3
+ metadata.gz: adc6299d9334a783b803177c762f1263d3c1d405afac264dc9a411489d8c46ce
4
+ data.tar.gz: 50f19f86deb3f1c5b2e15d0e857f58505f50c0e5e84ecd855e10b1b018cfcfaf
5
5
  SHA512:
6
- metadata.gz: 46fed87bbd604f81ec7e5c599efc89681db1d0a25fe7be3d3249d1b1ae6e08cf5cf81fb26429be086caf1221b4e776f7433fea4cc37853704d5a624085a44829
7
- data.tar.gz: e87e60345dd41be9c51274f2ac718c77bc9a4b5e88300bad64daaa8fd70b5af6f5ddc21f7d910a9bbcad134834acbe672ed6bf2bca9e50d5cbda016d08fcd564
6
+ metadata.gz: 0edfa038be2f40514ea2056e3373c7e5203776a44e180bc7df113a4ea4cf7575aff72ca5dd777f6f1dfbde6b85015a2837a62537be1a9b6be1d37d91967bc885
7
+ data.tar.gz: d00e5fdb01fdcec9e6c46b6d5e079f826b6ae1b20ec2744f12cf5aa79833d933bced087196a4da7ce23f2198d8245ca10396b6f59cf858440b6d8250b155ee82
@@ -11,25 +11,21 @@ jobs:
11
11
  fail-fast: false
12
12
  matrix:
13
13
  ruby:
14
- - '3.0'
15
14
  - '3.1'
16
15
  - '3.2'
17
16
  - '3.3'
18
17
  - '3.4'
18
+ - '4.0'
19
19
  gemfile:
20
- - rails_7.0
21
20
  - rails_7.1
22
21
  - rails_7.2
23
22
  - rails_8.0
23
+ - rails_8.1
24
24
  exclude:
25
- - ruby: '3.0'
26
- gemfile: rails_7.2
27
- - ruby: '3.0'
28
- gemfile: rails_8.0
29
25
  - ruby: '3.1'
30
26
  gemfile: rails_8.0
31
- - ruby: '3.4'
32
- gemfile: rails_7.0
27
+ - ruby: '3.1'
28
+ gemfile: rails_8.1
33
29
  name: Run test with Ruby ${{ matrix.ruby }} and Gemfile ${{ matrix.gemfile }}
34
30
  services:
35
31
  mysql:
@@ -47,7 +43,7 @@ jobs:
47
43
  env:
48
44
  BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile
49
45
  steps:
50
- - uses: actions/checkout@v4
46
+ - uses: actions/checkout@v6
51
47
  - uses: ruby/setup-ruby@v1
52
48
  with:
53
49
  ruby-version: ${{ matrix.ruby }}
data/.gitignore CHANGED
@@ -8,6 +8,7 @@
8
8
  /pkg/
9
9
  /spec/reports/
10
10
  /tmp/
11
+ /gemfiles/.bundle/config
11
12
 
12
13
  # rspec failure tracking
13
14
  .rspec_status
data/Appraisals CHANGED
@@ -1,8 +1,3 @@
1
- appraise 'rails-7.0' do
2
- gem 'rails', '~> 7.0.0'
3
- gem 'concurrent-ruby', '1.3.4'
4
- end
5
-
6
1
  appraise 'rails-7.1' do
7
2
  gem 'rails', '~> 7.1.0'
8
3
  end
@@ -15,4 +10,8 @@ appraise 'rails-8.0' do
15
10
  gem 'rails', '~> 8.0.0'
16
11
  end
17
12
 
13
+ appraise 'rails-8.1' do
14
+ gem 'rails', '~> 8.1.0'
15
+ end
16
+
18
17
  # vim: set ft=ruby:
data/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ # 6.0.0 (2026-03-31)
2
+ - [Breaking change] Drop `to_hash` in SentryParameterFilter to support sentry-ruby v6. This change also drops support for sentry-ruby <= v5. Please upgrade the gem and update your Sentry initializer if it uses `filter.process(event.to_hash)`.
3
+ - [Breaking change] Remove sentry-raven support
4
+ - Add Ruby 4.0 to CI
5
+
6
+ # 5.0.0 (2026-01-23)
7
+ - [Breaking change] Drop support for Ruby 3.0
8
+ - [Breaking change] Drop support for Rails 7.0
9
+ - Support Rails 8.1
10
+ - Fix version matching errors; Blouson::SensitiveQueryFilter::AbstractAdapterFilter was not loaded with Rails 8.0
11
+
1
12
  # 4.0.0 (2025-02-04)
2
13
  - [Breaking change] Drop support for arproxy v0. Please update >= v1
3
14
  - [Breaking change] Drop support for Ruby 2.7
data/README.md CHANGED
@@ -7,7 +7,7 @@ Blouson is a filter tool for Rails to conceal sensitive data from various logs.
7
7
  - HTTP Request parameters in Rails log
8
8
  - SQL query in Rails log
9
9
  - Exception messages in `ActiveRecord::StatementInvalid`
10
- - Sentry Raven parameters
10
+ - Sentry parameters
11
11
  - Mail parameters in Rails log
12
12
 
13
13
  ## Installation
@@ -81,28 +81,13 @@ Sentry.init do |config|
81
81
  filter = Blouson::SentryParameterFilter.new(filter_pattern, secure_headers)
82
82
 
83
83
  config.before_send = lambda do |event, _hint|
84
- filter.process(event.to_hash)
84
+ filter.process(event)
85
85
  end
86
86
  end
87
87
 
88
88
  ```
89
89
 
90
- ### RavenParameterFilterProcessor
91
- Blouson provides an [Raven-Ruby](https://github.com/getsentry/raven-ruby) processor to conceal sensitive data from query string, request body, request headers and cookie values.
92
-
93
- ```ruby
94
- require 'blouson/raven_parameter_filter_processor'
95
-
96
- filter_pattern = Rails.application.config.filter_parameters
97
- secure_headers = %w(secret_token)
98
-
99
- Raven.configure do |config|
100
- ...
101
- config.processors << Blouson::RavenParameterFilterProcessor.create(filter_pattern, secure_headers)
102
- ...
103
- end
104
- ```
105
-
90
+ **Note:** Since sentry-ruby v6, `event.to_hash` is no longer available. Pass `event` directly to `filter.process` instead of `filter.process(event.to_hash)`.
106
91
 
107
92
  ### SensitiveMailLogFilter
108
93
  ActionMailer outputs email address, all headers, and body text to the log when sending email.
data/blouson.gemspec CHANGED
@@ -21,13 +21,12 @@ Gem::Specification.new do |spec|
21
21
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
22
  spec.require_paths = ["lib"]
23
23
 
24
- spec.add_dependency 'rails', '>= 7.0.0'
24
+ spec.add_dependency 'rails', '>= 7.1.0'
25
25
 
26
26
  spec.add_development_dependency 'arproxy', '>= 1.0.0'
27
27
  spec.add_development_dependency 'mysql2'
28
28
  spec.add_development_dependency 'pry'
29
- spec.add_development_dependency 'sentry-raven'
30
- spec.add_development_dependency 'sentry-ruby'
29
+ spec.add_development_dependency 'sentry-ruby', '>= 6.0'
31
30
 
32
31
  spec.add_development_dependency 'appraisal'
33
32
  spec.add_development_dependency "bundler", ">= 1.14"
@@ -2,7 +2,6 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "rails", "~> 7.0.0"
6
- gem "concurrent-ruby", "1.3.4"
5
+ gem "rails", "~> 8.1.0"
7
6
 
8
7
  gemspec path: "../"
@@ -19,9 +19,15 @@ module Blouson
19
19
  ActiveRecord::StatementInvalid.class_eval do
20
20
  prepend Blouson::SensitiveQueryFilter::StatementInvalidErrorFilter
21
21
  end
22
- if Rails::VERSION::MAJOR >= 7 && Rails::VERSION::MINOR >= 1 && defined?(Mysql2::Error)
22
+ if ActiveRecord.gem_version >= Gem::Version.new('7.1') && defined?(Mysql2::Error)
23
23
  ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval do
24
- prepend Blouson::SensitiveQueryFilter::AbstractAdapterFilter
24
+ if ActiveRecord.gem_version >= Gem::Version.new('8.1')
25
+ prepend Blouson::SensitiveQueryFilter::AbstractAdapterFilter81
26
+ elsif ActiveRecord.gem_version >= Gem::Version.new('8.0')
27
+ prepend Blouson::SensitiveQueryFilter::AbstractAdapterFilter80
28
+ else
29
+ prepend Blouson::SensitiveQueryFilter::AbstractAdapterFilter71
30
+ end
25
31
  end
26
32
  end
27
33
  end
@@ -26,17 +26,7 @@ module Blouson
26
26
  end
27
27
  end
28
28
 
29
- if connection_pool
30
- # Rails >= 7.1
31
- #
32
- # - https://github.com/rails/rails/pull/48295
33
- super(message, sql: sql, binds: binds, connection_pool: connection_pool)
34
- else
35
- # Rails >= 6.0
36
- #
37
- # - https://github.com/rails/rails/pull/34468
38
- super(message, sql: sql, binds: binds)
39
- end
29
+ super(message, sql:, binds:, connection_pool:)
40
30
  end
41
31
 
42
32
  def set_query(sql, binds)
@@ -62,13 +52,25 @@ module Blouson
62
52
  end
63
53
  end
64
54
 
65
- module AbstractAdapterFilter
55
+ module AbstractAdapterFilter71
56
+ # https://github.com/rails/rails/blob/v7.1.0/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb#L1133
66
57
  def log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil, async: false, &block)
67
- if Rails::VERSION::MAJOR >= 8
68
- super(sql, name, binds, type_casted_binds, async: false, &block)
69
- else
70
- super(sql, name, binds, type_casted_binds, statement_name, async: false, &block)
58
+ super(sql, name, binds, type_casted_binds, statement_name, async:, &block)
59
+ rescue ActiveRecord::RecordNotUnique, Mysql2::Error => ex
60
+ if ex.cause.is_a?(Mysql2::Error)
61
+ ex.cause.extend(Mysql2Filter)
62
+ elsif $!.is_a?(Mysql2::Error)
63
+ $!.extend(Mysql2Filter)
71
64
  end
65
+ raise ex
66
+ end
67
+ private :log
68
+ end
69
+
70
+ module AbstractAdapterFilter80
71
+ # https://github.com/rails/rails/blob/v8.0.0/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb#L1128
72
+ def log(sql, name = "SQL", binds = [], type_casted_binds = [], async: false, &block)
73
+ super(sql, name, binds, type_casted_binds, async:, &block)
72
74
  rescue ActiveRecord::RecordNotUnique, Mysql2::Error => ex
73
75
  if ex.cause.is_a?(Mysql2::Error)
74
76
  ex.cause.extend(Mysql2Filter)
@@ -77,7 +79,21 @@ module Blouson
77
79
  end
78
80
  raise ex
79
81
  end
82
+ private :log
83
+ end
80
84
 
85
+ module AbstractAdapterFilter81
86
+ # https://github.com/rails/rails/blob/v8.1.0/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb#L1200
87
+ def log(sql, name = "SQL", binds = [], type_casted_binds = [], async: false, allow_retry: false, &block)
88
+ super(sql, name, binds, type_casted_binds, async:, allow_retry:, &block)
89
+ rescue ActiveRecord::RecordNotUnique, Mysql2::Error => ex
90
+ if ex.cause.is_a?(Mysql2::Error)
91
+ ex.cause.extend(Mysql2Filter)
92
+ elsif $!.is_a?(Mysql2::Error)
93
+ $!.extend(Mysql2Filter)
94
+ end
95
+ raise ex
96
+ end
81
97
  private :log
82
98
  end
83
99
  end
@@ -1,13 +1,7 @@
1
1
  module Blouson
2
2
  class SentryParameterFilter
3
3
  def initialize(filters, header_filters = [])
4
- # ActionDispatch::Http::ParameterFilter is deprecated and will be removed from Rails 6.1.
5
- parameter_filter_klass = if defined?(ActiveSupport::ParameterFilter)
6
- ActiveSupport::ParameterFilter
7
- else
8
- ActionDispatch::Http::ParameterFilter
9
- end
10
- @parameter_filter = parameter_filter_klass.new(filters)
4
+ @parameter_filter = ActiveSupport::ParameterFilter.new(filters)
11
5
  @header_filters = header_filters.map(&:downcase)
12
6
  end
13
7
 
@@ -23,53 +17,58 @@ module Blouson
23
17
  private
24
18
 
25
19
  def process_request_body(event)
26
- if event[:request] && event[:request][:data].present?
27
- data = event[:request][:data]
28
- if data.is_a?(String)
29
- # Maybe JSON request
30
- begin
31
- data = JSON.parse(data)
32
- event[:request][:data] = JSON.dump(@parameter_filter.filter(data))
33
- rescue JSON::ParserError => e
34
- # Record parser error to extra field
35
- event[:extra]['BlousonError'] = e.message
36
- end
37
- else
38
- event[:request][:data] = @parameter_filter.filter(data)
20
+ req = event.request
21
+ return unless req && req.data.present?
22
+
23
+ data = req.data
24
+ if data.is_a?(String)
25
+ # Maybe JSON request
26
+ begin
27
+ data = JSON.parse(data)
28
+ req.data = JSON.dump(@parameter_filter.filter(data))
29
+ rescue JSON::ParserError => e
30
+ # Record parser error to extra field
31
+ event.extra['BlousonError'] = e.message
39
32
  end
33
+ else
34
+ req.data = @parameter_filter.filter(data)
40
35
  end
41
36
  end
42
37
 
43
38
  def process_query_string(event)
44
- if event[:request] && event[:request][:query_string].present?
45
- query = Rack::Utils.parse_query(event[:request][:query_string])
46
- filtered = @parameter_filter.filter(query)
39
+ req = event.request
40
+ return unless req && req.query_string.present?
47
41
 
48
- event[:request][:query_string] = Rack::Utils.build_query(filtered)
49
- end
42
+ query = Rack::Utils.parse_query(req.query_string)
43
+ filtered = @parameter_filter.filter(query)
44
+
45
+ req.query_string = Rack::Utils.build_query(filtered)
50
46
  end
51
47
 
52
48
  def process_request_header(event)
53
- if event[:request] && event[:request][:headers]
54
- headers = event[:request][:headers]
55
- headers.each_key do |k|
56
- if @header_filters.include?(k.downcase)
57
- headers[k] = 'FILTERED'
58
- end
49
+ req = event.request
50
+ return unless req && req.headers
51
+
52
+ req.headers.each_key do |k|
53
+ if @header_filters.include?(k.downcase)
54
+ req.headers[k] = 'FILTERED'
59
55
  end
60
56
  end
61
57
  end
62
58
 
63
59
  def process_cookie(event)
64
- if (cookies = event.dig(:request, :cookies))
65
- event[:request][:cookies] = @parameter_filter.filter(cookies)
60
+ req = event.request
61
+ return unless req
62
+
63
+ if req.cookies
64
+ req.cookies = @parameter_filter.filter(req.cookies)
66
65
  end
67
66
 
68
- if event[:request] && event[:request][:headers] && event[:request][:headers]['Cookie']
69
- cookies = Hash[event[:request][:headers]['Cookie'].split('; ').map { |pair| pair.split('=', 2) }]
67
+ if req.headers && req.headers['Cookie']
68
+ cookies = Hash[req.headers['Cookie'].split('; ').map { |pair| pair.split('=', 2) }]
70
69
  filtered = @parameter_filter.filter(cookies)
71
70
 
72
- event[:request][:headers]['Cookie'] = filtered.map { |pair| pair.join('=') }.join('; ')
71
+ req.headers['Cookie'] = filtered.map { |pair| pair.join('=') }.join('; ')
73
72
  end
74
73
  end
75
74
  end
@@ -1,3 +1,3 @@
1
1
  module Blouson
2
- VERSION = "4.0.0"
2
+ VERSION = "6.0.0"
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blouson
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0
4
+ version: 6.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cookpad Inc.
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-02-04 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: rails
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: 7.0.0
18
+ version: 7.1.0
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
- version: 7.0.0
25
+ version: 7.1.0
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: arproxy
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -65,34 +65,20 @@ dependencies:
65
65
  - - ">="
66
66
  - !ruby/object:Gem::Version
67
67
  version: '0'
68
- - !ruby/object:Gem::Dependency
69
- name: sentry-raven
70
- requirement: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - ">="
73
- - !ruby/object:Gem::Version
74
- version: '0'
75
- type: :development
76
- prerelease: false
77
- version_requirements: !ruby/object:Gem::Requirement
78
- requirements:
79
- - - ">="
80
- - !ruby/object:Gem::Version
81
- version: '0'
82
68
  - !ruby/object:Gem::Dependency
83
69
  name: sentry-ruby
84
70
  requirement: !ruby/object:Gem::Requirement
85
71
  requirements:
86
72
  - - ">="
87
73
  - !ruby/object:Gem::Version
88
- version: '0'
74
+ version: '6.0'
89
75
  type: :development
90
76
  prerelease: false
91
77
  version_requirements: !ruby/object:Gem::Requirement
92
78
  requirements:
93
79
  - - ">="
94
80
  - !ruby/object:Gem::Version
95
- version: '0'
81
+ version: '6.0'
96
82
  - !ruby/object:Gem::Dependency
97
83
  name: appraisal
98
84
  requirement: !ruby/object:Gem::Requirement
@@ -168,13 +154,12 @@ files:
168
154
  - bin/console
169
155
  - bin/setup
170
156
  - blouson.gemspec
171
- - gemfiles/rails_7.0.gemfile
172
157
  - gemfiles/rails_7.1.gemfile
173
158
  - gemfiles/rails_7.2.gemfile
174
159
  - gemfiles/rails_8.0.gemfile
160
+ - gemfiles/rails_8.1.gemfile
175
161
  - lib/blouson.rb
176
162
  - lib/blouson/engine.rb
177
- - lib/blouson/raven_parameter_filter_processor.rb
178
163
  - lib/blouson/sensitive_mail_log_filter.rb
179
164
  - lib/blouson/sensitive_params_silencer.rb
180
165
  - lib/blouson/sensitive_query_filter.rb
@@ -200,7 +185,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
200
185
  - !ruby/object:Gem::Version
201
186
  version: '0'
202
187
  requirements: []
203
- rubygems_version: 3.6.2
188
+ rubygems_version: 3.6.9
204
189
  specification_version: 4
205
190
  summary: Filter tools to mask sensitive data in various logs
206
191
  test_files: []
@@ -1,88 +0,0 @@
1
- module Blouson
2
- class RavenParameterFilterProcessor
3
- def self.create(filters, header_filters)
4
- Class.new(Raven::Processor) do
5
- @filters = filters
6
- @header_filters = header_filters.map(&:downcase)
7
-
8
- def self.filters
9
- @filters
10
- end
11
-
12
- def self.header_filters
13
- @header_filters
14
- end
15
-
16
- def initialize(client = nil)
17
- # ActionDispatch::Http::ParameterFilter is deprecated and will be removed from Rails 6.1.
18
- parameter_filter_klass = if defined?(ActiveSupport::ParameterFilter)
19
- ActiveSupport::ParameterFilter
20
- else
21
- ActionDispatch::Http::ParameterFilter
22
- end
23
- @parameter_filter = parameter_filter_klass.new(self.class.filters)
24
- end
25
-
26
- def process(value)
27
- process_query_string(value)
28
- process_request_body(value)
29
- process_request_header(value)
30
- process_cookie(value)
31
- ensure
32
- return value
33
- end
34
-
35
- def process_request_body(value)
36
- if value[:request] && value[:request][:data].present?
37
- data = value[:request][:data]
38
- if data.is_a?(String)
39
- # Maybe JSON request
40
- begin
41
- data = JSON.parse(data)
42
- value[:request][:data] = JSON.dump(@parameter_filter.filter(data))
43
- rescue JSON::ParserError => e
44
- # Record parser error to extra field
45
- value[:extra]['BlousonError'] = e.message
46
- end
47
- else
48
- value[:request][:data] = @parameter_filter.filter(data)
49
- end
50
- end
51
- end
52
-
53
- def process_query_string(value)
54
- if value[:request] && value[:request][:query_string].present?
55
- query = Rack::Utils.parse_query(value[:request][:query_string])
56
- filtered = @parameter_filter.filter(query)
57
-
58
- value[:request][:query_string] = Rack::Utils.build_query(filtered)
59
- end
60
- end
61
-
62
- def process_request_header(value)
63
- if value[:request] && value[:request][:headers]
64
- headers = value[:request][:headers]
65
- headers.each_key do |k|
66
- if self.class.header_filters.include?(k.downcase)
67
- headers[k] = 'FILTERED'
68
- end
69
- end
70
- end
71
- end
72
-
73
- def process_cookie(value)
74
- if (cookies = value.dig(:request, :cookies))
75
- value[:request][:cookies] = @parameter_filter.filter(cookies)
76
- end
77
-
78
- if value[:request] && value[:request][:headers] && value[:request][:headers]['Cookie']
79
- cookies = Hash[value[:request][:headers]['Cookie'].split('; ').map { |pair| pair.split('=', 2) }]
80
- filtered = @parameter_filter.filter(cookies)
81
-
82
- value[:request][:headers]['Cookie'] = filtered.map { |pair| pair.join('=') }.join('; ')
83
- end
84
- end
85
- end
86
- end
87
- end
88
- end