View Javadoc

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.Ignore;
27  import org.junit.Rule;
28  import org.junit.Test;
29  import org.junit.rules.ExpectedException;
30  import org.junit.runner.RunWith;
31  import org.mockito.ArgumentCaptor;
32  import org.mockito.Captor;
33  import org.mockito.Mock;
34  import org.mockito.runners.MockitoJUnitRunner;
35  
36  
37  import java.io.IOException;
38  import java.nio.charset.StandardCharsets;
39  import java.text.MessageFormat;
40  import java.util.concurrent.ExecutionException;
41  import java.util.concurrent.TimeUnit;
42  
43  import static org.hamcrest.MatcherAssert.assertThat;
44  import static org.hamcrest.Matchers.arrayContaining;
45  import static org.hamcrest.Matchers.equalTo;
46  import static org.mockito.Matchers.any;
47  import static org.mockito.Matchers.anyInt;
48  import static org.mockito.Matchers.anyObject;
49  import static org.mockito.Matchers.anyString;
50  import static org.mockito.Matchers.eq;
51  import static org.mockito.Mockito.mock;
52  import static org.mockito.Mockito.verify;
53  import static org.mockito.Mockito.when;
54  
55  @RunWith (MockitoJUnitRunner.class)
56  public class TestHttpClientTrustedRequest
57  {
58  
59      private static final String DUMMY_HOST = "dummy.atlassian.test";
60      private static final String DUMMY_HTTP_URL = MessageFormat.format("http://{0}/", DUMMY_HOST);
61  
62      private static final String DUMMY_USERNAME = "dummy";
63      private static final String DUMMY_TRUSTED_TOKEN_ID = "dummy-id";
64  
65      @Rule
66      public ExpectedException thrown = ExpectedException.none();
67  
68      @Mock
69      private HttpRequestExecutor mockRequestExecutor;
70  
71      @Mock
72      private HttpClientConnectionManager mockConnectionManager;
73  
74      @Mock
75      private CertificateFactory certificateFactory;
76  
77      @Mock
78      private EncryptedCertificate encryptedCertificate;
79  
80      @Mock
81      private UserManager userManager;
82  
83      private HttpClientTrustedRequestFactory requestFactory;
84  
85      @Captor
86      private ArgumentCaptor<HttpRequest> requestCaptor;
87  
88      @Before
89      public void setup() throws InterruptedException, ExecutionException, IOException, HttpException
90      {
91          requestFactory = new HttpClientWithMockConnectionTrustedRequestFactory(userManager, certificateFactory, mockConnectionManager, mockRequestExecutor);
92  
93          // Always respond with a 200/OK message
94          when(mockRequestExecutor.execute(any(HttpRequest.class), any(HttpClientConnection.class),
95                  any(HttpContext.class))).thenReturn(createOkResponse());
96  
97          // This allows us to hook in to the connection details that HttpClient would have made
98          final HttpClientConnection conn = mock(HttpClientConnection.class);
99          final ConnectionRequest connRequest = mock(ConnectionRequest.class);
100         when(connRequest.get(anyInt(), any(TimeUnit.class))).thenReturn(conn);
101         when(mockConnectionManager.requestConnection(any(HttpRoute.class), anyObject())).thenReturn(connRequest);
102 
103         // Setup trusted apps mocks
104         when(userManager.getRemoteUsername()).thenReturn(DUMMY_USERNAME);
105         when(encryptedCertificate.getID()).thenReturn(DUMMY_TRUSTED_TOKEN_ID);
106         when(certificateFactory.createCertificate(eq(DUMMY_USERNAME), eq(DUMMY_HTTP_URL))).thenReturn(encryptedCertificate);
107     }
108 
109     private static HttpResponse createOkResponse()
110     {
111         final BasicHttpResponse response = new BasicHttpResponse(new ProtocolVersion("HTTP", 1, 1), HttpStatus.SC_OK, "OK");
112         response.setEntity(new StringEntity("test body", StandardCharsets.UTF_8));
113         return response;
114     }
115 
116     // TODO @alex fix TrustedTokenScheme#authenticate
117     @Test
118     public void assertThatTrustedTokenHeadersAdded() throws ResponseException, IOException, HttpException
119     {
120         final HttpClientTrustedRequest request = requestFactory.createTrustedRequest(Request.MethodType.GET, DUMMY_HTTP_URL);
121 
122         request.addTrustedTokenAuthentication(DUMMY_HOST);
123         request.execute();
124 
125         verify(mockRequestExecutor).execute(requestCaptor.capture(), any(HttpClientConnection.class), any(HttpContext.class));
126         final HttpRequest lastRequest = requestCaptor.getValue();
127         final Header[] headers = lastRequest.getHeaders(TrustedApplicationUtils.Header.Request.ID);
128 
129         //noinspection unchecked
130         assertThat(headers, arrayContaining(headerWithValue(equalTo(DUMMY_TRUSTED_TOKEN_ID))));
131 
132     }
133 
134     private static Matcher<Header> headerWithValue(final Matcher<String> valueMatcher)
135     {
136         return new FeatureMatcher<Header, String>(valueMatcher, "header with value", "header value")
137         {
138             @Override
139             protected String featureValueOf(final Header header)
140             {
141                 return header.getValue();
142             }
143         };
144     }
145 }