Default deny forward_auth requests
This commit is contained in:
@@ -71,8 +71,9 @@ module Api
|
|||||||
|
|
||||||
Rails.logger.info "ForwardAuth: User #{user.email_address} granted access to #{forwarded_host} by app #{app.domain_pattern} (policy: #{app.policy_for_user(user)})"
|
Rails.logger.info "ForwardAuth: User #{user.email_address} granted access to #{forwarded_host} by app #{app.domain_pattern} (policy: #{app.policy_for_user(user)})"
|
||||||
else
|
else
|
||||||
# No application found - allow access with default headers (original behavior)
|
# No application found - DENY by default (fail-closed security)
|
||||||
Rails.logger.info "ForwardAuth: No application found for domain: #{forwarded_host}, allowing with default headers"
|
Rails.logger.info "ForwardAuth: Access denied to #{forwarded_host} - no authentication rule configured"
|
||||||
|
return render_forbidden("No authentication rule configured for this domain")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
Rails.logger.info "ForwardAuth: User #{user.email_address} authenticated (no domain specified)"
|
Rails.logger.info "ForwardAuth: User #{user.email_address} authenticated (no domain specified)"
|
||||||
|
|||||||
@@ -46,14 +46,13 @@ module Api
|
|||||||
assert_response 200
|
assert_response 200
|
||||||
end
|
end
|
||||||
|
|
||||||
test "should return 200 with default headers when no rule matches" do
|
test "should return 403 when no rule matches (fail-closed security)" do
|
||||||
sign_in_as(@user)
|
sign_in_as(@user)
|
||||||
|
|
||||||
get "/api/verify", headers: { "X-Forwarded-Host" => "unknown.example.com" }
|
get "/api/verify", headers: { "X-Forwarded-Host" => "unknown.example.com" }
|
||||||
|
|
||||||
assert_response 200
|
assert_response 403
|
||||||
assert_equal @user.email_address, response.headers["x-remote-user"]
|
assert_equal "No authentication rule configured for this domain", response.headers["x-auth-reason"]
|
||||||
assert_equal @user.email_address, response.headers["x-remote-email"]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test "should return 403 when rule exists but is inactive" do
|
test "should return 403 when rule exists but is inactive" do
|
||||||
@@ -97,7 +96,8 @@ module Api
|
|||||||
assert_response 200
|
assert_response 200
|
||||||
|
|
||||||
get "/api/verify", headers: { "X-Forwarded-Host" => "other.com" }
|
get "/api/verify", headers: { "X-Forwarded-Host" => "other.com" }
|
||||||
assert_response 200 # Falls back to default behavior
|
assert_response 403 # No rule configured - fail-closed
|
||||||
|
assert_equal "No authentication rule configured for this domain", response.headers["x-auth-reason"]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "should match exact domains correctly" do
|
test "should match exact domains correctly" do
|
||||||
@@ -108,7 +108,8 @@ module Api
|
|||||||
assert_response 200
|
assert_response 200
|
||||||
|
|
||||||
get "/api/verify", headers: { "X-Forwarded-Host" => "app.api.example.com" }
|
get "/api/verify", headers: { "X-Forwarded-Host" => "app.api.example.com" }
|
||||||
assert_response 200 # Falls back to default behavior
|
assert_response 403 # No rule configured - fail-closed
|
||||||
|
assert_equal "No authentication rule configured for this domain", response.headers["x-auth-reason"]
|
||||||
end
|
end
|
||||||
|
|
||||||
# Header Configuration Tests
|
# Header Configuration Tests
|
||||||
@@ -228,8 +229,9 @@ module Api
|
|||||||
|
|
||||||
get "/api/verify"
|
get "/api/verify"
|
||||||
|
|
||||||
assert_response 200
|
# User is authenticated but no domain rule matches (default test host)
|
||||||
# User is authenticated even without host headers
|
assert_response 403
|
||||||
|
assert_equal "No authentication rule configured for this domain", response.headers["x-auth-reason"]
|
||||||
end
|
end
|
||||||
|
|
||||||
# Security Tests
|
# Security Tests
|
||||||
@@ -239,7 +241,8 @@ module Api
|
|||||||
|
|
||||||
get "/api/verify", headers: { "X-Forwarded-Host" => long_domain }
|
get "/api/verify", headers: { "X-Forwarded-Host" => long_domain }
|
||||||
|
|
||||||
assert_response 200 # Should fall back to default behavior
|
assert_response 403 # No rule configured - fail-closed
|
||||||
|
assert_equal "No authentication rule configured for this domain", response.headers["x-auth-reason"]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "should handle case insensitive domain matching" do
|
test "should handle case insensitive domain matching" do
|
||||||
@@ -425,7 +428,8 @@ module Api
|
|||||||
"X-Forwarded-Host" => "测试.example.com"
|
"X-Forwarded-Host" => "测试.example.com"
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_response 200
|
assert_response 403 # No rule configured - fail-closed
|
||||||
|
assert_equal "No authentication rule configured for this domain", response.headers["x-auth-reason"]
|
||||||
end
|
end
|
||||||
|
|
||||||
# Protocol and Scheme Tests
|
# Protocol and Scheme Tests
|
||||||
@@ -478,16 +482,15 @@ module Api
|
|||||||
5.times do |i|
|
5.times do |i|
|
||||||
threads << Thread.new do
|
threads << Thread.new do
|
||||||
get "/api/verify", headers: { "X-Forwarded-Host" => "app#{i}.example.com" }
|
get "/api/verify", headers: { "X-Forwarded-Host" => "app#{i}.example.com" }
|
||||||
results << { status: response.status, user: response.headers["x-remote-user"] }
|
results << { status: response.status }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
threads.each(&:join)
|
threads.each(&:join)
|
||||||
|
|
||||||
# All requests should succeed
|
# All requests should be denied (no rules configured for these domains)
|
||||||
results.each do |result|
|
results.each do |result|
|
||||||
assert_equal 200, result[:status]
|
assert_equal 403, result[:status]
|
||||||
assert_equal @user.email_address, result[:user]
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -508,8 +511,9 @@ module Api
|
|||||||
"X-Forwarded-Host" => "test.example.com\0.evil.com"
|
"X-Forwarded-Host" => "test.example.com\0.evil.com"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Should handle null bytes safely
|
# Should handle null bytes safely - domain doesn't match any rule
|
||||||
assert_response 200
|
assert_response 403
|
||||||
|
assert_equal "No authentication rule configured for this domain", response.headers["x-auth-reason"]
|
||||||
end
|
end
|
||||||
|
|
||||||
# Performance and Load Tests
|
# Performance and Load Tests
|
||||||
@@ -521,7 +525,7 @@ module Api
|
|||||||
|
|
||||||
request_count.times do |i|
|
request_count.times do |i|
|
||||||
get "/api/verify", headers: { "X-Forwarded-Host" => "app#{i}.example.com" }
|
get "/api/verify", headers: { "X-Forwarded-Host" => "app#{i}.example.com" }
|
||||||
assert_response 200
|
assert_response 403 # No rules configured for these domains
|
||||||
end
|
end
|
||||||
|
|
||||||
total_time = Time.current - start_time
|
total_time = Time.current - start_time
|
||||||
|
|||||||
Reference in New Issue
Block a user