Подтвердить что ты не робот

Как я могу защитить паролем мой /sidekiq маршрут (т.е. Требуется аутентификация для инструмента Sidekiq:: Web)?

Я использую sidekiq в моем приложении rails. По умолчанию, Sidekiq может быть доступен кем угодно, добавив "/sidekiq" после URL. Я хочу защитить паролем/аутентифицировать только часть sidekiq. Как я могу это сделать?

4b9b3361

Ответ 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.

Также используйте & (не используйте &&), чтобы оно не закорачивалось.

И, наконец, используйте дайджесты, чтобы остановить утечку информации о длине (по умолчанию 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