From 836c57fed60a2e5ea9e9f1d927a7a2d27d19a711 Mon Sep 17 00:00:00 2001 From: "A.Alimohammadi" Date: Wed, 15 Nov 2023 15:41:20 +0330 Subject: [PATCH] [feature]add mask key/value pair header value with secureParameterConfig added other overload for HttpFeignClientLogger in AbstractFeignConfiguration. added httpReplaceHelperDecider for mask key/value pair header value. create bean of httpReplaceHelperDecider and use this new HttpFeignClientLogger overload and inject this bean to mask key/value pair header value. --- .../config/feign/CustomServerFeignConfig.java | 16 ++++++- .../AbstractFeignConfiguration.java | 12 +++++ .../TosanFeignAutoConfiguration.java | 10 ++++ .../feign/logger/HttpFeignClientLogger.java | 16 ++++++- .../util/HttpReplaceHelperDecider.java | 27 +++++++++++ .../starter/util/KeyValueReplaceHelper.java | 48 +++++++++++++++++++ 6 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 tosan-httpclient-spring-boot-starter/src/main/java/com/tosan/client/http/starter/util/HttpReplaceHelperDecider.java create mode 100644 tosan-httpclient-spring-boot-starter/src/main/java/com/tosan/client/http/starter/util/KeyValueReplaceHelper.java diff --git a/tosan-httpclient-spring-boot-sample/src/main/java/com/tosan/client/http/sample/server/api/config/feign/CustomServerFeignConfig.java b/tosan-httpclient-spring-boot-sample/src/main/java/com/tosan/client/http/sample/server/api/config/feign/CustomServerFeignConfig.java index 8488720..6e1b0aa 100644 --- a/tosan-httpclient-spring-boot-sample/src/main/java/com/tosan/client/http/sample/server/api/config/feign/CustomServerFeignConfig.java +++ b/tosan-httpclient-spring-boot-sample/src/main/java/com/tosan/client/http/sample/server/api/config/feign/CustomServerFeignConfig.java @@ -10,6 +10,8 @@ import com.tosan.client.http.starter.impl.feign.CustomErrorDecoderConfig; import com.tosan.client.http.starter.impl.feign.ExceptionExtractType; import com.tosan.client.http.starter.impl.feign.exception.TosanWebServiceRuntimeException; +import com.tosan.client.http.starter.util.HttpReplaceHelperDecider; +import com.tosan.client.http.starter.util.KeyValueReplaceHelper; import com.tosan.tools.mask.starter.config.SecureParametersConfig; import com.tosan.tools.mask.starter.replace.JacksonReplaceHelper; import com.tosan.tools.mask.starter.replace.JsonReplaceHelperDecider; @@ -61,10 +63,20 @@ public JsonReplaceHelperDecider replaceHelperDecider(JacksonReplaceHelper jackso return super.replaceHelperDecider(jacksonReplaceHelper, regexReplaceHelper, secureParametersConfig); } + @Override + @Bean("customServer-http-replace-helper") + public HttpReplaceHelperDecider httpReplaceHelperDecider(KeyValueReplaceHelper keyValueReplaceHelper, + @Qualifier("customServer-secured-parameters") + SecureParametersConfig secureParametersConfig) { + return super.httpReplaceHelperDecider(keyValueReplaceHelper, secureParametersConfig); + } + @Bean("customServer-httpFeignClientLogger") public Logger httpFeignClientLogger(@Qualifier("customServer-replace-helper") - JsonReplaceHelperDecider replaceHelperDecider) { - return super.httpFeignClientLogger(replaceHelperDecider, "custom-server"); + JsonReplaceHelperDecider replaceHelperDecider, + @Qualifier("customServer-http-replace-helper") + HttpReplaceHelperDecider httpReplaceHelperDecider) { + return super.httpFeignClientLogger(replaceHelperDecider,httpReplaceHelperDecider, "custom-server"); } @Bean("customServer-secured-parameters") diff --git a/tosan-httpclient-spring-boot-starter/src/main/java/com/tosan/client/http/starter/configuration/AbstractFeignConfiguration.java b/tosan-httpclient-spring-boot-starter/src/main/java/com/tosan/client/http/starter/configuration/AbstractFeignConfiguration.java index 8495362..a9c980a 100644 --- a/tosan-httpclient-spring-boot-starter/src/main/java/com/tosan/client/http/starter/configuration/AbstractFeignConfiguration.java +++ b/tosan-httpclient-spring-boot-starter/src/main/java/com/tosan/client/http/starter/configuration/AbstractFeignConfiguration.java @@ -11,6 +11,8 @@ import com.tosan.client.http.starter.impl.feign.CustomErrorDecoderConfig; import com.tosan.client.http.starter.impl.feign.exception.FeignConfigurationException; import com.tosan.client.http.starter.impl.feign.logger.HttpFeignClientLogger; +import com.tosan.client.http.starter.util.HttpReplaceHelperDecider; +import com.tosan.client.http.starter.util.KeyValueReplaceHelper; import com.tosan.tools.mask.starter.config.SecureParameter; import com.tosan.tools.mask.starter.config.SecureParametersConfig; import com.tosan.tools.mask.starter.replace.JacksonReplaceHelper; @@ -40,6 +42,7 @@ import org.springframework.core.convert.ConversionService; import org.springframework.format.support.DefaultFormattingConversionService; import org.springframework.format.support.FormattingConversionService; +import org.springframework.http.HttpHeaders; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.http.converter.HttpMessageConverter; @@ -75,6 +78,11 @@ public JsonReplaceHelperDecider replaceHelperDecider(JacksonReplaceHelper jackso return new JsonReplaceHelperDecider(jacksonReplaceHelper, regexReplaceHelper, secureParametersConfig); } + public HttpReplaceHelperDecider httpReplaceHelperDecider(KeyValueReplaceHelper keyValueReplaceHelper, + SecureParametersConfig secureParametersConfig) { + return new HttpReplaceHelperDecider(keyValueReplaceHelper, secureParametersConfig); + } + public SecureParametersConfig secureParametersConfig() { HashSet securedParameters = new HashSet<>(SECURED_PARAMETERS); securedParameters.add(Constants.AUTHORIZATION_SECURE_PARAM); @@ -85,6 +93,10 @@ public SecureParametersConfig secureParametersConfig() { public Logger httpFeignClientLogger(JsonReplaceHelperDecider replaceHelperDecider, String serverName) { return new HttpFeignClientLogger(serverName, replaceHelperDecider); } + public Logger httpFeignClientLogger(JsonReplaceHelperDecider replaceHelperDecider, + HttpReplaceHelperDecider httpReplaceHelperDecider, String serverName) { + return new HttpFeignClientLogger(serverName, replaceHelperDecider, httpReplaceHelperDecider); + } public ApacheHttpClientFactory apacheHttpClientFactory(HttpClientBuilder builder, ApacheHttpClientConnectionManagerFactory clientConnectionManagerFactory, diff --git a/tosan-httpclient-spring-boot-starter/src/main/java/com/tosan/client/http/starter/configuration/TosanFeignAutoConfiguration.java b/tosan-httpclient-spring-boot-starter/src/main/java/com/tosan/client/http/starter/configuration/TosanFeignAutoConfiguration.java index 77b9790..2481f21 100644 --- a/tosan-httpclient-spring-boot-starter/src/main/java/com/tosan/client/http/starter/configuration/TosanFeignAutoConfiguration.java +++ b/tosan-httpclient-spring-boot-starter/src/main/java/com/tosan/client/http/starter/configuration/TosanFeignAutoConfiguration.java @@ -6,6 +6,9 @@ import com.tosan.client.http.starter.impl.feign.aspect.FeignUndeclaredThrowableExceptionAspect; import com.tosan.client.http.starter.impl.feign.exception.TosanWebServiceException; import com.tosan.client.http.starter.impl.feign.exception.TosanWebServiceRuntimeException; +import com.tosan.client.http.starter.util.KeyValueReplaceHelper; +import com.tosan.tools.mask.starter.business.ComparisonTypeFactory; +import com.tosan.tools.mask.starter.business.ValueMaskFactory; import feign.Feign; import feign.codec.ErrorDecoder; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -44,4 +47,11 @@ public FeignUndeclaredThrowableExceptionAspect undeclaredThrowableExceptionAspec public ErrorDecoder customErrorDecoder(CustomErrorDecoderConfig customErrorDecoderConfig) { return new CustomErrorDecoder(customErrorDecoderConfig); } + + @Bean + @ConditionalOnMissingBean + public KeyValueReplaceHelper keyValueReplaceHelper(ValueMaskFactory valueMaskFactory, + ComparisonTypeFactory comparisonTypeFactory) { + return new KeyValueReplaceHelper(valueMaskFactory,comparisonTypeFactory); + } } diff --git a/tosan-httpclient-spring-boot-starter/src/main/java/com/tosan/client/http/starter/impl/feign/logger/HttpFeignClientLogger.java b/tosan-httpclient-spring-boot-starter/src/main/java/com/tosan/client/http/starter/impl/feign/logger/HttpFeignClientLogger.java index b1c2a8a..1bb45db 100644 --- a/tosan-httpclient-spring-boot-starter/src/main/java/com/tosan/client/http/starter/impl/feign/logger/HttpFeignClientLogger.java +++ b/tosan-httpclient-spring-boot-starter/src/main/java/com/tosan/client/http/starter/impl/feign/logger/HttpFeignClientLogger.java @@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.util.RawValue; +import com.tosan.client.http.starter.util.HttpReplaceHelperDecider; import com.tosan.tools.mask.starter.dto.JsonReplaceResultDto; import com.tosan.tools.mask.starter.replace.JsonReplaceHelperDecider; import feign.Request; @@ -41,6 +42,14 @@ public class HttpFeignClientLogger extends feign.Logger { private final String webServiceName; private final JsonReplaceHelperDecider replaceHelperDecider; + private HttpReplaceHelperDecider httpReplaceHelperDecider; + + public HttpFeignClientLogger(String webServiceName, JsonReplaceHelperDecider replaceHelperDecider, + HttpReplaceHelperDecider httpReplaceHelperDecider) { + this.webServiceName = webServiceName; + this.replaceHelperDecider = replaceHelperDecider; + this.httpReplaceHelperDecider = httpReplaceHelperDecider; + } public HttpFeignClientLogger(String webServiceName, JsonReplaceHelperDecider replaceHelperDecider) { this.webServiceName = webServiceName; @@ -186,7 +195,12 @@ private Map> getMaskedHeaders(Map 0) { JsonReplaceResultDto jsonReplaceResultDto = replaceHelperDecider.checkJsonAndReplace(headerValue); if (!jsonReplaceResultDto.isJson()) { - maskedHeaderValues.add(replaceHelperDecider.replace(headerName, headerValue)); + if (httpReplaceHelperDecider != null) { + String replace = httpReplaceHelperDecider.keyValueHeaderReplace(headerValue); + maskedHeaderValues.add(replaceHelperDecider.replace(headerName, replace)); + } else { + maskedHeaderValues.add(replaceHelperDecider.replace(headerName, headerValue)); + } } else { maskedHeaderValues.add(jsonReplaceResultDto.getReplacedJson()); } diff --git a/tosan-httpclient-spring-boot-starter/src/main/java/com/tosan/client/http/starter/util/HttpReplaceHelperDecider.java b/tosan-httpclient-spring-boot-starter/src/main/java/com/tosan/client/http/starter/util/HttpReplaceHelperDecider.java new file mode 100644 index 0000000..98081db --- /dev/null +++ b/tosan-httpclient-spring-boot-starter/src/main/java/com/tosan/client/http/starter/util/HttpReplaceHelperDecider.java @@ -0,0 +1,27 @@ +package com.tosan.client.http.starter.util; + +import com.tosan.tools.mask.starter.config.SecureParametersConfig; + +/** + * @author Ali Alimohammadi + * @since 11/15/2023 + */ +public class HttpReplaceHelperDecider { + + private final KeyValueReplaceHelper keyValueReplaceHelper; + private final SecureParametersConfig secureParametersConfig; + + public HttpReplaceHelperDecider(KeyValueReplaceHelper keyValueReplaceHelper, + SecureParametersConfig secureParametersConfig) { + this.keyValueReplaceHelper = keyValueReplaceHelper; + this.secureParametersConfig = secureParametersConfig; + } + + public String keyValueHeaderReplace(String keyValueString) { + try { + return this.keyValueReplaceHelper.replace(keyValueString, this.secureParametersConfig.getSecuredParametersMap()); + } catch (Exception e) { + return keyValueString; + } + } +} diff --git a/tosan-httpclient-spring-boot-starter/src/main/java/com/tosan/client/http/starter/util/KeyValueReplaceHelper.java b/tosan-httpclient-spring-boot-starter/src/main/java/com/tosan/client/http/starter/util/KeyValueReplaceHelper.java new file mode 100644 index 0000000..f58b4f3 --- /dev/null +++ b/tosan-httpclient-spring-boot-starter/src/main/java/com/tosan/client/http/starter/util/KeyValueReplaceHelper.java @@ -0,0 +1,48 @@ +package com.tosan.client.http.starter.util; + +import com.tosan.tools.mask.starter.business.ComparisonTypeFactory; +import com.tosan.tools.mask.starter.business.ValueMaskFactory; +import com.tosan.tools.mask.starter.business.enumeration.MaskType; +import com.tosan.tools.mask.starter.config.SecureParameter; +import com.tosan.tools.mask.starter.replace.ReplaceHelper; + +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author Ali Alimohammadi + * @since 11/14/2023 + */ +public class KeyValueReplaceHelper extends ReplaceHelper { + + public KeyValueReplaceHelper(ValueMaskFactory valueMaskFactory, ComparisonTypeFactory comparisonTypeFactory) { + super(valueMaskFactory, comparisonTypeFactory); + } + + @Override + public String replace(String input, Map securedParameterNames) { + Pattern pattern = Pattern.compile("([^\\s;]+)([ ]*[=][ ]*)([^;]+)"); + Matcher matcher = pattern.matcher(input); + + while (matcher.find()) { + String tag = matcher.group(1); + MaskType maskType = this.checkAndGetMaskType(tag, securedParameterNames); + if (maskType != null) { + String originalTag = tag + matcher.group(2) + matcher.group(3); + String value = matcher.group(3); + String toBeReplacedTag; + if (value == null) { + toBeReplacedTag = tag + matcher.group(2) + "null"; + } else { + String maskedValue = this.maskValue(value, maskType); + toBeReplacedTag = tag + matcher.group(2) + maskedValue; + } + + input = input.replace(originalTag, toBeReplacedTag); + } + } + + return input; + } +}