/* * Copyright (C) 2015 Square, Inc. * * Licensed under the Apache 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://www.apache.org/licenses/LICENSE-2.0 * * 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 keywhiz.testing; import com.google.common.base.Throwables; import java.net.CookieManager; import java.net.CookiePolicy; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.annotation.Nullable; import javax.net.ssl.SSLContext; import okhttp3.ConnectionSpec; import okhttp3.HttpUrl; import okhttp3.Interceptor; import okhttp3.JavaNetCookieJar; import okhttp3.OkHttpClient; import org.apache.http.conn.ssl.SSLContextBuilder; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; /** * Helper methods for creating {@link OkHttpClient}s for testing. * * ONLY USE IN TEST. Assumptions are made which are not safe in production. */ public class HttpClients { private HttpClients() {} /** * Builds a localhost URL for testing given a path. */ public static HttpUrl testUrl(String path) { String urlString = "https://localhost:4445" + path; HttpUrl url = HttpUrl.parse(urlString); checkState(url != null, "URL %s invalid", urlString); return url; } /** * Create a {@link OkHttpClient} for tests. * * @param keyStore Use a client certificate from keystore if present. Client certs disabled if null. * @param keyStorePassword keyStore password. Client certs disabled if null. * @param requestInterceptors Any request interceptors to register with client. * @return new http client */ private static OkHttpClient testSslClient( @Nullable KeyStore keyStore, @Nullable String keyStorePassword, KeyStore trustStore, List<Interceptor> requestInterceptors) { boolean usingClientCert = keyStore != null && keyStorePassword != null; SSLContext sslContext; try { SSLContextBuilder sslContextBuilder = new SSLContextBuilder() .useProtocol("TLSv1.2") .loadTrustMaterial(trustStore); if (usingClientCert) { sslContextBuilder.loadKeyMaterial(keyStore, keyStorePassword.toCharArray()); } sslContext = sslContextBuilder.build(); } catch (NoSuchAlgorithmException | KeyStoreException | UnrecoverableKeyException | KeyManagementException e) { throw Throwables.propagate(e); } OkHttpClient.Builder client = new OkHttpClient().newBuilder() .sslSocketFactory(sslContext.getSocketFactory()) .connectionSpecs(Arrays.asList(ConnectionSpec.MODERN_TLS)) .followSslRedirects(false); client.followRedirects(false); client.retryOnConnectionFailure(false); // Won't use cookies and a client certificate at once. if (!usingClientCert) { CookieManager cookieManager = new CookieManager(); cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL); client.cookieJar(new JavaNetCookieJar(cookieManager)); } for (Interceptor interceptor : requestInterceptors) { client.networkInterceptors().add(interceptor); } return client.build(); } public static TestClientBuilder builder() { return new TestClientBuilder(); } public static class TestClientBuilder { private KeyStore keyStore; private String password; private List<Interceptor> requestInterceptors = new ArrayList<>(); private TestClientBuilder() {} public TestClientBuilder withClientCert(KeyStore keyStore, String password) { this.keyStore = keyStore; this.password = password; return this; } public TestClientBuilder addRequestInterceptors(Interceptor first, Interceptor... others) { checkNotNull(first); requestInterceptors.add(first); requestInterceptors.addAll(Arrays.asList(others)); return this; } public OkHttpClient build(KeyStore trustStore) { return testSslClient(keyStore, password, trustStore, requestInterceptors); } } }