Skip to content

Commit f3b4092

Browse files
Brice Figureaujamtur01
Brice Figureau
authored andcommitted
Fix #2308 - Mongrel should use X-Forwarded-For
Mongrel puppet code uses REMOTE_ADDR to set the ip address which will be use to authenticate the client access. Since mongrel is always used in a proxy mode with Puppet, REMOTE_ADDR is always the address of the proxy (usually 127.0.0.1), which defeats the purpose. With this changeset, the mongrel code now uses the X-Forwarded-For HTTP header value if it is passed over the REMOTE_ADDR. Signed-off-by: Brice Figureau <[email protected]>
1 parent 7b0413e commit f3b4092

File tree

4 files changed

+33
-3
lines changed

4 files changed

+33
-3
lines changed

lib/puppet/network/http/mongrel/rest.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def set_response(response, result, status = 200)
6262
def client_info(request)
6363
result = {}
6464
params = request.params
65-
result[:ip] = params["REMOTE_ADDR"]
65+
result[:ip] = params["HTTP_X_FORWARDED_FOR"] ? params["HTTP_X_FORWARDED_FOR"].split(',').last.strip : params["REMOTE_ADDR"]
6666

6767
# JJM #906 The following dn.match regular expression is forgiving
6868
# enough to match the two Distinguished Name string contents

lib/puppet/network/http_server/mongrel.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ def process(request, response)
118118

119119
def client_info(request)
120120
params = request.params
121-
ip = params["REMOTE_ADDR"]
121+
ip = params["HTTP_X_FORWARDED_FOR"] ? params["HTTP_X_FORWARDED_FOR"].split(',').last.strip : params["REMOTE_ADDR"]
122122
# JJM #906 The following dn.match regular expression is forgiving
123123
# enough to match the two Distinguished Name string contents
124124
# coming from Apache, Pound or other reverse SSL proxies.

spec/unit/network/http/mongrel/rest.rb

+16
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,22 @@
152152
@handler.params(@request)[:ip].should == "ipaddress"
153153
end
154154

155+
it "should pass the client's provided X-Forwared-For value as the ip" do
156+
@request.stubs(:params).returns("HTTP_X_FORWARDED_FOR" => "ipaddress")
157+
@handler.params(@request)[:ip].should == "ipaddress"
158+
end
159+
160+
it "should pass the client's provided X-Forwared-For first value as the ip" do
161+
@request.stubs(:params).returns("HTTP_X_FORWARDED_FOR" => "ipproxy1,ipproxy2,ipaddress")
162+
@handler.params(@request)[:ip].should == "ipaddress"
163+
end
164+
165+
it "should pass the client's provided X-Forwared-For value as the ip instead of the REMOTE_ADDR" do
166+
@request.stubs(:params).returns("REMOTE_ADDR" => "remote_addr")
167+
@request.stubs(:params).returns("HTTP_X_FORWARDED_FOR" => "ipaddress")
168+
@handler.params(@request)[:ip].should == "ipaddress"
169+
end
170+
155171
it "should use the :ssl_client_header to determine the parameter when looking for the certificate" do
156172
Puppet.settings.stubs(:value).returns "eh"
157173
Puppet.settings.expects(:value).with(:ssl_client_header).returns "myheader"

test/network/server/mongrel_test.rb

+15-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,19 @@ def test_client_info
2929
params[Puppet[:ssl_client_header]] = ""
3030
params[Puppet[:ssl_client_verify_header]] = "failure"
3131
info = nil
32-
Resolv.expects(:getname).with(ip).returns("host.domain.com").times(3)
32+
Resolv.expects(:getname).with(ip).returns("host.domain.com").times(4)
33+
assert_nothing_raised("Could not call client_info") do
34+
info = mongrel.send(:client_info, obj)
35+
end
36+
assert(! info.authenticated?, "Client info object was marked valid even though headers were missing")
37+
assert_equal(ip, info.ip, "Did not copy over ip correctly")
38+
39+
assert_equal("host.domain.com", info.name, "Did not copy over hostname correctly")
40+
41+
# Now pass the X-Forwarded-For header and check it is preferred over REMOTE_ADDR
42+
params["REMOTE_ADDR"] = '127.0.0.1'
43+
params["HTTP_X_FORWARDED_FOR"] = ip
44+
info = nil
3345
assert_nothing_raised("Could not call client_info") do
3446
info = mongrel.send(:client_info, obj)
3547
end
@@ -39,6 +51,8 @@ def test_client_info
3951
assert_equal("host.domain.com", info.name, "Did not copy over hostname correctly")
4052

4153
# Now add a valid auth header.
54+
params["REMOTE_ADDR"] = ip
55+
params["HTTP_X_FORWARDED_FOR"] = nil
4256
params[Puppet[:ssl_client_header]] = "/CN=host.domain.com"
4357
assert_nothing_raised("Could not call client_info") do
4458
info = mongrel.send(:client_info, obj)

0 commit comments

Comments
 (0)