opbeat 1.1.1 → 2.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
  SHA1:
3
- metadata.gz: f0e680f1743a61cd93df6a57aeae419b272fe26d
4
- data.tar.gz: 352da6e6062c4b524c8524c807f4fc82cddf441b
3
+ metadata.gz: 0cc7e45c2207d40f1deaa655ae2510e7f6c38d7c
4
+ data.tar.gz: 2793d306ca86292a30fedc2ee831af7086862adc
5
5
  SHA512:
6
- metadata.gz: 5a219a7467138cb9f88e4032028c05f465f76aaba9bf592ded9b8b84890f6d4d3a1da972899a97ee41550ea3ecf2efc512d902beadabe1ff627bf50166d6f723
7
- data.tar.gz: cdebe683a8ba86f2d27dd7652fc428bd75466c4dc2ac457dad548e4db1097e595ec1c0cfa45e80d49a08dbb7244e71e3ea08789cba67fadde2062f2baa840677
6
+ metadata.gz: 388d8dedb07d74f4ee42fa21855a037a0559ea4c783e2107a8158dcc9dd2510e6e4fdc0e90a19b1a4e7fa4fdf290a50ebf23aacab5934ca937ab9edd84a01616
7
+ data.tar.gz: 2dc336b2815d477d7fc2fd30d2941f60cf5dd95777bdb1e3a3e70440eaa119546daff324ab07798b6d2bc58d2c15083704aa6dabbabb6fdd5fcbebbd287b59b4
data/README.md CHANGED
@@ -4,15 +4,19 @@
4
4
 
