health_check 2.4.0 → 2.5.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: 80358069f525f51e0fc2751abe438c1d724fb3a0
4
- data.tar.gz: 37280de5cb5c4ef5b713069321d5ad82fb0aa0ed
3
+ metadata.gz: 4b5a934dfee4618efc3d217163112b251e926879
4
+ data.tar.gz: 811fdba5dd439ef0016ca94c8c2b0b6dbac19a99
5
5
  SHA512:
6
- metadata.gz: b5381bdf60fa524ca2bdd072655b83e036938b0a4d325183af6431366b77f34121b8b12ace9e7404e921248a84fc347caf549208b8062001ad10f38916ff127a
7
- data.tar.gz: 82da4951b07dd4e420c570a9469ff722fa2c726b5f9d9f2961df4830abbe02e71085c18dda5449d0c0f800f3f43d029d781a05bd28d30ededef039b4059264e5
6
+ metadata.gz: fd09549905a225cc3c25a02f295335dcb013cb565c52095d4b87e1fb4e74552d4231637d7a4e9b7698c28f896103cf529cd1aefbbf1089dfb1b161c650ca11da
7
+ data.tar.gz: 44fc64d17c2722c5bd3841d65dabf2bc5f55b0a61b01a862484ea79f4b64ebe29d4300667b5c6f572eb50f5c90c8be59bcb783517721c2de18e3bbdc54929f42
data/CHANGELOG CHANGED
@@ -1,5 +1,16 @@
1
1
  = Change Log =
2
2
 
3
+ * 2.5.0
4
+ * Added whitelist for IP# (Thanks Fernando Alvarez)
5
+ * reworked whitelist PR
6
+ * Expanded tests for whitelist and basic authentication
7
+ * reworked middleware, simplified error codes, added whitelist and basic authentication into middleware
8
+ * Removed unit tests as they where aonly applicable under rails 2.3 when installed in vendor/plugins
9
+ * #55 by mnoack - correct binstubs arg in test
10
+ * #54 by gkop - Lograge config snippet works with Rails 4.2.7.1, lograge 0.4.1
11
+ * Used ideas from #52 - use middleware to catch Rails stack exceptions
12
+ * #51 by tokenshift - Fixing NameError on `basic_auth_username`.
13
+ * Changes to address #50 by fillphafftek - allow standard check to be run from middleware if configured to do so, removed requirement for "middleware" to be passed in url for middleware tests
3
14
  * 2.4.0
4
15
  * Added tests for middleware
5
16
  * Changed contributed middleware code to conform to existing url scheme
@@ -76,7 +76,7 @@ To change the configuration of health_check, create a file `config/initializers/
76
76
 
77
77
  HealthCheck.setup do |config|
78
78
 
79
- # uri prefix
79
+ # uri prefix (no leading slash)
80
80
  config.uri = 'health_check'
81
81
 
82
82
  # Text output upon success
@@ -124,6 +124,13 @@ To change the configuration of health_check, create a file `config/initializers/
124
124
  # These default to nil and the endpoint is not protected
125
125
  config.basic_auth_username = 'my_username'
126
126
  config.basic_auth_password = 'my_password'
127
+
128
+ # Whitelist requesting IPs
129
+ # Defaults to blank and allows any IP
130
+ config.origin_ip_whitelist = %w(123.123.123.123)
131
+
132
+ # http status code used when the ip is not allowed for the request
133
+ config.http_status_for_ip_whitelist_error = 403
127
134
  end
128
135
 
129
136
  You may call add_custom_check multiple times with different tests. These tests will be included in the default list ("standard").
@@ -133,15 +140,21 @@ If you have a catchall route then add the following line above the catch all rou
133
140
 
134
141
  === Installing As Middleware
135
142
 
136
- Install health_check as middleware if you want to ignore exceptions from later parts of the Rails middleware stack,
137
- eg DB connection errors from QueryCache. Include "middleware" in the list of checks to have the checks processed by the middleware
138
- health check rather than the full stack check. The "middleware" check will fail if you have not installed health_check as middleware.
143
+ Install health_check as middleware if you want to sometimes ignore exceptions from later parts of the Rails middleware stack,
144
+ eg DB connection errors from QueryCache. The "middleware" check will fail if you have not installed health_check as middleware.
139
145
 
140
146
  To install health_check as middleware add the following line to the config/application.rb:
141
147
  config.middleware.insert_after "Rails::Rack::Logger", HealthCheck::MiddlewareHealthcheck
142
148
 
143
149
  Note: health_check is installed as a full rails engine even if it has been installed as middleware. This is so the
144
- standard checks continue to test the complete rails stack.
150
+ remaining checks continue to run through the complete rails stack.
151
+
152
+ You can also adjust what checks are run from middleware, eg if you want to exclude the checking of the database etc, then set
153
+ config.middleware_checks = ['middleware', 'standard', 'custom']
154
+ config.standard_checks = ['middleware', 'custom']
155
+
156
+ Middleware checks are run first, and then full stack checks.
157
+ When installed as middleware, exceptions thrown when running the full stack tests are formatted in the standard way.
145
158
 
146
159
  == Uptime Monitoring
147
160
 
@@ -200,7 +213,7 @@ It is recomended that you use silencer, lograge or one of the other log filterin
200
213
 
201
214
  For example, with lograge use the following to exclude health_check from being logged:
202
215
 
203
- config.lograge.ignore_actions = ["health_check/health_check#index"]
216
+ config.lograge.ignore_actions = ["HealthCheck::HealthCheckController#index"]
204
217
 
