summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lenz <thomas.lenz@egiz.gv.at>2019-09-13 13:23:21 +0200
committerThomas Lenz <thomas.lenz@egiz.gv.at>2019-09-13 13:23:21 +0200
commit5780d9aa93fcd363584046fb404c63b909faebdb (patch)
tree6257d77a34fffb342a9318fbc845a60ed47b1c45
parent8883fd1c0efa08fe0a73a11a1c8986fa3ea72753 (diff)
downloadEAAF-Components-5780d9aa93fcd363584046fb404c63b909faebdb.tar.gz
EAAF-Components-5780d9aa93fcd363584046fb404c63b909faebdb.tar.bz2
EAAF-Components-5780d9aa93fcd363584046fb404c63b909faebdb.zip
add SimpleStatusMessager.java that only perform String formatting
add SSL Client authentication and http basic authentication to HttpClientFactory.java
-rw-r--r--eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/logging/SimpleStatusMessager.java44
-rw-r--r--eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HttpClientFactory.java240
-rw-r--r--pom.xml4
3 files changed, 266 insertions, 22 deletions
diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/logging/SimpleStatusMessager.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/logging/SimpleStatusMessager.java
new file mode 100644
index 00000000..d36c79b9
--- /dev/null
+++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/logging/SimpleStatusMessager.java
@@ -0,0 +1,44 @@
+package at.gv.egiz.eaaf.core.impl.logging;
+
+import java.text.MessageFormat;
+
+import at.gv.egiz.eaaf.core.api.IStatusMessenger;
+
+/**
+ * Simple {@link IStatusMessenger} implementation that formats messages by using {@link MessageFormat}
+ *
+ * @author tlenz
+ *
+ */
+public class SimpleStatusMessager implements IStatusMessenger {
+
+ private static final String NOTSUPPORTED = "Error response-codes not supported";
+ private static final String NULLMESSAGE = "No error-message provided";
+
+ @Override
+ public String getMessage(String messageId, Object[] parameters) {
+ return getMessageWithoutDefault(messageId, parameters);
+
+ }
+
+ @Override
+ public String getMessageWithoutDefault(String messageId, Object[] parameters) {
+ if (messageId != null) {
+ return MessageFormat.format(messageId, parameters);
+
+ }
+
+ return NULLMESSAGE;
+ }
+
+ @Override
+ public String getResponseErrorCode(Throwable throwable) {
+ return NOTSUPPORTED;
+ }
+
+ @Override
+ public String mapInternalErrorToExternalError(String intErrorCode) {
+ return NOTSUPPORTED;
+ }
+
+}
diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HttpClientFactory.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HttpClientFactory.java
index a141d92d..73f2c518 100644
--- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HttpClientFactory.java
+++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HttpClientFactory.java
@@ -1,31 +1,46 @@
package at.gv.egiz.eaaf.core.impl.utils;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+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.annotation.PostConstruct;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
+import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.ProtocolException;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.RedirectStrategy;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultRedirectStrategy;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.HttpContext;
+import org.apache.http.ssl.SSLContexts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.exceptions.EAAFConfigurationException;
public class HttpClientFactory implements IHttpClientFactory {
private static final Logger log = LoggerFactory.getLogger(HttpClientFactory.class);
@@ -39,6 +54,13 @@ public class HttpClientFactory implements IHttpClientFactory {
public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_REQUEST = "client.http.connection.timeout.request";
public static final String PROP_CONFIG_CLIENT_HTTP_SSL_HOSTNAMEVERIFIER_TRUSTALL = "client.http.ssl.hostnameverifier.trustall";
+ public static final String PROP_CONFIG_CLIENT_MODE = "client.authmode";
+ public static final String PROP_CONFIG_CLIENT_AUTH_HTTP_USERNAME = "client.auth.http.username";
+ public static final String PROP_CONFIG_CLIENT_AUTH_HTTP_PASSORD = "client.auth.http.password";
+ public static final String PROP_CONFIG_CLIENT_AUTH_SSL_KEYSTORE_PATH = "client.auth.ssl.keystore.path";
+ public static final String PROP_CONFIG_CLIENT_AUTH_SSL_KEYSTORE_PASSORD = "client.auth.ssl.keystore.password";
+ public static final String PROP_CONFIG_CLIENT_AUTH_SSL_KEYSTORE_TYPE = "client.auth.ssl.keystore.type";
+
// default configuration values
public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_SOCKET = "15";
public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_CONNECTION = "15";
@@ -46,6 +68,79 @@ public class HttpClientFactory implements IHttpClientFactory {
public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL = "500";
public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE = "100";
+ public enum ClientAuthMode {
+ NONE("none"),
+ PASSWORD("password"),
+ SSL("ssl");
+
+ private final String mode;
+
+ private ClientAuthMode(String mode) {
+ this.mode = mode;
+ }
+
+ /**
+ * Get the PVP mode
+ *
+ * @return
+ */
+ public String getMode() {
+ return this.mode;
+ }
+
+ public static ClientAuthMode fromString(String s) {
+ try {
+ return ClientAuthMode.valueOf(s.toUpperCase());
+
+ } catch (IllegalArgumentException|NullPointerException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return getMode();
+
+ }
+
+ };
+
+ public enum KeyStoreType {
+ PKCS12("pkcs12"),
+ JKS("jks");
+
+ private final String type;
+
+ private KeyStoreType (String type) {
+ this.type = type;
+ }
+
+ /**
+ * Get the PVP mode
+ *
+ * @return
+ */
+ public String getType() {
+ return this.type;
+ }
+
+ public static KeyStoreType fromString(String s) {
+ try {
+ return KeyStoreType.valueOf(s.toUpperCase());
+
+ } catch (IllegalArgumentException|NullPointerException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return getType();
+
+ }
+
+ };
+
private HttpClientBuilder httpClientBuilder = null;
/* (non-Javadoc)
@@ -102,50 +197,155 @@ public class HttpClientFactory implements IHttpClientFactory {
.build();
httpClientBuilder.setDefaultRequestConfig(requestConfig);
- //set pool connection if requested
- if (basicConfig.getBasicConfigurationBoolean(
- PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_USE,
- true)) {
- final PoolingHttpClientConnectionManager pool = new PoolingHttpClientConnectionManager();
- pool.setDefaultMaxPerRoute(Integer.valueOf(basicConfig.getBasicConfiguration(
- PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE,
- DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE)));
- pool.setMaxTotal(Integer.valueOf(basicConfig.getBasicConfiguration(
- PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL,
- DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL)));
+ //set pool connection if required
+ injectConnectionPoolIfRequired();
+
+ final ClientAuthMode clientAuthMode = ClientAuthMode.fromString(
+ basicConfig.getBasicConfiguration(PROP_CONFIG_CLIENT_MODE, ClientAuthMode.NONE.getMode()));
+ log.info("Client authentication-mode is set to: {}", clientAuthMode);
+
+ //inject basic http authentication if required
+ injectBasicAuthenticationIfRequired(clientAuthMode);
+
+ //inject authentication if required
+ injectSSLContext(clientAuthMode);
+
+ }
+
+ private void injectBasicAuthenticationIfRequired(ClientAuthMode clientAuthMode) {
+ if (clientAuthMode.equals(ClientAuthMode.PASSWORD)) {
+ final CredentialsProvider provider = new BasicCredentialsProvider();
+ final String username = basicConfig.getBasicConfiguration(PROP_CONFIG_CLIENT_AUTH_HTTP_USERNAME);
+ final String password = basicConfig.getBasicConfiguration(PROP_CONFIG_CLIENT_AUTH_HTTP_PASSORD);
+ if (StringUtils.isEmpty(username)) {
+ log.warn("Http basic authentication was activated but NOT username was set!");
+
+ }
+
+ log.trace("Injecting basic authentication with username: {} and password: {}", username, password);
+ final UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(username, password);
+ provider.setCredentials(AuthScope.ANY, credentials);
+ httpClientBuilder.setDefaultCredentialsProvider(provider);
+ log.info("Basic http authentication was injected with username: {}", username);
+
+ } else {
+ log.trace("Injection of Http Basic authentication was skipped");
- httpClientBuilder.setConnectionManager(pool);
- log.debug("Initalize http-client pool with, maxTotal: {} maxPerRoute: {}", pool.getMaxTotal(), pool.getDefaultMaxPerRoute());
-
}
+ }
+
+ private SSLContext buildSSLContextWithSSLClientAuthentication() throws KeyManagementException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException, EAAFConfigurationException {
+ log.trace("Injecting SSL client-authentication into http client ... ");
+ final KeyStore keystore = getSSLAuthKeyStore();
+ final String keyPasswordString = basicConfig.getBasicConfiguration(PROP_CONFIG_CLIENT_AUTH_SSL_KEYSTORE_PASSORD);
+ log.trace("Open SSL Client-Auth keystore with password: {}", keyPasswordString);
+ final char[] keyPassword = (keyPasswordString == null) ? StringUtils.EMPTY.toCharArray() : keyPasswordString.toCharArray();
+ return SSLContexts.custom().loadKeyMaterial(keystore, keyPassword).build();
+
+ }
+
+ private KeyStore getSSLAuthKeyStore() throws EAAFConfigurationException {
+ final KeyStoreType keyStoreType = KeyStoreType.fromString(
+ basicConfig.getBasicConfiguration(PROP_CONFIG_CLIENT_AUTH_SSL_KEYSTORE_TYPE, KeyStoreType.PKCS12.getType()));
+ final String localKeyStorePath = basicConfig.getBasicConfiguration(PROP_CONFIG_CLIENT_AUTH_SSL_KEYSTORE_PATH, StringUtils.EMPTY);
+ final String keyStorePassword = basicConfig.getBasicConfiguration(PROP_CONFIG_CLIENT_AUTH_SSL_KEYSTORE_PASSORD, StringUtils.EMPTY);
+
+ try {
+ log.debug("Open keyStore with type: {}", keyStoreType);
+ KeyStore clientStore;
+ if (keyStoreType.equals(KeyStoreType.PKCS12)) {
+ clientStore = KeyStore.getInstance("pkcs12");
+ } else {
+ clientStore = KeyStore.getInstance("JKS");
+ }
+
+
+ log.debug("Read keyStore path: {} from configuration", localKeyStorePath);
+ if (StringUtils.isNotEmpty(localKeyStorePath)) {
+ String absFilePath = FileUtils.makeAbsoluteURL(localKeyStorePath, basicConfig.getConfigurationRootDirectory());
+
+ if (absFilePath.startsWith("file:")) {
+ absFilePath = absFilePath.substring("file:".length());
+
+ }
+
+ final File keyStoreFile = new File(absFilePath);
+ log.trace("Load keyStore: {} with password: {}", absFilePath, keyStorePassword);
+ clientStore.load(new FileInputStream(keyStoreFile), keyStorePassword.toCharArray());
+
+ return clientStore;
+
+ } else {
+ log.warn("Path to keyStore for SSL Client-Authentication is empty or null");
+ throw new EAAFConfigurationException("Path to keyStore for SSL Client-Authentication is empty or null", new Object[] {});
+
+ }
+
+ } catch (final KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) {
+ log.warn("Can NOT read keyStore: {} from filesystem", localKeyStorePath, null, e);
+ throw new EAAFConfigurationException("Can NOT read keyStore: {} from filesystem", new Object[] {localKeyStorePath}, e);
+
+ }
+
+ }
+
+ private void injectSSLContext(ClientAuthMode clientAuthMode) {
+ SSLContext sslContext = null;
try {
- log.trace("Initializing SSL Context ... ");
- final SSLContext sslContext = SSLContext.getDefault();
+ if (clientAuthMode.equals(ClientAuthMode.SSL)) {
+ sslContext = buildSSLContextWithSSLClientAuthentication();
+
+ } else {
+ log.trace("Initializing default SSL Context ... ");
+ sslContext = SSLContext.getDefault();
+
+ }
+
+ //set hostname verifier
HostnameVerifier hostnameVerifier = null;
if (basicConfig.getBasicConfigurationBoolean(
PROP_CONFIG_CLIENT_HTTP_SSL_HOSTNAMEVERIFIER_TRUSTALL,
false)) {
hostnameVerifier = new NoopHostnameVerifier();
log.warn("HTTP client-builder deactivates SSL Host-name verification!");
+
}
- final LayeredConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext , hostnameVerifier);
+ final LayeredConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext , hostnameVerifier);
httpClientBuilder.setSSLSocketFactory(sslSocketFactory );
- } catch (final NoSuchAlgorithmException e) {
+ } catch (final NoSuchAlgorithmException | KeyManagementException | UnrecoverableKeyException | KeyStoreException | EAAFConfigurationException e) {
log.warn("HTTP client-builder can NOT initialze SSL-Context", e);
}
-
log.info("HTTP client-builder successfuly initialized");
}
-
+ private void injectConnectionPoolIfRequired() {
+ if (basicConfig.getBasicConfigurationBoolean(
+ PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_USE,
+ true)) {
+ final PoolingHttpClientConnectionManager pool = new PoolingHttpClientConnectionManager();
+ pool.setDefaultMaxPerRoute(Integer.valueOf(basicConfig.getBasicConfiguration(
+ PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE,
+ DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE)));
+ pool.setMaxTotal(Integer.valueOf(basicConfig.getBasicConfiguration(
+ PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL,
+ DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL)));
+
+
+
+ httpClientBuilder.setConnectionManager(pool);
+ log.debug("Initalize http-client pool with, maxTotal: {} maxPerRoute: {}", pool.getMaxTotal(), pool.getDefaultMaxPerRoute());
+
+ }
+
+ }
diff --git a/pom.xml b/pom.xml
index 5711cf5a..c61b2961 100644
--- a/pom.xml
+++ b/pom.xml
@@ -151,9 +151,9 @@
<modules>
<module>eaaf_core_api</module>
+ <module>eaaf_core_utils</module>
<module>eaaf_core</module>
- <module>eaaf_modules</module>
- <module>eaaf_core_utils</module>
+ <module>eaaf_modules</module>
</modules>
<dependencyManagement>