5
5
  A client and integration layer for [Opbeat](https://opbeat.com). Forked from the [raven-ruby](https://github.com/getsentry/raven-ruby) project.
6
6
 
7
-
8
7
  ## Installation
9
8
 
10
9
  Add the following to your `Gemfile`:
11
10
 
12
11
  ```ruby
13
- gem "opbeat"
12
+ gem "opbeat", "~> 2.0"
14
13
  ```
15
14
 
15
+ The Opbeat gem adhere to [Semantic
16
+ Versioning](http://guides.rubygems.org/patterns/#semantic-versioning)
17
+ and so you can safely trust all minor and patch versions (e.g. 2.x.x) to
18
+ be backwards compatible.
19
+
16
20
  ## Usage
17
21
 
18
22
  ### Rails 3 and Rails 4
@@ -161,13 +165,23 @@ Opbeat.configure do |config|
161
165
  end
162
166
  ```
163
167
 
164
- ## Sanitizing Data (Processors)
168
+ ## Sanitizing Data
169
+
170
+ The Opbeat agent will sanitize the data sent to the Opbeat server based
171
+ on the following rules.
172
+
173
+ If you are running Rails, the agent will first try to fetch the
174
+ filtering settings from `Rails.application.config.filter_parameters`.
165
175
 
166
- If you need to sanitize or pre-process (before its sent to the server) data, you can do so using the Processors
167
- implementation. By default, a single processor is installed (Opbeat::Processors::SanitizeData), which will attempt to
168
- sanitize keys that match various patterns (e.g. password) and values that resemble credit card numbers.
176
+ If those are not set (or if you are not running Rails), the agent will
177
+ fall back to its own defaults:
169
178
 
170
- To specify your own (or to remove the defaults), simply pass them with your configuration:
179
+ ```ruby
180
+ /(authorization|password|passwd|secret)/i
181
+ ```
182
+
183
+ To specify your own (or to remove the defaults), simply set the
184
+ `filter_parameters` configuration parameter:
171
185
 
172
186
  ```ruby
173
187
  require 'opbeat'
@@ -177,10 +191,13 @@ Opbeat.configure do |config|
177
191
  config.app_id = '094e250818'
178
192
  config.secret_token = 'f0f5237a221637f561a15614f5fef218f8d6317d'
179
193
 
180
- config.processors = [Opbeat::Processor::SanitizeData]
194
+ config.filter_parameters = [:credit_card, /^pass(word)$/i]
181
195
  end
182
196
  ```
183
197
 
198
+ Note that only the `data`, `query_string` and `cookies` fields under
199
+ `http` are filtered.
200
+
184
201
  ## User information
185
202
 
186
203
  With Rails, Opbeat expects `controller#current_user` to return an object with `id`, `email` and/or `username` attributes. You can change the name of the current user method in the following manner:
data/lib/opbeat.rb CHANGED
@@ -8,7 +8,6 @@ require 'opbeat/interfaces/message'
8
8
  require 'opbeat/interfaces/exception'
9
9
  require 'opbeat/interfaces/stack_trace'
10
10
  require 'opbeat/interfaces/http'
11
- require 'opbeat/processors/sanitizedata'
12
11
 
13
12
  require 'opbeat/integrations/delayed_job'
14
13
  require 'opbeat/integrations/sidekiq'
data/lib/opbeat/client.rb CHANGED
@@ -5,6 +5,7 @@ require 'faraday'
5
5
 
6
6
  require 'opbeat/version'
7
7
  require 'opbeat/error'
8
+ require 'opbeat/filter'
8
9
 
9
10
  module Opbeat
10
11
 
@@ -52,7 +53,7 @@ module Opbeat
52
53
 
53
54
  @configuration = conf
54
55
  @state = ClientState.new conf
55
- @processors = conf.processors.map { |p| p.new(self) }
56
+ @filter = Filter.new conf.filter_parameters
56
57
  @base_url = "#{conf.server}/api/v1/organizations/#{conf.organization_id}/apps/#{conf.app_id}"
57
58
  @auth_header = 'Bearer ' + conf.secret_token
58
59
  end
@@ -69,11 +70,7 @@ module Opbeat
69
70
 
70
71
  def encode(event)
71
72
  event_hash = event.to_hash
72
-
73
- @processors.each do |p|
74
- event_hash = p.process(event_hash)
75
- end
76
-
73
+ event_hash = @filter.process_event_hash(event_hash)
77
74
  return MultiJson.encode(event_hash)
78
75
  end
79
76
 
@@ -25,8 +25,8 @@ module Opbeat
25
25
  # Which exceptions should never be sent
26
26
  attr_accessor :excluded_exceptions
27
27
 
28
- # Processors to run on data before sending upstream
29
- attr_accessor :processors
28
+ # An array of parameters whould should be filtered from the log
29
+ attr_accessor :filter_parameters
30
30
 
31
31
  # Timeout when waiting for the server to return data in seconds
32
32
  attr_accessor :timeout
@@ -48,15 +48,14 @@ module Opbeat
48
48
  attr_reader :async
49
49
 
50
50
  def initialize
51
- self.server = ENV['OPBEAT_SERVER'] || "https://opbeat.com"
51
+ self.server = ENV['OPBEAT_SERVER'] || "https://intake.opbeat.com"
52
52
  self.secret_token = ENV['OPBEAT_SECRET_TOKEN'] if ENV['OPBEAT_SECRET_TOKEN']
53
53
  self.organization_id = ENV['OPBEAT_ORGANIZATION_ID'] if ENV['OPBEAT_ORGANIZATION_ID']
54
54
  self.app_id = ENV['OPBEAT_APP_ID'] if ENV['OPBEAT_APP_ID']
55
55
  @context_lines = 3
56
56
  self.environments = %w[ development production default ]
57
- self.current_environment = (defined?(Rails) && Rails.env) || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'default'
57
+ self.current_environment = (defined?(::Rails) && ::Rails.env) || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'default'
58
58
  self.excluded_exceptions = []
59
- self.processors = [Opbeat::Processor::SanitizeData]
60
59
  self.timeout = 1
61
60
  self.open_timeout = 1
62
61
  self.backoff_multiplier = 2
@@ -0,0 +1,63 @@
1
+ module Opbeat
2
+ class Filter
3
+ MASK = '[FILTERED]'
4
+ DEFAULT_FILTER = [/(authorization|password|passwd|secret)/i]
5
+
6
+ def initialize(filters=nil)
7
+ if defined?(::Rails)
8
+ rails_filters = ::Rails.application.config.filter_parameters
9
+ rails_filters = nil if rails_filters.count == 0
10
+ end
11
+ @filters = filters || rails_filters || DEFAULT_FILTER
12
+ end
13
+
14
+ def apply(value, key=nil, &block)
15
+ if value.is_a?(Hash)
16
+ value.each.inject({}) do |memo, (k, v)|
17
+ memo[k] = apply(v, k, &block)
18
+ memo
19
+ end
20
+ elsif value.is_a?(Array)
21
+ value.map do |value|
22
+ apply(value, key, &block)
23
+ end
24
+ else
25
+ block.call(key, value)
26
+ end
27
+ end
28
+
29
+ def sanitize(key, value)
30
+ if !value.is_a?(String) || value.empty?
31
+ value
32
+ elsif @filters.any? { |filter| filter.is_a?(Regexp) ? filter.match(key) : filter.to_s == key.to_s }
33
+ MASK
34
+ else
35
+ value
36
+ end
37
+ end
38
+
39
+ def process_event_hash(data)
40
+ return data unless data.has_key? 'http'
41
+ if data['http'].has_key? 'data'
42
+ data['http']['data'] = process_hash(data['http']['data'])
43
+ end
44
+ if data['http'].has_key? 'query_string'
45
+ data['http']['query_string'] = process_string(data['http']['query_string'], '&')
46
+ end
47
+ if data['http'].has_key? 'cookies'
48
+ data['http']['cookies'] = process_string(data['http']['cookies'], ';')
49
+ end
50
+ data
51
+ end
52
+
53
+ def process_hash(data)
54
+ apply(data) do |key, value|
55
+ sanitize(key, value)
56
+ end
57
+ end
58
+
59
+ def process_string(str, separator='&')
60
+ str.split(separator).map { |s| s.split('=') }.map { |a| a[0]+'='+sanitize(a[0], a[1]) }.join(separator)
61
+ end
62
+ end
63
+ end
@@ -1,3 +1,3 @@
1
1
  module Opbeat
2
- VERSION = "1.1.1"
2
+ VERSION = "2.0.0"
3
3
  end
@@ -0,0 +1,101 @@
1
+ require File::expand_path('../../spec_helper', __FILE__)
2
+ require 'opbeat/filter'
3
+
4
+ describe Opbeat::Filter do
5
+ it 'should filter http data by default' do
6
+ data = {
7
+ 'http' => {
8
+ 'data' => {
9
+ 'foo' => 'bar',
10
+ 'password' => 'hello',
11
+ 'the_secret' => 'hello',
12
+ 'a_password_here' => 'hello',
13
+ 'mypasswd' => 'hello'
14
+ }
15
+ }
16
+ }
17
+
18
+ filter = Opbeat::Filter.new
19
+ result = filter.process_event_hash(data)
20
+
21
+ vars = result["http"]["data"]
22
+ expect(vars["foo"]).to eq("bar")
23
+ expect(vars["password"]).to eq(Opbeat::Filter::MASK)
24
+ expect(vars["the_secret"]).to eq(Opbeat::Filter::MASK)
25
+ expect(vars["a_password_here"]).to eq(Opbeat::Filter::MASK)
26
+ expect(vars["mypasswd"]).to eq(Opbeat::Filter::MASK)
27
+ end
28
+
29
+ it 'should filter http query_string by default' do
30
+ data = {
31
+ 'http' => {
32
+ 'query_string' => 'foo=bar&password=secret'
33
+ }
34
+ }
35
+
36
+ filter = Opbeat::Filter.new
37
+ result = filter.process_event_hash(data)
38
+
39
+ expect(result["http"]["query_string"]).to eq('foo=bar&password=' + Opbeat::Filter::MASK)
40
+ end
41
+
42
+ it 'should filter http cookies by default' do
43
+ data = {
44
+ 'http' => {
45
+ 'cookies' => 'foo=bar;password=secret'
46
+ }
47
+ }
48
+
49
+ filter = Opbeat::Filter.new
50
+ result = filter.process_event_hash(data)
51
+
52
+ expect(result["http"]["cookies"]).to eq('foo=bar;password=' + Opbeat::Filter::MASK)
53
+ end
54
+
55
+ it 'should not filter env, extra or headers' do
56
+ data = {
57
+ 'http' => {
58
+ 'env' => { 'password' => 'hello' },
59
+ 'extra' => { 'password' => 'hello' },
60
+ 'headers' => { 'password' => 'hello' }
61
+ }
62
+ }
63
+
64
+ filter = Opbeat::Filter.new
65
+ result = filter.process_event_hash(data)
66
+
67
+ expect(result).to eq(data)
68
+ end
69
+
70
+ it 'should be configurable' do
71
+ data = {
72
+ 'http' => {
73
+ 'data' => {
74
+ 'foo' => 'secret',
75
+ 'bar' => 'secret',
76
+ '-baz-' => 'secret',
77
+ 'password' => 'public',
78
+ 'the_secret' => 'public',
79
+ 'a_password_here' => 'public',
80
+ 'mypasswd' => 'public'
81
+ },
82
+ 'query_string' => 'foo=secret&password=public',
83
+ 'cookies' => 'foo=secret;password=public'
84
+ }
85
+ }
86
+
87
+ filter = Opbeat::Filter.new [:foo, 'bar', /baz/]
88
+ result = filter.process_event_hash(data)
89
+
90
+ vars = result["http"]["data"]
91
+ expect(vars["foo"]).to eq(Opbeat::Filter::MASK)
92
+ expect(vars["bar"]).to eq(Opbeat::Filter::MASK)
93
+ expect(vars["-baz-"]).to eq(Opbeat::Filter::MASK)
94
+ expect(vars["password"]).to eq("public")
95
+ expect(vars["the_secret"]).to eq("public")
96
+ expect(vars["a_password_here"]).to eq("public")
97
+ expect(vars["mypasswd"]).to eq("public")
98
+ expect(result["http"]["query_string"]).to eq('foo=' + Opbeat::Filter::MASK + '&password=public')
99
+ expect(result["http"]["cookies"]).to eq('foo=' + Opbeat::Filter::MASK + ';password=public')
100
+ end
101
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opbeat
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Watson Steen
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2015-02-03 00:00:00.000000000 Z
13
+ date: 2015-03-05 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: faraday
@@ -164,6 +164,7 @@ files:
164
164
  - lib/opbeat/configuration.rb
165
165
  - lib/opbeat/error.rb
166
166
  - lib/opbeat/event.rb
167
+ - lib/opbeat/filter.rb
167
168
  - lib/opbeat/integrations/delayed_job.rb
168
169
  - lib/opbeat/integrations/resque.rb
169
170
  - lib/opbeat/integrations/sidekiq.rb
@@ -174,8 +175,6 @@ files:
174
175
  - lib/opbeat/interfaces/stack_trace.rb
175
176
  - lib/opbeat/linecache.rb
176
177
  - lib/opbeat/logger.rb
177
- - lib/opbeat/processor.rb
178
- - lib/opbeat/processors/sanitizedata.rb
179
178
  - lib/opbeat/rack.rb
180
179
  - lib/opbeat/rails/middleware/debug_exceptions_catcher.rb
181
180
  - lib/opbeat/railtie.rb
@@ -186,11 +185,11 @@ files:
186
185
  - spec/opbeat/client_spec.rb
187
186
  - spec/opbeat/configuration_spec.rb
188
187
  - spec/opbeat/event_spec.rb
188
+ - spec/opbeat/filter_spec.rb
189
189
  - spec/opbeat/integrations/delayed_job_spec.rb
190
190
  - spec/opbeat/logger_spec.rb
191
191
  - spec/opbeat/opbeat_spec.rb
192
192
  - spec/opbeat/rack_spec.rb
193
- - spec/opbeat/sanitizedata_processor_spec.rb
194
193
  - spec/spec_helper.rb
195
194
  homepage: https://github.com/opbeat/opbeat_ruby
196
195
  licenses:
@@ -1,15 +0,0 @@
1
- module Opbeat
2
-
3
- module Processor
4
- class Processor
5
- def initialize(client)
6
- @client = client
7
- end
8
-
9
- def process(data)
10
- data
11
- end
12
- end
13
- end
14
-
15
- end
@@ -1,43 +0,0 @@
1
- require 'opbeat/processor'
2
-
3
- module Opbeat
4
- module Processor
5
- class SanitizeData < Processor
6
-
7
- MASK = '********'
8
- FIELDS_RE = /(authorization|password|passwd|secret)/i
9
- VALUES_RE = /^\d{16}$/
10
-
11
- def apply(value, key=nil, &block)
12
- if value.is_a?(Hash)
13
- value.each.inject({}) do |memo, (k, v)|
14
- memo[k] = apply(v, k, &block)
15
- memo
16
- end
17
- elsif value.is_a?(Array)
18
- value.map do |value|
19
- apply(value, key, &block)
20
- end
21
- else
22
- block.call(key, value)
23
- end
24
- end
25
-
26
- def sanitize(key, value)
27
- if !value.is_a?(String) || value.empty?
28
- value
29
- elsif VALUES_RE.match(value) or FIELDS_RE.match(key)
30
- MASK
31
- else
32
- value
33
- end
34
- end
35
-
36
- def process(data)
37
- apply(data) do |key, value|
38
- sanitize(key, value)
39
- end
40
- end
41
- end
42
- end
43
- end
@@ -1,42 +0,0 @@
1
- require File::expand_path('../../spec_helper', __FILE__)
2
- require 'opbeat/processors/sanitizedata'
3
-
4
- describe Opbeat::Processor::SanitizeData do
5
- before do
6
- @client = double("client")
7
- @processor = Opbeat::Processor::SanitizeData.new(@client)
8
- end
9
-
10
- it 'should filter http data' do
11
- data = {
12
- 'http' => {
13
- 'data' => {
14
- 'foo' => 'bar',
15
- 'password' => 'hello',
16
- 'the_secret' => 'hello',
17
- 'a_password_here' => 'hello',
18
- 'mypasswd' => 'hello',
19
- }
20
- }
21
- }
22
-
23
- result = @processor.process(data)
24
-
25
- vars = result["http"]["data"]
26
- expect(vars["foo"]).to eq("bar")
27
- expect(vars["password"]).to eq(Opbeat::Processor::SanitizeData::MASK)
28
- expect(vars["the_secret"]).to eq(Opbeat::Processor::SanitizeData::MASK)
29
- expect(vars["a_password_here"]).to eq(Opbeat::Processor::SanitizeData::MASK)
30
- expect(vars["mypasswd"]).to eq(Opbeat::Processor::SanitizeData::MASK)
31
- end
32
-
33
- it 'should filter credit card values' do
34
- data = {
35
- 'ccnumba' => '4242424242424242'
36
- }
37
-
38
- result = @processor.process(data)
39
- expect(result["ccnumba"]).to eq(Opbeat::Processor::SanitizeData::MASK)
40
- end
41
-
42
- end