205
218
  Likewise you will probably want to exclude health_check from monitoring systems like newrelic.
206
219
 
@@ -277,7 +290,7 @@ The command `rake test` will also launch these tests, except it cannot install t
277
290
 
278
291
  == Copyright
279
292
 
280
- Copyright (c) 2010-2014 Ian Heggie, released under the MIT license.
293
+ Copyright (c) 2010-2016 Ian Heggie, released under the MIT license.
281
294
  See MIT-LICENSE for details.
282
295
 
283
296
  == Contributors
data/Rakefile CHANGED
@@ -3,38 +3,9 @@ require "bundler/gem_tasks"
3
3
  #require 'rubygems'
4
4
  require 'rake'
5
5
 
6
- # Tests are conducted with health_test as a plugin
7
- environment_file = File.join(File.dirname(__FILE__), '..', '..', '..', 'config', 'environment.rb')
8
- plugin_dir = File.join(File.dirname(__FILE__), '..', 'plugins')
9
-
10
- if File.exists?(environment_file) and File.directory?(plugin_dir)
11
- # test as plugin
12
-
13
- require 'rake/testtask'
14
- Rake::TestTask.new(:test) do |test|
15
- test.libs << 'lib' << 'test'
16
- test.pattern = 'test/**/*_test.rb'
17
- test.verbose = true
18
- end
19
-
20
- begin
21
- require 'rcov/rcovtask'
22
- Rcov::RcovTask.new do |test|
23
- test.libs << 'test'
24
- test.pattern = 'test/**/*_test.rb'
25
- test.verbose = true
26
- end
27
- rescue LoadError
28
- task :rcov do
29
- abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
30
- end
31
- end
32
-
33
- else
34
- #tests as gem
35
- task :test do
36
- exec '/bin/bash', './test/test_with_railsapp'
37
- end
6
+ #tests as gem
7
+ task :test do
8
+ exec '/bin/bash', './test/test_with_railsapp'
38
9
  end
39
10
 
40
11
  task :default => :test
@@ -23,6 +23,14 @@ module HealthCheck
23
23
  mattr_accessor :http_status_for_error_object
24
24
  self.http_status_for_error_object = 500
25
25
 
26
+ # http status code used when the ip is not allowed for the request
27
+ mattr_accessor :http_status_for_ip_whitelist_error
28
+ self.http_status_for_ip_whitelist_error = 403
29
+
30
+ # ips allowed to perform requests
31
+ mattr_accessor :origin_ip_whitelist
32
+ self.origin_ip_whitelist = []
33
+
26
34
  # max-age of response in seconds
27
35
  # cache-control is public when max_age > 1 and basic authentication is used
28
36
  mattr_accessor :max_age
@@ -32,7 +40,7 @@ module HealthCheck
32
40
  mattr_accessor :buckets
33
41
  self.buckets = {}
34
42
 
35
- # health check uri path for middleware check
43
+ # health check uri path
36
44
  mattr_accessor :uri
37
45
  self.uri = 'health_check'
38
46
 
@@ -49,6 +57,12 @@ module HealthCheck
49
57
  self.full_checks = ['database', 'migrations', 'custom', 'email', 'cache', 'redis-if-present', 'sidekiq-redis-if-present', 'resque-redis-if-present', 's3-if-present']
50
58
  self.standard_checks = [ 'database', 'migrations', 'custom', 'emailconf' ]
51
59
 
60
+ # Middleware based checks
61
+ mattr_accessor :middleware_checks
62
+ self.middleware_checks = [ 'middleware' ]
63
+
64
+ mattr_accessor :installed_as_middleware
65
+
52
66
  def self.add_custom_check(&block)
53
67
  custom_checks << block
54
68
  end
@@ -5,6 +5,7 @@ module HealthCheck
5
5
  class HealthCheckController < ActionController::Base
6
6
 
7
7
  layout false if self.respond_to? :layout
8
+ before_action :check_origin_ip
8
9
  before_action :authenticate
9
10
 
10
11
  def index
@@ -13,34 +14,21 @@ module HealthCheck
13
14
  if max_age > 1
14
15
  last_modified = Time.at((last_modified.to_f / max_age).floor * max_age).utc
15
16
  end
16
- public = (max_age > 1) && ! basic_auth_username
17
+ public = (max_age > 1) && ! HealthCheck.basic_auth_username
17
18
  if stale?(:last_modified => last_modified, :public => public)
18
- # Rails 4.0 doesn't have :plain, but it is deprecated later on
19
- plain_key = Rails.version < '4.1' ? :text : :plain
20
- checks = params[:checks] || 'standard'
19
+ checks = params[:checks] ? params[:checks].split('_') : ['standard']
20
+ checks -= HealthCheck.middleware_checks if HealthCheck.installed_as_middleware
21
21
  begin
22
22
  errors = HealthCheck::Utils.process_checks(checks)
23
23
  rescue Exception => e
24
24
  errors = e.message.blank? ? e.class.to_s : e.message.to_s
25
- end
25
+ end
26
26
  response.headers['Cache-control'] = (public ? 'public' : 'private') + ', no-cache, must-revalidate' + (max_age > 0 ? ", max-age=#{max_age}" : '')
27
27
  if errors.blank?
28
- obj = { :healthy => true, :message => HealthCheck.success }
29
- respond_to do |format|
30
- format.html { render plain_key => HealthCheck.success, :content_type => 'text/plain' }
31
- format.json { render :json => obj }
32
- format.xml { render :xml => obj }
33
- format.any { render plain_key => HealthCheck.success, :content_type => 'text/plain' }
34
- end
28
+ send_response nil, :ok, :ok
35
29
  else
