health_check 2.4.0 → 2.5.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: 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