diff options
| author | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2020-11-10 14:20:56 +0100 | 
|---|---|---|
| committer | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2020-11-10 14:20:56 +0100 | 
| commit | b49e72d172d9671898a79842b6cd3db7a7304937 (patch) | |
| tree | 776a77377384a3679efacaf5d9f02f286f994140 /eaaf_core_utils | |
| parent | 83697944c66fff1b5ee47850b46fd970907a9757 (diff) | |
| parent | 0964aa4dfbf5543fff4e023290beefaeed31f3c5 (diff) | |
| download | EAAF-Components-b49e72d172d9671898a79842b6cd3db7a7304937.tar.gz EAAF-Components-b49e72d172d9671898a79842b6cd3db7a7304937.tar.bz2 EAAF-Components-b49e72d172d9671898a79842b6cd3db7a7304937.zip | |
Merge branch 'nightlyBuild' of gitlab.iaik.tugraz.at:egiz/eaaf_components into nightlyBuild
Diffstat (limited to 'eaaf_core_utils')
7 files changed, 184 insertions, 193 deletions
| 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()); 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<String, HttpClientBuilder> availableBuilders = new HashMap<>(); +  private final Map<String, Pair<HttpClientBuilder, HttpClientConnectionManager>>  +      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<String, Pair<HttpClientBuilder, HttpClientConnectionManager>> 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, Provider> keyStore = keyStoreFactory.buildNewKeyStore(httpClientConfig.getKeyStoreConfig()); +      final Pair<KeyStore, Provider> 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<ConnectionSocketFactory> socketFactoryRegistry = -            RegistryBuilder.<ConnectionSocketFactory>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<ConnectionSocketFactory> getDefaultRegistry( +      final LayeredConnectionSocketFactory sslConnectionFactory) { +    final RegistryBuilder<ConnectionSocketFactory> builder = +        RegistryBuilder.<ConnectionSocketFactory>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(); + +  }  } 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..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);      }    } @@ -144,9 +141,8 @@ 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); -        throw new PendingReqIdValidationException(null, "PendingReqId has an unvalid format"); +        log.info("PendingRequestId: {}", stringToken); +        throw new PendingReqIdValidationException(null, "internal.pendingreqid.01");        } @@ -155,16 +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.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"); +            "internal.pendingreqid.06");        }        log.debug("Token valid-period check successful"); @@ -174,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");      } @@ -201,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");      } @@ -225,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());      }        } | 