36
30
  msg = "health_check failed: #{errors}"
37
- obj = { :healthy => false, :message => msg }
38
- respond_to do |format|
39
- format.html { render plain_key => msg, :status => HealthCheck.http_status_for_error_text, :content_type => 'text/plain' }
40
- format.json { render :json => obj, :status => HealthCheck.http_status_for_error_object}
41
- format.xml { render :xml => obj, :status => HealthCheck.http_status_for_error_object }
42
- format.any { render plain_key => msg, :status => HealthCheck.http_status_for_error_text, :content_type => 'text/plain' }
43
- end
31
+ send_response msg, HealthCheck.http_status_for_error_text, HealthCheck.http_status_for_error_object
44
32
  # Log a single line as some uptime checkers only record that it failed, not the text returned
45
33
  if logger
46
34
  logger.info msg
@@ -49,20 +37,44 @@ module HealthCheck
49
37
  end
50
38
  end
51
39
 
52
-
53
40
  protected
54
41
 
42
+ def send_response(msg, text_status, obj_status)
43
+ healthy = !msg
44
+ msg ||= HealthCheck.success
45
+ obj = { :healthy => healthy, :message => msg}
46
+ respond_to do |format|
47
+ format.html { render plain_key => msg, :status => text_status, :content_type => 'text/plain' }
48
+ format.json { render :json => obj, :status => obj_status }
49
+ format.xml { render :xml => obj, :status => obj_status }
50
+ format.any { render plain_key => msg, :status => text_status, :content_type => 'text/plain' }
51
+ end
52
+ end
53
+
55
54
  def authenticate
56
55
  return unless HealthCheck.basic_auth_username && HealthCheck.basic_auth_password
57
- authenticate_or_request_with_http_basic do |username, password|
56
+ authenticate_or_request_with_http_basic('Health Check') do |username, password|
58
57
  username == HealthCheck.basic_auth_username && password == HealthCheck.basic_auth_password
59
58
  end
60
59
  end
61
60
 
61
+ def check_origin_ip
62
+ unless HealthCheck.origin_ip_whitelist.blank? ||
63
+ HealthCheck.origin_ip_whitelist.include?(request.ip)
64
+ render plain_key => 'Health check is not allowed for the requesting IP',
65
+ :status => HealthCheck.http_status_for_ip_whitelist_error,
66
+ :content_type => 'text/plain'
67
+ end
68
+ end
69
+
62
70
  # turn cookies for CSRF off
63
71
  def protect_against_forgery?
64
72
  false
65
73
  end
66
74
 
75
+ def plain_key
76
+ # Rails 4.0 doesn't have :plain, but it is deprecated later on
77
+ Rails.version < '4.1' ? :text : :plain
78
+ end
67
79
  end
68
80
  end
@@ -8,7 +8,7 @@ module ActionDispatch::Routing
8
8
 
9
9
  def add_health_check_routes(prefix = nil)
10
10
  HealthCheck.uri = prefix if prefix
11
- match "#{HealthCheck.uri}(/:checks)(.:format)", :to => 'health_check/health_check#index', via: [:get, :post]
11
+ match "#{HealthCheck.uri}(/:checks)(.:format)", :to => 'health_check/health_check#index', via: [:get, :post], :defaults => { :format => 'txt' }
12
12
  end
13
13
 
14
14
  end
@@ -6,13 +6,20 @@ module HealthCheck
6
6
  end
7
7
 
8
8
  def call(env)
9
- uri = env['PATH_INFO']
10
- if uri =~ /^\/?#{HealthCheck.uri}\/([-_0-9a-zA-Z]*)middleware_?([-_0-9a-zA-Z]*)(\.(\w*))?/
11
- checks = $1 + ($1 != '' && $2 != '' ? '_' : '') + $2
12
- checks = 'standard' if checks == ''
13
- response_type = $4
9
+ (response_type, middleware_checks, full_stack_checks) = parse_env(env)
10
+ if response_type
11
+ if error_response = (ip_blocked(env) || not_authenticated(env))
12
+ return error_response
13
+ end
14
+ HealthCheck.installed_as_middleware = true
15
+ errors = ''
14
16
  begin
15
- errors = HealthCheck::Utils.process_checks(checks)
17
+ # Process the checks to be run from middleware
18
+ errors = HealthCheck::Utils.process_checks(middleware_checks, true)
19
+ # Process remaining checks through the full stack if there are any
20
+ unless full_stack_checks.empty?
21
+ return @app.call(env)
22
+ end
16
23
  rescue => e
17
24
  errors = e.message.blank? ? e.class.to_s : e.message.to_s
18
25
  end
@@ -21,17 +28,75 @@ module HealthCheck
21
28
  if response_type == 'xml'
22
29
  content_type = 'text/xml'
23
30
  msg = { healthy: healthy, message: msg }.to_xml
31
+ error_code = HealthCheck.http_status_for_error_object
24
32
  elsif response_type == 'json'
25
33
  content_type = 'application/json'
26
34
  msg = { healthy: healthy, message: msg }.to_json
35
+ error_code = HealthCheck.http_status_for_error_object
27
36
  else
28
37
  content_type = 'text/plain'
38
+ error_code = HealthCheck.http_status_for_error_text
29
39
  end
30
- [ (healthy ? 200 : 500), { 'Content-Type' => content_type }, [msg] ]
40
+ [ (healthy ? 200 : error_code), { 'Content-Type' => content_type }, [msg] ]
31
41
  else
