Rails6のActionDispatch::HostAuthorization設定とokcomputerを利用した Nginx - Rails - RDS
という経路のヘルスチェックの共存に少しコツが必要だったので記事にしました。
ActionDispatch::HostAuthorization
https://github.com/rails/rails/pull/33145
Rails6から追加された、DNSリバインディング攻撃から保護する新機能です。
下記のように設定することで、指定したホスト以外からのアクセスはエラーとなります。
Rails.application.config.hosts << "product.com"
okcomputer
https://github.com/sportngin/okcomputer
HealthCheck系のgemです。
2019/10/26(執筆時点の一週間前)にRails6対応がリリースされました。
Rails - DB
という経路のヘルスチェックを簡単に追加することができます。
例えば、下記のような設定で、/custom_path
というパスにDBまでのヘルスチェック機能を追加することができます。
# config/initializers/okcomputer.rb
OkComputer.mount_at = false
# config/routes.rb, at any priority that suits you
mount OkComputer::Engine, at: "/custom_path"
発生した問題
Rails6 + AWSで下記の構成のようなアプリを開発していました。
ECS
+----------------+
ALB---|--Nginx--Rails--|---RDS
+----------------+
Rails6のHostAuthorization
とokcomputer
gemを利用し、/healthcheck
というパスでALBからのヘルスチェックをDBまで通して行おうとしました。
しかし、Railsが403エラー
を返し、ヘルスチェックが失敗してしまいました。
問題の原因
Nginx、Railsの設定はそれぞれ下記のようになっていました。
Nginxの設定
# healthcheck部分のみ抜粋
server {
location /healthcheck {
access_log off;
proxy_pass http://rails:3000;
}
}
Railsの設定
Rails.application.config.hosts << "product.com"
原因はシンプルで、**「ヘルスチェック時のホスト名がproduct.com
でないからエラーになっていた」**というものです。
対策
いくつか対策方法が考えられますが、今回はシンプルにNginxでHostヘッダを設定する対策を採用しました。
Nginxの設定
server {
location /healthcheck {
access_log off;
# 以下を追加
proxy_set_header Host healthcheck.localhost;
proxy_pass http://rails:3000;
}
}
Railsの設定
Rails.application.config.hosts << "product.com"
Rails.application.config.hosts << "healthcheck.localhost"
この設定で無事、ALBからのhealthcheckでhealthyとなりました!
もう少しスマートな対応方法ありましたら、教えていただけると嬉しいです