/**
* Licensed to The Apereo Foundation under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
*
* The Apereo Foundation licenses this file to you under the Educational
* Community License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License
* at:
*
* http://opensource.org/licenses/ecl2.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
*/
package org.opencastproject.kernel.security;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.isA;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.opencastproject.job.api.Job;
import org.opencastproject.kernel.http.api.HttpClient;
import org.opencastproject.kernel.http.impl.HttpClientFactory;
import org.opencastproject.security.api.DefaultOrganization;
import org.opencastproject.security.api.JaxbUser;
import org.opencastproject.security.api.SecurityService;
import org.opencastproject.security.api.TrustedHttpClientException;
import org.opencastproject.security.urlsigning.exception.UrlSigningException;
import org.opencastproject.security.urlsigning.service.UrlSigningService;
import org.opencastproject.serviceregistry.api.ServiceRegistry;
import com.entwinemedia.fn.data.Opt;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.ProtocolVersion;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.message.BasicHttpResponse;
import org.apache.http.message.BasicStatusLine;
import org.apache.http.params.HttpParams;
import org.easymock.Capture;
import org.easymock.EasyMock;
import org.easymock.IMocksControl;
import org.junit.Before;
import org.junit.Test;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;
import java.io.IOException;
import junit.framework.Assert;
public class TrustedHttpClientImplTest {
private TrustedHttpClientImpl client;
private ComponentContext componentContextMock;
private BundleContext bundleContextMock;
private BasicHttpResponse okResponse;
private BasicHttpResponse digestResponse;
private BasicHttpResponse nonceResponse;
private ServiceRegistry serviceRegistry;
private SecurityService securityService;
@Before
public void setUp() throws Exception {
// Setup bundle context for TrustedHttpClientImpl
bundleContextMock = createNiceMock(BundleContext.class);
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.DIGEST_AUTH_USER_KEY)).andReturn(
"matterhorn_system_account");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.DIGEST_AUTH_PASS_KEY)).andReturn("CHANGE_ME");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.NONCE_TIMEOUT_RETRY_KEY)).andReturn("3");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.NONCE_TIMEOUT_RETRY_BASE_TIME_KEY)).andReturn("0");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.NONCE_TIMEOUT_RETRY_MAXIMUM_VARIABLE_TIME_KEY))
.andReturn("0");
replay(bundleContextMock);
componentContextMock = createNiceMock(ComponentContext.class);
expect(componentContextMock.getBundleContext()).andReturn(bundleContextMock).anyTimes();
replay(componentContextMock);
long currentJobId = 20L;
Job currentJob = createNiceMock(Job.class);
expect(currentJob.getId()).andReturn(currentJobId).anyTimes();
replay(currentJob);
securityService = createNiceMock(SecurityService.class);
expect(securityService.getOrganization()).andReturn(new DefaultOrganization()).anyTimes();
expect(securityService.getUser()).andReturn(new JaxbUser()).anyTimes();
replay(securityService);
serviceRegistry = createNiceMock(ServiceRegistry.class);
expect(serviceRegistry.getCurrentJob()).andReturn(currentJob).anyTimes();
expect(serviceRegistry.getJob(currentJobId)).andReturn(currentJob).anyTimes();
replay(serviceRegistry);
client = new TrustedHttpClientImpl("matterhorn_system_account", "CHANGE_ME");
client.setServiceRegistry(serviceRegistry);
client.setSecurityService(securityService);
client.activate(componentContextMock);
// Setup responses.
String digestValue = "Digest realm=\"testrealm@host.com\"," + "qop=\"auth,auth-int\","
+ "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\"," + "opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"";
okResponse = new BasicHttpResponse(new BasicStatusLine(new ProtocolVersion("Http", 1, 1), 200, "Good to go"));
digestResponse = new BasicHttpResponse(new ProtocolVersion("Http", 1, 1), 401, "Unauthorized");
digestResponse.addHeader("WWW-Authenticate", digestValue);
nonceResponse = new BasicHttpResponse(new BasicStatusLine(new ProtocolVersion("Http", 1, 1), 401,
"Nonce has expired/timed out"));
}
@Test
public void noDefaultHttpConnectionFactoryResultsInException() {
try {
client.execute(new HttpPost("http://localhost:8080/fakeEndpoint"));
// It should fail without a default http connection factory
Assert.fail();
} catch (TrustedHttpClientException e) {
}
}
@Test
public void nonceTimeoutRetryPropertySetsOkay() {
// Test Default value
componentContextMock = null;
bundleContextMock = null;
client = null;
bundleContextMock = createNiceMock("DefaultRetryValueMock", BundleContext.class);
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.DIGEST_AUTH_USER_KEY)).andReturn(
"matterhorn_system_account");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.DIGEST_AUTH_PASS_KEY)).andReturn("CHANGE_ME");
replay(bundleContextMock);
componentContextMock = createMock(ComponentContext.class);
expect(componentContextMock.getBundleContext()).andReturn(bundleContextMock).anyTimes();
replay(componentContextMock);
client = new TrustedHttpClientImpl("matterhorn_system_account", "CHANGE_ME");
client.activate(componentContextMock);
Assert.assertEquals(TrustedHttpClientImpl.DEFAULT_NONCE_TIMEOUT_RETRIES, client.getNonceTimeoutRetries());
setupNonceRetries(0);
Assert.assertEquals(0, client.getNonceTimeoutRetries());
setupNonceRetries(1);
Assert.assertEquals(1, client.getNonceTimeoutRetries());
setupNonceRetries(100);
Assert.assertEquals(100, client.getNonceTimeoutRetries());
setupNonceRetries(Integer.MAX_VALUE);
Assert.assertEquals(Integer.MAX_VALUE, client.getNonceTimeoutRetries());
setupNonceRetries(Integer.MIN_VALUE);
Assert.assertEquals(Integer.MIN_VALUE, client.getNonceTimeoutRetries());
}
private void setupNonceRetries(int retries) {
componentContextMock = null;
bundleContextMock = null;
client = null;
bundleContextMock = createNiceMock(BundleContext.class);
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.DIGEST_AUTH_USER_KEY)).andReturn(
"matterhorn_system_account");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.DIGEST_AUTH_PASS_KEY)).andReturn("CHANGE_ME");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.NONCE_TIMEOUT_RETRY_KEY)).andReturn(retries + "")
.anyTimes();
replay(bundleContextMock);
componentContextMock = createNiceMock(ComponentContext.class);
EasyMock.reset(componentContextMock);
expect(componentContextMock.getBundleContext()).andReturn(bundleContextMock).anyTimes();
replay(componentContextMock);
client = new TrustedHttpClientImpl("matterhorn_system_account", "CHANGE_ME");
client.activate(componentContextMock);
}
@Test
public void nonceRetryBaseTimePropertySetsOkay() {
// Test Default value
componentContextMock = null;
bundleContextMock = null;
client = null;
bundleContextMock = createNiceMock("DefaultRetryValueMock", BundleContext.class);
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.DIGEST_AUTH_USER_KEY)).andReturn(
"matterhorn_system_account");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.DIGEST_AUTH_PASS_KEY)).andReturn("CHANGE_ME");
replay(bundleContextMock);
componentContextMock = createMock(ComponentContext.class);
expect(componentContextMock.getBundleContext()).andReturn(bundleContextMock).anyTimes();
replay(componentContextMock);
client = new TrustedHttpClientImpl("matterhorn_system_account", "CHANGE_ME");
client.activate(componentContextMock);
Assert.assertEquals(TrustedHttpClientImpl.DEFAULT_RETRY_BASE_TIME, client.getRetryBaseDelay());
setupNonceBaseDelay(0);
Assert.assertEquals(0, client.getRetryBaseDelay());
setupNonceBaseDelay(1);
Assert.assertEquals(1, client.getRetryBaseDelay());
setupNonceBaseDelay(100);
Assert.assertEquals(100, client.getRetryBaseDelay());
setupNonceBaseDelay(Integer.MAX_VALUE);
Assert.assertEquals(Integer.MAX_VALUE, client.getRetryBaseDelay());
setupNonceBaseDelay(Integer.MIN_VALUE);
Assert.assertEquals(Integer.MIN_VALUE, client.getRetryBaseDelay());
}
private void setupNonceBaseDelay(int baseDelay) {
componentContextMock = null;
bundleContextMock = null;
client = null;
bundleContextMock = createNiceMock(BundleContext.class);
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.DIGEST_AUTH_USER_KEY)).andReturn(
"matterhorn_system_account");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.DIGEST_AUTH_PASS_KEY)).andReturn("CHANGE_ME");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.NONCE_TIMEOUT_RETRY_BASE_TIME_KEY)).andReturn(
baseDelay + "").anyTimes();
replay(bundleContextMock);
componentContextMock = createNiceMock(ComponentContext.class);
EasyMock.reset(componentContextMock);
expect(componentContextMock.getBundleContext()).andReturn(bundleContextMock).anyTimes();
replay(componentContextMock);
client = new TrustedHttpClientImpl("matterhorn_system_account", "CHANGE_ME");
client.activate(componentContextMock);
}
@Test
public void nonceRetryMaximumVariablePropertySetsOkay() {
// Test Default value
componentContextMock = null;
bundleContextMock = null;
client = null;
bundleContextMock = createNiceMock("DefaultRetryValueMock", BundleContext.class);
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.DIGEST_AUTH_USER_KEY)).andReturn(
"matterhorn_system_account");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.DIGEST_AUTH_PASS_KEY)).andReturn("CHANGE_ME");
replay(bundleContextMock);
componentContextMock = createMock(ComponentContext.class);
expect(componentContextMock.getBundleContext()).andReturn(bundleContextMock).anyTimes();
replay(componentContextMock);
client = new TrustedHttpClientImpl("matterhorn_system_account", "CHANGE_ME");
client.activate(componentContextMock);
Assert.assertEquals(TrustedHttpClientImpl.DEFAULT_RETRY_MAXIMUM_VARIABLE_TIME, client.getRetryMaximumVariableTime());
setupNonceMaximumVariableDelay(0);
Assert.assertEquals(0, client.getRetryMaximumVariableTime());
setupNonceMaximumVariableDelay(1);
Assert.assertEquals(1, client.getRetryMaximumVariableTime());
setupNonceMaximumVariableDelay(100);
Assert.assertEquals(100, client.getRetryMaximumVariableTime());
setupNonceMaximumVariableDelay(Integer.MAX_VALUE);
Assert.assertEquals(Integer.MAX_VALUE, client.getRetryMaximumVariableTime());
setupNonceMaximumVariableDelay(Integer.MIN_VALUE);
Assert.assertEquals(Integer.MIN_VALUE, client.getRetryMaximumVariableTime());
}
private void setupNonceMaximumVariableDelay(int maxVariableDelay) {
componentContextMock = null;
bundleContextMock = null;
client = null;
bundleContextMock = createNiceMock(BundleContext.class);
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.DIGEST_AUTH_USER_KEY)).andReturn(
"matterhorn_system_account");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.DIGEST_AUTH_PASS_KEY)).andReturn("CHANGE_ME");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.NONCE_TIMEOUT_RETRY_MAXIMUM_VARIABLE_TIME_KEY))
.andReturn(maxVariableDelay + "").anyTimes();
replay(bundleContextMock);
componentContextMock = createNiceMock(ComponentContext.class);
EasyMock.reset(componentContextMock);
expect(componentContextMock.getBundleContext()).andReturn(bundleContextMock).anyTimes();
replay(componentContextMock);
client = new TrustedHttpClientImpl("matterhorn_system_account", "CHANGE_ME");
client.activate(componentContextMock);
}
@Test
public void successfullRequestResultsInNoRetries() throws ClientProtocolException, IOException {
HttpPost httpPost = new HttpPost("http://localhost:8080/fake");
HttpParams httpParams = createNiceMock(HttpParams.class);
ClientConnectionManager clientConnectionManager = createMock(ClientConnectionManager.class);
// Setup DefaultHttpClients
HttpClient securityDefaultHttpClient = createMock("Digest", HttpClient.class);
expect(securityDefaultHttpClient.execute(isA(HttpUriRequest.class))).andReturn(digestResponse);
expect(securityDefaultHttpClient.getConnectionManager()).andReturn(clientConnectionManager);
replay(securityDefaultHttpClient);
HttpClient requestDefaultHttpClient = createMock("Request", HttpClient.class);
expect(requestDefaultHttpClient.getParams()).andReturn(httpParams);
expect(requestDefaultHttpClient.execute(isA(HttpUriRequest.class))).andReturn(okResponse);
replay(requestDefaultHttpClient);
// Setup DefaultHttpClientFactory
HttpClientFactory httpClientFactory = createMock(HttpClientFactory.class);
expect(httpClientFactory.makeHttpClient()).andReturn(requestDefaultHttpClient);
expect(httpClientFactory.makeHttpClient()).andReturn(securityDefaultHttpClient);
replay(httpClientFactory);
client.setHttpClientFactory(httpClientFactory);
HttpResponse response = client.execute(httpPost);
Assert.assertEquals(200, response.getStatusLine().getStatusCode());
}
@Test
public void failsIfNonceReturnAndNoRetries() throws ClientProtocolException, IOException {
// Setup bundle context for TrustedHttpClientImpl
bundleContextMock = createNiceMock(BundleContext.class);
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.DIGEST_AUTH_USER_KEY)).andReturn(
"matterhorn_system_account");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.DIGEST_AUTH_PASS_KEY)).andReturn("CHANGE_ME");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.NONCE_TIMEOUT_RETRY_KEY)).andReturn("0");
replay(bundleContextMock);
componentContextMock = createNiceMock(ComponentContext.class);
expect(componentContextMock.getBundleContext()).andReturn(bundleContextMock).anyTimes();
replay(componentContextMock);
client = new TrustedHttpClientImpl("matterhorn_system_account", "CHANGE_ME");
client.setServiceRegistry(serviceRegistry);
client.setSecurityService(securityService);
client.activate(componentContextMock);
HttpPost httpPost = new HttpPost("http://localhost:8080/fake");
HttpParams httpParams = createNiceMock(HttpParams.class);
ClientConnectionManager clientConnectionManager = createMock(ClientConnectionManager.class);
HttpClient requestDefaultHttpClient = createMock("Request", HttpClient.class);
expect(requestDefaultHttpClient.getParams()).andReturn(httpParams);
// Digest authentication and close
expect(requestDefaultHttpClient.execute(isA(HttpUriRequest.class))).andReturn(digestResponse);
expect(requestDefaultHttpClient.getConnectionManager()).andReturn(clientConnectionManager);
// Try request and close.
expect(requestDefaultHttpClient.execute(isA(HttpUriRequest.class))).andReturn(nonceResponse);
replay(requestDefaultHttpClient);
// Setup DefaultHttpClientFactory
HttpClientFactory httpClientFactory = createMock(HttpClientFactory.class);
expect(httpClientFactory.makeHttpClient()).andReturn(requestDefaultHttpClient).atLeastOnce();
replay(httpClientFactory);
client.setHttpClientFactory(httpClientFactory);
HttpResponse response = client.execute(httpPost);
Assert.assertEquals(401, response.getStatusLine().getStatusCode());
verify(requestDefaultHttpClient);
}
@Test
public void failsIfNonceReturnAndOneRetries() throws ClientProtocolException, IOException {
// Setup bundle context for TrustedHttpClientImpl
bundleContextMock = createNiceMock(BundleContext.class);
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.DIGEST_AUTH_USER_KEY)).andReturn(
"matterhorn_system_account");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.DIGEST_AUTH_PASS_KEY)).andReturn("CHANGE_ME");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.NONCE_TIMEOUT_RETRY_KEY)).andReturn("1");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.NONCE_TIMEOUT_RETRY_BASE_TIME_KEY)).andReturn("0");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.NONCE_TIMEOUT_RETRY_MAXIMUM_VARIABLE_TIME_KEY))
.andReturn("0");
replay(bundleContextMock);
componentContextMock = createNiceMock(ComponentContext.class);
expect(componentContextMock.getBundleContext()).andReturn(bundleContextMock).anyTimes();
replay(componentContextMock);
client = new TrustedHttpClientImpl("matterhorn_system_account", "CHANGE_ME");
client.setServiceRegistry(serviceRegistry);
client.setSecurityService(securityService);
client.activate(componentContextMock);
HttpPost httpPost = new HttpPost("http://localhost:8080/fake");
HttpParams httpParams = createNiceMock(HttpParams.class);
ClientConnectionManager clientConnectionManager = createMock(ClientConnectionManager.class);
HttpClient httpClient = createMock("Request", HttpClient.class);
expect(httpClient.getParams()).andReturn(httpParams);
// Security Handshake and close.
expect(httpClient.execute(isA(HttpUriRequest.class))).andReturn(digestResponse);
expect(httpClient.getConnectionManager()).andReturn(clientConnectionManager);
// First request and close.
expect(httpClient.execute(isA(HttpUriRequest.class))).andReturn(nonceResponse);
expect(httpClient.getConnectionManager()).andReturn(clientConnectionManager);
// Second Security Handshake and close.
expect(httpClient.execute(isA(HttpUriRequest.class))).andReturn(digestResponse);
expect(httpClient.getConnectionManager()).andReturn(clientConnectionManager);
// Retry request and close.
expect(httpClient.execute(isA(HttpUriRequest.class))).andReturn(nonceResponse);
expect(httpClient.getConnectionManager()).andReturn(clientConnectionManager);
replay(httpClient);
// Setup DefaultHttpClientFactory
HttpClientFactory httpClientFactory = createMock(HttpClientFactory.class);
expect(httpClientFactory.makeHttpClient()).andReturn(httpClient).atLeastOnce();
replay(httpClientFactory);
client.setHttpClientFactory(httpClientFactory);
HttpResponse response = client.execute(httpPost);
Assert.assertEquals(401, response.getStatusLine().getStatusCode());
}
@Test
public void successIfNonceReturnOnceAndOneRetries() throws ClientProtocolException, IOException {
// Setup bundle context for TrustedHttpClientImpl
bundleContextMock = createNiceMock(BundleContext.class);
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.DIGEST_AUTH_USER_KEY)).andReturn(
"matterhorn_system_account");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.DIGEST_AUTH_PASS_KEY)).andReturn("CHANGE_ME");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.NONCE_TIMEOUT_RETRY_KEY)).andReturn("1");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.NONCE_TIMEOUT_RETRY_BASE_TIME_KEY)).andReturn("0");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.NONCE_TIMEOUT_RETRY_MAXIMUM_VARIABLE_TIME_KEY))
.andReturn("0");
replay(bundleContextMock);
componentContextMock = createNiceMock(ComponentContext.class);
expect(componentContextMock.getBundleContext()).andReturn(bundleContextMock).anyTimes();
replay(componentContextMock);
client = new TrustedHttpClientImpl("matterhorn_system_account", "CHANGE_ME");
client.setServiceRegistry(serviceRegistry);
client.setSecurityService(securityService);
client.activate(componentContextMock);
HttpPost httpPost = new HttpPost("http://localhost:8080/fake");
HttpParams httpParams = createNiceMock(HttpParams.class);
ClientConnectionManager clientConnectionManager = createMock(ClientConnectionManager.class);
HttpClient httpClient = createMock("Request", HttpClient.class);
expect(httpClient.getParams()).andReturn(httpParams);
// Security Handshake and close.
expect(httpClient.execute(isA(HttpUriRequest.class))).andReturn(digestResponse);
expect(httpClient.getConnectionManager()).andReturn(clientConnectionManager);
// First request and close
expect(httpClient.execute(isA(HttpUriRequest.class))).andReturn(nonceResponse);
expect(httpClient.getConnectionManager()).andReturn(clientConnectionManager);
// Nonce retry and close.
expect(httpClient.execute(isA(HttpUriRequest.class))).andReturn(digestResponse);
expect(httpClient.getConnectionManager()).andReturn(clientConnectionManager);
// Final request with success.
expect(httpClient.execute(isA(HttpUriRequest.class))).andReturn(okResponse);
replay(httpClient);
// Setup DefaultHttpClientFactory
HttpClientFactory httpClientFactory = createMock(HttpClientFactory.class);
expect(httpClientFactory.makeHttpClient()).andReturn(httpClient).atLeastOnce();
replay(httpClientFactory);
client.setHttpClientFactory(httpClientFactory);
HttpResponse response = client.execute(httpPost);
Assert.assertEquals(200, response.getStatusLine().getStatusCode());
}
@Test
public void successIfNonceReturnOnceAndThreeRetries() throws ClientProtocolException, IOException {
// Setup bundle context for TrustedHttpClientImpl
bundleContextMock = createNiceMock(BundleContext.class);
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.DIGEST_AUTH_USER_KEY)).andReturn(
"matterhorn_system_account");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.DIGEST_AUTH_PASS_KEY)).andReturn("CHANGE_ME");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.NONCE_TIMEOUT_RETRY_KEY)).andReturn("3");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.NONCE_TIMEOUT_RETRY_BASE_TIME_KEY)).andReturn("0");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.NONCE_TIMEOUT_RETRY_MAXIMUM_VARIABLE_TIME_KEY))
.andReturn("0");
replay(bundleContextMock);
componentContextMock = createNiceMock(ComponentContext.class);
expect(componentContextMock.getBundleContext()).andReturn(bundleContextMock).anyTimes();
replay(componentContextMock);
client = new TrustedHttpClientImpl("matterhorn_system_account", "CHANGE_ME");
client.setServiceRegistry(serviceRegistry);
client.setSecurityService(securityService);
client.activate(componentContextMock);
HttpPost httpPost = new HttpPost("http://localhost:8080/fake");
HttpParams httpParams = createNiceMock(HttpParams.class);
ClientConnectionManager clientConnectionManager = createMock(ClientConnectionManager.class);
IMocksControl ctrl = EasyMock.createNiceControl();
ctrl.checkOrder(false);
HttpClient httpClient = createMock("Request", HttpClient.class);
expect(httpClient.getParams()).andReturn(httpParams);
// First Digest handshake and close
expect(httpClient.execute(isA(HttpUriRequest.class))).andReturn(digestResponse);
expect(httpClient.getConnectionManager()).andReturn(clientConnectionManager);
// First request and close.
expect(httpClient.execute(isA(HttpUriRequest.class))).andReturn(nonceResponse);
expect(httpClient.getConnectionManager()).andReturn(clientConnectionManager);
// Second Digest handshake and close
expect(httpClient.execute(isA(HttpUriRequest.class))).andReturn(digestResponse);
expect(httpClient.getConnectionManager()).andReturn(clientConnectionManager);
// First request retry.
expect(httpClient.execute(isA(HttpUriRequest.class))).andReturn(okResponse);
replay(httpClient);
// Setup DefaultHttpClientFactory
HttpClientFactory httpClientFactory = createMock(HttpClientFactory.class);
expect(httpClientFactory.makeHttpClient()).andReturn(httpClient).atLeastOnce();
replay(httpClientFactory);
client.setHttpClientFactory(httpClientFactory);
HttpResponse response = client.execute(httpPost);
Assert.assertEquals(200, response.getStatusLine().getStatusCode());
}
@Test
public void successIfNonceReturnThreeAndThreeRetries() throws ClientProtocolException, IOException {
// Setup bundle context for TrustedHttpClientImpl
bundleContextMock = createNiceMock(BundleContext.class);
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.DIGEST_AUTH_USER_KEY)).andReturn(
"matterhorn_system_account");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.DIGEST_AUTH_PASS_KEY)).andReturn("CHANGE_ME");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.NONCE_TIMEOUT_RETRY_KEY)).andReturn("3");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.NONCE_TIMEOUT_RETRY_BASE_TIME_KEY)).andReturn("0");
expect(bundleContextMock.getProperty(TrustedHttpClientImpl.NONCE_TIMEOUT_RETRY_MAXIMUM_VARIABLE_TIME_KEY))
.andReturn("0");
replay(bundleContextMock);
componentContextMock = createNiceMock(ComponentContext.class);
expect(componentContextMock.getBundleContext()).andReturn(bundleContextMock).anyTimes();
replay(componentContextMock);
client = new TrustedHttpClientImpl("matterhorn_system_account", "CHANGE_ME");
client.setServiceRegistry(serviceRegistry);
client.setSecurityService(securityService);
client.activate(componentContextMock);
HttpPost httpPost = new HttpPost("http://localhost:8080/fake");
HttpParams httpParams = createNiceMock(HttpParams.class);
ClientConnectionManager clientConnectionManager = createMock(ClientConnectionManager.class);
HttpClient httpClient = createMock("Request", HttpClient.class);
expect(httpClient.getParams()).andReturn(httpParams);
// First Digest handshake and close
expect(httpClient.execute(isA(HttpUriRequest.class))).andReturn(digestResponse);
expect(httpClient.getConnectionManager()).andReturn(clientConnectionManager);
// First request with a nonce timeout and close.
expect(httpClient.execute(isA(HttpUriRequest.class))).andReturn(nonceResponse);
expect(httpClient.getConnectionManager()).andReturn(clientConnectionManager);
// First retry getting nonce and close.
expect(httpClient.execute(isA(HttpUriRequest.class))).andReturn(digestResponse);
expect(httpClient.getConnectionManager()).andReturn(clientConnectionManager);
// First retry request and close.
expect(httpClient.execute(isA(HttpUriRequest.class))).andReturn(nonceResponse);
expect(httpClient.getConnectionManager()).andReturn(clientConnectionManager);
// Second retry getting nonce and close.
expect(httpClient.execute(isA(HttpUriRequest.class))).andReturn(digestResponse);
expect(httpClient.getConnectionManager()).andReturn(clientConnectionManager);
// Second retry request and close
expect(httpClient.execute(isA(HttpUriRequest.class))).andReturn(nonceResponse);
expect(httpClient.getConnectionManager()).andReturn(clientConnectionManager);
// Third retry getting nonce and close.
expect(httpClient.execute(isA(HttpUriRequest.class))).andReturn(digestResponse);
expect(httpClient.getConnectionManager()).andReturn(clientConnectionManager);
// Third retry with successful request.
expect(httpClient.execute(isA(HttpUriRequest.class))).andReturn(okResponse);
replay(httpClient);
// Setup DefaultHttpClientFactory
HttpClientFactory httpClientFactory = createMock(HttpClientFactory.class);
expect(httpClientFactory.makeHttpClient()).andReturn(httpClient).atLeastOnce();
replay(httpClientFactory);
client.setHttpClientFactory(httpClientFactory);
HttpResponse response = client.execute(httpPost);
Assert.assertEquals(200, response.getStatusLine().getStatusCode());
}
@Test
public void testNotAcceptsUrlSigningService() throws IOException {
String notAcceptsUrl = "http://notaccepts.com";
HttpGet get = new HttpGet(notAcceptsUrl);
// Setup signing service
UrlSigningService urlSigningService = EasyMock.createMock(UrlSigningService.class);
EasyMock.expect(urlSigningService.accepts(notAcceptsUrl)).andReturn(false);
EasyMock.replay(urlSigningService);
CredentialsProvider cp = EasyMock.createNiceMock(CredentialsProvider.class);
Capture<HttpUriRequest> request = EasyMock.newCapture();
// Setup Http Client
HttpClient httpClient = createMock("Request", HttpClient.class);
HttpParams httpParams = createNiceMock(HttpParams.class);
expect(httpClient.getParams()).andReturn(httpParams);
expect(httpClient.getCredentialsProvider()).andReturn(cp);
expect(httpClient.execute(EasyMock.capture(request))).andReturn(new BasicHttpResponse(new BasicStatusLine(HttpVersion.HTTP_1_1, 200, "ok")));
EasyMock.replay(httpClient);
// Setup DefaultHttpClientFactory
HttpClientFactory httpClientFactory = createMock(HttpClientFactory.class);
expect(httpClientFactory.makeHttpClient()).andReturn(httpClient).atLeastOnce();
replay(httpClientFactory);
client = new TrustedHttpClientImpl("user", "pass");
client.setHttpClientFactory(httpClientFactory);
client.setSecurityService(securityService);
client.setUrlSigningService(urlSigningService);
client.execute(get);
assertTrue(request.hasCaptured());
assertEquals(get.getURI().toString(), request.getValue().getURI().toString());
}
@Test
public void testAcceptsUrlSigningService() throws IOException, UrlSigningException {
String acceptsUrl = "http://accepts.com";
String signedUrl = "http://accepts.com?policy=testPolicy&signature=testSignature&keyId=testKeyId";
HttpGet get = new HttpGet(acceptsUrl);
// Setup signing service
UrlSigningService urlSigningService = EasyMock.createMock(UrlSigningService.class);
EasyMock.expect(urlSigningService.accepts(acceptsUrl)).andReturn(true);
EasyMock.expect(urlSigningService.sign(EasyMock.anyString(), EasyMock.anyLong(), EasyMock.anyLong(),
EasyMock.anyString())).andReturn(signedUrl);
EasyMock.replay(urlSigningService);
CredentialsProvider cp = EasyMock.createNiceMock(CredentialsProvider.class);
Capture<HttpUriRequest> request = EasyMock.newCapture();
// Setup Http Client
HttpClient httpClient = createMock("Request", HttpClient.class);
HttpParams httpParams = createNiceMock(HttpParams.class);
expect(httpClient.getParams()).andReturn(httpParams);
expect(httpClient.getCredentialsProvider()).andReturn(cp);
expect(httpClient.execute(EasyMock.capture(request))).andReturn(new BasicHttpResponse(new BasicStatusLine(HttpVersion.HTTP_1_1, 200, "ok")));
EasyMock.replay(httpClient);
// Setup DefaultHttpClientFactory
HttpClientFactory httpClientFactory = createMock(HttpClientFactory.class);
expect(httpClientFactory.makeHttpClient()).andReturn(httpClient).atLeastOnce();
replay(httpClientFactory);
client = new TrustedHttpClientImpl("user", "pass");
client.setHttpClientFactory(httpClientFactory);
client.setSecurityService(securityService);
client.setUrlSigningService(urlSigningService);
client.execute(get);
assertTrue(request.hasCaptured());
assertEquals(signedUrl, request.getValue().getURI().toString());
}
@Test
public void testAlreadySignedUrlIgnoredByUrlSigningService() throws IOException, UrlSigningException {
String acceptsUrl = "http://alreadysigned.com?signature=thesig&policy=thepolicy&keyId=thekey";
HttpHead headRequest = new HttpHead(acceptsUrl);
// Setup signing service
UrlSigningService urlSigningService = EasyMock.createMock(UrlSigningService.class);
EasyMock.expect(urlSigningService.accepts(acceptsUrl)).andReturn(true);
EasyMock.replay(urlSigningService);
CredentialsProvider cp = EasyMock.createNiceMock(CredentialsProvider.class);
Capture<HttpUriRequest> request = EasyMock.newCapture();
// Setup Http Client
HttpClient httpClient = createMock("Request", HttpClient.class);
HttpParams httpParams = createNiceMock(HttpParams.class);
expect(httpClient.getParams()).andReturn(httpParams);
expect(httpClient.getCredentialsProvider()).andReturn(cp);
expect(httpClient.execute(EasyMock.capture(request))).andReturn(new BasicHttpResponse(new BasicStatusLine(HttpVersion.HTTP_1_1, 200, "ok")));
EasyMock.replay(httpClient);
// Setup DefaultHttpClientFactory
HttpClientFactory httpClientFactory = createMock(HttpClientFactory.class);
expect(httpClientFactory.makeHttpClient()).andReturn(httpClient).atLeastOnce();
replay(httpClientFactory);
client = new TrustedHttpClientImpl("user", "pass");
client.setHttpClientFactory(httpClientFactory);
client.setSecurityService(securityService);
client.setUrlSigningService(urlSigningService);
client.execute(headRequest);
assertTrue(request.hasCaptured());
assertEquals(acceptsUrl, request.getValue().getURI().toString());
}
@Test
public void testGetSignedUrl() throws IOException, UrlSigningException {
HttpGet notAccepted = new HttpGet("http://notAccepted.com");
HttpGet alreadySigned = new HttpGet("http://alreadySigned.com?signature=thesignature&keyId=theKeyId&policy=thePolicy");
HttpPost notGetOrHead = new HttpPost("http://notGetOrHead.com");
HttpGet ok = new HttpGet("http://ok.com");
String signedOk = "http://ok.com?signature=thesignature&keyId=theKeyId&policy=thePolicy";
// Setup signing service
UrlSigningService urlSigningService = EasyMock.createMock(UrlSigningService.class);
EasyMock.expect(urlSigningService.accepts(notAccepted.getURI().toString())).andReturn(false);
EasyMock.expect(urlSigningService.accepts(alreadySigned.getURI().toString())).andReturn(true);
EasyMock.expect(urlSigningService.accepts(notGetOrHead.getURI().toString())).andReturn(true);
EasyMock.expect(urlSigningService.accepts(ok.getURI().toString())).andReturn(true);
EasyMock.expect(
urlSigningService.sign(ok.getURI().toString(), TrustedHttpClientImpl.DEFAULT_URL_SIGNING_EXPIRES_DURATION,
null, null)).andReturn(signedOk);
EasyMock.replay(urlSigningService);
client = new TrustedHttpClientImpl("user", "pass");
client.setUrlSigningService(urlSigningService);
assertTrue(client.getSignedUrl(notAccepted).isNone());
assertTrue(client.getSignedUrl(notGetOrHead).isNone());
Opt<HttpUriRequest> result = client.getSignedUrl(ok);
assertTrue(result.isSome());
assertEquals(signedOk, result.get().getURI().toString());
}
}