32
42
  @app.call(env)
33
43
  end
34
44
  end
35
45
 
46
+ protected
47
+
48
+ def parse_env(env)
49
+ uri = env['PATH_INFO']
50
+ if uri =~ /^\/#{Regexp.escape HealthCheck.uri}(\/([-_0-9a-zA-Z]*))?(\.(\w*))?$/
51
+ checks = $2.to_s == '' ? ['standard'] : $2.split('_')
52
+ response_type = $4.to_s
53
+ middleware_checks = checks & HealthCheck.middleware_checks
54
+ full_stack_checks = (checks - HealthCheck.middleware_checks) - ['and']
55
+ [response_type, middleware_checks, full_stack_checks ]
56
+ end
57
+ end
58
+
59
+ def ip_blocked(env)
60
+ return false if HealthCheck.origin_ip_whitelist.blank?
61
+ req = Rack::Request.new(env)
62
+ unless HealthCheck.origin_ip_whitelist.include?(req.ip)
63
+ [ HealthCheck.http_status_for_ip_whitelist_error,
64
+ { 'Content-Type' => 'text/plain' },
65
+ [ 'Health check is not allowed for the requesting IP' ]
66
+ ]
67
+ end
68
+ end
69
+
70
+ def not_authenticated(env)
71
+ return false unless HealthCheck.basic_auth_username && HealthCheck.basic_auth_password
72
+ auth = MiddlewareHealthcheck::Request.new(env)
73
+ if auth.provided? && auth.basic? && Rack::Utils.secure_compare(HealthCheck.basic_auth_username, auth.username) && Rack::Utils.secure_compare(HealthCheck.basic_auth_password, auth.password)
74
+ env['REMOTE_USER'] = auth.username
75
+ return false
76
+ end
77
+ [ 401,
78
+ { 'Content-Type' => 'text/plain', 'WWW-Authenticate' => 'Basic realm="Health Check"' },
79
+ [ ]
80
+ ]
81
+ end
82
+
83
+ class Request < Rack::Auth::AbstractRequest
84
+ def basic?
85
+ "basic" == scheme
86
+ end
87
+
88
+ def credentials
89
+ @credentials ||= params.unpack("m*").first.split(/:/, 2)
90
+ end
91
+
92
+ def username
93
+ credentials.first
94
+ end
95
+
96
+ def password
97
+ credentials.last
98
+ end
99
+ end
100
+
36
101
  end
37
102
  end
@@ -17,9 +17,10 @@ module HealthCheck
17
17
 
18
18
  cattr_accessor :default_smtp_settings
19
19
 
20
- def self.process_checks(checks)
20
+ # process an array containing a list of checks
21
+ def self.process_checks(checks, called_from_middleware = false)
21
22
  errors = ''
22
- checks.split('_').each do |check|
23
+ checks.each do |check|
23
24
  case check
24
25
  when 'and', 'site'
25
26
  # do nothing
@@ -63,15 +64,17 @@ module HealthCheck
63
64
  when 's3'
64
65
  errors << HealthCheck::S3HealthCheck.check
65
66
  when "standard"
66
- errors << HealthCheck::Utils.process_checks(HealthCheck.standard_checks.join('_'))
67
+ errors << HealthCheck::Utils.process_checks(HealthCheck.standard_checks, called_from_middleware)
68
+ when "middleware"
69
+ errors << "Health check not called from middleware - probably not installed as middleware." unless called_from_middleware
67
70
  when "custom"
68
71
  HealthCheck.custom_checks.each do |custom_check|
69
72
  errors << custom_check.call(self)
70
73
  end
71
74
  when "all", "full"
72
- errors << HealthCheck::Utils.process_checks(HealthCheck.full_checks.join('_'))
75
+ errors << HealthCheck::Utils.process_checks(HealthCheck.full_checks, called_from_middleware)
73
76
  else
74
- return "invalid argument to health_test. "
77
+ return "invalid argument to health_test."
75
78
  end
76
79
  end
77
80
  return errors
@@ -1,3 +1,3 @@
1
1
  module HealthCheck
2
- VERSION = "2.4.0"
2
+ VERSION = "2.5.0"
3
3
  end
@@ -70,16 +70,16 @@ rake="$base_dir/test/bin/rake"
70
70
 
71
71
  echo Checking $rails is present ...
72
72
  [ -f $rails -a -f $rake ] || bundle exec rake rails:update:bin || echo '(ignored rake rails:update:bin exit status)'
73
- [ -f $rails ] || bundle binstub railties || echo '(ignored bundle exit status)'
74
- [ -f $rails ] || bundle binstub rails || echo '(ignored bundle exit status)'
73
+ [ -f $rails ] || bundle binstubs railties || echo '(ignored bundle exit status)'
74
+ [ -f $rails ] || bundle binstubs rails || echo '(ignored bundle exit status)'
75
75
  if [ ! -f $rails ]; then
76
76
  echo "Test aborted (unable to create $rails)"
77
77
  exit 2
78
78
  fi
79
79
 
80
80
  if [ ! -f $rake ]; then
81
- echo "Running bundle --binstub rake ..."
82
- if ! bundle --binstub rake || [ ! -f $rake ]; then
81
+ echo "Running bundle binstubs rake ..."
82
+ if ! bundle binstubs rake || [ ! -f $rake ]; then
83
83
  echo "Test aborted (unable to create $rake)"
84
84
  exit 2
85
85
  fi
