1 package com.atlassian.sal.core.net;
2
3 import com.atlassian.sal.api.net.Request;
4 import com.atlassian.sal.api.net.ResponseException;
5 import com.atlassian.sal.api.user.UserManager;
6 import com.atlassian.sal.core.trusted.CertificateFactory;
7 import com.atlassian.security.auth.trustedapps.EncryptedCertificate;
8 import com.atlassian.security.auth.trustedapps.TrustedApplicationUtils;
9 import org.apache.http.Header;
10 import org.apache.http.HttpClientConnection;
11 import org.apache.http.HttpException;
12 import org.apache.http.HttpRequest;
13 import org.apache.http.HttpResponse;
14 import org.apache.http.HttpStatus;
15 import org.apache.http.ProtocolVersion;
16 import org.apache.http.conn.ConnectionRequest;
17 import org.apache.http.conn.HttpClientConnectionManager;
18 import org.apache.http.conn.routing.HttpRoute;
19 import org.apache.http.entity.StringEntity;
20 import org.apache.http.message.BasicHttpResponse;
21 import org.apache.http.protocol.HttpContext;
22 import org.apache.http.protocol.HttpRequestExecutor;
23 import org.hamcrest.FeatureMatcher;
24 import org.hamcrest.Matcher;
25 import org.junit.Before;
26 import org.junit.Rule;
27 import org.junit.Test;
28 import org.junit.rules.ExpectedException;
29 import org.junit.runner.RunWith;
30 import org.mockito.ArgumentCaptor;
31 import org.mockito.Captor;
32 import org.mockito.Mock;
33 import org.mockito.runners.MockitoJUnitRunner;
34
35 import java.io.IOException;
36 import java.nio.charset.StandardCharsets;
37 import java.text.MessageFormat;
38 import java.util.concurrent.ExecutionException;
39 import java.util.concurrent.TimeUnit;
40
41 import static org.hamcrest.MatcherAssert.assertThat;
42 import static org.hamcrest.Matchers.arrayContaining;
43 import static org.hamcrest.Matchers.equalTo;
44 import static org.mockito.Matchers.any;
45 import static org.mockito.Matchers.anyInt;
46 import static org.mockito.Matchers.anyObject;
47 import static org.mockito.Matchers.eq;
48 import static org.mockito.Mockito.mock;
49 import static org.mockito.Mockito.verify;
50 import static org.mockito.Mockito.when;
51
52 @RunWith(MockitoJUnitRunner.class)
53 public class TestHttpClientTrustedRequest {
54
55 private static final String DUMMY_HOST = "dummy.atlassian.test";
56 private static final String DUMMY_HTTP_URL = MessageFormat.format("http://{0}/", DUMMY_HOST);
57
58 private static final String DUMMY_USERNAME = "dummy";
59 private static final String DUMMY_TRUSTED_TOKEN_ID = "dummy-id";
60
61 @Rule
62 public ExpectedException thrown = ExpectedException.none();
63
64 @Mock
65 private HttpRequestExecutor mockRequestExecutor;
66
67 @Mock
68 private HttpClientConnectionManager mockConnectionManager;
69
70 @Mock
71 private CertificateFactory certificateFactory;
72
73 @Mock
74 private EncryptedCertificate encryptedCertificate;
75
76 @Mock
77 private UserManager userManager;
78
79 private HttpClientTrustedRequestFactory requestFactory;
80
81 @Captor
82 private ArgumentCaptor<HttpRequest> requestCaptor;
83
84 @Before
85 public void setup() throws InterruptedException, ExecutionException, IOException, HttpException {
86 requestFactory = new HttpClientWithMockConnectionTrustedRequestFactory(userManager, certificateFactory, mockConnectionManager, mockRequestExecutor);
87
88
89 when(mockRequestExecutor.execute(any(HttpRequest.class), any(HttpClientConnection.class),
90 any(HttpContext.class))).thenReturn(createOkResponse());
91
92
93 final HttpClientConnection conn = mock(HttpClientConnection.class);
94 final ConnectionRequest connRequest = mock(ConnectionRequest.class);
95 when(connRequest.get(anyInt(), any(TimeUnit.class))).thenReturn(conn);
96 when(mockConnectionManager.requestConnection(any(HttpRoute.class), anyObject())).thenReturn(connRequest);
97
98
99 when(userManager.getRemoteUsername()).thenReturn(DUMMY_USERNAME);
100 when(encryptedCertificate.getID()).thenReturn(DUMMY_TRUSTED_TOKEN_ID);
101 when(certificateFactory.createCertificate(eq(DUMMY_USERNAME), eq(DUMMY_HTTP_URL))).thenReturn(encryptedCertificate);
102 }
103
104 private static HttpResponse createOkResponse() {
105 final BasicHttpResponse response = new BasicHttpResponse(new ProtocolVersion("HTTP", 1, 1), HttpStatus.SC_OK, "OK");
106 response.setEntity(new StringEntity("test body", StandardCharsets.UTF_8));
107 return response;
108 }
109
110
111 @Test
112 public void assertThatTrustedTokenHeadersAdded() throws ResponseException, IOException, HttpException {
113 final HttpClientTrustedRequest request = requestFactory.createTrustedRequest(Request.MethodType.GET, DUMMY_HTTP_URL);
114
115 request.addTrustedTokenAuthentication(DUMMY_HOST);
116 request.execute();
117
118 verify(mockRequestExecutor).execute(requestCaptor.capture(), any(HttpClientConnection.class), any(HttpContext.class));
119 final HttpRequest lastRequest = requestCaptor.getValue();
120 final Header[] headers = lastRequest.getHeaders(TrustedApplicationUtils.Header.Request.ID);
121
122
123 assertThat(headers, arrayContaining(headerWithValue(equalTo(DUMMY_TRUSTED_TOKEN_ID))));
124
125 }
126
127 private static Matcher<Header> headerWithValue(final Matcher<String> valueMatcher) {
128 return new FeatureMatcher<Header, String>(valueMatcher, "header with value", "header value") {
129 @Override
130 protected String featureValueOf(final Header header) {
131 return header.getValue();
132 }
133 };
134 }
135 }