roo_on_rails 1.7.0 → 1.8.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 +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
|