@@ -168,6 +168,9 @@ HealthCheck.setup do |config|
168
168
  config.http_status_for_error_text = 550
169
169
  config.http_status_for_error_object = 555
170
170
  config.uri = '$route_prefix'
171
+ config.origin_ip_whitelist = ENV['IP_WHITELIST'].split(',') unless ENV['IP_WHITELIST'].blank?
172
+ config.basic_auth_username = ENV['AUTH_USER'] unless ENV['AUTH_USER'].blank?
173
+ config.basic_auth_password = ENV['AUTH_PASSWORD'] unless ENV['AUTH_PASSWORD'].blank?
171
174
 
172
175
  config.add_custom_check do
173
176
  File.exists?("$custom_file") ? '' : '$custom_file is missing!'
@@ -208,15 +211,15 @@ then
208
211
 
209
212
  echo Checking $rails is present ...
210
213
  [ -f $rails -a -f $rake ] || bundle exec rake rails:update:bin || echo '(ignored rake rails:update:bin exit status)'
211
- [ -f $rails ] || bundle binstub railties || echo '(ignored bundle exit status)'
212
- [ -f $rails ] || bundle binstub rails || echo '(ignored bundle exit status)'
214
+ [ -f $rails ] || bundle binstubs railties || echo '(ignored bundle exit status)'
215
+ [ -f $rails ] || bundle binstubs rails || echo '(ignored bundle exit status)'
213
216
  if [ ! -f $rails ]; then
214
217
  echo "Test aborted (unable to create $rails)"
215
218
  exit 2
216
219
  fi
217
220
 
218
221
  echo Checking $rake is present ...
219
- [ -f $rake ] || bundle binstub rake || echo '(ignored bundle exit status)'
222
+ [ -f $rake ] || bundle binstubs rake || echo '(ignored bundle exit status)'
220
223
  if [ ! -f $rake ]; then
221
224
  echo "Test aborted (unable to create $rake)"
222
225
  exit 2
@@ -141,24 +141,33 @@ stop_server()
141
141
  [0-9]*)
142
142
  echo ========================================================
143
143
  echo "Killing rails server [pid: $server_pid]"
144
- kill -1 $server_pid || true
145
- [ ! -x bin/spring ] || bin/spring stop || true
146
- sleep 2
147
- kill -9 $server_pid || true
144
+ kill -QUIT $server_pid || echo server has already exited ..
145
+ if [ -x bin/spring ] ; then
146
+ echo Stopping spring ...
147
+ bin/spring stop || echo spring had already exited ..
148
+ fi
149
+ sleep 1
150
+ kill -9 $server_pid || echo server had already exited ...
151
+ sleep 1
152
+ # needed for unicorn - it doesn't die when it is supposed to
153
+ killall "$server_arg" || echo server and child processes had already stopped ...
148
154
  ;;
149
155
  esac
150
156
  case "$fake_smtp_pid" in
151
157
  [0-9]*)
152
158
  echo ========================================================
153
159
  echo "Killing fake smtp server [pid: $fake_smtp_pid]"
154
- kill -1 $fake_smtp_pid || true
160
+ kill -QUIT $fake_smtp_pid || echo fake_smtp had already exited ..
155
161
  sleep 2
156
- kill -9 $fake_smtp_pid || true
162
+ kill -9 $fake_smtp_pid || echo fake_smtp had already exited ..
157
163
  ;;
158
164
  esac
159
165
  server_pid=''
160
166
  fake_smtp_pid=''
167
+ ps -f
168
+ echo Waiting for sub processes to complete ...
161
169
  wait
170
+ echo Finished waiting for sub processes, sleeping 2 seconds ...
162
171
  sleep 2
163
172
  }
164
173
 
@@ -188,7 +197,9 @@ finish()
188
197
  stop_server
189
198
  trap "" 0
190
199
  echo ========================================================
191
- echo TEST ${1:-FAILED}
200
+ ps uxf || echo ps failed
201
+ echo ========================================================
202
+ echo TEST ${1:-FAILED}, exiting with status ${2:-2}
192
203
  echo ========================================================
193
204
  exit ${2:-2}
194
205
  }
@@ -476,22 +487,114 @@ common_tests()
476
487
  date > $custom_file
477
488
  }
478
489
 
479
-
480
490
  # required for rails 4.1+ in production mode
481
491
  export SECRET_KEY_BASE=cf2f49c38a3fe67416ddf680f4f3187c0fce7dd1b9b117b34d195df75b274e08a04877e23803b2fdf1aa9a655269d94bc4888aa325cf7e721cc47368cfe56a80
482
492
 
483
493
  # required for rails 5 to server static files
484
494
  export RAILS_SERVE_STATIC_FILES=on
485
495
 
496
+ export IP_WHITELIST='123.123.123.123'
497
+ unset AUTH_USER
498
+ unset AUTH_PASSWORD
499
+
486
500
  case "$run_test" in
487
- ???)
501
+ ''|[12])
502
+ echo ========================================================
503
+ echo TESTING whitelist ban WITHOUT CATCHALL in test env
504
+ echo ========================================================
505
+ export RAILS_ENV=test RACK_ENV=test
506
+
507
+ start_server
508
+
509
+ echo '1: TESTING controller prohibited by ip...'
510
+ expected_status=403
511
+ $testurl ${host}/${route_prefix}/site $expected_status
512
+
513
+ if $has_middleware; then
514
+ echo
515
+ echo '2: TESTING middleware prohibited by ip...'
516
+ expected_status=403
517
+ $testurl ${host}/${route_prefix}/middleware $expected_status
518
+ fi
488
519
  ;;
