aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@sonarsource.com>2017-10-02 14:48:30 +0200
committerSimon Brandhof <simon.brandhof@sonarsource.com>2017-10-02 18:04:42 +0200
commit3601435b31bfdeaee7a7e2251d275e4b1a9e254e (patch)
tree6ff7f0df01d1351f37325e930cce037c03f57cb3 /server
parentcf6b9cb7a653e875f693a8364642411b46d38d95 (diff)
downloadsonarqube-3601435b31bfdeaee7a7e2251d275e4b1a9e254e.tar.gz
sonarqube-3601435b31bfdeaee7a7e2251d275e4b1a9e254e.zip
SONAR-9896 Webhook must support basic authentication
Diffstat (limited to 'server')
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/webhook/WebhookCallerImpl.java13
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/webhook/WebhookCallerImplTest.java48
2 files changed, 55 insertions, 6 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/webhook/WebhookCallerImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/webhook/WebhookCallerImpl.java
index 40cb2b128d8..3c14782e586 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/webhook/WebhookCallerImpl.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/projectanalysis/webhook/WebhookCallerImpl.java
@@ -20,6 +20,7 @@
package org.sonar.server.computation.task.projectanalysis.webhook;
import java.io.IOException;
+import okhttp3.Credentials;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
@@ -32,8 +33,10 @@ import org.sonar.api.utils.System2;
import static java.lang.String.format;
import static java.net.HttpURLConnection.HTTP_MOVED_PERM;
import static java.net.HttpURLConnection.HTTP_MOVED_TEMP;
+import static java.nio.charset.StandardCharsets.UTF_8;
import static okhttp3.internal.http.StatusLine.HTTP_PERM_REDIRECT;
import static okhttp3.internal.http.StatusLine.HTTP_TEMP_REDIRECT;
+import static org.apache.commons.lang.StringUtils.isNotEmpty;
@ComputeEngineSide
public class WebhookCallerImpl implements WebhookCaller {
@@ -71,9 +74,17 @@ public class WebhookCallerImpl implements WebhookCaller {
}
private static Request buildHttpRequest(Webhook webhook, WebhookPayload payload) {
+ HttpUrl url = HttpUrl.parse(webhook.getUrl());
+ if (url == null) {
+ throw new IllegalArgumentException("Webhook URL is not valid: " + webhook.getUrl());
+ }
Request.Builder request = new Request.Builder();
- request.url(webhook.getUrl());
+ request.url(url);
request.header(PROJECT_KEY_HEADER, payload.getProjectKey());
+ if (isNotEmpty(url.username())) {
+ request.header("Authorization", Credentials.basic(url.username(), url.password(), UTF_8));
+ }
+
RequestBody body = RequestBody.create(JSON, payload.getJson());
request.post(body);
return request.build();
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/webhook/WebhookCallerImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/webhook/WebhookCallerImplTest.java
index aff151adb48..155ec647963 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/webhook/WebhookCallerImplTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/task/projectanalysis/webhook/WebhookCallerImplTest.java
@@ -19,6 +19,7 @@
*/
package org.sonar.server.computation.task.projectanalysis.webhook;
+import okhttp3.Credentials;
import okhttp3.HttpUrl;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
@@ -103,7 +104,7 @@ public class WebhookCallerImplTest {
assertThat(delivery.getHttpStatus()).isEmpty();
assertThat(delivery.getDurationInMs()).isEmpty();
assertThat(delivery.getError().get()).isInstanceOf(IllegalArgumentException.class);
- assertThat(delivery.getErrorMessage().get()).isEqualTo("unexpected url: this_is_not_an_url");
+ assertThat(delivery.getErrorMessage().get()).isEqualTo("Webhook URL is not valid: this_is_not_an_url");
assertThat(delivery.getAt()).isEqualTo(NOW);
assertThat(delivery.getWebhook()).isSameAs(webhook);
assertThat(delivery.getPayload()).isSameAs(PAYLOAD);
@@ -134,6 +135,26 @@ public class WebhookCallerImplTest {
}
@Test
+ public void credentials_are_propagated_to_POST_redirects() throws Exception {
+ HttpUrl url = server.url("/redirect").newBuilder().username("theLogin").password("thePassword").build();
+ Webhook webhook = new Webhook(PROJECT_UUID, CE_TASK_UUID, "my-webhook", url.toString());
+
+ // /redirect redirects to /target
+ server.enqueue(new MockResponse().setResponseCode(307).setHeader("Location", server.url("target")));
+ server.enqueue(new MockResponse().setResponseCode(200));
+
+ WebhookDelivery delivery = newSender().call(webhook, PAYLOAD);
+
+ assertThat(delivery.getHttpStatus().get()).isEqualTo(200);
+
+ RecordedRequest redirectedRequest = takeAndVerifyPostRequest("/redirect");
+ assertThat(redirectedRequest.getHeader("Authorization")).isEqualTo(Credentials.basic(url.username(), url.password()));
+
+ RecordedRequest targetRequest = takeAndVerifyPostRequest("/target");
+ assertThat(targetRequest.getHeader("Authorization")).isEqualTo(Credentials.basic(url.username(), url.password()));
+ }
+
+ @Test
public void redirects_throws_ISE_if_header_Location_is_missing() throws Exception {
HttpUrl url = server.url("/redirect");
Webhook webhook = new Webhook(PROJECT_UUID, CE_TASK_UUID, "my-webhook", url.toString());
@@ -163,11 +184,28 @@ public class WebhookCallerImplTest {
.hasMessage("Unsupported protocol in redirect of " + url + " to ftp://foo");
}
- private void takeAndVerifyPostRequest(String expectedPath) throws Exception {
- RecordedRequest redirectedRequest = server.takeRequest();
+ @Test
+ public void send_basic_authentication_header_if_url_contains_credentials() throws Exception {
+ HttpUrl url = server.url("/ping").newBuilder().username("theLogin").password("thePassword").build();
+ Webhook webhook = new Webhook(PROJECT_UUID, CE_TASK_UUID, "my-webhook", url.toString());
+ server.enqueue(new MockResponse().setBody("pong"));
+
+ WebhookDelivery delivery = newSender().call(webhook, PAYLOAD);
+
+ assertThat(delivery.getWebhook().getUrl())
+ .isEqualTo(url.toString())
+ .contains("://theLogin:thePassword@");
+ RecordedRequest recordedRequest = takeAndVerifyPostRequest("/ping");
+ assertThat(recordedRequest.getHeader("Authorization")).isEqualTo(Credentials.basic(url.username(), url.password()));
+ }
+
+ private RecordedRequest takeAndVerifyPostRequest(String expectedPath) throws Exception {
+ RecordedRequest request = server.takeRequest();
- assertThat(redirectedRequest.getMethod()).isEqualTo("POST");
- assertThat(redirectedRequest.getPath()).isEqualTo(expectedPath);
+ assertThat(request.getMethod()).isEqualTo("POST");
+ assertThat(request.getPath()).isEqualTo(expectedPath);
+ assertThat(request.getHeader("User-Agent")).isEqualTo("SonarQube/6.2");
+ return request;
}
private WebhookCaller newSender() {