Skip to content

Commit

Permalink
[JENKINS-75160] NO_PROXY configuration seems to be ignored (#972)
Browse files Browse the repository at this point in the history
Fix proxy configuration to be used in the Apache client created from the ProxyConfiguration class using only the hostname instead passing the configured serverURL. The NO_PROXY configuration matches only hostname, that means if the given hostname contains also scheme or port match fails.
  • Loading branch information
nfalco79 committed Jan 18, 2025
1 parent c4dd43b commit 7645694
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -166,17 +166,17 @@ protected HttpClientBuilder setupClientBuilder(@Nullable String host) {
context = HttpClientContext.create();
authenticator.configureContext(context, getHost());
}
setClientProxyParams(host, httpClientBuilder);
setClientProxyParams(httpClientBuilder);
return httpClientBuilder;
}

private void setClientProxyParams(String host, HttpClientBuilder builder) {
protected void setClientProxyParams(HttpClientBuilder builder) {
Jenkins jenkins = Jenkins.getInstanceOrNull(); // because unit test
ProxyConfiguration proxyConfig = jenkins != null ? jenkins.proxy : null;

final Proxy proxy;
if (proxyConfig != null) {
proxy = proxyConfig.createProxy(host);
proxy = proxyConfig.createProxy(getHost().getHostName());
} else {
proxy = Proxy.NO_PROXY;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,11 @@
import com.cloudbees.jenkins.plugins.bitbucket.client.repository.BitbucketCloudRepository;
import com.cloudbees.jenkins.plugins.bitbucket.endpoints.BitbucketCloudEndpoint;
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.JsonParser;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.ProxyConfiguration;
import io.jenkins.cli.shaded.org.apache.commons.lang.RandomStringUtils;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Optional;
Expand All @@ -51,13 +50,9 @@

import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

class BitbucketCloudApiClientTest {

Expand All @@ -69,17 +64,13 @@ private String loadPayload(String api) throws IOException {

@Test
@WithJenkins
void test_proxy_configurad_without_password(JenkinsRule r) throws Exception {
Proxy proxy = mock(Proxy.class);
when(proxy.address()).thenReturn(new InetSocketAddress("proxy.lan", 8080));
ProxyConfiguration proxyConfiguration = mock(ProxyConfiguration.class);
doReturn(proxy).when(proxyConfiguration).createProxy(anyString());
doReturn("username").when(proxyConfiguration).getUserName();
void test_proxy_configurated_without_password(JenkinsRule r) throws Exception {
ProxyConfiguration proxyConfiguration = spy(new ProxyConfiguration("proxy.lan", 8080, "username", null));

r.jenkins.setProxy(proxyConfiguration);
BitbucketIntegrationClientFactory.getApiMockClient(BitbucketCloudEndpoint.SERVER_URL);

verify(proxyConfiguration).createProxy(eq("bitbucket.org"));
verify(proxyConfiguration).createProxy("api.bitbucket.org");
verify(proxyConfiguration).getUserName();
verify(proxyConfiguration).getSecretPassword();
}
Expand All @@ -94,8 +85,7 @@ void verify_status_notitication_name_max_length() throws Exception {

client.postBuildStatus(status);

IRequestAudit clientAudit = ((IRequestAudit) client).getAudit();
HttpRequestBase request = extractRequest(clientAudit);
HttpRequestBase request = extractRequest(client);
assertThat(request).isNotNull()
.isInstanceOf(HttpPost.class);
try (InputStream content = ((HttpPost) request).getEntity().getContent()) {
Expand All @@ -104,12 +94,17 @@ void verify_status_notitication_name_max_length() throws Exception {
}
}

private HttpRequestBase extractRequest(IRequestAudit clientAudit) {
private HttpRequestBase extractRequest(@NonNull BitbucketApi client) {
IRequestAudit audit = ((IRequestAudit) client).getAudit();
ArgumentCaptor<HttpRequestBase> captor = ArgumentCaptor.forClass(HttpRequestBase.class);
verify(clientAudit).request(captor.capture());
verify(audit).request(captor.capture());
return captor.getValue();
}

private void resetAudit(@NonNull BitbucketApi client) {
reset(((IRequestAudit) client).getAudit());
}

@Test
void get_repository_parse_correctly_date_from_cloud() throws Exception {
BitbucketCloudRepository repository = JsonParser.toJava(loadPayload("getRepository"), BitbucketCloudRepository.class);
Expand All @@ -121,15 +116,14 @@ void get_repository_parse_correctly_date_from_cloud() throws Exception {
@Test
void verifyUpdateWebhookURL() throws Exception {
BitbucketApi client = BitbucketIntegrationClientFactory.getApiMockClient(BitbucketCloudEndpoint.SERVER_URL);
IRequestAudit audit = ((IRequestAudit) client).getAudit();
Optional<? extends BitbucketWebHook> webHook = client.getWebHooks().stream()
.filter(h -> h.getDescription().contains("Jenkins"))
.findFirst();
assertThat(webHook).isPresent();

reset(audit);
resetAudit(client);
client.updateCommitWebHook(webHook.get());
HttpRequestBase request = extractRequest(audit);
HttpRequestBase request = extractRequest(client);
assertThat(request).isNotNull()
.isInstanceOfSatisfying(HttpPut.class, put ->
assertThat(put.getURI()).hasToString("https://api.bitbucket.org/2.0/repositories/amuniz/test-repos/hooks/%7B202cf34e-7ccf-44b7-ba6b-8827a14d5324%7D"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@
import com.cloudbees.jenkins.plugins.bitbucket.client.BitbucketIntegrationClientFactory;
import com.cloudbees.jenkins.plugins.bitbucket.client.BitbucketIntegrationClientFactory.BitbucketServerIntegrationClient;
import com.cloudbees.jenkins.plugins.bitbucket.client.BitbucketIntegrationClientFactory.IRequestAudit;
import hudson.ProxyConfiguration;
import io.jenkins.cli.shaded.org.apache.commons.lang.RandomStringUtils;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
Expand Down Expand Up @@ -64,6 +66,7 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;

@WithJenkins
Expand Down Expand Up @@ -223,4 +226,24 @@ void verify_HttpHost_built_when_server_has_context_root() throws Exception {
verify(authenticator).configureContext(any(HttpClientContext.class), eq(expectedHost));
}

@Issue("JENKINS-75160")
@Test
void test_no_proxy_configurations() throws Exception {
ProxyConfiguration proxyConfiguration = spy(new ProxyConfiguration("proxy.lan", 8080, null, null, "*.internaldomain.com"));

j.jenkins.setProxy(proxyConfiguration);

AtomicReference<HttpClientBuilder> builderReference = new AtomicReference<>();
try(BitbucketApi client = new BitbucketServerAPIClient("https://git.internaldomain.com:7990/bitbucket", "amuniz", "test-repos", mock(BitbucketAuthenticator.class), false) {
@Override
protected void setClientProxyParams(HttpClientBuilder builder) {
builderReference.set(spy(builder));
super.setClientProxyParams(builderReference.get());
}
}) {}

verify(proxyConfiguration).createProxy("git.internaldomain.com");
verify(builderReference.get(), never()).setProxy(any(HttpHost.class));
}

}

0 comments on commit 7645694

Please sign in to comment.