489
- *)
520
+ esac
521
+
522
+ export IP_WHITELIST=''
523
+ export AUTH_USER='someone'
524
+ export AUTH_PASSWORD='secret'
525
+
526
+ case "$run_test" in
527
+ ''|[3456789]|10)
490
528
  echo ========================================================
491
- echo TESTING WITHOUT CATCHALL in test env
529
+ echo TESTING basic auth, no whitelist WITHOUT CATCHALL in test env
492
530
  echo ========================================================
493
531
  export RAILS_ENV=test RACK_ENV=test
494
532
 
533
+ case "$run_trest" in
534
+ '')
535
+ stop_server
536
+ cleanup_db
537
+ ;;
538
+ esac
539
+
540
+ start_server
541
+
542
+ expected_status=401
543
+ echo '3: TESTING controller without authentication insists on authentication ...'
544
+ AUTH_USER= $testurl ${host}/${route_prefix}/site $expected_status
545
+
546
+ echo '4: TESTING controller with wrong password insists on authentication ...'
547
+ AUTH_PASSWORD=wrong $testurl ${host}/${route_prefix}/site $expected_status
548
+
549
+ echo '5: TESTING controller with wrong user insists on authentication ...'
550
+ AUTH_USER=wrong $testurl ${host}/${route_prefix}/site $expected_status
551
+
552
+ echo '6: TESTING controller with authentication works ...'
553
+ expected_status=200
554
+ $testurl ${host}/${route_prefix}/site $expected_status
555
+
556
+ if $has_middleware; then
557
+ echo
558
+ echo '7: TESTING middleware without authentication insists on authentication ...'
559
+ expected_status=401
560
+ AUTH_USER= $testurl ${host}/${route_prefix}/middleware $expected_status
561
+
562
+ echo
563
+ echo '8: TESTING middleware with wrong password insists on authentication ...'
564
+ AUTH_PASSWORD=wrong $testurl ${host}/${route_prefix}/middleware $expected_status
565
+
566
+ echo
567
+ echo '9: TESTING middleware with wrong user insists on authentication ...'
568
+ AUTH_USER=wrong $testurl ${host}/${route_prefix}/middleware $expected_status
569
+
570
+ echo
571
+ echo '10: TESTING middleware with authentication works ...'
572
+ expected_status=200
573
+ $testurl ${host}/${route_prefix}/middleware $expected_status
574
+ else
575
+ echo
576
+ echo "Skipped middleware tests as it is not configured..."
577
+ fi
578
+ ;;
579
+ esac
580
+
581
+ unset AUTH_USER
582
+ unset AUTH_PASSWORD
583
+
584
+ case "$run_test" in
585
+ ''|1??)
586
+ echo ========================================================
587
+ echo TESTING WITHOUT CATCHALL, no whitelist or user in test env
588
+ echo ========================================================
589
+ export RAILS_ENV=test RACK_ENV=test
590
+
591
+ case "$run_trest" in
592
+ '')
593
+ stop_server
594
+ cleanup_db
595
+ ;;
596
+ esac
597
+
495
598
  start_server
496
599
 
497
600
  # get a static file
@@ -505,15 +608,18 @@ case "$run_test" in
505
608
  expected_status=404,500,502
506
609
  $testurl ${host}/health_check/site $expected_status
507
610
 
508
- common_tests 1
611
+ common_tests 100
509
612
  ;;
510
613
  esac
511
614
 
615
+ export IP_WHITELIST='127.0.0.1'
616
+ export AUTH_USER='someone'
617
+ export AUTH_PASSWORD='secret'
512
618
 
513
619
  case "$run_test" in
514
- ''|???)
620
+ ''|2??)
515
621
  echo ========================================================
516
- echo TESTING WITH CATCHALL in ${RAILS_ENV2:-production} env
622
+ echo TESTING WITH CATCHALL with whitelist and user in ${RAILS_ENV2:-production} env
517
623
  echo ========================================================
518
624
  export RAILS_ENV=${RAILS_ENV2:-production} RACK_ENV=${RAILS_ENV2:-production}
519
625
 
@@ -533,7 +639,7 @@ case "$run_test" in
533
639
  $testurl ${host}/another/url 200 text/html 'catch all route'
534
640
  echo
535
641
 
536
- common_tests 101
642
+ common_tests 200
537
643
  ;;
538
644
  esac
539
645
 
@@ -542,4 +648,4 @@ rm -f $catchall_file
542
648
  finish PASSED 0
543
649
  exit 0
544
650
 
545
- # vi: sw=4 ai sm:
651
+ # vi: sw=4 ai sm:
@@ -3,7 +3,11 @@ require 'net/http'
3
3
  require 'uri'
4
4
 
5
5
  def open(url)
6
- Net::HTTP.get_response(URI.parse(url))
6
+ parsed_uri = URI.parse(url)
7
+ http = Net::HTTP.new(parsed_uri.host, parsed_uri.port)
8
+ req = Net::HTTP::Get.new(parsed_uri.request_uri)
9
+ req.basic_auth(ENV['AUTH_USER'], ENV['AUTH_PASSWORD'].to_s) if ENV['AUTH_USER']
10
+ http.request(req)
7
11
  end
8
12
 
9
13
  response = open(ARGV[0]) rescue nil
@@ -11,6 +15,7 @@ unless response
11
15
  i=0
12
16
  print "waiting.."
13
17
  while i < 120 and not response
18
+ #puts 'RESPONSE:', response.inspect
14
19
  print "."
