opbeat 1.1.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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