From a4ddc0e93b05e4c6a903920abe159cb18c918a94 Mon Sep 17 00:00:00 2001 From: jvmdev4 Date: Tue, 28 Jul 2026 10:09:11 +0400 Subject: [PATCH] Bump spring boot 4 Spring Boot 3.3.1 -> 4.0.6, Jackson 2 -> 3, versions from the BOM. Align woody 3.0.0 and damsel 1.698-99c91c9 with error-mapping-java-v2 1.0.0. Remove the vault/secret layer marked @Deprecated(forRemoval = true) --- .github/workflows/build.yml | 2 +- .github/workflows/deploy.yml | 2 +- pom.xml | 110 +++++---- .../component/RestTemplateComponent.java | 10 +- .../common/component/SimpleErrorMapping.java | 9 +- .../common/component/SimpleObjectMapper.java | 24 -- .../common/exception/HexDecodeException.java | 11 - .../SecretAlreadyModifyException.java | 14 -- .../exception/SecretNotFoundException.java | 11 - .../SecretPathNotFoundException.java | 11 - .../exception/SecretsNotFoundException.java | 11 - .../common/secret/DigestAlgorithms.java | 17 -- .../adapter/common/secret/DigestSigner.java | 16 -- .../adapter/common/secret/HmacAlgorithms.java | 19 -- .../adapter/common/secret/HmacSigner.java | 22 -- .../adapter/common/secret/SecretObj.java | 28 --- .../adapter/common/secret/SecretRef.java | 22 -- .../adapter/common/secret/SecretService.java | 99 -------- .../adapter/common/secret/SecretValue.java | 16 -- .../common/secret/VaultSecretService.java | 110 --------- .../common/secret/VersionedSecret.java | 29 --- .../adapter/common/utils/CommonConverter.java | 6 +- .../adapter/common/utils/HmacEncryption.java | 78 ------- .../common/utils/UpperSnakeCaseStrategy.java | 58 ----- .../common/secret/VaultSecretServiceTest.java | 211 ------------------ .../utils/encryption/HmacEncryptionTest.java | 22 -- 26 files changed, 67 insertions(+), 901 deletions(-) delete mode 100644 src/main/java/dev/vality/adapter/common/component/SimpleObjectMapper.java delete mode 100644 src/main/java/dev/vality/adapter/common/exception/HexDecodeException.java delete mode 100644 src/main/java/dev/vality/adapter/common/exception/SecretAlreadyModifyException.java delete mode 100644 src/main/java/dev/vality/adapter/common/exception/SecretNotFoundException.java delete mode 100644 src/main/java/dev/vality/adapter/common/exception/SecretPathNotFoundException.java delete mode 100644 src/main/java/dev/vality/adapter/common/exception/SecretsNotFoundException.java delete mode 100644 src/main/java/dev/vality/adapter/common/secret/DigestAlgorithms.java delete mode 100644 src/main/java/dev/vality/adapter/common/secret/DigestSigner.java delete mode 100644 src/main/java/dev/vality/adapter/common/secret/HmacAlgorithms.java delete mode 100644 src/main/java/dev/vality/adapter/common/secret/HmacSigner.java delete mode 100644 src/main/java/dev/vality/adapter/common/secret/SecretObj.java delete mode 100644 src/main/java/dev/vality/adapter/common/secret/SecretRef.java delete mode 100644 src/main/java/dev/vality/adapter/common/secret/SecretService.java delete mode 100644 src/main/java/dev/vality/adapter/common/secret/SecretValue.java delete mode 100644 src/main/java/dev/vality/adapter/common/secret/VaultSecretService.java delete mode 100644 src/main/java/dev/vality/adapter/common/secret/VersionedSecret.java delete mode 100644 src/main/java/dev/vality/adapter/common/utils/HmacEncryption.java delete mode 100644 src/main/java/dev/vality/adapter/common/utils/UpperSnakeCaseStrategy.java delete mode 100644 src/test/java/dev/vality/adapter/common/secret/VaultSecretServiceTest.java delete mode 100644 src/test/java/dev/vality/adapter/common/utils/encryption/HmacEncryptionTest.java diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 92f0c6c0..f660fa85 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,4 +7,4 @@ on: jobs: build: - uses: valitydev/java-workflow/.github/workflows/maven-library-build.yml@v3 + uses: valitydev/java-workflow/.github/workflows/maven-library-build.yml@v4 diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 3ccda4ee..d155578a 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -8,7 +8,7 @@ on: jobs: deploy: - uses: valitydev/java-workflow/.github/workflows/maven-library-deploy.yml@v3 + uses: valitydev/java-workflow/.github/workflows/maven-library-deploy.yml@v4 secrets: server-username: ${{ secrets.OSSRH_USERNAME }} server-password: ${{ secrets.OSSRH_TOKEN }} diff --git a/pom.xml b/pom.xml index a526c0ea..58fe6779 100644 --- a/pom.xml +++ b/pom.xml @@ -7,11 +7,11 @@ dev.vality library-parent-pom - 3.1.0 + 4.0.0 adapter-common-lib - 3.1.1 + 4.0.0 jar adapter-common-lib @@ -41,19 +41,29 @@ ${env.REGISTRY} - 6.1.10 - 3.3.1 - 2.17.1 + 4.0.6 + 1.18.46 1.27-753b935 1.71-b3db02c - 0.0.4 - 0.0.3 - 2.1.0 - 1.668-8cab698 + 1.0.0 + 3.0.0 + 1.698-99c91c9 1.17-7481bb4 - 1.0.2 + 1.0.2 + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + @@ -61,11 +71,6 @@ error-mapping-java-v2 ${error-mapping-java-v2.version} - - dev.vality - vault-client - ${vault-client.version} - dev.vality damsel @@ -84,6 +89,12 @@ ${woody.version} provided + + dev.vality.woody + libthrift + ${woody.version} + provided + dev.vality msgpack-proto @@ -93,7 +104,7 @@ dev.vality.geck serializer - ${geck.verion} + ${geck.version} provided @@ -112,31 +123,16 @@ org.apache.commons commons-lang3 - 3.18.0 provided - commons-codec - commons-codec - 1.15 + org.springframework.boot + spring-boot-jackson provided - com.fasterxml.jackson.core + tools.jackson.core jackson-databind - ${jackson.version} - provided - - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - ${jackson.version} - provided - - - com.fasterxml.jackson.core - jackson-core - ${jackson.version} provided @@ -153,55 +149,47 @@ org.aspectj aspectjweaver - 1.9.7 provided org.slf4j slf4j-api - 1.7.36 provided org.slf4j slf4j-simple - 1.7.36 provided org.projectlombok lombok - 1.18.32 + ${lombok.version} provided jakarta.xml.bind jakarta.xml.bind-api - 4.0.0 provided jakarta.activation jakarta.activation-api - 2.1.0 provided jakarta.servlet jakarta.servlet-api - 6.1.0 provided com.sun.xml.bind jaxb-impl - 4.0.0 provided org.apache.httpcomponents.client5 httpclient5 - 5.3.1 provided @@ -209,31 +197,26 @@ org.springframework spring-core - ${spring.version} provided org.springframework spring-web - ${spring.version} provided org.springframework.boot spring-boot - ${spring-boot.version} provided org.springframework.boot - spring-boot-actuator - ${spring-boot.version} + spring-boot-restclient provided - org.springframework.vault - spring-vault-core - 3.1.1 + org.springframework.boot + spring-boot-micrometer-metrics provided @@ -241,14 +224,25 @@ org.junit.jupiter junit-jupiter-engine - 5.10.3 - test - - - org.testcontainers - vault - 1.20.0 test + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + org.projectlombok + lombok + ${lombok.version} + + + + + + diff --git a/src/main/java/dev/vality/adapter/common/component/RestTemplateComponent.java b/src/main/java/dev/vality/adapter/common/component/RestTemplateComponent.java index 807ba88d..2c9704c6 100644 --- a/src/main/java/dev/vality/adapter/common/component/RestTemplateComponent.java +++ b/src/main/java/dev/vality/adapter/common/component/RestTemplateComponent.java @@ -4,8 +4,8 @@ import dev.vality.woody.api.trace.context.TraceContext; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.classic.HttpClients; -import org.springframework.boot.actuate.metrics.web.client.ObservationRestTemplateCustomizer; -import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.boot.restclient.RestTemplateBuilder; +import org.springframework.boot.restclient.observation.ObservationRestTemplateCustomizer; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.web.client.RestTemplate; @@ -40,8 +40,8 @@ public RestTemplate getRestTemplate(RestTemplateBuilder restTemplateBuilder, int int executionTimeout = ContextUtils.getExecutionTimeout(TraceContext.getCurrentTraceData().getServiceSpan(), networkTimeout); return restTemplateBuilder - .setConnectTimeout(Duration.ofMillis(executionTimeout)) - .setReadTimeout(Duration.ofMillis(executionTimeout)) + .connectTimeout(Duration.ofMillis(executionTimeout)) + .readTimeout(Duration.ofMillis(executionTimeout)) .build(); } @@ -65,4 +65,4 @@ public CloseableHttpClient getSimpleHttpClient() { .disableAutomaticRetries() .build(); } -} \ No newline at end of file +} diff --git a/src/main/java/dev/vality/adapter/common/component/SimpleErrorMapping.java b/src/main/java/dev/vality/adapter/common/component/SimpleErrorMapping.java index ac3ef4e6..a9c30379 100644 --- a/src/main/java/dev/vality/adapter/common/component/SimpleErrorMapping.java +++ b/src/main/java/dev/vality/adapter/common/component/SimpleErrorMapping.java @@ -1,17 +1,18 @@ package dev.vality.adapter.common.component; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.ObjectMapper; import dev.vality.adapter.common.v2.mapper.ErrorMapping; import org.springframework.core.io.Resource; +import tools.jackson.core.json.JsonReadFeature; +import tools.jackson.databind.json.JsonMapper; import java.io.IOException; public record SimpleErrorMapping(Resource filePath, String patternReason) { public ErrorMapping createErrorMapping() throws IOException { - var mapper = new ObjectMapper(); - mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); + var mapper = JsonMapper.builder() + .enable(JsonReadFeature.ALLOW_SINGLE_QUOTES) + .build(); return new ErrorMapping(filePath.getInputStream(), patternReason, mapper); } diff --git a/src/main/java/dev/vality/adapter/common/component/SimpleObjectMapper.java b/src/main/java/dev/vality/adapter/common/component/SimpleObjectMapper.java deleted file mode 100644 index 9dfcf44a..00000000 --- a/src/main/java/dev/vality/adapter/common/component/SimpleObjectMapper.java +++ /dev/null @@ -1,24 +0,0 @@ -package dev.vality.adapter.common.component; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import dev.vality.adapter.common.utils.UpperSnakeCaseStrategy; - -public class SimpleObjectMapper { - - public ObjectMapper createSimpleObjectMapperFactory() { - return new ObjectMapper() - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - .registerModule(new JavaTimeModule()) - .configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true) - .setSerializationInclusion(JsonInclude.Include.NON_NULL); - } - - public ObjectMapper createUpperSnakeCaseStrategyMapper() { - return createSimpleObjectMapperFactory() - .setPropertyNamingStrategy(new UpperSnakeCaseStrategy()); - } -} diff --git a/src/main/java/dev/vality/adapter/common/exception/HexDecodeException.java b/src/main/java/dev/vality/adapter/common/exception/HexDecodeException.java deleted file mode 100644 index bc1740d5..00000000 --- a/src/main/java/dev/vality/adapter/common/exception/HexDecodeException.java +++ /dev/null @@ -1,11 +0,0 @@ -package dev.vality.adapter.common.exception; - -/** - * @deprecated Use {@code vault-client}. This API will be removed in the next major release. - */ -@Deprecated(forRemoval = true) -public class HexDecodeException extends RuntimeException { - public HexDecodeException(String message) { - super("Secret must be in hex-format: " + message); - } -} diff --git a/src/main/java/dev/vality/adapter/common/exception/SecretAlreadyModifyException.java b/src/main/java/dev/vality/adapter/common/exception/SecretAlreadyModifyException.java deleted file mode 100644 index 7eee937f..00000000 --- a/src/main/java/dev/vality/adapter/common/exception/SecretAlreadyModifyException.java +++ /dev/null @@ -1,14 +0,0 @@ -package dev.vality.adapter.common.exception; - -/** - * @deprecated Use {@code vault-client}. This API will be removed in the next major release. - */ -@Deprecated(forRemoval = true) -public class SecretAlreadyModifyException extends RuntimeException { - - public static final String CAS_ERROR_MESSAGE = "check-and-set parameter did not match the current version"; - - public SecretAlreadyModifyException(Throwable cause) { - super(cause); - } -} diff --git a/src/main/java/dev/vality/adapter/common/exception/SecretNotFoundException.java b/src/main/java/dev/vality/adapter/common/exception/SecretNotFoundException.java deleted file mode 100644 index 61f5ef17..00000000 --- a/src/main/java/dev/vality/adapter/common/exception/SecretNotFoundException.java +++ /dev/null @@ -1,11 +0,0 @@ -package dev.vality.adapter.common.exception; - -/** - * @deprecated Use {@code vault-client}. This API will be removed in the next major release. - */ -@Deprecated(forRemoval = true) -public class SecretNotFoundException extends RuntimeException { - public SecretNotFoundException(String message) { - super(message); - } -} diff --git a/src/main/java/dev/vality/adapter/common/exception/SecretPathNotFoundException.java b/src/main/java/dev/vality/adapter/common/exception/SecretPathNotFoundException.java deleted file mode 100644 index 23b9318b..00000000 --- a/src/main/java/dev/vality/adapter/common/exception/SecretPathNotFoundException.java +++ /dev/null @@ -1,11 +0,0 @@ -package dev.vality.adapter.common.exception; - -/** - * @deprecated Use {@code vault-client}. This API will be removed in the next major release. - */ -@Deprecated(forRemoval = true) -public class SecretPathNotFoundException extends RuntimeException { - public SecretPathNotFoundException(String message) { - super(message); - } -} diff --git a/src/main/java/dev/vality/adapter/common/exception/SecretsNotFoundException.java b/src/main/java/dev/vality/adapter/common/exception/SecretsNotFoundException.java deleted file mode 100644 index 4da9506a..00000000 --- a/src/main/java/dev/vality/adapter/common/exception/SecretsNotFoundException.java +++ /dev/null @@ -1,11 +0,0 @@ -package dev.vality.adapter.common.exception; - -/** - * @deprecated Use {@code vault-client}. This API will be removed in the next major release. - */ -@Deprecated(forRemoval = true) -public class SecretsNotFoundException extends RuntimeException { - public SecretsNotFoundException(String message) { - super(message); - } -} diff --git a/src/main/java/dev/vality/adapter/common/secret/DigestAlgorithms.java b/src/main/java/dev/vality/adapter/common/secret/DigestAlgorithms.java deleted file mode 100644 index af119b3f..00000000 --- a/src/main/java/dev/vality/adapter/common/secret/DigestAlgorithms.java +++ /dev/null @@ -1,17 +0,0 @@ -package dev.vality.adapter.common.secret; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -/** - * @deprecated Use {@code vault-client}. This API will be removed in the next major release. - */ -@Deprecated(forRemoval = true) -@Getter -@RequiredArgsConstructor -public enum DigestAlgorithms { - MD5("MD5"), - SHA256("SHA-256"); - - private final String name; -} diff --git a/src/main/java/dev/vality/adapter/common/secret/DigestSigner.java b/src/main/java/dev/vality/adapter/common/secret/DigestSigner.java deleted file mode 100644 index edcef2ec..00000000 --- a/src/main/java/dev/vality/adapter/common/secret/DigestSigner.java +++ /dev/null @@ -1,16 +0,0 @@ -package dev.vality.adapter.common.secret; - -import org.apache.commons.codec.digest.DigestUtils; - -/** - * @deprecated Use {@code vault-client}. This API will be removed in the next major release. - */ -@Deprecated(forRemoval = true) -class DigestSigner { - public String sign(String data, String secret, DigestAlgorithms algorithm) { - return switch (algorithm) { - case MD5 -> DigestUtils.md5Hex(data + secret); - case SHA256 -> DigestUtils.sha256Hex(data + secret); - }; - } -} diff --git a/src/main/java/dev/vality/adapter/common/secret/HmacAlgorithms.java b/src/main/java/dev/vality/adapter/common/secret/HmacAlgorithms.java deleted file mode 100644 index 65dfc8a6..00000000 --- a/src/main/java/dev/vality/adapter/common/secret/HmacAlgorithms.java +++ /dev/null @@ -1,19 +0,0 @@ -package dev.vality.adapter.common.secret; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -/** - * @deprecated Use {@code vault-client}. This API will be removed in the next major release. - */ -@Deprecated(forRemoval = true) -@Getter -@RequiredArgsConstructor -public enum HmacAlgorithms { - HMAC_MD5("HmacMD5"), - HMAC_SHA_1("HmacSHA1"), - HMAC_SHA_256("HmacSHA256"), - HMAC_SHA_512("HmacSHA512"); - - private final String name; -} diff --git a/src/main/java/dev/vality/adapter/common/secret/HmacSigner.java b/src/main/java/dev/vality/adapter/common/secret/HmacSigner.java deleted file mode 100644 index a34af92c..00000000 --- a/src/main/java/dev/vality/adapter/common/secret/HmacSigner.java +++ /dev/null @@ -1,22 +0,0 @@ -package dev.vality.adapter.common.secret; - -import dev.vality.adapter.common.exception.HexDecodeException; -import org.apache.commons.codec.DecoderException; -import org.apache.commons.codec.binary.Hex; -import org.apache.commons.codec.digest.HmacUtils; - -/** - * @deprecated Use {@code vault-client}. This API will be removed in the next major release. - */ -@Deprecated(forRemoval = true) -class HmacSigner { - public String sign(String data, String hexSecret, SecretRef secretRef, HmacAlgorithms hmacAlgorithm) - throws HexDecodeException { - try { - byte[] key = Hex.decodeHex(hexSecret); - return new HmacUtils(hmacAlgorithm.getName(), key).hmacHex(data); - } catch (DecoderException e) { - throw new HexDecodeException(secretRef.toString()); - } - } -} diff --git a/src/main/java/dev/vality/adapter/common/secret/SecretObj.java b/src/main/java/dev/vality/adapter/common/secret/SecretObj.java deleted file mode 100644 index 1bf7ead4..00000000 --- a/src/main/java/dev/vality/adapter/common/secret/SecretObj.java +++ /dev/null @@ -1,28 +0,0 @@ -package dev.vality.adapter.common.secret; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.ToString; - -import java.util.Map; - -/** - * Объект с секретами для сохранения в vault - * path - путь, по которому в vault будут храниться секреты, передданые в объекте. Хранится в options платежа. - * value - значение ключа - * Например, - * SecretObj{ - * 'tinkoff-merchant-882347345', - * {'secret-password','PASSWORD'} - * } - * @deprecated Use {@code vault-client}. This API will be removed in the next major release. - */ - -@Deprecated(forRemoval = true) -@Data -@ToString -@AllArgsConstructor -public class SecretObj { - private String path; - private Map values; -} diff --git a/src/main/java/dev/vality/adapter/common/secret/SecretRef.java b/src/main/java/dev/vality/adapter/common/secret/SecretRef.java deleted file mode 100644 index 0e4a01f1..00000000 --- a/src/main/java/dev/vality/adapter/common/secret/SecretRef.java +++ /dev/null @@ -1,22 +0,0 @@ -package dev.vality.adapter.common.secret; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.ToString; - -/** - * Идентификатор секрета в vault - * path - путь, по которому в vault хранятся секреты одного терминала. Хранится в options платежа. - * key - ключ секрета в vault по указанному пути - * Например, SecretRef{'tinkoff-merchant-882347345', 'PASSWORD'} - * @deprecated Use {@code vault-client}. This API will be removed in the next major release. - */ - -@Deprecated(forRemoval = true) -@Data -@ToString -@AllArgsConstructor -public class SecretRef { - private String path; - private String key; -} diff --git a/src/main/java/dev/vality/adapter/common/secret/SecretService.java b/src/main/java/dev/vality/adapter/common/secret/SecretService.java deleted file mode 100644 index cef776af..00000000 --- a/src/main/java/dev/vality/adapter/common/secret/SecretService.java +++ /dev/null @@ -1,99 +0,0 @@ -package dev.vality.adapter.common.secret; - -import dev.vality.adapter.common.exception.*; - -import java.util.Map; - -/** - * @deprecated Use {@code vault-client}. This API will be removed in the next major release. - */ -@Deprecated(forRemoval = true) -public interface SecretService { - - /** - * Возвращает все секреты по заданному пути (по смыслу терминала) - * - * @param serviceName - имя сервиса, которому принадлежат секреты. Хранится в настройках сервиса. - * @param path - путь, по которому в vault хранятся секреты одного терминала. Хранится в options платежа. - * @return - kv всех секретов этого терминала, например {'TERMINAL_ID':'user11', 'PASSWORD':'Parolec1'} - * @throws SecretPathNotFoundException если путь не найден - */ - Map getSecrets(String serviceName, String path) throws SecretPathNotFoundException; - - /** - * Возвращает все секреты по заданному пути (по смыслу терминала) с версией хранилища - * - * @param serviceName - имя сервиса, которому принадлежат секреты. Хранится в настройках сервиса. - * @param path - путь, по которому в vault хранятся секреты одного терминала. Хранится в options платежа. - * @return - kv всех секретов этого терминала и версию хранаилища, например, {{'key':'key11', 'pass':'pass'},42} - * @throws SecretsNotFoundException если путь не найден или значения пустые - */ - VersionedSecret getVersionSecrets(String serviceName, String path) throws SecretsNotFoundException; - - /** - * Возвращает конкретный секрет из kv - * - * @param serviceName - имя сервиса, которому принадлежат секреты. Хранится в настройках сервиса. - * @param secretRef Идентификатор секрета, например, SecretRef{'882347345', 'PASSWORD'} - * @return Возвращает секрет - * @throws SecretNotFoundException если секрет не найден - */ - SecretValue getSecret(String serviceName, SecretRef secretRef) throws SecretNotFoundException; - - /** - * Возвращает hex-encoded hmac-подпись data. Секрет должен быть hex-encoded. - * - * @param serviceName - имя сервиса, которому принадлежат секреты. Хранится в настройках сервиса. - * @param data Данные для подписи, например, invoiceId=123&amount=222 - * @param secretRef Идентификатор секрета, например, SecretRef{'882347345', 'PASSWORD'} - * @param hmacAlgorithm Алгоритм подписи, например, HmacSHA256 - * @return Возвращает подпись - * @throws SecretNotFoundException если секрет не найден - * @throws HexDecodeException если секрет не в hex-формате - */ - String hmac(String serviceName, String data, SecretRef secretRef, HmacAlgorithms hmacAlgorithm) - throws SecretNotFoundException, HexDecodeException; - - /** - * Возвращает hex-encoded хэш от data + secret - * - * @param serviceName - имя сервиса, которому принадлежат секреты. Хранится в настройках сервиса. - * @param data Данные для подписи, например, invoiceId=123&amount=222 - * @param secretRef Идентификатор секрета, например, SecretRef{'882347345', 'PASSWORD'} - * @param digestAlgorithm Алгоритм хэширования, например, MD5 - * @return Возвращает подпись - * @throws SecretNotFoundException если секрет не найден - */ - String digest(String serviceName, String data, SecretRef secretRef, DigestAlgorithms digestAlgorithm) - throws SecretNotFoundException; - - /** - * Сохраняет секреты для терминала - * - * @param serviceName - имя сервиса, для которого сохраняются секреты. Хранится в настройках сервиса. - * @param secretObj - объект с секретами, {@link SecretObj} - */ - void writeSecret(String serviceName, SecretObj secretObj); - - /** - * Сохраняет секреты для терминала - * - * @param serviceName - имя сервиса, для которого сохраняются секреты. Хранится в настройках сервиса. - * @param secretObj - объект с секретами, {@link SecretObj} - * @return Возвращает версию созданного хранилища для терминала - */ - Integer writeVersionSecret(String serviceName, SecretObj secretObj); - - /** - * Сохраняет секреты для терминала, используя CAS (Check-And-Set) - * - * @param serviceName - имя сервиса, для которого сохраняются секреты. Хранится в настройках сервиса. - * @param secretObj - объект с секретами, {@link SecretObj} - * @param version - значение текущей версии секретов, которая требует обновления. - * @return Возвращает обновленную версию хранилища для терминала - * @throws SecretAlreadyModifyException в случае некорректной версии - */ - Integer writeWithCas(String serviceName, SecretObj secretObj, Integer version) - throws SecretAlreadyModifyException; - -} diff --git a/src/main/java/dev/vality/adapter/common/secret/SecretValue.java b/src/main/java/dev/vality/adapter/common/secret/SecretValue.java deleted file mode 100644 index c014e95d..00000000 --- a/src/main/java/dev/vality/adapter/common/secret/SecretValue.java +++ /dev/null @@ -1,16 +0,0 @@ -package dev.vality.adapter.common.secret; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.ToString; - -/** - * @deprecated Use {@code vault-client}. This API will be removed in the next major release. - */ -@Deprecated(forRemoval = true) -@Data -@AllArgsConstructor -public class SecretValue { - @ToString.Exclude - private String value; -} diff --git a/src/main/java/dev/vality/adapter/common/secret/VaultSecretService.java b/src/main/java/dev/vality/adapter/common/secret/VaultSecretService.java deleted file mode 100644 index f34e80b4..00000000 --- a/src/main/java/dev/vality/adapter/common/secret/VaultSecretService.java +++ /dev/null @@ -1,110 +0,0 @@ -package dev.vality.adapter.common.secret; - -import dev.vality.adapter.common.exception.*; -import lombok.RequiredArgsConstructor; -import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; -import org.springframework.vault.VaultException; -import org.springframework.vault.core.VaultTemplate; -import org.springframework.vault.support.Versioned; - -import java.util.Map; -import java.util.Objects; -import java.util.stream.Collectors; - -import static dev.vality.adapter.common.exception.SecretAlreadyModifyException.CAS_ERROR_MESSAGE; - -/** - * @deprecated Use {@code vault-client}. This API will be removed in the next major release. - */ -@Deprecated(forRemoval = true) -@RequiredArgsConstructor -public class VaultSecretService implements SecretService { - - private final VaultTemplate vaultTemplate; - - @Override - public Map getSecrets(String serviceName, String path) throws SecretPathNotFoundException { - var map = vaultTemplate.opsForVersionedKeyValue(serviceName).get(path); - if (map == null || map.getData() == null) { - throw new SecretPathNotFoundException(path); - } - return map.getData().entrySet().stream() - .collect(Collectors.toMap(Map.Entry::getKey, e -> new SecretValue(e.getValue().toString()))); - } - - @Override - public VersionedSecret getVersionSecrets(String serviceName, String path) throws SecretPathNotFoundException { - var map = vaultTemplate.opsForVersionedKeyValue(serviceName).get(path); - if (map == null || !map.hasData() || CollectionUtils.isEmpty(map.getData()) || isEmptyValues(map)) { - throw new SecretsNotFoundException("Secrets doesn't exist or empty for path %s".formatted(path)); - } - - Map secretes = map.getData().entrySet().stream() - .collect(Collectors.toMap(Map.Entry::getKey, e -> new SecretValue(e.getValue().toString()))); - return new VersionedSecret(secretes, map.getVersion().getVersion()); - } - - private boolean isEmptyValues(Versioned> map) { - return map.getData().values().stream() - .noneMatch(o -> StringUtils.hasText(o.toString())); - } - - @Override - public SecretValue getSecret(String serviceName, SecretRef secretRef) throws SecretNotFoundException { - String secret = getSecretString(serviceName, secretRef); - return new SecretValue(secret); - } - - @Override - public String hmac(String serviceName, String data, SecretRef secretRef, HmacAlgorithms hmacAlgorithm) - throws SecretNotFoundException, HexDecodeException { - String hexSecret = getSecretString(serviceName, secretRef); - return new HmacSigner().sign(data, hexSecret, secretRef, hmacAlgorithm); - } - - @Override - public String digest(String serviceName, String data, SecretRef secretRef, DigestAlgorithms algorithm) - throws SecretNotFoundException { - String secret = getSecretString(serviceName, secretRef); - return new DigestSigner().sign(data, secret, algorithm); - } - - @Override - public void writeSecret(String serviceName, SecretObj secretObj) { - vaultTemplate.opsForVersionedKeyValue(serviceName).put(secretObj.getPath(), secretObj.getValues()); - } - - @Override - public Integer writeVersionSecret(String serviceName, SecretObj secretObj) { - Versioned.Metadata metadata = - vaultTemplate.opsForVersionedKeyValue(serviceName).put(secretObj.getPath(), secretObj.getValues()); - return metadata.getVersion().getVersion(); - } - - @Override - public Integer writeWithCas(String serviceName, SecretObj secretObj, Integer version) { - try { - var versionedBody = Versioned.create(secretObj.getValues(), Versioned.Version.from(version)); - var metadata = vaultTemplate.opsForVersionedKeyValue(serviceName).put(secretObj.getPath(), versionedBody); - return metadata.getVersion().getVersion(); - } catch (VaultException e) { - if (isCasError(e)) { - throw new SecretAlreadyModifyException(e); - } - throw e; - } - } - - private static boolean isCasError(VaultException e) { - return Objects.nonNull(e.getMessage()) && e.getMessage().contains(CAS_ERROR_MESSAGE); - } - - private String getSecretString(String serviceName, SecretRef secretRef) throws SecretNotFoundException { - var map = vaultTemplate.opsForVersionedKeyValue(serviceName).get(secretRef.getPath()); - if (map == null || map.getData() == null || map.getData().get(secretRef.getKey()) == null) { - throw new SecretNotFoundException(secretRef.toString()); - } - return map.getData().get(secretRef.getKey()).toString(); - } -} diff --git a/src/main/java/dev/vality/adapter/common/secret/VersionedSecret.java b/src/main/java/dev/vality/adapter/common/secret/VersionedSecret.java deleted file mode 100644 index e2060471..00000000 --- a/src/main/java/dev/vality/adapter/common/secret/VersionedSecret.java +++ /dev/null @@ -1,29 +0,0 @@ -package dev.vality.adapter.common.secret; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.ToString; - -import java.util.Map; - -/** - * Объект с секретами - * secretes - карта с ключами и соответсвующими им занчениями секретов. - * version - версия хранилища секретов - * Например, - * VersionedSecret{ - * {'secret-password','PASSWORD'}, - * 42 - * } - * @deprecated Use {@code vault-client}. This API will be removed in the next major release. - */ - -@Deprecated(forRemoval = true) -@Data -@ToString -@AllArgsConstructor -public class VersionedSecret { - - private Map secretes; - private Integer version; -} diff --git a/src/main/java/dev/vality/adapter/common/utils/CommonConverter.java b/src/main/java/dev/vality/adapter/common/utils/CommonConverter.java index 4d304e97..7d12c1fb 100644 --- a/src/main/java/dev/vality/adapter/common/utils/CommonConverter.java +++ b/src/main/java/dev/vality/adapter/common/utils/CommonConverter.java @@ -1,9 +1,9 @@ package dev.vality.adapter.common.utils; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import tools.jackson.core.JacksonException; +import tools.jackson.databind.ObjectMapper; import java.io.IOException; import java.nio.ByteBuffer; @@ -20,7 +20,7 @@ public static Map byteBufferToMap(ByteBuffer byteBuffer) throws IOException { return new ObjectMapper().readValue(new String(byteBuffer.array(), StandardCharsets.UTF_8), HashMap.class); } - public static ByteBuffer mapToByteBuffer(Map map) throws JsonProcessingException { + public static ByteBuffer mapToByteBuffer(Map map) throws JacksonException { return ByteBuffer.wrap(new ObjectMapper().writeValueAsString(map).getBytes()); } diff --git a/src/main/java/dev/vality/adapter/common/utils/HmacEncryption.java b/src/main/java/dev/vality/adapter/common/utils/HmacEncryption.java deleted file mode 100644 index dd4d6b51..00000000 --- a/src/main/java/dev/vality/adapter/common/utils/HmacEncryption.java +++ /dev/null @@ -1,78 +0,0 @@ -package dev.vality.adapter.common.utils; - -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import lombok.SneakyThrows; -import org.apache.commons.codec.binary.Hex; -import org.apache.commons.codec.digest.HmacAlgorithms; -import org.springframework.util.MultiValueMap; - -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.function.Consumer; - -/** - * @deprecated Use {@code vault-client}. This API will be removed in the next major release. - */ -@Deprecated(forRemoval = true) -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public final class HmacEncryption { - - public static String calculateHMacSha1(String data, String key) { - return calculateHmac(data, key, HmacAlgorithms.HMAC_SHA_1.getName()); - } - - public static String calculateHMacSha256(String data, String key) { - return calculateHmac(data, key, HmacAlgorithms.HMAC_SHA_256.getName()); - } - - @SneakyThrows - public static String calculateHmac(String data, String hexEncodedKey, String algorithm) { - byte[] decodedKey = Hex.decodeHex(hexEncodedKey.toCharArray()); - return calculateHmac(data, decodedKey, algorithm); - } - - @SneakyThrows - public static String calculateHmac(String data, byte[] key, String algorithm) { - SecretKeySpec keySpec = new SecretKeySpec(key, algorithm); - Mac mac = Mac.getInstance(algorithm); - mac.init(keySpec); - byte[] dataBytes = data.getBytes(StandardCharsets.UTF_8); - byte[] resultBytes = mac.doFinal(dataBytes); - return new String(new Hex().encode(resultBytes)); - } - - public static String prepareDataForHmac(String[] fields, MultiValueMap params) { - StringBuilder dataHmac = new StringBuilder(); - Arrays.asList(fields).forEach(fillDataHmac(params, dataHmac)); - return dataHmac.toString(); - } - - private static Consumer fillDataHmac(MultiValueMap params, StringBuilder dataHmac) { - return field -> { - if (hasFieldAndNotEmpty(params, field)) { - dataHmac.append(params.get(field).get(0).length()); - dataHmac.append(params.get(field).get(0)); - } else { - dataHmac.append("-"); - } - }; - } - - private static boolean hasFieldAndNotEmpty(MultiValueMap params, String field) { - return params.get(field) != null && !params.get(field).isEmpty() - && params.get(field).get(0) != null && !params.get(field).get(0).isEmpty(); - } - - public static String sign(String[] fieldsForSign, - MultiValueMap params, - String key, - String algorithm) { - String dataHmac = prepareDataForHmac(fieldsForSign, params); - String sign = calculateHmac(dataHmac, key, algorithm); - return sign.toUpperCase(); - } - -} diff --git a/src/main/java/dev/vality/adapter/common/utils/UpperSnakeCaseStrategy.java b/src/main/java/dev/vality/adapter/common/utils/UpperSnakeCaseStrategy.java deleted file mode 100644 index 87e1f37d..00000000 --- a/src/main/java/dev/vality/adapter/common/utils/UpperSnakeCaseStrategy.java +++ /dev/null @@ -1,58 +0,0 @@ -package dev.vality.adapter.common.utils; - -import com.fasterxml.jackson.databind.PropertyNamingStrategy; -import com.fasterxml.jackson.databind.cfg.MapperConfig; -import com.fasterxml.jackson.databind.introspect.AnnotatedField; -import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; - -public class UpperSnakeCaseStrategy extends PropertyNamingStrategy { - - @Override - public String nameForField(MapperConfig config, AnnotatedField field, String defaultName) { - return convert(field.getName()); - } - - @Override - public String nameForGetterMethod(MapperConfig config, AnnotatedMethod method, String defaultName) { - return convert(method.getName()); - } - - @Override - public String nameForSetterMethod(MapperConfig config, AnnotatedMethod method, String defaultName) { - return convert(method.getName()); - } - - private String convert(String inputString) { - if (inputString == null) { - return inputString; - } - String input = inputString.substring(3); - - if (input.length() > 1 && Character.isUpperCase(input.charAt(0)) && Character.isUpperCase(input.charAt(1))) { - input = input.substring(0, 1).toLowerCase() + input.substring(1); - } - int length = input.length(); - StringBuilder result = new StringBuilder(length * 2); - int resultLength = 0; - boolean wasPrevTranslated = false; - for (int i = 0; i < length; i++) { - char c = input.charAt(i); - if (i > 0 || c != '_') { // skip first starting underscore - if (Character.isUpperCase(c)) { - if (!wasPrevTranslated && resultLength > 0 && result.charAt(resultLength - 1) != '_') { - result.append('_'); - resultLength++; - } - c = Character.toLowerCase(c); - wasPrevTranslated = true; - } else { - wasPrevTranslated = false; - } - result.append(c); - resultLength++; - } - } - String finalString = resultLength > 0 ? result.toString() : input; - return finalString.toUpperCase(); - } -} \ No newline at end of file diff --git a/src/test/java/dev/vality/adapter/common/secret/VaultSecretServiceTest.java b/src/test/java/dev/vality/adapter/common/secret/VaultSecretServiceTest.java deleted file mode 100644 index 7c5d7909..00000000 --- a/src/test/java/dev/vality/adapter/common/secret/VaultSecretServiceTest.java +++ /dev/null @@ -1,211 +0,0 @@ -package dev.vality.adapter.common.secret; - -import dev.vality.adapter.common.exception.*; -import dev.vality.adapter.common.utils.HmacEncryption; -import org.apache.commons.codec.digest.DigestUtils; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.springframework.util.CollectionUtils; -import org.springframework.vault.authentication.TokenAuthentication; -import org.springframework.vault.client.VaultEndpoint; -import org.springframework.vault.core.VaultTemplate; -import org.testcontainers.utility.DockerImageName; -import org.testcontainers.vault.VaultContainer; -import org.testcontainers.vault.VaultLogLevel; - -import java.io.IOException; -import java.util.Map; - -import static org.junit.jupiter.api.Assertions.*; - -public class VaultSecretServiceTest { - - public static final String SIMPLE_KEY = "simpleKey"; - public static final String SIMPLE_SECRET = "sbdhfvh2y32bub"; - public static final String HMAC_KEY = "hmacKey"; - public static final String HMAC_SECRET = "6d6b6c6172657772"; - public static final String SERVICE_NAME = "adapter-vtb"; - public static final String TOKEN = "token"; - public static final String TOKEN_VALUE = "token-value"; - public static final String TOKEN_EXP_DATE = "token_exp_date"; - public static final String TOKEN_EXP_DATE_VALUE = "2023-04-20T12:26:17.191286"; - private static VaultSecretService vaultService; - - private static final String TEST_PATH = "test-terminal-123"; - private static final String TEST_TOKEN_PATH = "test-terminal-345"; - private static final String TEST_EMPTY_PATH = "test-terminal-765"; - - @BeforeAll - public static void setUp() throws IOException, InterruptedException { - VaultContainer container = new VaultContainer<>(DockerImageName.parse("vault:1.1.3")) - .withLogLevel(VaultLogLevel.Trace) - .withVaultToken("my-root-token"); - container.start(); - container.execInContainer("vault", "secrets", "enable", "-version=2", "-path=" + SERVICE_NAME, " kv"); - VaultEndpoint vaultEndpoint = VaultEndpoint.create("localhost", container.getFirstMappedPort()); - vaultEndpoint.setScheme("http"); - VaultTemplate vaultTemplate = new VaultTemplate(vaultEndpoint, new TokenAuthentication("my-root-token")); - vaultTemplate.opsForVersionedKeyValue(SERVICE_NAME).put(TEST_PATH, - Map.of(SIMPLE_KEY, SIMPLE_SECRET, - HMAC_KEY, HMAC_SECRET - )); - vaultTemplate.opsForVersionedKeyValue(SERVICE_NAME).put(TEST_EMPTY_PATH, - Map.of(SIMPLE_KEY, "", - HMAC_KEY, "" - )); - vaultService = new VaultSecretService(vaultTemplate); - } - - @Test - void testGetSecrets() { - assertNotNull(vaultService.getSecrets(SERVICE_NAME, TEST_PATH)); - assertThrows(SecretPathNotFoundException.class, () -> vaultService.getSecrets(SERVICE_NAME, "kekek")); - } - - @Test - void testGetVersionSecretsWithEmptyValues() { - assertThrows(SecretsNotFoundException.class, - () -> vaultService.getVersionSecrets(SERVICE_NAME, TEST_EMPTY_PATH)); - } - - @Test - void testGetVersionSecretsWithNotExistPath() { - assertThrows(SecretsNotFoundException.class, - () -> vaultService.getVersionSecrets(SERVICE_NAME, "kekek")); - } - - @Test - void testGetVersionSecrets() { - VersionedSecret versionSecrets = vaultService.getVersionSecrets(SERVICE_NAME, TEST_PATH); - - assertFalse(CollectionUtils.isEmpty(versionSecrets.getSecretes())); - - assertNotNull(versionSecrets.getVersion()); - assertEquals(1, versionSecrets.getVersion()); - } - - @Test - void testGetSecret() { - assertEquals(SIMPLE_SECRET, - vaultService.getSecret(SERVICE_NAME, new SecretRef(TEST_PATH, SIMPLE_KEY)).getValue()); - assertThrows(SecretNotFoundException.class, - () -> vaultService.getSecret(SERVICE_NAME, new SecretRef(TEST_PATH, "der"))); - } - - @Test - void testHmac() { - String expected = HmacEncryption.calculateHMacSha256("some_dat", "6d6b6c6172657772"); - SecretRef hmacRef = new SecretRef(TEST_PATH, HMAC_KEY); - String actual = vaultService.hmac(SERVICE_NAME, "some_dat", hmacRef, HmacAlgorithms.HMAC_SHA_256); - assertEquals(expected, actual); - assertThrows(HexDecodeException.class, - () -> vaultService.hmac(SERVICE_NAME, "some_dat", new SecretRef(TEST_PATH, SIMPLE_KEY), - HmacAlgorithms.HMAC_MD5)); - } - - @Test - void digest() { - String expected = DigestUtils.md5Hex("some_da" + SIMPLE_SECRET); - String actual = vaultService.digest(SERVICE_NAME, "some_da", new SecretRef(TEST_PATH, SIMPLE_KEY), - DigestAlgorithms.MD5); - assertEquals(expected, actual); - } - - @Test - void writeSingleSecret() { - SecretObj secretObj = new SecretObj(TEST_TOKEN_PATH, Map.of(TOKEN, TOKEN_VALUE)); - vaultService.writeSecret(SERVICE_NAME, secretObj); - - SecretValue secret = vaultService.getSecret(SERVICE_NAME, new SecretRef(TEST_TOKEN_PATH, TOKEN)); - - assertNotNull(secret); - assertEquals(TOKEN_VALUE, secret.getValue()); - - } - - @Test - void writeMultipleSecret() { - SecretObj secretObj = new SecretObj( - TEST_TOKEN_PATH, - Map.of( - TOKEN, TOKEN_VALUE, - TOKEN_EXP_DATE, TOKEN_EXP_DATE_VALUE - ) - ); - vaultService.writeSecret(SERVICE_NAME, secretObj); - - Map secret = vaultService.getSecrets(SERVICE_NAME, TEST_TOKEN_PATH); - - assertNotNull(secret); - assertEquals(TOKEN_VALUE, secret.get(TOKEN).getValue()); - assertEquals(TOKEN_EXP_DATE_VALUE, secret.get(TOKEN_EXP_DATE).getValue()); - - } - - @Test - void writeMultipleVersionSecret() { - SecretObj secretObj = new SecretObj( - TEST_TOKEN_PATH, - Map.of( - TOKEN, TOKEN_VALUE, - TOKEN_EXP_DATE, TOKEN_EXP_DATE_VALUE - ) - ); - Integer version = vaultService.writeVersionSecret(SERVICE_NAME, secretObj); - - VersionedSecret versionSecrets = vaultService.getVersionSecrets(SERVICE_NAME, TEST_TOKEN_PATH); - - assertNotNull(versionSecrets); - assertEquals(version, versionSecrets.getVersion()); - assertEquals(TOKEN_VALUE, versionSecrets.getSecretes().get(TOKEN).getValue()); - assertEquals(TOKEN_EXP_DATE_VALUE, versionSecrets.getSecretes().get(TOKEN_EXP_DATE).getValue()); - } - - @Test - void writeMultipleWithCasError() { - SecretObj secretObj = new SecretObj( - TEST_TOKEN_PATH, - Map.of( - TOKEN, TOKEN_VALUE, - TOKEN_EXP_DATE, TOKEN_EXP_DATE_VALUE - ) - ); - Integer version = vaultService.writeVersionSecret(SERVICE_NAME, secretObj); - SecretObj updatedSecretObj = new SecretObj( - TEST_TOKEN_PATH, - Map.of( - TOKEN, TOKEN_VALUE + "refresh", - TOKEN_EXP_DATE, TOKEN_EXP_DATE_VALUE - ) - ); - int wrongVersion = version + 1; - - assertThrows(SecretAlreadyModifyException.class, - () -> vaultService.writeWithCas(SERVICE_NAME, updatedSecretObj, wrongVersion)); - } - - @Test - void writeMultipleWithCasSuccess() { - SecretObj secretObj = new SecretObj( - TEST_TOKEN_PATH, - Map.of( - TOKEN, TOKEN_VALUE, - TOKEN_EXP_DATE, TOKEN_EXP_DATE_VALUE - ) - ); - Integer version = vaultService.writeVersionSecret(SERVICE_NAME, secretObj); - SecretObj updatedSecretObj = new SecretObj( - TEST_TOKEN_PATH, - Map.of( - TOKEN, TOKEN_VALUE + "refresh", - TOKEN_EXP_DATE, TOKEN_EXP_DATE_VALUE - ) - ); - - Integer newVersion = vaultService.writeWithCas(SERVICE_NAME, updatedSecretObj, version); - - assertNotNull(newVersion); - assertEquals(version + 1, newVersion); - - } -} \ No newline at end of file diff --git a/src/test/java/dev/vality/adapter/common/utils/encryption/HmacEncryptionTest.java b/src/test/java/dev/vality/adapter/common/utils/encryption/HmacEncryptionTest.java deleted file mode 100644 index e9617774..00000000 --- a/src/test/java/dev/vality/adapter/common/utils/encryption/HmacEncryptionTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package dev.vality.adapter.common.utils.encryption; - -import org.junit.jupiter.api.Test; - -import static dev.vality.secret.utils.HmacEncryption.calculateHMacSha256; -import static org.junit.jupiter.api.Assertions.assertEquals; - -public class HmacEncryptionTest { - - private String message = "511.483USD677144616IT Books. Qty: 217Books Online Inc." + - "14www.sample.com1512345678901234589999999919pgw@mail.sample.com11--" + - "142003010515302116F2B2DD7E603A7ADA33https://www.sample.com/shop/reply"; - private String secret = "00112233445566778899AABBCCDDEEFF"; - - @Test - public void testHMacSha256() { - String expectedHMac = "3fd9ee801d3aeda5d33af83580279ef920ad78e8883a0b9bc3942c74129db2f0"; - String hmac = calculateHMacSha256(message, secret); - assertEquals(expectedHMac, hmac); - } - -}