/** * Copyright (c) Codice Foundation * <p> * This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software Foundation, either version 3 of the * License, or any later version. * <p> * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. A copy of the GNU Lesser General Public License * is distributed along with this program and can be found at * <http://www.gnu.org/licenses/lgpl.html>. */ package org.codice.ddf.commands.solr; import java.io.FileInputStream; import java.io.IOException; import java.net.URI; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import javax.net.ssl.SSLContext; import org.apache.commons.lang.StringUtils; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.SSLContexts; import org.apache.http.impl.client.BasicCookieStore; import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicHttpResponse; import org.codice.solr.factory.impl.HttpSolrClientFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ddf.security.SecurityConstants; public class SolrHttpWrapper implements HttpWrapper { private static final Logger LOGGER = LoggerFactory.getLogger(SolrHttpWrapper.class); HttpClient solrClient; public SolrHttpWrapper() { SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory( getSslContext(), getProtocols(), getCipherSuites(), SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); solrClient = HttpClients.custom() .setSSLSocketFactory(sslConnectionSocketFactory) .setDefaultCookieStore(new BasicCookieStore()) .setMaxConnTotal(128) .setMaxConnPerRoute(32) .build(); } private static KeyStore getKeyStore(String location, String password) { LOGGER.debug("Loading keystore from {}", location); KeyStore keyStore = null; try (FileInputStream storeStream = new FileInputStream(location)) { keyStore = KeyStore.getInstance(System.getProperty("javax.net.ssl.keyStoreType")); keyStore.load(storeStream, password.toCharArray()); } catch (CertificateException | IOException | NoSuchAlgorithmException | KeyStoreException e) { LOGGER.warn("Unable to load keystore at {}", location, e); } return keyStore; } private static String[] getCipherSuites() { if (System.getProperty(SecurityConstants.HTTPS_CIPHER_SUITES) != null) { return StringUtils.split(System.getProperty(SecurityConstants.HTTPS_CIPHER_SUITES), ","); } return HttpSolrClientFactory.DEFAULT_CIPHER_SUITES.toArray(new String[HttpSolrClientFactory.DEFAULT_CIPHER_SUITES.size()]); } @Override public ResponseWrapper execute(URI uri) { HttpResponse httpResponse; HttpGet get = new HttpGet(uri); try { LOGGER.debug("Executing uri: {}", uri.toString()); httpResponse = solrClient.execute(get); return new ResponseWrapper(httpResponse); } catch (IOException e) { LOGGER.debug("Error during request. Returning null response."); } BasicHttpResponse response = new BasicHttpResponse(null, HttpStatus.SC_INTERNAL_SERVER_ERROR, "Error during request."); return new ResponseWrapper(response); } private SSLContext getSslContext() { String keystorePath = System.getProperty(SecurityConstants.KEYSTORE_PATH); String keystorePassword = System.getProperty(SecurityConstants.KEYSTORE_PASSWORD); String truststorePath = System.getProperty(SecurityConstants.TRUSTSTORE_PATH); String truststorePassword = System.getProperty(SecurityConstants.TRUSTSTORE_PASSWORD); if (keystorePath == null || keystorePassword == null || truststorePath == null || truststorePassword == null) { throw new IllegalArgumentException( "KeyStore and TrustStore system properties must be set."); } KeyStore trustStore = getKeyStore(truststorePath, truststorePassword); KeyStore keyStore = getKeyStore(keystorePath, keystorePassword); SSLContext sslContext; try { sslContext = SSLContexts.custom() .loadKeyMaterial(keyStore, keystorePassword.toCharArray()) .loadTrustMaterial(trustStore) .useTLS() .build(); } catch (UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) { LOGGER.error("Unable to create secure HttpClient for Solr. The server should not be used in this state.", e); return null; } sslContext.getDefaultSSLParameters() .setNeedClientAuth(true); sslContext.getDefaultSSLParameters() .setWantClientAuth(true); return sslContext; } private String[] getProtocols() { if (System.getProperty("https.protocols") != null) { return StringUtils.split(System.getProperty("https.protocols"), ","); } return HttpSolrClientFactory.DEFAULT_PROTOCOLS.toArray(new String[HttpSolrClientFactory.DEFAULT_PROTOCOLS.size()]); } }