Skip to content

Commit

Permalink
Merge branch 'main' into kzkn-20230930-task-protection
Browse files Browse the repository at this point in the history
  • Loading branch information
kzkn authored Oct 31, 2023
2 parents c30dcb7 + 9ed506f commit dd3a77b
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 13 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## [Unreleased]
## リリース内容は [Releases](https://github.com/SonicGarden/sg_fargate_rails/releases) に移動しました

## [0.1.6](https://github.com/SonicGarden/sg_fargate_rails/compare/v0.1.5...v0.1.6)

Expand Down
13 changes: 12 additions & 1 deletion lib/sg_fargate_rails/config.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
module SgFargateRails
class Config
attr_accessor :proxy_ip_addresses, :paths_to_allow_access_only_from_proxy
attr_accessor :paths_to_allow_access_only_from_proxy
attr_reader :proxy_ip_addresses

def initialize
self.proxy_ip_addresses = ENV['SG_PROXY_IP_ADDRESSES']
end

def proxy_ip_addresses=(ip_addresses)
@proxy_ip_addresses = Array(ip_addresses).flat_map do |ip_address_str|
ip_address_str.split(',').map(&:strip).reject(&:blank?).map { |ip| IPAddr.new(ip) }
end
end

def proxy_access?(ip_address)
@proxy_ip_addresses.any? { |proxy_ip_address| proxy_ip_address.include?(ip_address) }
end
end
end
6 changes: 5 additions & 1 deletion lib/sg_fargate_rails/maintenance.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def initialize(app, options = {})
end

def call(env)
if maintenance_mode?(env) && !public_file_access?(env)
if maintenance_mode?(env) && !public_file_access?(env) && !proxy_access?(Rack::Request.new(env))
headers = { 'Content-Type' => 'text/html' }
[503, headers, File.open(maintenance_file_path)]
else
Expand All @@ -36,5 +36,9 @@ def public_files
def maintenance_file_path
Rails.public_path.join('503.html')
end

def proxy_access?(req)
SgFargateRails.config.proxy_access?(req.ip) || req.forwarded_for&.any? { |forwarded_for| SgFargateRails.config.proxy_access?(forwarded_for) }
end
end
end
13 changes: 4 additions & 9 deletions lib/sg_fargate_rails/rack_attack.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@ module SgFargateRails
class RackAttack
class << self
def setup
proxy_ip_addresses = Array(SgFargateRails.config.proxy_ip_addresses).flat_map do |ip_address_str|
ip_address_str.split(',').map(&:strip).reject(&:blank?)
end
return if proxy_ip_addresses.empty?
return if SgFargateRails.config.proxy_ip_addresses.empty?

Rack::Attack.blocklist('allow only from proxy') do |req|
ip_retricted_path?(req.path) && !access_from?(req, proxy_ip_addresses)
ip_retricted_path?(req.path) && !proxy_access?(req)
end
end

Expand All @@ -19,10 +16,8 @@ def ip_retricted_path?(path)
rectricted_paths.any? { path.match?(/^#{_1}/) }
end

def access_from?(req, proxy_ip_addresses)
proxy_ip_addresses.any? do |proxy_ip_address|
req.ip == proxy_ip_address || req.forwarded_for&.include?(proxy_ip_address)
end
def proxy_access?(req)
SgFargateRails.config.proxy_access?(req.ip) || req.forwarded_for&.any? { |forwarded_for| SgFargateRails.config.proxy_access?(forwarded_for) }
end
end
end
Expand Down
2 changes: 2 additions & 0 deletions lib/sg_fargate_rails/railtie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
require 'sg_fargate_rails/healthcheck'
require 'sg_fargate_rails/maintenance'
require 'sg_fargate_rails/rack_attack'
require 'sg_fargate_rails/remote_ip'
require 'sg_fargate_rails/task_protection'

module SgFargateRails
Expand All @@ -13,6 +14,7 @@ class Railtie < ::Rails::Railtie
app.config.middleware.insert 0, SgFargateRails::AdjustCloudfrontHeaders
app.config.middleware.insert 1, SgFargateRails::Healthcheck
app.config.middleware.insert 2, SgFargateRails::Maintenance
app.config.middleware.swap ActionDispatch::RemoteIp, SgFargateRails::RemoteIp, app.config.action_dispatch.ip_spoofing_check, app.config.action_dispatch.trusted_proxies
end
end
end
Expand Down
12 changes: 12 additions & 0 deletions lib/sg_fargate_rails/remote_ip.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module SgFargateRails
# NOTE: HTTP_CLOUDFRONT_VIEWER_ADDRESSを考慮するように上書きしている
# SEE: https://github.com/rails/rails/blob/main/actionpack/lib/action_dispatch/middleware/remote_ip.rb
class RemoteIp < ActionDispatch::RemoteIp
def call(env)
req = ActionDispatch::Request.new env
# NOTE: HTTP_CLOUDFRONT_VIEWER_ADDRESSヘッダには127.0.0.1:3000といったIP4アドレスや2406:2d40:3090:af00:25c1:6071:b820:8e47:3000といったIP6アドレスが入っている
req.remote_ip = req.headers['HTTP_CLOUDFRONT_VIEWER_ADDRESS'] ? req.headers['HTTP_CLOUDFRONT_VIEWER_ADDRESS'].remove(/:\d+$/) : ActionDispatch::RemoteIp::GetIp.new(req, check_ip, proxies)
@app.call(req.env)
end
end
end
2 changes: 1 addition & 1 deletion lib/sg_fargate_rails/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module SgFargateRails
VERSION = "0.1.6"
VERSION = "0.1.8"
end

0 comments on commit dd3a77b

Please sign in to comment.