redis 如何使用密码保护我的/sidekiq路由(即是否需要对Sidekiq::Web工具进行身份验证?

pkln4tw6  于 2023-10-15  发布在  Redis
关注(0)|答案(9)|浏览(107)

我在我的rails应用程序中使用sidekiq。默认情况下,任何人都可以通过在URL后添加“/sidekiq”来访问Sidekiq。我想密码保护/身份验证只有sidekiq部分。我该怎么做?

hc8w905p

hc8w905p1#

将以下内容放入sidekiq初始化器中

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
  Rack::Utils.secure_compare(::Digest::SHA256.hexdigest(user), ::Digest::SHA256.hexdigest(ENV["SIDEKIQ_USER"])) &
  Rack::Utils.secure_compare(::Digest::SHA256.hexdigest(password), ::Digest::SHA256.hexdigest(ENV["SIDEKIQ_PASSWORD"]))
end

在routes文件中:

mount Sidekiq::Web => '/sidekiq'
6tqwzwtp

6tqwzwtp2#

很抱歉迟到了,但是Sidekiq's 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

This wiki post也有许多其他的安全方案。
这是使用Rails 5.1.3、Devise 4.3和Sidekiq 5.0测试的

wgx48brx

wgx48brx3#

参见https://github.com/mperham/sidekiq/wiki/Monitoring下的“安全性”
Sidekiq::Web使用Rack::Protection来保护您的应用程序免受典型的Web攻击(例如CSRFXSS等)。如果Rack::Protection发现您的请求不满足安全要求,它将使您的会话无效并引发Forbidden错误。其中一种可能的情况是,您的应用程序在反向代理之后工作,并且不向其传递重要的头(X-Forwarded-ForX-Forwarded-Proto)。这种情况和解决方案可以找到in this articleissue #2560.

kpbpu008

kpbpu0084#

如果您正在滚动自己的自定义身份验证,那么您可以使用下面的示例,该示例在此处的文档中引用。

# 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
zaq34kh6

zaq34kh65#

如果您正在使用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
mrwjdhj3

mrwjdhj36#

公认的答案是好的,但我认为它可以更安全地实现,正如Sidekiq文档所提到的(在我发布后,它被编辑以展示正确的解决方案)。
要保护您的应用免受计时攻击,请使用ActiveSupport::SecurityUtils.secure_compare

另外,使用&(不要使用&&),这样它就不会短路。
最后,使用扩展器来阻止长度信息泄漏(Active Support 5中的默认值为secure_compare)。
因此,在一个初始化器文件中,通常在Rails项目的config/initializers/sidekiq.rb中,根据您的Active Support/Rails版本,编写以下内容。

主动支持5+:由于Rails PR #24510,传递给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
jm81lzqq

jm81lzqq7#

如果您使用Sorcery进行身份验证,则可以使用how to use Rails routes constraints来保护某些路由。
这里复制从巫术维基冗余:
本教程展示了如何在Sorcery gem中使用Rails路由约束。感谢@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
b1payxdu

b1payxdu8#

另一种选择是添加类似CanCan和基于角色的特殊访问。

cetgtptt

cetgtptt9#

能够使用devise用户名/密码
这也适用于API

config/initializers/sidekiq.rb

require "sidekiq/web"

Sidekiq::Web.use Rack::Auth::Basic do |username, password|
    User.find_by(username: username)&.valid_password?(password)
end

config/routes.rb

mount Sidekiq::Web => "/sidekiq"

相关问题