roo_on_rails 1.7.0 → 1.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +6 -1
- data/CHANGELOG.md +20 -0
- data/README.google_oauth2.md +84 -0
- data/README.md +38 -18
- data/gemfiles/rails_3.gemfile.lock +3 -3
- data/gemfiles/rails_4.gemfile.lock +3 -3
- data/gemfiles/rails_5.gemfile.lock +3 -3
- data/gemfiles/rails_5_1.gemfile.lock +3 -3
- data/lib/roo_on_rails/checks/base.rb +2 -0
- data/lib/roo_on_rails/checks/documentation/playbook.rb +26 -4
- data/lib/roo_on_rails/checks/documentation/playbook_template.md +29 -0
- data/lib/roo_on_rails/checks/environment.rb +0 -6
- data/lib/roo_on_rails/checks/sidekiq/settings.rb +8 -1
- data/lib/roo_on_rails/checks/sidekiq/sidekiq.rb +2 -6
- data/lib/roo_on_rails/config.rb +8 -0
- data/lib/roo_on_rails/default.env +3 -1
- data/lib/roo_on_rails/harness.rb +20 -6
- data/lib/roo_on_rails/railties/google_oauth.rb +75 -0
- data/lib/roo_on_rails/sidekiq/metrics_worker.rb +7 -1
- data/lib/roo_on_rails/sidekiq/process_scaling.rb +15 -14
- data/lib/roo_on_rails/sidekiq/queue_latency.rb +11 -12
- data/lib/roo_on_rails/sidekiq/settings.rb +47 -13
- data/lib/roo_on_rails/sidekiq/sla_metric.rb +2 -2
- data/lib/roo_on_rails/version.rb +1 -1
- data/lib/roo_on_rails.rb +1 -1
- metadata +5 -6
- data/lib/roo_on_rails/checks/google_oauth/_template.rb +0 -49
- data/lib/roo_on_rails/checks/google_oauth/initializer.rb +0 -43
- data/lib/roo_on_rails/rack/google_oauth.rb +0 -34
- data/lib/roo_on_rails/railties/google_auth.rb +0 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3c14df25a7b6424101a9e98b40db865b5481b507
|
4
|
+
data.tar.gz: dfff2f9bea33530d06533183c2d31be578d0aa96
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8c8811e21f02b5eaf1ce83a6653e5e0329c8c0a80f9ef9cf80e407576409c57818ed90662d4ced4b1f44bc6ac51a46dff57376af82a6d8f905d66069acfa6205
|
7
|
+
data.tar.gz: 5e5b53d7ca2df0137cc3326c13231242f30d2ae9743024e34131ad6b9ad167aa429f746d205484e9995b472a2317e235ea528d47de73af14864ca7989dda72ae
|
data/.rubocop.yml
CHANGED
@@ -28,7 +28,7 @@ Metrics/LineLength:
|
|
28
28
|
Max: 100
|
29
29
|
Exclude:
|
30
30
|
- Gemfile
|
31
|
-
|
31
|
+
|
32
32
|
Style/Documentation:
|
33
33
|
Enabled: false
|
34
34
|
|
@@ -39,3 +39,8 @@ Style/DotPosition:
|
|
39
39
|
Enabled: false
|
40
40
|
Metrics/AbcSize:
|
41
41
|
Max: 30
|
42
|
+
|
43
|
+
Rubocop/Metrics/MethodLength:
|
44
|
+
Max: 20
|
45
|
+
Rubocop/Style/TrailingCommaInLiteral:
|
46
|
+
Enabled: false
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,23 @@
|
|
1
|
+
# v1.8.0 (2017-07-26)
|
2
|
+
|
3
|
+
Bug fixes:
|
4
|
+
|
5
|
+
- Do not consider 'quiet' workers in the SLA sidekiq metric (#51)
|
6
|
+
|
7
|
+
Features:
|
8
|
+
|
9
|
+
- Provides a `PLAYBOOK.md` template when detected missing (#42)
|
10
|
+
- Adds pre-baked Google OAuth support (#44, #49)
|
11
|
+
- Reports Sidekiq metrics only for queues defined in process (#50)
|
12
|
+
- Finer-grained Sidekiq configuration (#46)
|
13
|
+
- adds 'default' to list of default Sidekiq queues
|
14
|
+
- accepts custom Sidekiq queue names and permitted latency values
|
15
|
+
- allows environment-specific application checks
|
16
|
+
|
17
|
+
Other:
|
18
|
+
|
19
|
+
- Fixes the test harness (#48)
|
20
|
+
|
1
21
|
# v1.7.0 (2017-07-18)
|
2
22
|
|
3
23
|
Features:
|
@@ -0,0 +1,84 @@
|
|
1
|
+
## Using the Google OAuth feature
|
2
|
+
|
3
|
+
This feature is only supported when using Rails 5+.
|
4
|
+
|
5
|
+
`roo_on_rails` provides a pre-baked Omniauth setup to help protect your app with
|
6
|
+
Google authentication. Read the main `README` first to set things up; you'll
|
7
|
+
need at least `GOOGLE_AUTH_ENABLED=YES`, and `GOOGLE_AUTH_CLIENT_ID` and
|
8
|
+
`GOOGLE_AUTH_CLIENT_SECRET` configured.
|
9
|
+
|
10
|
+
Let's build a tiny app that has just a homepage, prompts you to sign in, and
|
11
|
+
show your email once you have.
|
12
|
+
|
13
|
+
We add the landing page route:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
# config/routes.rb
|
17
|
+
Rails.application.routes.draw do
|
18
|
+
root to: 'landing#index'
|
19
|
+
end
|
20
|
+
```
|
21
|
+
|
22
|
+
And a controller/view:
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
# app/controllers/landing_controller.rb
|
26
|
+
class LandingController < ApplicationController
|
27
|
+
def index
|
28
|
+
if session[:email]
|
29
|
+
render inline: %{
|
30
|
+
You are logged in as <%= session[:email] %>! <br/>
|
31
|
+
<%= link_to 'Logout', auth_logout_path %>
|
32
|
+
}
|
33
|
+
else
|
34
|
+
render inline: %{
|
35
|
+
You are not logged in <br/>
|
36
|
+
<%= link_to 'Login', auth_google_oauth2_path %>
|
37
|
+
}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
The authentication routes get added by `roo_on_rails`; we need to implement at
|
44
|
+
least session creation, destruction, and handling of failure:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
# app/controllers/sessions_controller.rb
|
48
|
+
|
49
|
+
class SessionsController < ApplicationController
|
50
|
+
def create
|
51
|
+
auth_data = request.env['omniauth.auth']
|
52
|
+
session[:email] = auth_data.info.email.downcase
|
53
|
+
redirect_to root_path
|
54
|
+
end
|
55
|
+
|
56
|
+
def destroy
|
57
|
+
session.clear
|
58
|
+
redirect_to root_path
|
59
|
+
end
|
60
|
+
|
61
|
+
def failure
|
62
|
+
@error = env['omniauth.error']
|
63
|
+
render inline: %{
|
64
|
+
Authentication failed: <br/>
|
65
|
+
<%= @error.class.name %> <br/>
|
66
|
+
<%= @error.message %>
|
67
|
+
}
|
68
|
+
end
|
69
|
+
end
|
70
|
+
```
|
71
|
+
|
72
|
+
And that's it. If you want to blanket-protect a controller, an idiomatic way
|
73
|
+
would be to:
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
before_filter { redirect_to auth_google_oauth2_path unless session[:email] }
|
77
|
+
```
|
78
|
+
|
79
|
+
If you dislike the name `SessionsController`, you can update
|
80
|
+
`GOOGLE_AUTH_CONTROLLER` to point to a different controller.
|
81
|
+
|
82
|
+
You can also change the `/auth` path prefix used by this feature; in this case
|
83
|
+
you'll want to update the example above. For instance, if you change `/auth` to
|
84
|
+
`/prefix`, `auth_google_oauth2_path` becomes `prefix_google_oauth2_path`.
|
data/README.md
CHANGED
@@ -103,6 +103,11 @@ statement timeouts directly in the database._
|
|
103
103
|
|
104
104
|
### Sidekiq
|
105
105
|
|
106
|
+
Deliveroo services implement Sidekiq with an _urgency_ pattern. By only having
|
107
|
+
time-based [SLA](https://en.wikipedia.org/wiki/Service-level_agreement) queue
|
108
|
+
names (eg. `within5minutes`) we can automatically create incident alerting for
|
109
|
+
queues which take longer than the time the application needs them to be processed.
|
110
|
+
|
106
111
|
When `SIDEKIQ_ENABLED` is set we'll:
|
107
112
|
|
108
113
|
- check for the existence of a worker line in your Procfile;
|
@@ -112,11 +117,16 @@ When `SIDEKIQ_ENABLED` is set we'll:
|
|
112
117
|
The following ENV are available:
|
113
118
|
|
114
119
|
- `SIDEKIQ_ENABLED`
|
120
|
+
- `SIDEKIQ_QUEUES` - comma-separated custom queue names; if not specified, default queues are processed which are defined [here](./lib/roo_on_rails/sidekiq/settings.rb). For accurate health reporting and scaling for your custom queue names, you can specify their permitted latency within this variable e.g. `within5seconds,queue-one:10seconds,queue-two:20minutes,queue-three:3hours,queue-four:1day,default`. For non-default queue names that don't follow the `withinXunit` pattern, you will **need** to specify the permitted latency otherwise the initialization will error.
|
115
121
|
- `SIDEKIQ_THREADS` (default: 25) - Sets sidekiq concurrency value
|
116
122
|
- `SIDEKIQ_DATABASE_REAPING_FREQUENCY` (default: 10) - For sidekiq processes the
|
117
123
|
amount of time in seconds rails will wait before attempting to find and
|
118
124
|
recover connections from dead threads
|
119
125
|
|
126
|
+
NB. If you are migrating to SLA-based queue names, do not set `SIDEKIQ_ENABLED`
|
127
|
+
to `true` before your old queues have finished processing (this will prevent
|
128
|
+
Sidekiq from seeing the old queues at all).
|
129
|
+
|
120
130
|
### HireFire (for Sidekiq workers)
|
121
131
|
|
122
132
|
When `HIREFIRE_TOKEN` is set an endpoint will be mounted at `/hirefire` that
|
@@ -173,25 +183,21 @@ logger.with(a: 1, b: 2).info('Stuff')
|
|
173
183
|
See the [class documentation](lib/roo_on_rails/context_logging.rb) for further
|
174
184
|
details.
|
175
185
|
|
176
|
-
### Google
|
186
|
+
### Google OAuth authentication
|
187
|
+
|
188
|
+
When `GOOGLE_AUTH_ENABLED` is set to true we inject a `Omniauth` Rack middleware
|
189
|
+
with a pre-configured strategy for Google Oauth2.
|
177
190
|
|
178
|
-
|
191
|
+
Parameters:
|
179
192
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
* Generate the `config/initializers/google_oauth.rb` file that contains some
|
184
|
-
examples of how to wire in your authentication logic.
|
193
|
+
- `GOOGLE_AUTH_CLIENT_ID` and `GOOGLE_AUTH_CLIENT_SECRET` (mandatory)
|
194
|
+
- `GOOGLE_AUTH_PATH_PREFIX` (optional, defaults to `/auth`)
|
195
|
+
- `GOOGLE_AUTH_CONTROLLER` (optional, defaults to `sessions`)
|
185
196
|
|
186
|
-
|
197
|
+
This feature is bring-your-own-controller — it won't magically protect your
|
198
|
+
application.
|
187
199
|
|
188
|
-
|
189
|
-
`GOOGLE_AUTH_CLIENT_ID` and `GOOGLE_AUTH_CLIENT_SECRET`.
|
190
|
-
* Provide in `GOOGLE_AUTH_ALLOWED_DOMAINS` a comma-separated list of domains, to
|
191
|
-
whitelist the allowed email addresses.
|
192
|
-
* Customize the code in the generated Rails initializer to hook into your
|
193
|
-
application's authentication logic.
|
194
|
-
* Update your Rails controllers to require authentication, when necessary.
|
200
|
+
A simple but secure example is detailed in `README.google_oauth2.md`.
|
195
201
|
|
196
202
|
|
197
203
|
## Command features
|
@@ -204,9 +210,23 @@ Run the following from your app's top-level directory:
|
|
204
210
|
bundle exec roo_on_rails
|
205
211
|
```
|
206
212
|
|
207
|
-
|
208
|
-
|
209
|
-
|
213
|
+
That command will sequentially run a number of checks. For it to run successfully, you will need:
|
214
|
+
|
215
|
+
- a GitHub API token that can read your GitHub repository's settings placed in `~/.roo_on_rails/github-token`
|
216
|
+
- the Heroku toolbelt installed and logged in
|
217
|
+
- admin privileges on the `roo-dd-bridge-production` (this will be addressed eventually)
|
218
|
+
- checks are run sequentially for staging and then for production. The process halts at any non-fixable failing check. To process only specific environments, you can set a config variable while running the command, like so:
|
219
|
+
|
220
|
+
```
|
221
|
+
# the default behaviour:
|
222
|
+
ROO_ON_RAILS_ENVIRONMENTS=staging,production bundle exec roo_on_rails
|
223
|
+
|
224
|
+
# run checks only on staging:
|
225
|
+
ROO_ON_RAILS_ENVIRONMENTS=staging bundle exec roo_on_rails
|
226
|
+
|
227
|
+
# run checks only on production:
|
228
|
+
ROO_ON_RAILS_ENVIRONMENTS=production bundle exec roo_on_rails
|
229
|
+
```
|
210
230
|
|
211
231
|
|
212
232
|
### Description
|
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
roo_on_rails (1.
|
4
|
+
roo_on_rails (1.8.0)
|
5
5
|
dogstatsd-ruby
|
6
6
|
dotenv-rails (~> 2.1)
|
7
7
|
faraday
|
@@ -74,7 +74,7 @@ GEM
|
|
74
74
|
railties (>= 3.2, < 5.2)
|
75
75
|
erubis (2.7.0)
|
76
76
|
excon (0.57.1)
|
77
|
-
faraday (0.12.
|
77
|
+
faraday (0.12.2)
|
78
78
|
multipart-post (>= 1.2, < 3)
|
79
79
|
faraday_middleware (0.11.0.1)
|
80
80
|
faraday (>= 0.7.4, < 1.0)
|
@@ -137,7 +137,7 @@ GEM
|
|
137
137
|
omniauth (1.4.2)
|
138
138
|
hashie (>= 1.2, < 4)
|
139
139
|
rack (>= 1.0, < 3)
|
140
|
-
omniauth-google-oauth2 (0.5.
|
140
|
+
omniauth-google-oauth2 (0.5.1)
|
141
141
|
jwt (~> 1.5)
|
142
142
|
multi_json (~> 1.3)
|
143
143
|
omniauth (>= 1.1.1)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
roo_on_rails (1.
|
4
|
+
roo_on_rails (1.8.0)
|
5
5
|
dogstatsd-ruby
|
6
6
|
dotenv-rails (~> 2.1)
|
7
7
|
faraday
|
@@ -81,7 +81,7 @@ GEM
|
|
81
81
|
railties (>= 3.2, < 5.2)
|
82
82
|
erubis (2.7.0)
|
83
83
|
excon (0.57.1)
|
84
|
-
faraday (0.12.
|
84
|
+
faraday (0.12.2)
|
85
85
|
multipart-post (>= 1.2, < 3)
|
86
86
|
faraday_middleware (0.11.0.1)
|
87
87
|
faraday (>= 0.7.4, < 1.0)
|
@@ -151,7 +151,7 @@ GEM
|
|
151
151
|
omniauth (1.6.1)
|
152
152
|
hashie (>= 3.4.6, < 3.6.0)
|
153
153
|
rack (>= 1.6.2, < 3)
|
154
|
-
omniauth-google-oauth2 (0.5.
|
154
|
+
omniauth-google-oauth2 (0.5.1)
|
155
155
|
jwt (~> 1.5)
|
156
156
|
multi_json (~> 1.3)
|
157
157
|
omniauth (>= 1.1.1)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
roo_on_rails (1.
|
4
|
+
roo_on_rails (1.8.0)
|
5
5
|
dogstatsd-ruby
|
6
6
|
dotenv-rails (~> 2.1)
|
7
7
|
faraday
|
@@ -84,7 +84,7 @@ GEM
|
|
84
84
|
railties (>= 3.2, < 5.2)
|
85
85
|
erubis (2.7.0)
|
86
86
|
excon (0.57.1)
|
87
|
-
faraday (0.12.
|
87
|
+
faraday (0.12.2)
|
88
88
|
multipart-post (>= 1.2, < 3)
|
89
89
|
faraday_middleware (0.11.0.1)
|
90
90
|
faraday (>= 0.7.4, < 1.0)
|
@@ -155,7 +155,7 @@ GEM
|
|
155
155
|
omniauth (1.6.1)
|
156
156
|
hashie (>= 3.4.6, < 3.6.0)
|
157
157
|
rack (>= 1.6.2, < 3)
|
158
|
-
omniauth-google-oauth2 (0.5.
|
158
|
+
omniauth-google-oauth2 (0.5.1)
|
159
159
|
jwt (~> 1.5)
|
160
160
|
multi_json (~> 1.3)
|
161
161
|
omniauth (>= 1.1.1)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
roo_on_rails (1.
|
4
|
+
roo_on_rails (1.8.0)
|
5
5
|
dogstatsd-ruby
|
6
6
|
dotenv-rails (~> 2.1)
|
7
7
|
faraday
|
@@ -85,7 +85,7 @@ GEM
|
|
85
85
|
erubi (1.6.0)
|
86
86
|
erubis (2.7.0)
|
87
87
|
excon (0.57.1)
|
88
|
-
faraday (0.12.
|
88
|
+
faraday (0.12.2)
|
89
89
|
multipart-post (>= 1.2, < 3)
|
90
90
|
faraday_middleware (0.11.0.1)
|
91
91
|
faraday (>= 0.7.4, < 1.0)
|
@@ -156,7 +156,7 @@ GEM
|
|
156
156
|
omniauth (1.6.1)
|
157
157
|
hashie (>= 3.4.6, < 3.6.0)
|
158
158
|
rack (>= 1.6.2, < 3)
|
159
|
-
omniauth-google-oauth2 (0.5.
|
159
|
+
omniauth-google-oauth2 (0.5.1)
|
160
160
|
jwt (~> 1.5)
|
161
161
|
multi_json (~> 1.3)
|
162
162
|
omniauth (>= 1.1.1)
|
@@ -20,10 +20,12 @@ module RooOnRails
|
|
20
20
|
@fix = @options.delete(:fix) { false }
|
21
21
|
@context = @options.delete(:context) { Hashie::Mash.new }
|
22
22
|
@shell = @options.delete(:shell) { Shell.new }
|
23
|
+
@dry_run = options.fetch(:dry_run, false)
|
23
24
|
end
|
24
25
|
|
25
26
|
def run
|
26
27
|
resolve dependencies
|
28
|
+
return true if @dry_run
|
27
29
|
say intro
|
28
30
|
call
|
29
31
|
true
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'roo_on_rails/checks/base'
|
2
|
+
require 'fileutils'
|
2
3
|
|
3
4
|
module RooOnRails
|
4
5
|
module Checks
|
@@ -11,11 +12,32 @@ module RooOnRails
|
|
11
12
|
end
|
12
13
|
|
13
14
|
def call
|
14
|
-
if
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
fail! "no playbook at #{LOCATION}." if playbook_missing?
|
16
|
+
fail! 'playbook still contains FIXME template sections' if playbook_unfinished?
|
17
|
+
pass 'playbook found, legion on-call engineers thank you.'
|
18
|
+
end
|
19
|
+
|
20
|
+
def fix
|
21
|
+
if !playbook_missing? && playbook_unfinished?
|
22
|
+
fail! 'please add detail to your playbook, removing FIXME sections'
|
18
23
|
end
|
24
|
+
|
25
|
+
FileUtils.cp(
|
26
|
+
File.join(__dir__, 'playbook_template.md'),
|
27
|
+
LOCATION
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def playbook_unfinished?
|
34
|
+
# The regexp is so that you can still refer to strings saying FIXME in your readme
|
35
|
+
# if you need to, by putting the phrase in backticks: `FIXME`
|
36
|
+
!File.read(LOCATION).match(/FIXME(?!`)/).nil?
|
37
|
+
end
|
38
|
+
|
39
|
+
def playbook_missing?
|
40
|
+
!File.exist?(LOCATION)
|
19
41
|
end
|
20
42
|
end
|
21
43
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Playbook
|
2
|
+
|
3
|
+
This document details the failure modes of this service and mitigating steps that can be taken.
|
4
|
+
|
5
|
+
_FIXME: go through this document and fill out the sections marked FIXME._
|
6
|
+
|
7
|
+
## Responsible humans
|
8
|
+
|
9
|
+
As a last resort, in an emergency, the following people have experience working with this service and have claimed responsibility for the running of this service. **If you have executed the plays below** and there is still a clear and present SEV-1 or greater issue, use the links below to get in touch:
|
10
|
+
|
11
|
+
- Responsible McPerson ([PagerDuty](https://deliveroo.pagerduty.com/users/FIXME), [Slack](https://deliveroo.slack.com/team/FIXME))
|
12
|
+
|
13
|
+
## Owned models
|
14
|
+
|
15
|
+
- _FIXME_ - very brief description of the model, to aid in assessing what knock-on effects trouble with this service might have.
|
16
|
+
|
17
|
+
## Failure modes
|
18
|
+
|
19
|
+
### FIXME: an ability/functional area of the service
|
20
|
+
|
21
|
+
FIXME: A very brief high-level explanation of what this functional area does
|
22
|
+
|
23
|
+
#### 🚨 FIXME: a New Relic alert which might be raised - named so it can be searched for
|
24
|
+
|
25
|
+
FIXME: A description of the New Relic alert, what it means for the service, and what actions should be taken to remedy the situation.
|
26
|
+
|
27
|
+
#### 🚨 FIXME: an action which might need to be taken during an incident
|
28
|
+
|
29
|
+
FIXME: A description of how to perform this action, and any side-effects that the on-call engineer should be aware of.
|
@@ -3,10 +3,7 @@ require 'roo_on_rails/checks/github/branch_protection'
|
|
3
3
|
require 'roo_on_rails/checks/heroku/app_exists'
|
4
4
|
require 'roo_on_rails/checks/heroku/preboot_enabled'
|
5
5
|
require 'roo_on_rails/checks/heroku/app_exists'
|
6
|
-
require 'roo_on_rails/checks/sidekiq/settings'
|
7
6
|
require 'roo_on_rails/checks/heroku/drains_metrics'
|
8
|
-
require 'roo_on_rails/checks/documentation/playbook'
|
9
|
-
require 'roo_on_rails/checks/google_oauth/initializer'
|
10
7
|
require 'roo_on_rails/checks/papertrail/all'
|
11
8
|
|
12
9
|
module RooOnRails
|
@@ -15,9 +12,6 @@ module RooOnRails
|
|
15
12
|
requires GitHub::BranchProtection
|
16
13
|
requires Heroku::DrainsMetrics
|
17
14
|
requires Heroku::PrebootEnabled
|
18
|
-
requires Sidekiq::Settings
|
19
|
-
requires Documentation::Playbook
|
20
|
-
requires GoogleOauth::Initializer
|
21
15
|
requires Papertrail::All
|
22
16
|
|
23
17
|
def call
|
@@ -12,7 +12,14 @@ module RooOnRails
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def call
|
15
|
-
|
15
|
+
if File.exist?('config/sidekiq.yml')
|
16
|
+
message = [
|
17
|
+
'Custom Sidekiq settings found.',
|
18
|
+
' Please see the Roo On Rails readme for more information.'
|
19
|
+
].join("\n")
|
20
|
+
|
21
|
+
fail! message
|
22
|
+
end
|
16
23
|
end
|
17
24
|
end
|
18
25
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'roo_on_rails/checks/base'
|
2
|
-
require 'thor'
|
3
2
|
|
4
3
|
module RooOnRails
|
5
4
|
module Checks
|
@@ -20,11 +19,8 @@ module RooOnRails
|
|
20
19
|
end
|
21
20
|
|
22
21
|
def fix
|
23
|
-
|
24
|
-
|
25
|
-
else
|
26
|
-
create_file 'Procfile', WORKER_PROCFILE_LINE
|
27
|
-
end
|
22
|
+
output = File.exist?('Procfile') ? "\n#{WORKER_PROCFILE_LINE}" : WORKER_PROCFILE_LINE
|
23
|
+
File.open('Procfile', 'a') { |f| f.write(output) }
|
28
24
|
end
|
29
25
|
|
30
26
|
def check_for_procfile
|
data/lib/roo_on_rails/config.rb
CHANGED
@@ -17,6 +17,14 @@ module RooOnRails
|
|
17
17
|
enabled? 'GOOGLE_AUTH_ENABLED', default: false
|
18
18
|
end
|
19
19
|
|
20
|
+
def google_auth_path_prefix
|
21
|
+
ENV.fetch('GOOGLE_AUTH_PATH_PREFIX')
|
22
|
+
end
|
23
|
+
|
24
|
+
def google_auth_controller
|
25
|
+
ENV.fetch('GOOGLE_AUTH_CONTROLLER')
|
26
|
+
end
|
27
|
+
|
20
28
|
private
|
21
29
|
|
22
30
|
ENABLED_PATTERN = /\A(YES|TRUE|ON|1)\Z/i
|
@@ -1,7 +1,9 @@
|
|
1
|
-
GOOGLE_AUTH_ENABLED=
|
1
|
+
GOOGLE_AUTH_ENABLED=false
|
2
2
|
GOOGLE_AUTH_CLIENT_ID=''
|
3
3
|
GOOGLE_AUTH_CLIENT_SECRET=''
|
4
4
|
GOOGLE_AUTH_ALLOWED_DOMAINS=''
|
5
|
+
GOOGLE_AUTH_PATH_PREFIX=/auth
|
6
|
+
GOOGLE_AUTH_CONTROLLER=sessions
|
5
7
|
NEW_RELIC_LOG=stdout
|
6
8
|
NEW_RELIC_AGENT_ENABLED=true
|
7
9
|
NEW_RELIC_MONITOR_MODE=true
|
data/lib/roo_on_rails/harness.rb
CHANGED
@@ -2,21 +2,29 @@ require 'thor'
|
|
2
2
|
require 'hashie'
|
3
3
|
require 'roo_on_rails/checks/environment'
|
4
4
|
require 'roo_on_rails/environment'
|
5
|
+
require 'roo_on_rails/checks/sidekiq/settings'
|
6
|
+
require 'roo_on_rails/checks/documentation/playbook'
|
5
7
|
|
6
8
|
module RooOnRails
|
7
9
|
class Harness
|
8
10
|
include Thor::Shell
|
9
11
|
|
10
|
-
def initialize(try_fix: false, context:
|
12
|
+
def initialize(try_fix: false, context: Hashie::Mash.new, dry_run: false)
|
11
13
|
@try_fix = try_fix
|
12
|
-
@context = context
|
14
|
+
@context = context
|
15
|
+
@dry_run = dry_run
|
13
16
|
end
|
14
17
|
|
15
18
|
def run
|
16
|
-
[
|
17
|
-
Checks::
|
18
|
-
Checks::
|
19
|
-
]
|
19
|
+
checks = [
|
20
|
+
Checks::Sidekiq::Settings.new(fix: @try_fix, context: @context, dry_run: @dry_run),
|
21
|
+
Checks::Documentation::Playbook.new(fix: @try_fix, context: @context, dry_run: @dry_run),
|
22
|
+
]
|
23
|
+
environments.each do |env|
|
24
|
+
checks << Checks::Environment.new(env: env.strip, fix: @try_fix, context: @context, dry_run: @dry_run)
|
25
|
+
end
|
26
|
+
|
27
|
+
checks.each(&:run)
|
20
28
|
self
|
21
29
|
rescue Shell::CommandFailed
|
22
30
|
say 'A command failed to run, aborting', %i[bold red]
|
@@ -25,5 +33,11 @@ module RooOnRails
|
|
25
33
|
say 'A check failed, exiting', %i[bold red]
|
26
34
|
exit 1
|
27
35
|
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def environments
|
40
|
+
ENV.fetch('ROO_ON_RAILS_ENVIRONMENTS', 'staging,production').split(',')
|
41
|
+
end
|
28
42
|
end
|
29
43
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module RooOnRails
|
2
|
+
module Railties
|
3
|
+
class GoogleOAuth < Rails::Railtie
|
4
|
+
initializer 'roo_on_rails.google_auth.middleware' do |app|
|
5
|
+
_if_enabled do
|
6
|
+
_add_middleware(app)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
initializer 'roo_on_rails.google_auth.routes', after: :set_routes_reloader_hook do |app|
|
11
|
+
_if_enabled do
|
12
|
+
_add_routes(app)
|
13
|
+
# support development mode on route changes (only works in Rails 5)
|
14
|
+
app.reloader.to_prepare { _add_routes(app) }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def _if_enabled
|
21
|
+
return unless Config.google_auth_enabled?
|
22
|
+
if Rails::VERSION::MAJOR < 5
|
23
|
+
Rails.logger.warn 'The Google OAuth feature is not supported with Rails < 5'
|
24
|
+
return
|
25
|
+
end
|
26
|
+
|
27
|
+
yield
|
28
|
+
end
|
29
|
+
|
30
|
+
def _add_middleware(app)
|
31
|
+
$stderr.puts 'initializer roo_on_rails.google_auth.middleware'
|
32
|
+
|
33
|
+
require 'roo_on_rails/config'
|
34
|
+
require 'omniauth'
|
35
|
+
require 'omniauth-google-oauth2'
|
36
|
+
require 'active_support/core_ext/object/blank'
|
37
|
+
|
38
|
+
options = {
|
39
|
+
path_prefix: Config.google_auth_path_prefix,
|
40
|
+
prompt: 'consent',
|
41
|
+
# https://stackoverflow.com/questions/45271730/jwtinvalidissuererror-invalid-issuer-expected-accounts-google-com-received
|
42
|
+
# https://github.com/zquestz/omniauth-google-oauth2/issues/197
|
43
|
+
skip_jwt: true,
|
44
|
+
}
|
45
|
+
|
46
|
+
domain_list = ENV.fetch('GOOGLE_AUTH_ALLOWED_DOMAINS', '').split(',').reject(&:blank?)
|
47
|
+
options[:hd] = domain_list if domain_list.any?
|
48
|
+
|
49
|
+
app.config.middleware.use ::OmniAuth::Builder do
|
50
|
+
provider :google_oauth2,
|
51
|
+
ENV.fetch('GOOGLE_AUTH_CLIENT_ID'),
|
52
|
+
ENV.fetch('GOOGLE_AUTH_CLIENT_SECRET'),
|
53
|
+
options
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def _add_routes(app)
|
58
|
+
$stderr.puts 'initializer roo_on_rails.google_auth.routes'
|
59
|
+
|
60
|
+
prefix = Config.google_auth_path_prefix
|
61
|
+
ctrl = Config.google_auth_controller
|
62
|
+
|
63
|
+
app.routes.disable_clear_and_finalize = true
|
64
|
+
app.routes.draw do
|
65
|
+
get "#{prefix}/google_oauth2", controller: ctrl, action: 'failure'
|
66
|
+
get "#{prefix}/google_oauth2/callback", controller: ctrl, action: 'create'
|
67
|
+
post "#{prefix}/google_oauth2/callback", controller: ctrl, action: 'create'
|
68
|
+
get "#{prefix}/failure", controller: ctrl, action: 'failure'
|
69
|
+
get "#{prefix}/logout", controller: ctrl, action: 'destroy'
|
70
|
+
end
|
71
|
+
app.routes.disable_clear_and_finalize = false
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -1,8 +1,14 @@
|
|
1
1
|
require 'sidekiq/api'
|
2
2
|
require 'roo_on_rails/sidekiq/queue_latency'
|
3
3
|
require 'roo_on_rails/sidekiq/process_scaling'
|
4
|
+
require 'roo_on_rails/sidekiq/settings'
|
4
5
|
require 'roo_on_rails/statsd'
|
5
6
|
|
7
|
+
# Reports Sidekiq queue metrics for queues configured within the current Sidekiq process
|
8
|
+
# i.e. queues returned by `RooOnRails::Sidekiq::Settings.queues`
|
9
|
+
# To enable reporting for custom queues, ensure your process is running the monitoring
|
10
|
+
# queue e.g. `SIDEKIQ_QUEUES="new-queue:5seconds,monitoring" bundle exec sidekiq`
|
11
|
+
|
6
12
|
module RooOnRails
|
7
13
|
module Sidekiq
|
8
14
|
class MetricsWorker
|
@@ -12,7 +18,7 @@ module RooOnRails
|
|
12
18
|
|
13
19
|
def perform
|
14
20
|
RooOnRails.statsd.batch do |stats|
|
15
|
-
queues =
|
21
|
+
queues = QueueLatency.queues
|
16
22
|
queue_stats(stats, queues)
|
17
23
|
process_stats(stats, queues)
|
18
24
|
end
|
@@ -3,37 +3,38 @@ require 'sidekiq/api'
|
|
3
3
|
module RooOnRails
|
4
4
|
module Sidekiq
|
5
5
|
class ProcessScaling
|
6
|
+
WORKER_INCREASE_THRESHOLD = ENV.fetch('WORKER_INCREASE_THRESHOLD', 0.5).to_f
|
7
|
+
WORKER_DECREASE_THRESHOLD = ENV.fetch('WORKER_DECREASE_THRESHOLD', 0.1).to_f
|
8
|
+
private_constant :WORKER_INCREASE_THRESHOLD
|
9
|
+
private_constant :WORKER_DECREASE_THRESHOLD
|
10
|
+
|
6
11
|
def initialize(queue_latencies)
|
7
12
|
@queue_latencies = queue_latencies
|
13
|
+
@queue_names = @queue_latencies.map(&:name)
|
8
14
|
end
|
9
15
|
|
10
16
|
def current_processes
|
11
|
-
::Sidekiq::ProcessSet.new.count
|
17
|
+
::Sidekiq::ProcessSet.new.count do |process|
|
18
|
+
process['quiet'] == 'false' &&
|
19
|
+
@queue_names.any? do |queue_name|
|
20
|
+
process['queues'].include?(queue_name)
|
21
|
+
end
|
22
|
+
end
|
12
23
|
end
|
13
24
|
|
14
25
|
def max_normalised_latency
|
15
|
-
|
26
|
+
@queue_latencies.any? ? @queue_latencies.map(&:normalised_latency).max.to_f : 0.0
|
16
27
|
end
|
17
28
|
|
18
29
|
def requested_processes
|
19
|
-
if max_normalised_latency >
|
30
|
+
if max_normalised_latency > WORKER_INCREASE_THRESHOLD
|
20
31
|
current_processes + 1
|
21
|
-
elsif max_normalised_latency <
|
32
|
+
elsif max_normalised_latency < WORKER_DECREASE_THRESHOLD
|
22
33
|
[current_processes - 1, 1].max
|
23
34
|
else
|
24
35
|
current_processes
|
25
36
|
end
|
26
37
|
end
|
27
|
-
|
28
|
-
protected
|
29
|
-
|
30
|
-
def increasing_latency
|
31
|
-
ENV.fetch('WORKER_INCREASE_THRESHOLD', 0.5).to_f
|
32
|
-
end
|
33
|
-
|
34
|
-
def decreasing_latency
|
35
|
-
ENV.fetch('WORKER_DECREASE_THRESHOLD', 0.1).to_f
|
36
|
-
end
|
37
38
|
end
|
38
39
|
end
|
39
40
|
end
|
@@ -1,4 +1,6 @@
|
|
1
|
+
require 'active_support'
|
1
2
|
require 'active_support/core_ext/numeric'
|
3
|
+
require 'roo_on_rails/sidekiq/settings'
|
2
4
|
|
3
5
|
module RooOnRails
|
4
6
|
module Sidekiq
|
@@ -8,23 +10,20 @@ module RooOnRails
|
|
8
10
|
def_delegators :@queue, :size, :latency, :name
|
9
11
|
attr_reader :queue
|
10
12
|
|
13
|
+
def self.queues
|
14
|
+
::Sidekiq::Queue.all.each_with_object([]) do |q, array|
|
15
|
+
array << new(q) if Settings.queues.include?(q.name.to_s)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
11
19
|
def initialize(queue)
|
12
20
|
@queue = queue
|
13
21
|
end
|
14
22
|
|
15
23
|
def normalised_latency
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
def permitted_latency
|
21
|
-
prefix, number, unit = queue.name.partition(/[0-9]+/)
|
22
|
-
case prefix
|
23
|
-
when 'monitoring', 'realtime' then 10.seconds.to_i
|
24
|
-
when 'default' then 1.day.to_i
|
25
|
-
when 'within' then number.to_i.public_send(unit.to_sym).to_i
|
26
|
-
else raise "Cannot determine permitted latency for queue #{queue.name}"
|
27
|
-
end
|
24
|
+
permitted_latency = Settings.permitted_latency_values[queue.name]
|
25
|
+
return queue.latency.fdiv(permitted_latency).round(3) if permitted_latency
|
26
|
+
raise("Cannot determine permitted latency for queue #{queue.name}")
|
28
27
|
end
|
29
28
|
end
|
30
29
|
end
|
@@ -1,20 +1,54 @@
|
|
1
|
+
require_relative './queue_latency'
|
2
|
+
|
1
3
|
module RooOnRails
|
2
4
|
module Sidekiq
|
3
5
|
class Settings
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
6
|
+
DEFAULT_QUEUE_LATENCY_VALUES = {
|
7
|
+
'monitoring' => 10.seconds.to_i,
|
8
|
+
'realtime' => 10.seconds.to_i,
|
9
|
+
'within1minute' => 1.minute.to_i,
|
10
|
+
'within5minutes' => 5.minutes.to_i,
|
11
|
+
'within30minutes' => 30.minutes.to_i,
|
12
|
+
'within1hour' => 1.hour.to_i,
|
13
|
+
'within1day' => 1.day.to_i,
|
14
|
+
'default' => 1.day.to_i
|
15
|
+
}.freeze
|
16
|
+
|
17
|
+
class << self
|
18
|
+
def queues
|
19
|
+
@queues ||= permitted_latency_values.sort_by(&:last).map(&:first).freeze
|
20
|
+
end
|
21
|
+
|
22
|
+
def concurrency
|
23
|
+
ENV.fetch('SIDEKIQ_THREADS', 25)
|
24
|
+
end
|
25
|
+
|
26
|
+
def permitted_latency_values
|
27
|
+
@permitted_latency_values ||= ENV.key?('SIDEKIQ_QUEUES') ? env_queue_latency_values.freeze : DEFAULT_QUEUE_LATENCY_VALUES
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
15
31
|
|
16
|
-
|
17
|
-
|
32
|
+
def env_queue_latency_values
|
33
|
+
{}.tap do |hash|
|
34
|
+
ENV['SIDEKIQ_QUEUES'].split(',').each do |entry|
|
35
|
+
queue_entry = entry.strip
|
36
|
+
if DEFAULT_QUEUE_LATENCY_VALUES.key?(queue_entry)
|
37
|
+
queue_name = queue_entry
|
38
|
+
hash[queue_name] = DEFAULT_QUEUE_LATENCY_VALUES[queue_entry]
|
39
|
+
elsif queue_entry.match(/\Awithin\d+.+\z/)
|
40
|
+
_, number, unit = queue_entry.partition(/\d+/)
|
41
|
+
hash[queue_entry] = number.to_i.public_send(unit.strip).to_i
|
42
|
+
elsif queue_entry.include?(':')
|
43
|
+
queue_name, latency_info = queue_entry.split(':')
|
44
|
+
_, number, unit = latency_info.partition(/\d+/)
|
45
|
+
hash[queue_name] = number.to_i.public_send(unit.strip).to_i
|
46
|
+
else
|
47
|
+
hash[queue_entry] = nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
18
52
|
end
|
19
53
|
end
|
20
54
|
end
|
@@ -6,10 +6,10 @@ module RooOnRails
|
|
6
6
|
module Sidekiq
|
7
7
|
# Returns stats on the current SLA performance of queues in a Sidekiq instance.
|
8
8
|
#
|
9
|
-
#
|
9
|
+
# Only returns stats for queues being processed by current Sidekiq process
|
10
10
|
class SlaMetric
|
11
11
|
def self.queue
|
12
|
-
queues =
|
12
|
+
queues = QueueLatency.queues
|
13
13
|
global_stats = ProcessScaling.new(queues)
|
14
14
|
global_stats.requested_processes
|
15
15
|
end
|
data/lib/roo_on_rails/version.rb
CHANGED
data/lib/roo_on_rails.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: roo_on_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julien Letessier
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-07-
|
11
|
+
date: 2017-07-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dotenv-rails
|
@@ -358,6 +358,7 @@ files:
|
|
358
358
|
- Gemfile
|
359
359
|
- Guardfile
|
360
360
|
- LICENSE.txt
|
361
|
+
- README.google_oauth2.md
|
361
362
|
- README.md
|
362
363
|
- Rakefile
|
363
364
|
- appraise
|
@@ -377,13 +378,12 @@ files:
|
|
377
378
|
- lib/roo_on_rails/checks.rb
|
378
379
|
- lib/roo_on_rails/checks/base.rb
|
379
380
|
- lib/roo_on_rails/checks/documentation/playbook.rb
|
381
|
+
- lib/roo_on_rails/checks/documentation/playbook_template.md
|
380
382
|
- lib/roo_on_rails/checks/env_specific.rb
|
381
383
|
- lib/roo_on_rails/checks/environment.rb
|
382
384
|
- lib/roo_on_rails/checks/git/origin.rb
|
383
385
|
- lib/roo_on_rails/checks/github/branch_protection.rb
|
384
386
|
- lib/roo_on_rails/checks/github/token.rb
|
385
|
-
- lib/roo_on_rails/checks/google_oauth/_template.rb
|
386
|
-
- lib/roo_on_rails/checks/google_oauth/initializer.rb
|
387
387
|
- lib/roo_on_rails/checks/helpers.rb
|
388
388
|
- lib/roo_on_rails/checks/heroku/app_exists.rb
|
389
389
|
- lib/roo_on_rails/checks/heroku/drains_metrics.rb
|
@@ -408,11 +408,10 @@ files:
|
|
408
408
|
- lib/roo_on_rails/harness.rb
|
409
409
|
- lib/roo_on_rails/logfmt.rb
|
410
410
|
- lib/roo_on_rails/papertrail_client.rb
|
411
|
-
- lib/roo_on_rails/rack/google_oauth.rb
|
412
411
|
- lib/roo_on_rails/rack/safe_timeouts.rb
|
413
412
|
- lib/roo_on_rails/railtie.rb
|
414
413
|
- lib/roo_on_rails/railties/database.rb
|
415
|
-
- lib/roo_on_rails/railties/
|
414
|
+
- lib/roo_on_rails/railties/google_oauth.rb
|
416
415
|
- lib/roo_on_rails/railties/http.rb
|
417
416
|
- lib/roo_on_rails/railties/new_relic.rb
|
418
417
|
- lib/roo_on_rails/railties/rake_tasks.rb
|
@@ -1,49 +0,0 @@
|
|
1
|
-
# Google Oauth initializer, generated by RooOnRails
|
2
|
-
|
3
|
-
require 'roo_on_rails/rack/google_oauth'
|
4
|
-
|
5
|
-
Rails.application.config.middleware.use RooOnRails::Rack::GoogleOauth do |env|
|
6
|
-
# This is your auth strategy.
|
7
|
-
# Here you're supposed to do something with the OAuth payload and
|
8
|
-
# return a valid Rack response.
|
9
|
-
|
10
|
-
# A simple and insecure example:
|
11
|
-
#
|
12
|
-
require 'digest/md5'
|
13
|
-
auth_data = env['omniauth.auth']
|
14
|
-
naive_token = Digest::MD5.hexdigest(auth_data.info.email.downcase)
|
15
|
-
expires_in = Time.current + 60 * 60 * 24
|
16
|
-
headers = { 'Location' => '/' }
|
17
|
-
Rack::Utils.set_cookie_header!(headers, 'naive_auth_cookie', {
|
18
|
-
value: naive_token, expires: expires_in, path: '/'
|
19
|
-
})
|
20
|
-
[302, headers, ['You are being redirecred to /']]
|
21
|
-
|
22
|
-
# You can also hand it over to a Rails controller action, where the
|
23
|
-
# OAuth payload will be available in `request.env['omniauth.auth']`.
|
24
|
-
# If you do this, the controller will take care of returning a valid
|
25
|
-
# response for Rack.
|
26
|
-
#
|
27
|
-
# This is the recommenced approach as it makes it easier to use
|
28
|
-
# Rails encrypted cookies and other security features.
|
29
|
-
#
|
30
|
-
# For example:
|
31
|
-
# MyAuthController.action(:login).call(env)
|
32
|
-
end
|
33
|
-
|
34
|
-
# What to do in case of failure.
|
35
|
-
# Must be a 302 redirect.
|
36
|
-
# It can invoke a Rails controller action
|
37
|
-
#
|
38
|
-
OmniAuth.config.on_failure = proc do |env|
|
39
|
-
error = env['omniauth.error'] # e.g. #<OmniAuth::Strategies::OAuth2::CallbackError: OmniAuth::Strategies::OAuth2::CallbackError>
|
40
|
-
details = error.message # e.g. "invalid_hd | Invalid Hosted Domain"
|
41
|
-
error_type = env['omniauth.error.type'] # e.g. :invalid_credentials
|
42
|
-
|
43
|
-
Rails.logger.info("[RooOnRails] Login failed (#{error_type}): #{details}")
|
44
|
-
|
45
|
-
# To use a rails controller;
|
46
|
-
# MyAuthController.action(:login_failed).call(env)
|
47
|
-
|
48
|
-
[302, { 'Location' => '/' }, ['']]
|
49
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
require 'roo_on_rails/config'
|
2
|
-
require 'roo_on_rails/checks/base'
|
3
|
-
require 'fileutils'
|
4
|
-
|
5
|
-
module RooOnRails
|
6
|
-
module Checks
|
7
|
-
module GoogleOauth
|
8
|
-
class Initializer < Base
|
9
|
-
LOCATION = 'config/initializers/google_oauth.rb'.freeze
|
10
|
-
|
11
|
-
def intro
|
12
|
-
'Google Oauth protection'
|
13
|
-
end
|
14
|
-
|
15
|
-
def call
|
16
|
-
if RooOnRails::Config.google_auth_enabled?
|
17
|
-
check_initializer
|
18
|
-
else
|
19
|
-
pass 'Google Oauth is not enabled. Doing nothing'
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def fix
|
24
|
-
FileUtils.cp(template, LOCATION)
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def check_initializer
|
30
|
-
if File.exist? LOCATION
|
31
|
-
pass 'Google Oauth initializer is present. Doing nothing.'
|
32
|
-
else
|
33
|
-
fail! 'Google Oauth is enabled but the initializer is missing.'
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def template
|
38
|
-
File.join(__dir__, '_template.rb')
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
require 'rack'
|
2
|
-
|
3
|
-
module RooOnRails
|
4
|
-
module Rack
|
5
|
-
class GoogleOauth
|
6
|
-
OAUTH_CALLBACK = '/auth/google_oauth2/callback'.freeze
|
7
|
-
|
8
|
-
def initialize(app, *args, &block)
|
9
|
-
@app = app
|
10
|
-
@args = args
|
11
|
-
@strategy = block
|
12
|
-
end
|
13
|
-
|
14
|
-
def call(env)
|
15
|
-
if is_oauth_callback?(env)
|
16
|
-
@strategy.call(env)
|
17
|
-
else
|
18
|
-
send_to_upstream(env)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def send_to_upstream(env)
|
25
|
-
@app.call(env)
|
26
|
-
end
|
27
|
-
|
28
|
-
def is_oauth_callback?(env)
|
29
|
-
request = ::Rack::Request.new(env)
|
30
|
-
request.fullpath.start_with?(OAUTH_CALLBACK)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'roo_on_rails/config'
|
2
|
-
require 'omniauth'
|
3
|
-
require 'omniauth-google-oauth2'
|
4
|
-
require 'active_support/core_ext/object/blank'
|
5
|
-
|
6
|
-
module RooOnRails
|
7
|
-
module Railties
|
8
|
-
class GoogleAuth < Rails::Railtie
|
9
|
-
initializer 'roo_on_rails.google_auth' do |app|
|
10
|
-
if RooOnRails::Config.google_auth_enabled?
|
11
|
-
$stderr.puts 'initializer roo_on_rails.google_auth'
|
12
|
-
|
13
|
-
google_oauth2_client_id = ENV.fetch('GOOGLE_AUTH_CLIENT_ID')
|
14
|
-
google_oauth2_client_secret = ENV.fetch('GOOGLE_AUTH_CLIENT_SECRET')
|
15
|
-
|
16
|
-
options = {
|
17
|
-
path_prefix: '/auth',
|
18
|
-
prompt: 'consent',
|
19
|
-
}
|
20
|
-
|
21
|
-
domain_list = ENV.fetch('GOOGLE_AUTH_ALLOWED_DOMAINS', '').split(',').reject(&:blank?)
|
22
|
-
options[:hd] = domain_list if domain_list.any?
|
23
|
-
|
24
|
-
app.config.middleware.use ::OmniAuth::Builder do
|
25
|
-
provider :google_oauth2,
|
26
|
-
google_oauth2_client_id,
|
27
|
-
google_oauth2_client_secret,
|
28
|
-
options
|
29
|
-
end
|
30
|
-
else
|
31
|
-
$stderr.puts 'skipping initializer roo_on_rails.google_auth'
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|