Я использую sidekiq в моем приложении rails. По умолчанию, Sidekiq может быть доступен кем угодно, добавив "/sidekiq" после URL. Я хочу защитить паролем/аутентифицировать только часть sidekiq. Как я могу это сделать?
Как я могу защитить паролем мой /sidekiq маршрут (т.е. Требуется аутентификация для инструмента Sidekiq:: Web)?
Ответ 1
Поместите следующее в ваш инициализатор sidekiq
require 'sidekiq'
require 'sidekiq/web'
Sidekiq::Web.use(Rack::Auth::Basic) do |user, password|
[user, password] == ["sidekiqadmin", "yourpassword"]
end
И в файле маршрутов:
authenticate :user do
mount Sidekiq::Web => '/sidekiq'
end
Ответ 2
См. "Безопасность" в разделе https://github.com/mperham/sidekiq/wiki/Monitoring
Sidekiq:: Web использует Rack:: Protection для защиты вашего приложения от типичных сетевых атак (таких как CSRF, XSS и т.д.). Rack:: Protection приведет к аннулированию вашего сеанса и вызову
Forbidden
, если он обнаружит, что ваш запрос не отвечает требованиям безопасности. Одна из возможных ситуаций - заставить ваше приложение работать за обратным прокси-сервером и не передавать ему важные заголовки (X-Forwarded-For
,X-Forwarded-Proto
). Такую ситуацию и решение можно найти в этой статье и issue # 2560...
Ответ 3
Если вы используете Devise (или другую проверку на основе Warden), вы можете сделать это, предположив, что у вас есть модель AdminUser в вашем приложении.
# config/routes.rb
# This defines the authentication constraint
constraint = lambda do |request|
request.env['warden'].authenticate!({ scope: :admin_user })
end
# This mounts the route using the constraint.
# You could use any other path to make it less obvious
constraints constraint do
mount Sidekiq::Web => '/sidekiq'
end
Ответ 4
Извините, что опоздал на вечеринку, но Sidekiq wiki рекомендует следующее для Devise:
Чтобы разрешить любому аутентифицированному User
:
# config/routes.rb
authenticate :user do
mount Sidekiq::Web => '/sidekiq'
end
Чтобы ограничить доступ к User.admin?
# config/routes.rb
authenticate :user, lambda { |u| u.admin? } do
mount Sidekiq::Web => '/sidekiq'
end
Этот вики-пост также имеет много других схем безопасности.
Это было протестировано с использованием Rails 5.1.3, Devise 4.3 и Sidekiq 5.0
Ответ 5
Если вы свертывают свою собственную пользовательскую проверку подлинности, то вы можете использовать приведенный ниже пример, который ссылается на документы здесь.
# lib/admin_constraint.rb
class AdminConstraint
def matches?(request)
return false unless request.session[:user_id]
user = User.find request.session[:user_id]
user && user.admin?
end
end
# config/routes.rb
require 'sidekiq/web'
require 'admin_constraint'
mount Sidekiq::Web => '/sidekiq', :constraints => AdminConstraint.new
Ответ 6
Другой вариант - добавить что-то вроде CanCan и специальный доступ на основе ролей.
Ответ 7
Если вы используете Sorcery для аутентификации, здесь how для использования ограничений маршрутов Rails для защиты определенных маршрутов.
Скопировано здесь из вики-колдовства для избыточности:
В этом учебном пособии показано, как использовать ограничения маршрутов Rails с помощью Sorcery gem. Благодаря @anthonator для его написания!
Сначала определите модуль UserConstraint
, который будет использоваться для всех ограничений:
module RouteConstraints::UserConstraint
def current_user(request)
User.find_by_id(request.session[:user_id])
end
end
Затем, имея этот модуль, вы можете указать определенные классы ограничений. В этих примерах первый маршрут будет работать только в том случае, если пользователь не зарегистрирован, второй будет работать только для зарегистрированного пользователя, который является администратором:
class RouteConstraints::NoUserRequiredConstraint
include RouteConstraints::UserConstraint
def matches?(request)
!current_user(request).present?
end
end
class RouteConstraints::AdminRequiredConstraint
include RouteConstraints::UserConstraint
def matches?(request)
user = current_user(request)
user.present? && user.is_admin?
end
end
Наконец, вы можете добавить ограничения на config/routes.rb
:
MyApp::Application.routes.draw do
# other routes …
root :to => 'admin#dashboard', :constraints => RouteConstraints::AdminRequiredConstraint.new
root :to => 'home#welcome', :constraints => RouteConstraints::NoUserRequiredConstraint.new
end
Ответ 8
Принятый ответ хорош, но я думаю, что он может быть реализован более безопасно, как упоминается в документации Sidekiq.
Чтобы защитить приложение от временных атак, используйте ActiveSupport::SecurityUtils.secure_compare
.
- Смотрите https://codahale.com/a-lesson-in-timing-attacks/
- Смотрите https://thisdata.com/blog/timing-attacks-against-string-comparison/
Также используйте &
(не используйте &&
), чтобы оно не закорачивалось.
И, наконец, используйте дайджесты, чтобы остановить утечку информации о длине (по умолчанию secure_compare
в Active Support 5).
Активная поддержка 5. Благодаря Rails PR # 24510 параметры, передаваемые в secure_compare
по secure_compare
проходят через Digest::SHA256.hexdigest
.
require 'active_support/security_utils'
require 'sidekiq'
require 'sidekiq/web'
Sidekiq::Web.use(Rack::Auth::Basic) do |user, password|
# Protect against timing attacks:
# - See https://codahale.com/a-lesson-in-timing-attacks/
# - See https://thisdata.com/blog/timing-attacks-against-string-comparison/
# - Use & (do not use &&) so that it doesn't short circuit.
# - Use digests to stop length information leaking
ActiveSupport::SecurityUtils.secure_compare(user, ENV["SIDEKIQ_ADMIN_USER"]) &
ActiveSupport::SecurityUtils.secure_compare(password, ENV["SIDEKIQ_ADMIN_PASSWORD"])
end
Активная поддержка 4:
require 'active_support/security_utils'
require 'sidekiq'
require 'sidekiq/web'
Sidekiq::Web.use(Rack::Auth::Basic) do |user, password|
# Protect against timing attacks:
# - See https://codahale.com/a-lesson-in-timing-attacks/
# - See https://thisdata.com/blog/timing-attacks-against-string-comparison/
# - Use & (do not use &&) so that it doesn't short circuit.
# - Use digests to stop length information leaking
ActiveSupport::SecurityUtils.secure_compare(
::Digest::SHA256.hexdigest(user),
::Digest::SHA256.hexdigest(ENV["SIDEKIQ_ADMIN_USER"])
) &
ActiveSupport::SecurityUtils.secure_compare(
::Digest::SHA256.hexdigest(password),
::Digest::SHA256.hexdigest(ENV["SIDEKIQ_ADMIN_PASSWORD"])
)
end