From ed67667ea4e069fb1c19708788ff82c7455a7e99 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Tue, 3 Nov 2020 17:20:21 +0100 Subject: Initialize IAIK-MOA on any request, because there is an open unknown issue with signature-verification and lost configuration states --- .../eaaf/core/impl/credential/EaafKeyStoreFactory.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'eaaf_core_utils/src') diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreFactory.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreFactory.java index 955648c6..1c6e6e76 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreFactory.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/credential/EaafKeyStoreFactory.java @@ -27,6 +27,11 @@ import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEKeySpec; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; + import at.gv.egiz.eaaf.core.api.idp.IConfiguration; import at.gv.egiz.eaaf.core.exception.EaafKeyAccessException; import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; @@ -37,12 +42,6 @@ import at.gv.egiz.eaaf.core.impl.credential.SymmetricKeyConfiguration.SymmetricK import at.gv.egiz.eaaf.core.impl.data.Pair; import at.gv.egiz.eaaf.core.impl.utils.FileUtils; import at.gv.egiz.eaaf.core.impl.utils.KeyStoreUtils; - -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.io.Resource; -import org.springframework.core.io.ResourceLoader; - import lombok.extern.slf4j.Slf4j; @Slf4j @@ -246,7 +245,8 @@ public class EaafKeyStoreFactory { clientUsername, clientPassword, hsmFacadeHost, port); if (rawProvider instanceof Provider) { - Security.insertProviderAt((Provider) rawProvider, 0); + Security.addProvider((Provider) rawProvider); + isHsmFacadeInitialized = true; log.info("HSM Facade is initialized. {} can provide KeyStores based on remote HSM", EaafKeyStoreFactory.class.getSimpleName()); -- cgit v1.2.3 From 62e36db9929c944754a3cebabcbb8227b3f8b592 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Wed, 4 Nov 2020 17:50:28 +0100 Subject: update logging --- .../AuthenticatedEncryptionPendingRequestIdGenerationStrategy.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'eaaf_core_utils/src') diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/AuthenticatedEncryptionPendingRequestIdGenerationStrategy.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/AuthenticatedEncryptionPendingRequestIdGenerationStrategy.java index ebfe7500..b10f8586 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/AuthenticatedEncryptionPendingRequestIdGenerationStrategy.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/AuthenticatedEncryptionPendingRequestIdGenerationStrategy.java @@ -144,8 +144,7 @@ public class AuthenticatedEncryptionPendingRequestIdGenerationStrategy log.debug("Token decryption successful"); if (!(StringUtils.countMatches(stringToken, TOKEN_SEPARATOR) == ENCODED_TOKEN_PARTS - 1)) { - log.warn("PendingRequestId has an unvalid format"); - log.debug("PendingRequestId: {}", stringToken); + log.info("PendingRequestId: {}", stringToken); throw new PendingReqIdValidationException(null, "PendingReqId has an unvalid format"); } @@ -161,8 +160,7 @@ public class AuthenticatedEncryptionPendingRequestIdGenerationStrategy final DateTime now = DateTime.now(); if (timeStamp.withFieldAdded(DurationFieldType.seconds(), maxPendingRequestIdLifeTime) .isBefore(now)) { - log.warn("Token exceeds the valid period"); - log.debug("Token: {} | Now: {}", timeStamp, now); + log.info("Token exceeds the valid period. Token: {} | Now: {}", timeStamp, now); throw new PendingReqIdValidationException(internalPendingReqId, "PendingRequestId exceeds the valid period"); -- cgit v1.2.3 From 83e19359c762bd5652dfa8e2a66d7e5a0c3f2184 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Thu, 5 Nov 2020 11:39:02 +0100 Subject: add scheduled eviction policy to clean-up expired or old http connections from pool --- .../eaaf/core/impl/http/HttpClientFactory.java | 168 +++++++++++++-------- 1 file changed, 104 insertions(+), 64 deletions(-) (limited to 'eaaf_core_utils/src') diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/HttpClientFactory.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/HttpClientFactory.java index 647c0636..07522b56 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/HttpClientFactory.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/HttpClientFactory.java @@ -4,6 +4,8 @@ import java.security.KeyStore; import java.security.Provider; import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.TimeUnit; import javax.annotation.Nonnull; import javax.annotation.PostConstruct; @@ -23,6 +25,7 @@ import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.config.SocketConfig; +import org.apache.http.conn.HttpClientConnectionManager; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.LayeredConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; @@ -33,10 +36,12 @@ 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.BasicHttpClientConnectionManager; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.protocol.HttpContext; import org.apache.http.ssl.SSLContexts; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; import at.gv.egiz.eaaf.core.api.idp.IConfiguration; import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; @@ -65,10 +70,10 @@ public class HttpClientFactory implements IHttpClientFactory { public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_CONNECTION = "client.http.connection.timeout.connection"; public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_REQUEST = - "client.http.connection.timeout.request"; - public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_RETRY_COUNT = + "client.http.connection.timeout.request"; + public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_RETRY_COUNT = "client.http.connection.retry.count"; - public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_RETRY_POST = + public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_RETRY_POST = "client.http.connection.retry.post"; public static final String PROP_CONFIG_CLIENT_HTTP_SSL_HOSTNAMEVERIFIER_TRUSTALL = "client.http.ssl.hostnameverifier.trustall"; @@ -97,9 +102,14 @@ public class HttpClientFactory implements IHttpClientFactory { public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE = "100"; public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_RETRY_COUNT = "3"; public static final String DEFAUTL_CONFIG_CLIENT_HTTP_CONNECTION_RETRY_POST = String.valueOf(false); + + public static final int DEFAULT_CLEANUP_RUNNER_TIME = 30000; + public static final int DEFAULT_CLEANUP_IDLE_TIME = 60; + private String defaultConfigurationId = null; - private final Map availableBuilders = new HashMap<>(); + private final Map> + availableBuilders = new HashMap<>(); /* * (non-Javadoc) @@ -114,7 +124,7 @@ public class HttpClientFactory implements IHttpClientFactory { @Override public CloseableHttpClient getHttpClient(final boolean followRedirects) { - return availableBuilders.get(defaultConfigurationId).setRedirectStrategy( + return availableBuilders.get(defaultConfigurationId).getFirst().setRedirectStrategy( buildRedirectStrategy(followRedirects)).build(); } @@ -124,30 +134,31 @@ public class HttpClientFactory implements IHttpClientFactory { log.trace("Build http client for: {}", config.getFriendlyName()); HttpClientBuilder builder = null; if (availableBuilders.containsKey(config.getUuid())) { - builder = availableBuilders.get(config.getUuid()); + builder = availableBuilders.get(config.getUuid()).getFirst(); } else { log.debug("Initialize new http-client builder for: {}", config.getFriendlyName()); - //validate configuration object + // validate configuration object config.validate(); builder = HttpClients.custom(); - - //inject request configuration + + // inject request configuration builder.setDefaultRequestConfig(buildDefaultRequestConfig()); injectInternalRetryHandler(builder, config); - - //inject basic authentication infos + + // inject basic authentication infos injectBasicAuthenticationIfRequired(builder, config); - //inject authentication if required + // inject authentication if required final LayeredConnectionSocketFactory sslConnectionFactory = getSslContext(config); // set pool connection if required - injectDefaultConnectionPoolIfRequired(builder, sslConnectionFactory); + HttpClientConnectionManager connectionManager + = injectConnectionManager(builder, sslConnectionFactory); - availableBuilders.put(config.getUuid(), builder); + availableBuilders.put(config.getUuid(), Pair.newInstance(builder, connectionManager)); } @@ -156,27 +167,45 @@ public class HttpClientFactory implements IHttpClientFactory { } - private void injectInternalRetryHandler(HttpClientBuilder builder, HttpClientConfiguration config) { + /** + * Worker that closes expired connections or connections that in idle + * for more than DEFAULT_CLEANUP_IDLE_TIME seconds. + * + */ + @Scheduled(fixedDelay = DEFAULT_CLEANUP_RUNNER_TIME) + private void httpConnectionPoolCleaner() { + log.trace("Starting http connection-pool eviction policy ... "); + for (final Entry> el + : availableBuilders.entrySet()) { + log.trace("Checking connections of http-client: {}", el.getKey()); + el.getValue().getSecond().closeExpiredConnections(); + el.getValue().getSecond().closeIdleConnections(DEFAULT_CLEANUP_IDLE_TIME, TimeUnit.SECONDS); + + } + + } + + private void injectInternalRetryHandler(HttpClientBuilder builder, HttpClientConfiguration config) { if (config.getHttpErrorRetryCount() > 0) { - log.info("Set HTTP error-retry to {} for http-client: {}", + log.info("Set HTTP error-retry to {} for http-client: {}", config.getHttpErrorRetryCount(), config.getFriendlyName()); builder.setRetryHandler(new EaafHttpRequestRetryHandler( - config.getHttpErrorRetryCount(), - config.isHttpErrorRetryPost())); - + config.getHttpErrorRetryCount(), + config.isHttpErrorRetryPost())); + if (config.getServiceUnavailStrategy() != null) { log.debug("HttpClient configuration: {} set custom ServiceUnavailableRetryStrategy: {}", config.getFriendlyName(), config.getServiceUnavailStrategy().getClass().getName()); builder.setServiceUnavailableRetryStrategy(config.getServiceUnavailStrategy()); - + } - + } else { log.info("Disable HTTP error-retry for http-client: {}", config.getFriendlyName()); builder.disableAutomaticRetries(); - + } - + } @PostConstruct @@ -190,8 +219,8 @@ public class HttpClientFactory implements IHttpClientFactory { // set default request configuration defaultHttpClientBuilder.setDefaultRequestConfig(buildDefaultRequestConfig()); injectInternalRetryHandler(defaultHttpClientBuilder, defaultHttpClientConfig); - - //inject http basic authentication + + // inject http basic authentication injectBasicAuthenticationIfRequired(defaultHttpClientBuilder, defaultHttpClientConfig); // inject authentication if required @@ -199,11 +228,13 @@ public class HttpClientFactory implements IHttpClientFactory { getSslContext(defaultHttpClientConfig); // set pool connection if required - injectDefaultConnectionPoolIfRequired(defaultHttpClientBuilder, sslConnectionFactory); + HttpClientConnectionManager connectionManager + = injectConnectionManager(defaultHttpClientBuilder, sslConnectionFactory); - //set default http client builder + // set default http client builder defaultConfigurationId = defaultHttpClientConfig.getUuid(); - availableBuilders.put(defaultConfigurationId, defaultHttpClientBuilder); + availableBuilders.put(defaultConfigurationId, + Pair.newInstance(defaultHttpClientBuilder, connectionManager)); } @@ -239,13 +270,12 @@ public class HttpClientFactory implements IHttpClientFactory { PROP_CONFIG_CLIENT_HTTP_SSL_HOSTNAMEVERIFIER_TRUSTALL, false)); config.setHttpErrorRetryCount(Integer.parseInt(basicConfig.getBasicConfiguration( - PROP_CONFIG_CLIENT_HTTP_CONNECTION_RETRY_COUNT, + PROP_CONFIG_CLIENT_HTTP_CONNECTION_RETRY_COUNT, DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_RETRY_COUNT))); config.setHttpErrorRetryPost(Boolean.parseBoolean(basicConfig.getBasicConfiguration( - PROP_CONFIG_CLIENT_HTTP_CONNECTION_RETRY_POST, + PROP_CONFIG_CLIENT_HTTP_CONNECTION_RETRY_POST, DEFAUTL_CONFIG_CLIENT_HTTP_CONNECTION_RETRY_POST))); - - + // validate configuration object config.validate(); @@ -280,7 +310,8 @@ public class HttpClientFactory implements IHttpClientFactory { SSLContext sslContext = null; if (httpClientConfig.getAuthMode().equals(HttpClientConfiguration.ClientAuthMode.SSL)) { log.debug("Open keyStore with type: {}", httpClientConfig.getKeyStoreConfig().getKeyStoreType()); - final Pair keyStore = keyStoreFactory.buildNewKeyStore(httpClientConfig.getKeyStoreConfig()); + final Pair keyStore = keyStoreFactory.buildNewKeyStore(httpClientConfig + .getKeyStoreConfig()); log.trace("Injecting SSL client-authentication into http client ... "); sslContext = HttpUtils.buildSslContextWithSslClientAuthentication(keyStore, @@ -290,7 +321,7 @@ public class HttpClientFactory implements IHttpClientFactory { } else { log.trace("Initializing default SSL Context ... "); sslContext = SSLContexts.createDefault(); - + } // set hostname verifier @@ -308,48 +339,37 @@ public class HttpClientFactory implements IHttpClientFactory { } - private void injectDefaultConnectionPoolIfRequired( + @Nonnull + private HttpClientConnectionManager injectConnectionManager( HttpClientBuilder builder, final LayeredConnectionSocketFactory sslConnectionFactory) { if (basicConfig.getBasicConfigurationBoolean(PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_USE, true)) { - PoolingHttpClientConnectionManager pool; - - // set socketFactoryRegistry if SSLConnectionFactory is Set - if (sslConnectionFactory != null) { - final Registry socketFactoryRegistry = - RegistryBuilder.create() - .register("http", PlainConnectionSocketFactory.getSocketFactory()) - .register("https", sslConnectionFactory).build(); - log.trace("Inject SSLSocketFactory into pooled connection"); - pool = new PoolingHttpClientConnectionManager(socketFactoryRegistry); - - } else { - pool = new PoolingHttpClientConnectionManager(); - - } - - pool.setDefaultMaxPerRoute(Integer.parseInt( + PoolingHttpClientConnectionManager connectionPool + = new PoolingHttpClientConnectionManager(getDefaultRegistry(sslConnectionFactory)); + connectionPool.setDefaultMaxPerRoute(Integer.parseInt( basicConfig.getBasicConfiguration(PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE, DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE))); - pool.setMaxTotal(Integer.parseInt( + connectionPool.setMaxTotal(Integer.parseInt( basicConfig.getBasicConfiguration(PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL, DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL))); - - pool.setDefaultSocketConfig(SocketConfig.custom().setSoTimeout(Integer.parseInt( + connectionPool.setDefaultSocketConfig(SocketConfig.custom().setSoTimeout(Integer.parseInt( basicConfig.getBasicConfiguration(PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_SOCKET, DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_SOCKET)) * 1000).build()); + builder.setConnectionManager(connectionPool); + log.debug("Initalize http-client pool with, maxTotal: {} maxPerRoute: {}", + connectionPool.getMaxTotal(), connectionPool.getDefaultMaxPerRoute()); + return connectionPool; + + } else { + log.debug("Building http-client without Connection-Pool ... "); + final BasicHttpClientConnectionManager basicPool = new BasicHttpClientConnectionManager( + getDefaultRegistry(sslConnectionFactory)); + builder.setConnectionManager(basicPool); + return basicPool; - builder.setConnectionManager(pool); - log.debug("Initalize http-client pool with, maxTotal: {} maxPerRoute: {}", pool.getMaxTotal(), - pool.getDefaultMaxPerRoute()); - - } else if (sslConnectionFactory != null) { - log.trace("Inject SSLSocketFactory without connection pool"); - builder.setSSLSocketFactory(sslConnectionFactory); - } - + } private RequestConfig buildDefaultRequestConfig() { @@ -392,5 +412,25 @@ public class HttpClientFactory implements IHttpClientFactory { return redirectStrategy; } + + private static Registry getDefaultRegistry( + final LayeredConnectionSocketFactory sslConnectionFactory) { + final RegistryBuilder builder = + RegistryBuilder.create() + .register("http", PlainConnectionSocketFactory.getSocketFactory()); + + if (sslConnectionFactory != null) { + log.trace("Inject own SSLSocketFactory into pooled connection"); + builder.register("https", sslConnectionFactory); + + } else { + log.trace("Inject default SSLSocketFactory into pooled connection"); + builder.register("https", SSLConnectionSocketFactory.getSocketFactory()); + + } + + return builder.build(); + + } } -- cgit v1.2.3 From 0964aa4dfbf5543fff4e023290beefaeed31f3c5 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Mon, 9 Nov 2020 18:18:52 +0100 Subject: refactor error-handling in pending-request generation-stategies --- ...cryptionPendingRequestIdGenerationStrategy.java | 37 +++++-------- .../SecurePendingRequestIdGenerationStrategy.java | 59 ++++++++------------ .../eaaf/core/impl/utils/TransactionIdUtils.java | 19 +++++-- .../messages/eaaf_utils_message.properties | 11 +++- ...tionPendingRequestIdGenerationStrategyTest.java | 63 +++++----------------- 5 files changed, 71 insertions(+), 118 deletions(-) (limited to 'eaaf_core_utils/src') diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/AuthenticatedEncryptionPendingRequestIdGenerationStrategy.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/AuthenticatedEncryptionPendingRequestIdGenerationStrategy.java index b10f8586..83ea7da0 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/AuthenticatedEncryptionPendingRequestIdGenerationStrategy.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/AuthenticatedEncryptionPendingRequestIdGenerationStrategy.java @@ -1,6 +1,6 @@ package at.gv.egiz.eaaf.core.impl.utils; -import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import java.security.Provider; import java.util.Base64; @@ -98,10 +98,10 @@ public class AuthenticatedEncryptionPendingRequestIdGenerationStrategy } return Base64.getUrlEncoder() - .encodeToString(encToken.getCompactSerialization().getBytes("UTF-8")); + .encodeToString(encToken.getCompactSerialization().getBytes(StandardCharsets.UTF_8)); - } catch (final JoseException | UnsupportedEncodingException e) { - throw new EaafException("internal.99", new Object[] { e.getMessage() }, e); + } catch (final JoseException e) { + throw new EaafException("internal.pendingreqid.02", new Object[] { e.getMessage() }, e); } @@ -117,7 +117,7 @@ public class AuthenticatedEncryptionPendingRequestIdGenerationStrategy if (!(StringUtils.countMatches(stringToken, TOKEN_SEPARATOR) == ENCODED_TOKEN_PARTS - 1)) { log.warn("PendingRequestId has an unvalid format"); log.debug("PendingRequestId: {}", stringToken); - throw new PendingReqIdValidationException(null, "PendingReqId has an unvalid format"); + throw new PendingReqIdValidationException(null, "internal.pendingreqid.01"); } @@ -125,13 +125,10 @@ public class AuthenticatedEncryptionPendingRequestIdGenerationStrategy StringUtils.split(stringToken, TOKEN_SEPARATOR, ENCODED_TOKEN_PARTS); return tokenElements[1]; - } catch (final UnsupportedEncodingException e) { - throw new RuntimeException(e); - } catch (JoseException e) { log.warn("Token is NOT a valid String. Msg: {}", e.getMessage()); log.debug("TokenValue: {}", externalPendingReqId); - throw new PendingReqIdValidationException(null, "PendingReqId is NOT a valid String", e); + throw new PendingReqIdValidationException(null, "internal.pendingreqid.05", e); } } @@ -145,7 +142,7 @@ public class AuthenticatedEncryptionPendingRequestIdGenerationStrategy if (!(StringUtils.countMatches(stringToken, TOKEN_SEPARATOR) == ENCODED_TOKEN_PARTS - 1)) { log.info("PendingRequestId: {}", stringToken); - throw new PendingReqIdValidationException(null, "PendingReqId has an unvalid format"); + throw new PendingReqIdValidationException(null, "internal.pendingreqid.01"); } @@ -154,15 +151,13 @@ public class AuthenticatedEncryptionPendingRequestIdGenerationStrategy final String internalPendingReqId = tokenElements[1]; final DateTime timeStamp = TOKEN_TEXTUAL_DATE_FORMAT.parseDateTime(tokenElements[0]); - - log.trace("Checking valid period ... "); final DateTime now = DateTime.now(); if (timeStamp.withFieldAdded(DurationFieldType.seconds(), maxPendingRequestIdLifeTime) .isBefore(now)) { log.info("Token exceeds the valid period. Token: {} | Now: {}", timeStamp, now); throw new PendingReqIdValidationException(internalPendingReqId, - "PendingRequestId exceeds the valid period"); + "internal.pendingreqid.06"); } log.debug("Token valid-period check successful"); @@ -172,25 +167,22 @@ public class AuthenticatedEncryptionPendingRequestIdGenerationStrategy } catch (JoseException e) { log.warn("Token is NOT a valid encrypt. Msg: {}", e.getMessage()); log.debug("TokenValue: {}", externalPendingReqId); - throw new PendingReqIdValidationException(null, "PendingReqId is NOT a valid encrypted", e); + throw new PendingReqIdValidationException(null, "internal.pendingreqid.04", e); } catch (final IllegalArgumentException e) { log.warn("Token is NOT a valid String. Msg: {}", e.getMessage()); log.debug("TokenValue: {}", externalPendingReqId); - throw new PendingReqIdValidationException(null, "PendingReqId is NOT a valid String", e); - - } catch (final UnsupportedEncodingException e) { - throw new RuntimeException(e); + throw new PendingReqIdValidationException(null, "internal.pendingreqid.05", e); } } @Nonnull private String getDecryptedExternalPendingRequestId(String externalPendingReqId) - throws JoseException, PendingReqIdValidationException, UnsupportedEncodingException { + throws JoseException, PendingReqIdValidationException { if (StringUtils.isEmpty(externalPendingReqId)) { log.info("PendingReqId is 'null' or empty"); - throw new PendingReqIdValidationException(null, "PendingReqId is 'null' or empty"); + throw new PendingReqIdValidationException(null, "internal.pendingreqid.00"); } @@ -199,8 +191,7 @@ public class AuthenticatedEncryptionPendingRequestIdGenerationStrategy if (externalPendingReqIdBytes.length > maxPendingReqIdSize) { log.warn("pendingReqId size exceeds {}", maxPendingReqIdSize); - throw new PendingReqIdValidationException(null, - "pendingReqId exceeds max.size: " + maxPendingReqIdSize); + throw new PendingReqIdValidationException(null, "internal.pendingreqid.03"); } @@ -223,7 +214,7 @@ public class AuthenticatedEncryptionPendingRequestIdGenerationStrategy } - encToken.setCompactSerialization(new String(externalPendingReqIdBytes, "UTF-8")); + encToken.setCompactSerialization(new String(externalPendingReqIdBytes, StandardCharsets.UTF_8)); return encToken.getPayload(); } diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SecurePendingRequestIdGenerationStrategy.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SecurePendingRequestIdGenerationStrategy.java index ad6471d5..8ec5f3a8 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SecurePendingRequestIdGenerationStrategy.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/SecurePendingRequestIdGenerationStrategy.java @@ -1,6 +1,6 @@ package at.gv.egiz.eaaf.core.impl.utils; -import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.Arrays; @@ -80,33 +80,22 @@ public class SecurePendingRequestIdGenerationStrategy @Override public String generateExternalPendingRequestId() throws EaafException { - try { - final String toSign = buildInternalToken(Random.nextLongRandom(), DateTime.now()); - final StringBuilder externalPendingRequestId = new StringBuilder(); - externalPendingRequestId.append(toSign); - externalPendingRequestId.append(TOKEN_SEPARATOR); - externalPendingRequestId.append(Base64.getEncoder().encodeToString(calculateHmac(toSign))); - return Base64.getUrlEncoder() - .encodeToString(externalPendingRequestId.toString().getBytes("UTF-8")); - - } catch (final UnsupportedEncodingException e) { - throw new EaafException("internal.99", new Object[] { e.getMessage() }, e); - - } + final String toSign = buildInternalToken(Random.nextLongRandom(), DateTime.now()); + final StringBuilder externalPendingRequestId = new StringBuilder(); + externalPendingRequestId.append(toSign); + externalPendingRequestId.append(TOKEN_SEPARATOR); + externalPendingRequestId.append(Base64.getEncoder().encodeToString(calculateHmac(toSign))); + return Base64.getUrlEncoder() + .encodeToString(externalPendingRequestId.toString().getBytes(StandardCharsets.UTF_8)); } @Override public String getPendingRequestIdWithOutChecks(final String externalPendingReqId) throws PendingReqIdValidationException { - try { - final String[] tokenElements = extractTokens(externalPendingReqId); - return tokenElements[1]; - - } catch (final UnsupportedEncodingException e) { - throw new RuntimeException(e); - - } + final String[] tokenElements = extractTokens(externalPendingReqId); + return tokenElements[1]; + } @Override @@ -123,8 +112,7 @@ public class SecurePendingRequestIdGenerationStrategy if (!Arrays.equals(tokenDigest, refDigist)) { log.warn("Digest of Token does NOT match"); log.debug("Token: {} | Ref: {}", tokenDigest, refDigist); - throw new PendingReqIdValidationException(null, - "Digest of pendingRequestId does NOT match"); + throw new PendingReqIdValidationException(null, "internal.pendingreqid.04"); } log.debug("PendingRequestId HMAC digest check successful"); @@ -135,8 +123,7 @@ public class SecurePendingRequestIdGenerationStrategy .isBefore(now)) { log.warn("Token exceeds the valid period"); log.debug("Token: {} | Now: {}", timeStamp, now); - throw new PendingReqIdValidationException(internalPendingReqId, - "PendingRequestId exceeds the valid period"); + throw new PendingReqIdValidationException(internalPendingReqId, "internal.pendingreqid.06"); } log.debug("Token valid-period check successful"); @@ -146,20 +133,17 @@ public class SecurePendingRequestIdGenerationStrategy } catch (final IllegalArgumentException | EaafIllegalStateException e) { log.warn("Token is NOT a valid String. Msg: {}", e.getMessage()); log.debug("TokenValue: {}", externalPendingReqId); - throw new PendingReqIdValidationException(null, "PendingReqId is NOT a valid String", e); - - } catch (final UnsupportedEncodingException e) { - throw new RuntimeException(e); + throw new PendingReqIdValidationException(null, "internal.pendingreqid.06", e); } } @NonNull private String[] extractTokens(@Nullable final String externalPendingReqId) - throws PendingReqIdValidationException, UnsupportedEncodingException { + throws PendingReqIdValidationException { if (StringUtils.isEmpty(externalPendingReqId)) { log.info("PendingReqId is 'null' or empty"); - throw new PendingReqIdValidationException(null, "PendingReqId is 'null' or empty"); + throw new PendingReqIdValidationException(null, "internal.pendingreqid.00"); } @@ -168,12 +152,11 @@ public class SecurePendingRequestIdGenerationStrategy if (externalPendingReqIdBytes.length > maxPendingReqIdSize) { log.warn("pendingReqId size exceeds {}", maxPendingReqIdSize); - throw new PendingReqIdValidationException(null, - "pendingReqId exceeds max.size: " + maxPendingReqIdSize); + throw new PendingReqIdValidationException(null, "internal.pendingreqid.03"); } - final String stringToken = new String(externalPendingReqIdBytes, "UTF-8"); + final String stringToken = new String(externalPendingReqIdBytes, StandardCharsets.UTF_8); if (StringUtils.countMatches(stringToken, TOKEN_SEPARATOR) == ENCODED_TOKEN_PARTS - 1) { final String[] tokenElements = StringUtils.split(stringToken, TOKEN_SEPARATOR, ENCODED_TOKEN_PARTS); @@ -182,7 +165,7 @@ public class SecurePendingRequestIdGenerationStrategy } else { log.warn("PendingRequestId has an unvalid format"); log.debug("PendingRequestId: {}", stringToken); - throw new PendingReqIdValidationException(null, "PendingReqId has an unvalid format"); + throw new PendingReqIdValidationException(null, "internal.pendingreqid.01"); } @@ -243,9 +226,9 @@ public class SecurePendingRequestIdGenerationStrategy try { final Mac mac = Mac.getInstance(digistAlgorithm); mac.init(key); - return mac.doFinal(toSign.getBytes("UTF-8")); + return mac.doFinal(toSign.getBytes(StandardCharsets.UTF_8)); - } catch (UnsupportedEncodingException | NoSuchAlgorithmException | InvalidKeyException e) { + } catch (NoSuchAlgorithmException | InvalidKeyException e) { log.error("Can NOT generate secure pendingRequestId", e); throw new EaafIllegalStateException( new Object[] { "Can NOT caluclate digist for secure pendingRequestId" }, e); diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/TransactionIdUtils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/TransactionIdUtils.java index 4c1601c0..d1613d16 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/TransactionIdUtils.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/utils/TransactionIdUtils.java @@ -21,7 +21,10 @@ package at.gv.egiz.eaaf.core.impl.utils; import java.util.UUID; +import javax.annotation.Nullable; + import at.gv.egiz.eaaf.core.api.IRequest; +import lombok.extern.slf4j.Slf4j; /** * Transaction Identifier Utils. @@ -29,6 +32,7 @@ import at.gv.egiz.eaaf.core.api.IRequest; * @author tlenz * */ +@Slf4j public class TransactionIdUtils { /** @@ -58,11 +62,16 @@ public class TransactionIdUtils { * * @param pendingRequest Http request object */ - public static void setAllLoggingVariables(final IRequest pendingRequest) { - setTransactionId(pendingRequest.getUniqueTransactionIdentifier()); - setSessionId(pendingRequest.getUniqueSessionIdentifier()); - setServiceProviderId(pendingRequest.getServiceProviderConfiguration().getUniqueIdentifier()); - + public static void setAllLoggingVariables(@Nullable final IRequest pendingRequest) { + if (pendingRequest != null) { + setTransactionId(pendingRequest.getUniqueTransactionIdentifier()); + setSessionId(pendingRequest.getUniqueSessionIdentifier()); + setServiceProviderId(pendingRequest.getServiceProviderConfiguration().getUniqueIdentifier()); + + } else { + log.warn("Can NOT set MDC variables from pendingRequest because it is 'null'"); + + } } /** diff --git a/eaaf_core_utils/src/main/resources/messages/eaaf_utils_message.properties b/eaaf_core_utils/src/main/resources/messages/eaaf_utils_message.properties index 5b398bb0..79f82af8 100644 --- a/eaaf_core_utils/src/main/resources/messages/eaaf_utils_message.properties +++ b/eaaf_core_utils/src/main/resources/messages/eaaf_utils_message.properties @@ -20,4 +20,13 @@ internal.key.01=Can not use key from Keystore: {0} Reason: {1} internal.httpclient.00=HttpClient:{0} uses http Basic-Auth, but 'Username' is NOT set internal.httpclient.01=HttpClient:{0} uses X509 client-auth, but 'KeyStoreConfig' is NOT set internal.httpclient.02=HttpClient:{0} uses KeyStore:{1}, but 'keyPassword' is NOT set -internal.httpclient.03=Can not initialize SSLContext for HttpClient:{0} Reason:{1} \ No newline at end of file +internal.httpclient.03=Can not initialize SSLContext for HttpClient:{0} Reason:{1} + +internal.pendingreqid.00=Process Token is 'null' or 'empty' +internal.pendingreqid.01=Process Token is NOT valid because it has an invalid format +internal.pendingreqid.02=Can not create process Token +internal.pendingreqid.03=Process Token is NOT valid because it reached maximum size +internal.pendingreqid.04=Process Token is NOT valid because it is cryptographically invalid +internal.pendingreqid.05=Process Token is NOT valid because it has an invalid encoding +internal.pendingreqid.06=Process Token is NOT valid because it exceeds the valid period + diff --git a/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/impl/utils/test/AuthenticatedEncryptionPendingRequestIdGenerationStrategyTest.java b/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/impl/utils/test/AuthenticatedEncryptionPendingRequestIdGenerationStrategyTest.java index 34f4a3b1..8b437dcf 100644 --- a/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/impl/utils/test/AuthenticatedEncryptionPendingRequestIdGenerationStrategyTest.java +++ b/eaaf_core_utils/src/test/java/at/gv/egiz/eaaf/core/impl/utils/test/AuthenticatedEncryptionPendingRequestIdGenerationStrategyTest.java @@ -71,10 +71,7 @@ public class AuthenticatedEncryptionPendingRequestIdGenerationStrategyTest { } catch (PendingReqIdValidationException e) { Assert.assertNull("internal pendingReqId", e.getInvalidInternalPendingReqId()); Assert.assertNull("internal pendingReq", e.getInvalidPendingReq()); - Assert.assertEquals("Wrong errorId", "process.99", e.getErrorId()); - Assert.assertEquals("Wrong errorMsg", - "No StatusMessager-Backend available! StatusCode:process.99 Params:[null, PendingReqId is 'null' or empty]", - e.getMessage()); + Assert.assertEquals("Wrong errorId", "internal.pendingreqid.00", e.getErrorId()); } } @@ -88,10 +85,7 @@ public class AuthenticatedEncryptionPendingRequestIdGenerationStrategyTest { } catch (PendingReqIdValidationException e) { Assert.assertNull("internal pendingReqId", e.getInvalidInternalPendingReqId()); Assert.assertNull("internal pendingReq", e.getInvalidPendingReq()); - Assert.assertEquals("Wrong errorId", "process.99", e.getErrorId()); - Assert.assertEquals("Wrong errorMsg", - "No StatusMessager-Backend available! StatusCode:process.99 Params:[null, PendingReqId is 'null' or empty]", - e.getMessage()); + Assert.assertEquals("Wrong errorId", "internal.pendingreqid.00", e.getErrorId()); } } @@ -105,11 +99,7 @@ public class AuthenticatedEncryptionPendingRequestIdGenerationStrategyTest { } catch (PendingReqIdValidationException e) { Assert.assertNull("internal pendingReqId", e.getInvalidInternalPendingReqId()); Assert.assertNull("internal pendingReq", e.getInvalidPendingReq()); - Assert.assertEquals("Wrong errorId", "process.99", e.getErrorId()); - Assert.assertEquals("Wrong errorMsg", - "No StatusMessager-Backend available! StatusCode:process.99 Params:[null, " - + "PendingReqId is NOT a valid String]", - e.getMessage()); + Assert.assertEquals("Wrong errorId", "internal.pendingreqid.05", e.getErrorId()); } } @@ -124,11 +114,7 @@ public class AuthenticatedEncryptionPendingRequestIdGenerationStrategyTest { } catch (PendingReqIdValidationException e) { Assert.assertNull("internal pendingReqId", e.getInvalidInternalPendingReqId()); Assert.assertNull("internal pendingReq", e.getInvalidPendingReq()); - Assert.assertEquals("Wrong errorId", "process.99", e.getErrorId()); - Assert.assertEquals("Wrong errorMsg", - "No StatusMessager-Backend available! StatusCode:process.99 Params:[null, " - + "pendingReqId exceeds max.size: 1024]", - e.getMessage()); + Assert.assertEquals("Wrong errorId", "internal.pendingreqid.03", e.getErrorId()); } } @@ -150,11 +136,7 @@ public class AuthenticatedEncryptionPendingRequestIdGenerationStrategyTest { } catch (PendingReqIdValidationException e) { Assert.assertNull("internal pendingReqId", e.getInvalidInternalPendingReqId()); Assert.assertNull("internal pendingReq", e.getInvalidPendingReq()); - Assert.assertEquals("Wrong errorId", "process.99", e.getErrorId()); - Assert.assertEquals("Wrong errorMsg", - "No StatusMessager-Backend available! StatusCode:process.99 Params:[null, " - + "PendingReqId has an unvalid format]", - e.getMessage()); + Assert.assertEquals("Wrong errorId", "internal.pendingreqid.01", e.getErrorId()); } } @@ -177,11 +159,7 @@ public class AuthenticatedEncryptionPendingRequestIdGenerationStrategyTest { } catch (PendingReqIdValidationException e) { Assert.assertNull("internal pendingReqId", e.getInvalidInternalPendingReqId()); Assert.assertNull("internal pendingReq", e.getInvalidPendingReq()); - Assert.assertEquals("Wrong errorId", "process.99", e.getErrorId()); - Assert.assertEquals("Wrong errorMsg", - "No StatusMessager-Backend available! StatusCode:process.99 Params:[null, " - + "PendingReqId has an unvalid format]", - e.getMessage()); + Assert.assertEquals("Wrong errorId", "internal.pendingreqid.01", e.getErrorId()); } } @@ -204,11 +182,7 @@ public class AuthenticatedEncryptionPendingRequestIdGenerationStrategyTest { } catch (PendingReqIdValidationException e) { Assert.assertNull("internal pendingReqId", e.getInvalidInternalPendingReqId()); Assert.assertNull("internal pendingReq", e.getInvalidPendingReq()); - Assert.assertEquals("Wrong errorId", "process.99", e.getErrorId()); - Assert.assertEquals("Wrong errorMsg", - "No StatusMessager-Backend available! StatusCode:process.99 Params:[null, " - + "PendingReqId is NOT a valid String]", - e.getMessage()); + Assert.assertEquals("Wrong errorId", "internal.pendingreqid.05", e.getErrorId()); } } @@ -231,8 +205,7 @@ public class AuthenticatedEncryptionPendingRequestIdGenerationStrategyTest { } catch (PendingReqIdValidationException e) { Assert.assertNotNull("internal pendingReqId", e.getInvalidInternalPendingReqId()); Assert.assertNull("internal pendingReq", e.getInvalidPendingReq()); - Assert.assertEquals("Wrong errorId", "process.99", e.getErrorId()); - Assert.assertTrue("Wrong errorMsg", e.getMessage().contains("PendingRequestId exceeds the valid period")); + Assert.assertEquals("Wrong errorId", "internal.pendingreqid.06", e.getErrorId()); } } @@ -254,11 +227,7 @@ public class AuthenticatedEncryptionPendingRequestIdGenerationStrategyTest { } catch (PendingReqIdValidationException e) { Assert.assertNull("internal pendingReqId", e.getInvalidInternalPendingReqId()); Assert.assertNull("internal pendingReq", e.getInvalidPendingReq()); - Assert.assertEquals("Wrong errorId", "process.99", e.getErrorId()); - Assert.assertEquals("Wrong errorMsg", - "No StatusMessager-Backend available! StatusCode:process.99 Params:[null, " - + "PendingReqId has an unvalid format]", - e.getMessage()); + Assert.assertEquals("Wrong errorId", "internal.pendingreqid.01", e.getErrorId()); } } @@ -281,12 +250,8 @@ public class AuthenticatedEncryptionPendingRequestIdGenerationStrategyTest { } catch (PendingReqIdValidationException e) { Assert.assertNull("internal pendingReqId", e.getInvalidInternalPendingReqId()); Assert.assertNull("internal pendingReq", e.getInvalidPendingReq()); - Assert.assertEquals("Wrong errorId", "process.99", e.getErrorId()); - Assert.assertEquals("Wrong errorMsg", - "No StatusMessager-Backend available! StatusCode:process.99 Params:[null, " - + "PendingReqId has an unvalid format]", - e.getMessage()); - + Assert.assertEquals("Wrong errorId", "internal.pendingreqid.01", e.getErrorId()); + } } @@ -399,11 +364,7 @@ public class AuthenticatedEncryptionPendingRequestIdGenerationStrategyTest { } catch (PendingReqIdValidationException e) { Assert.assertNull("internal pendingReqId", e.getInvalidInternalPendingReqId()); Assert.assertNull("internal pendingReq", e.getInvalidPendingReq()); - Assert.assertEquals("Wrong errorId", "process.99", e.getErrorId()); - Assert.assertEquals("Wrong errorMsg", - "No StatusMessager-Backend available! StatusCode:process.99 Params:[null, " - + "PendingReqId is NOT a valid encrypted]", - e.getMessage()); + Assert.assertEquals("Wrong errorId", "internal.pendingreqid.04", e.getErrorId()); } } -- cgit v1.2.3 From 6aa0ba667a6608e34b19b31dba18673181c85a5f Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Thu, 26 Nov 2020 17:38:50 +0100 Subject: add building block of a http ResponseHandler that returns the http status-code --- .../at/gv/egiz/eaaf/core/impl/http/HttpUtils.java | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'eaaf_core_utils/src') diff --git a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/HttpUtils.java b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/HttpUtils.java index 81ebe1fe..10555822 100644 --- a/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/HttpUtils.java +++ b/eaaf_core_utils/src/main/java/at/gv/egiz/eaaf/core/impl/http/HttpUtils.java @@ -18,6 +18,7 @@ package at.gv.egiz.eaaf.core.impl.http; +import java.io.IOException; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; @@ -31,10 +32,15 @@ import javax.net.ssl.SSLContext; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpResponse; +import org.apache.http.StatusLine; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.ResponseHandler; import org.apache.http.conn.ssl.TrustAllStrategy; import org.apache.http.ssl.SSLContextBuilder; import org.apache.http.ssl.SSLContexts; import org.apache.http.ssl.TrustStrategy; +import org.apache.http.util.EntityUtils; import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider; import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; @@ -47,6 +53,23 @@ public class HttpUtils { private static final String ERROR_03 = "internal.httpclient.03"; + + /** + * Simple Http response-handler that only give http status-code as result. + * + * @return Status-Code of http response + */ + public static ResponseHandler simpleStatusCodeResponseHandler() { + return new ResponseHandler() { + @Override + public StatusLine handleResponse(HttpResponse response) throws ClientProtocolException, IOException { + EntityUtils.consumeQuietly(response.getEntity()); + return response.getStatusLine(); + + } + }; + } + /** * Helper method to retrieve server URL including context path. * -- cgit v1.2.3