Skip to content

Commit 9dbf155

Browse files
author
Arne De Herdt
authored
[CIOPS-1084] Bearer Token Support (#3)
### Description This pull request adds support for Basic Auth on the endpoint. This allows projects implementing this gem to secure their endpoint when they are public facing. That way the Rails stack is safe from being hammered with requests and prevents the application from being taken down. ### Changes * Moved the actual endpoint to a dedicated controller * Added support for Bearer tokens * Updated the documentation * Added minitest for the token functionality ### Ticket [CIOPS-1084](https://customink.atlassian.net/browse/CIOPS-1084)
2 parents 1d5ad36 + 463c6d1 commit 9dbf155

File tree

11 files changed

+103
-13
lines changed

11 files changed

+103
-13
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Is It Ready? CHANGELOG
22

3+
## 0.0.4
4+
* Add support for HTTP Authorization Bearer tokens
5+
36
## 0.0.3
47
* Make the mounting of the engine dynamic based upon the configuration
58

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,12 @@ or conflicts with another plugin. In this case, creating an initializer under `c
7070
# * https://your-domain/something_else
7171
# This is more for cosmetic purposes, or when mountain multiple engines under the same endpoint with distinct routes.
7272
::IsItReady.endpoint = '/something_else'
73+
74+
# Setting the bearer token will protect the endpoint with Basic HTTP Auth.
75+
# When this value is set, every incoming request on this endpoint must provided the
76+
# AUTHORIZATION header with a Bearer or Token associated to it.
77+
# Failure to do so, will return in an HTTP UNAUTHORIZED response.
78+
::IsItReady.bearer_token = 'my-secret-token'
7379
```
7480

7581
## Contributing

app/controllers/is_it_ready/application_controller.rb

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,5 @@ module IsItReady
1111
# See the general configuration options to enable this protection in the controller.
1212
class ApplicationController < ActionController::Base
1313
protect_from_forgery :with => :exception
14-
15-
# GET /is_it_ready
16-
#
17-
# Returns the desired output, running through the entire Ruby on Rails stack to indicate that
18-
# this application is able to serve requests. The routing is controlled through the Engine,
19-
# but we might be mounted under a specific endpoint or with a custom path.
20-
def is_it_ready
21-
render :json => { :status => 'ok', :code => 200 }
22-
end
2314
end
2415
end
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# frozen_string_literal: true
2+
3+
module IsItReady
4+
class HealthCheckController < ::IsItReady::ApplicationController
5+
# Disable the CSRF security checks, since this controller will receive calls from external
6+
# services that do not have the ability to generate the required CSRF token
7+
skip_before_action :verify_authenticity_token
8+
9+
# Ensure that all incoming requests supply a valid Bearer token in their Authorization header.
10+
# The function will determine whether the check is required or not based upon the configuration.
11+
before_action :authenticate!
12+
13+
AUTHORIZATION_HEADER = 'HTTP_AUTHORIZATION'
14+
15+
# GET /is_it_ready
16+
#
17+
# Returns the desired output, running through the entire Ruby on Rails stack to indicate that
18+
# this application is able to serve requests. The routing is controlled through the Engine,
19+
# but we might be mounted under a specific endpoint or with a custom path.
20+
def is_it_ready
21+
render :json => { :status => 'ok', :code => 200 }
22+
end
23+
24+
private
25+
26+
# This action will look up the HTTP Authorization header when the configuration has a Bearer token set.
27+
# When the token is set, the incoming requests must provide this as a Bearer token, otherwise the request
28+
# will be refused with an HTTP UNAUTHORIZED response.
29+
def authenticate!
30+
return unless ::IsItReady.bearer_token.present?
31+
32+
authenticate_or_request_with_http_token do |token, _options|
33+
::IsItReady.bearer_token == token
34+
end
35+
end
36+
end
37+
end

config/routes.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44
# This follows the same pattern as standard Ruby on Rails routing, but is scoped to
55
# just the Rails Engine.
66
::IsItReady::Engine.routes.draw do
7-
root :to => 'application#is_it_ready'
7+
root :to => 'health_check#is_it_ready'
88
end

lib/is_it_ready.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,10 @@ module IsItReady
1313
# but if this is already claimed by an application, it can be overwritten.
1414
mattr_accessor :endpoint
1515
@@endpoint = DEFAULT_PATH
16+
17+
# Sets the Bearer token to be used when securing the endpoint.
18+
# By default this is left blank, and disables the security verification of the controller.
19+
# When enabled however, the request will need to provide the required token as a Bearer value
20+
# in the AUTHORIZATION header of the request.
21+
mattr_accessor :bearer_token
1622
end

lib/is_it_ready/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# frozen_string_literal: true
22

33
module IsItReady
4-
VERSION = '0.0.3'
4+
VERSION = '0.0.4'
55
end

test/dummy/config/initializers/secret_token.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
# If you change this key, all old signed cookies will become invalid!
55
# Make sure the secret is at least 30 characters and all random,
66
# no regular words or you'll be exposed to dictionary attacks.
7-
Dummy::Application.config.secret_token = 'f72b0ec7b89beb76a5a4782594beaa709ced5f43d2a078c71cd4ce26ed2775dffc0e65babff2783e0073be64dabff10ee03e9eca67d7b6d2787111da8ed615a5'
7+
Dummy::Application.config.secret_key_base = 'f72b0ec7b89beb76a5a4782594beaa709ced5f43d2a078c71cd4ce26ed2775dffc0e65babff2783e0073be64dabff10ee03e9eca67d7b6d2787111da8ed615a5'
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# frozen_string_literal: true
2+
3+
# This initializer configures SQLite to silence warnings and make sure the "database" is usable
4+
# across all Rails versions the way a normal database is used during testing.
5+
6+
# Enforce booleans to represented as integers in the database.
7+
# This was an old SQLite feature that we do not want to support anymore.
8+
# Note: This is only for older versions of Sqlite3, the configuration option was dropped at some point
9+
if ::Rails.application.config.active_record.sqlite3.respond_to?(:represent_boolean_as_integer)
10+
::Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true
11+
end
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
require 'test_helper'
2+
require 'securerandom'
3+
4+
module IsItReady
5+
class NavigationWithTokenTest < ActionDispatch::IntegrationTest
6+
include Engine.routes.url_helpers
7+
8+
setup do
9+
::IsItReady.bearer_token = ::SecureRandom.hex(15)
10+
end
11+
12+
teardown do
13+
::IsItReady.bearer_token = nil
14+
end
15+
16+
test('it returns the correct response status on the root') do
17+
get root_url, headers: { 'HTTP_AUTHORIZATION' => "Bearer token=#{::IsItReady.bearer_token}" }
18+
19+
assert_response :success
20+
end
21+
22+
test('it returns the correct output on the root') do
23+
get root_url, headers: { 'HTTP_AUTHORIZATION' => "Bearer token=#{::IsItReady.bearer_token}" }
24+
25+
response = ::JSON.parse(@response.body, symbolize_names: true)
26+
27+
assert_equal({ :status => "ok", :code => 200 }, response)
28+
end
29+
30+
test('it returns the correct response status on the root without token') do
31+
get root_url
32+
33+
assert_response :unauthorized
34+
end
35+
end
36+
end

0 commit comments

Comments
 (0)