mirror of
https://github.com/jenkinsci/jenkins.git
synced 2026-11-15 21:12:15 +00:00
[FIXED JENKINS-23294] Deal with X-Forwarded-Port.
If this is set, use it instead of ServletRequest.getServerPort() for purposes of getRootUrlFromRequest(). Also treat the default port as scheme-specific in that method (which presumes that we in fact got the reported port right). And enhance the reverse proxy setup monitor to validate that the Referer header (/manage) actually matches what we have computed from getRootUrlFromRequest; if it does not, something is messed up, though it may require some digging to find what. (Would be better to let the monitor specify the exact problem it determined, though this is not always actually possible; for example if you are missing AllowEncodedSlashes NoDecode in Apache, you just get a 404 from Apache without even getting to Jenkins.)
This commit is contained in:
1 parent
1aec030e08
commit
cffe9df017
4 files changed
+78
-31
No files matched your search
@@ -37,7 +37,10 @@ import org.junit.runner.RunWith;
|
||||
import org.jvnet.hudson.test.Bug;
|
||||
import org.kohsuke.stapler.Stapler;
|
||||
import org.kohsuke.stapler.StaplerRequest;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
|
||||
@@ -107,19 +110,34 @@ public class JenkinsGetRootUrlTest {
|
||||
@Test
|
||||
public void useForwardedProtoWhenPresent() {
|
||||
configured("https://ci/jenkins/");
|
||||
|
||||
|
||||
// Without a forwarded protocol, it should use the request protocol
|
||||
accessing("http://ci/jenkins/");
|
||||
rootUrlFromRequestIs("http://ci/jenkins/");
|
||||
|
||||
|
||||
accessing("http://ci:8080/jenkins/");
|
||||
rootUrlFromRequestIs("http://ci:8080/jenkins/");
|
||||
|
||||
// With a forwarded protocol, it should use the forwarded protocol
|
||||
accessing("http://ci/jenkins/");
|
||||
accessing("https://ci/jenkins/");
|
||||
withHeader("X-Forwarded-Proto", "https");
|
||||
rootUrlFromRequestIs("https://ci/jenkins/");
|
||||
|
||||
accessing("https://ci/jenkins/");
|
||||
|
||||
accessing("http://ci/jenkins/");
|
||||
withHeader("X-Forwarded-Proto", "http");
|
||||
rootUrlFromRequestIs("http://ci/jenkins/");
|
||||
|
||||
// ServletRequest.getServerPort is not always meaningful.
|
||||
// http://tomcat.apache.org/tomcat-5.5-doc/config/http.html#Proxy_Support or
|
||||
// http://wiki.eclipse.org/Jetty/Howto/Configure_mod_proxy#Configuring_mod_proxy_as_a_Reverse_Proxy.5D
|
||||
// can be used to ensure that it is hardcoded or that X-Forwarded-Port is interpreted.
|
||||
// But this is not something that can be configured purely from the reverse proxy; the container must be modified too.
|
||||
// And the standard bundled Jetty in Jenkins does not work that way;
|
||||
// it will return 80 even when Jenkins is fronted by Apache with SSL.
|
||||
accessing("http://ci/jenkins/"); // as if the container is not aware of the forwarded port
|
||||
withHeader("X-Forwarded-Port", "443"); // but we tell it
|
||||
withHeader("X-Forwarded-Proto", "https");
|
||||
rootUrlFromRequestIs("https://ci/jenkins/");
|
||||
}
|
||||
|
||||
private void rootUrlFromRequestIs(final String expectedRootUrl) {
|
||||
@@ -137,7 +155,7 @@ public class JenkinsGetRootUrlTest {
|
||||
when(config.getUrl()).thenReturn(configuredHost);
|
||||
}
|
||||
|
||||
private void withHeader(String name, String value) {
|
||||
private void withHeader(String name, final String value) {
|
||||
final StaplerRequest req = Stapler.getCurrentRequest();
|
||||
when(req.getHeader(name)).thenReturn(value);
|
||||
}
|
||||
@@ -149,8 +167,15 @@ public class JenkinsGetRootUrlTest {
|
||||
final StaplerRequest req = mock(StaplerRequest.class);
|
||||
when(req.getScheme()).thenReturn(url.getProtocol());
|
||||
when(req.getServerName()).thenReturn(url.getHost());
|
||||
when(req.getServerPort()).thenReturn(url.getPort() == -1 ? 80 : url.getPort());
|
||||
when(req.getServerPort()).thenReturn(url.getPort() == -1 ? ("https".equals(url.getProtocol()) ? 443 : 80) : url.getPort());
|
||||
when(req.getContextPath()).thenReturn(url.getPath().replaceAll("/$", ""));
|
||||
when(req.getIntHeader(anyString())).thenAnswer(new Answer<Integer>() {
|
||||
@Override public Integer answer(InvocationOnMock invocation) throws Throwable {
|
||||
String name = (String) invocation.getArguments()[0];
|
||||
String value = ((StaplerRequest) invocation.getMock()).getHeader(name);
|
||||
return value != null ? Integer.parseInt(value) : -1;
|
||||
}
|
||||
});
|
||||
|
||||
when(Stapler.getCurrentRequest()).thenReturn(req);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user