15
20
  STDOUT.flush
16
21
  i += 1
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: health_check
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 2.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ian Heggie
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-10-10 00:00:00.000000000 Z
11
+ date: 2016-12-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -110,11 +110,8 @@ files:
110
110
  - test/rails_5.0.gemfile
111
111
  - test/rails_edge.gemfile
112
112
  - test/setup_railsapp
113
- - test/test_helper.rb
114
113
  - test/test_with_railsapp
115
114
  - test/testurl
116
- - test/unit/health_check_controller_test.rb
117
- - test/unit/routes_test.rb
118
115
  homepage: https://github.com/ianheggie/health_check
119
116
  licenses: []
120
117
  metadata: {}
@@ -153,8 +150,5 @@ test_files:
153
150
  - test/rails_5.0.gemfile
154
151
  - test/rails_edge.gemfile
155
152
  - test/setup_railsapp
156
- - test/test_helper.rb
157
153
  - test/test_with_railsapp
158
154
  - test/testurl
159
- - test/unit/health_check_controller_test.rb
160
- - test/unit/routes_test.rb
@@ -1,68 +0,0 @@
1
- ENV['RAILS_ENV'] = 'test'
2
-
3
- require 'test/unit'
4
- require 'rubygems'
5
-
6
- # Tests are conducted with health_test as a plugin
7
- environment_file = File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'config', 'environment.rb')
8
- if File.exists?(environment_file)
9
- # test as plugin
10
- require environment_file
11
- else
12
- #tests as gem
13
- fail "TODO: Work out how to test as a gem (test as a plugin instead)"
14
- end
15
-
16
- gem "shoulda"
17
- require 'shoulda'
18
- require 'shoulda/action_controller'
19
-
20
- # rails test help
21
-
22
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
23
- $LOAD_PATH.unshift(File.dirname(__FILE__))
24
-
25
- # gem init
26
- #require 'health_check'
27
-
28
- # plugin init
29
- require File.join(File.dirname(__FILE__), '..', 'init')
30
-
31
- ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :dbfile => ":memory:", :database => 'health_test_test')
32
-
33
- EXAMPLE_SMTP_SETTINGS = {
34
- :address => "smtp.gmail.com",
35
- :domain => "test.example.com",
36
- :port => 587
37
- }
38
-
39
- ActionMailer::Base.delivery_method = :test
40
-
41
- # Make sure sendmail settings are set to something that is executrable (we wont actually execute it)
42
- sendmail_path = '/usr/sbin/sendmail'
43
- ['/bin/true', 'c:/windows/explorer.exe', 'c:/winnt/explorer.exe',
44
- File.join(Rails.root, 'script', 'about')].each do |f|
45
- sendmail_path = f if File.executable? f
46
- end
47
-
48
- EXAMPLE_SENDMAIL_SETTINGS = {
49
- :location => sendmail_path,
50
- :arguments => '--help'
51
- }
52
-
53
- def setup_db(version)
54
- ActiveRecord::Base.connection.initialize_schema_migrations_table
55
- ActiveRecord::Schema.define(:version => version) do
56
- create_table :kitchen do |t|
57
- t.column :owner, :string
58
- t.column :description, :string
59
- end
60
- end if version
61
- end
62
-
63
- def teardown_db
64
- ActiveRecord::Base.connection.tables.each do |table|
65
- ActiveRecord::Base.connection.drop_table(table)
66
- end
67
- end
68
-
@@ -1,175 +0,0 @@
1
- require File.dirname(__FILE__) + '/../test_helper'
2
-
3
- class HealthCheckControllerTest < ActionController::TestCase
4
- #context "HealthCheck plugin" do
5
- # should route :get, "/health_check", :controller => :health_check, :action => :index
6
- # should route :get, "/health_check/two_checks", :controller => :health_check, :action => :index, :checks => 'two_checks'
7
- #end
8
-
9
- context "GET standard on empty db" do
10
- setup do
11
- HealthCheck.db_migrate_path = File.join(File.dirname(__FILE__), 'migrate', 'empty')
12
- setup_db(nil)
13
- ActionMailer::Base.delivery_method = :test
14
- get :index
15
- end
16
-
17
- teardown do
18
- teardown_db
19
- end
20
-
21
- should respond_with :success
22
- should_not set_the_flash
23
- should respond_with_content_type 'text/plain'
24
- should_not render_with_layout
25
- should "return 'success' text" do
26
- assert_equal HealthCheck.success, @response.body
27
- end
28
- end
29
-
30
- context "GET migrations on db with migrations" do
31
- setup do
32
- HealthCheck.db_migrate_path = File.join(File.dirname(__FILE__), 'migrate', 'twelve')
33
- setup_db(12)
34
- ActionMailer::Base.delivery_method = :test
35
- get :check, :checks => 'migrations'
36
- end
37
-
38
- teardown do
39
- teardown_db
40
- end
41
-
42
- should respond_with :success
43
- should_not set_the_flash
44
- should respond_with_content_type 'text/plain'
45
- should_not render_with_layout
46
- should "return 'success' text" do
47
- assert_equal HealthCheck.success, @response.body
48
- end
49
- end
50
-
51
- context "GET standard with unactioned migrations" do
52
- setup do
53
- HealthCheck.db_migrate_path = File.join(File.dirname(__FILE__), 'migrate', 'twelve')
54
- setup_db(nil)
55
- ActionMailer::Base.delivery_method = :test
56
- get :index
57
- end
58
-
59
- teardown do
60
- teardown_db
61
- end
62
-
63
- should respond_with 500
64
- should_not set_the_flash
65
- should respond_with_content_type 'text/plain'
66
- should_not render_with_layout
67
- should "not return 'success' text" do
68
- assert_not_equal HealthCheck.success, @response.body
69
- end
70
- end
71
-
72
- context "GET email with :test" do
73
- setup do
74
- ActionMailer::Base.delivery_method = :test
75
- get :check, :checks => 'email'
76
- end
77
-
78
- should respond_with :success
79
- should_not set_the_flash
80
- should respond_with_content_type 'text/plain'
81
- should_not render_with_layout
82
- should "return 'success' text" do
83
- assert_equal HealthCheck.success, @response.body
84
- end
85
- end
86
-
87
- context "GET standard with bad smtp" do
88
- setup do
89
- HealthCheck.db_migrate_path = File.join(File.dirname(__FILE__), 'migrate', 'twelve')
90
- setup_db(12)
91
- HealthCheck.smtp_timeout = 2.0
92
- ActionMailer::Base.delivery_method = :smtp
93
- ActionMailer::Base.smtp_settings = {
94
- :address => "127.0.0.1",
95
- :domain => "testing.example.com",
96
- :port => 7
97
- }
98
- get :index
99
- end
100
-
101
- teardown do
102
- teardown_db
103
- end
104
-
105
- should respond_with 500
106
- should_not set_the_flash
107
- should respond_with_content_type 'text/plain'
108
- should_not render_with_layout
109
- should "not return 'success' text" do
110
- assert_not_equal HealthCheck.success, @response.body
111
- end
112
- end
113
-
114
-
115
- context "GET email with :smtp" do
116
- setup do
117
- # it should not care that the database isnt setup correctly
118
- HealthCheck.db_migrate_path = File.join(File.dirname(__FILE__), 'migrate', 'empty')
119
- setup_db(nil)
120
- ActionMailer::Base.delivery_method = :smtp
121
- HealthCheck.smtp_timeout = 60.0
122
- ActionMailer::Base.smtp_settings = EXAMPLE_SMTP_SETTINGS
123
- get :check, :checks => 'email'
124
- end
125
-
126
- should respond_with :success
127
- should respond_with_content_type 'text/plain'
128
- should "return 'success' text" do
129
- assert_equal HealthCheck.success, @response.body
130
- end
131
- end
132
-
133
-
134
- context "GET database_migration_email with missing sendmail" do
135
- setup do
136
- HealthCheck.db_migrate_path = File.join(File.dirname(__FILE__), 'migrate', 'twelve')
137
- setup_db(12)
138
- ActionMailer::Base.delivery_method = :sendmail
139
- ActionMailer::Base.sendmail_settings = { :location => '/no/such/executable', :arguments => '' }
140
- get :check, :checks => 'database_migration_email'
141
- end
142
-
143
- teardown do
144
- teardown_db
145
- end
146
-
147
- should respond_with 500
148
- should_not set_the_flash
149
- should respond_with_content_type 'text/plain'
150
- should_not render_with_layout
151
- should "not return 'success' text" do
152
- assert_not_equal HealthCheck.success, @response.body
153
- end
154
- end
155
-
156
- context "GET all with :sendmail" do
157
- setup do
158
- ActionMailer::Base.delivery_method = :sendmail
159
- ActionMailer::Base.sendmail_settings = EXAMPLE_SENDMAIL_SETTINGS
160
- HealthCheck.db_migrate_path = File.join(File.dirname(__FILE__), 'migrate', 'empty')
161
- setup_db(nil)
162
- get :check, :checks => 'all'
163
- end
164
-
165
- teardown do
166
- teardown_db
167
- end
168
-
169
- should respond_with :success
170
- should respond_with_content_type 'text/plain'
171
- should "return 'success' text" do
172
- assert_equal HealthCheck.success, @response.body
173
- end
174
- end
175
- end
@@ -1,42 +0,0 @@
1
- require File.dirname(__FILE__) + '/../test_helper'
2
-
3
- class RoutingTest < Test::Unit::TestCase
4
-
5
- def setup
6
- if defined?(Rails) and defined?(Rails.application) and Rails.application.routes
7
- Rails.application.routes.draw do |map|
8
- # do nothing - routes should be added automatically
9
- end
10
- else
11
- ActionController::Routing::Routes.draw do |map|
12
- # do nothing - routes should be added automatically
13
- end
14
- end
15
- end
16
-
17
- def test_health_check_plain_route
18
- assert_recognition :get, "/health_check", :controller => "health_check", :action => "index"
19
- end
20
-
21
- def test_health_check_checks_specified_route
22
- assert_recognition :get, "/health_check/two_checks", :controller => "health_check", :action => "check", :checks => 'two_checks'
23
- end
24
-
25
- private
26
-
27
- # yes, I know about assert_recognizes, but it has proven problematic to
28
- # use in these tests, since it uses RouteSet#recognize (which actually
29
- # tries to instantiate the controller) and because it uses an awkward
30
- # parameter order.
31
- def assert_recognition(method, path, options)
32
- if defined?(Rails) and defined?(Rails.application) and Rails.application.routes
33
- result = Rails.application.routes.recognize_path(path, :method => method)
34
- else
35
- result = ActionController::Routing::Routes.recognize_path(path, :method => method)
36
- end
37
- assert_equal options, result
38
- end
39
-
40
- # with Thanks to http://izumi.plan99.net/manuals/creating_plugins-8f53e4d6.html
41
-
42
- end