From c8d046277a2dfafc5d79e1e5d3656fd23324dcfb Mon Sep 17 00:00:00 2001 From: skyflow-vivek Date: Wed, 26 Nov 2025 15:40:04 +0530 Subject: [PATCH 1/3] SK-2418 Add vaultURL as config parameter in VaultConfig - Refactor `VaultConfig` POJO to `V2` and `V3` modules along with unit tests. - Made necessary changes to `common` module including cleaning imports. - Added vaultURL config parameter only for `V3` module's `VaultConfig`. - Added unit tests and logic for proper prioritisation of `vaultURL`. - `vaultURL` (config) > `vaultURL` (env) > `clusterId` (config). - Added validations to ensure atlease one of `vaultURL` or `clusterId` is provided. --- .../main/java/com/skyflow/BaseSkyflow.java | 15 +- .../java/com/skyflow/errors/ErrorMessage.java | 3 +- .../main/java/com/skyflow/logs/ErrorLogs.java | 1 + .../utils/validations/BaseValidations.java | 43 ++-- v2/src/main/java/com/skyflow/Skyflow.java | 7 + .../java/com/skyflow/config/VaultConfig.java | 0 .../utils/validations/Validations.java | 23 ++ .../com/skyflow/config/VaultConfigTests.java | 18 +- v3/src/main/java/com/skyflow/Skyflow.java | 7 + v3/src/main/java/com/skyflow/VaultClient.java | 10 +- .../java/com/skyflow/config/VaultConfig.java | 68 ++++++ v3/src/main/java/com/skyflow/utils/Utils.java | 20 +- .../utils/validations/Validations.java | 18 +- .../com/skyflow/config/VaultConfigTests.java | 213 ++++++++++++++++++ 14 files changed, 400 insertions(+), 46 deletions(-) rename {common => v2}/src/main/java/com/skyflow/config/VaultConfig.java (100%) rename {common => v2}/test/java/com/skyflow/config/VaultConfigTests.java (91%) create mode 100644 v3/src/main/java/com/skyflow/config/VaultConfig.java create mode 100644 v3/src/test/java/com/skyflow/config/VaultConfigTests.java diff --git a/common/src/main/java/com/skyflow/BaseSkyflow.java b/common/src/main/java/com/skyflow/BaseSkyflow.java index 9a117a16..f54c57d9 100644 --- a/common/src/main/java/com/skyflow/BaseSkyflow.java +++ b/common/src/main/java/com/skyflow/BaseSkyflow.java @@ -1,14 +1,11 @@ package com.skyflow; import com.skyflow.config.Credentials; -import com.skyflow.config.VaultConfig; import com.skyflow.enums.LogLevel; import com.skyflow.logs.InfoLogs; import com.skyflow.utils.BaseUtils; import com.skyflow.utils.logger.LogUtil; -import java.util.LinkedHashMap; - class BaseSkyflow { private final BaseSkyflowClientBuilder builder; @@ -20,18 +17,18 @@ public LogLevel getLogLevel() { return this.builder.logLevel; } - public VaultConfig getVaultConfig() { - Object[] array = this.builder.vaultConfigMap.values().toArray(); - return (VaultConfig) array[0]; - } +// public VaultConfig getVaultConfig() { +// Object[] array = this.builder.vaultConfigMap.values().toArray(); +// return (VaultConfig) array[0]; +// } static class BaseSkyflowClientBuilder { - protected final LinkedHashMap vaultConfigMap; + // protected final LinkedHashMap vaultConfigMap; protected Credentials skyflowCredentials; protected LogLevel logLevel; protected BaseSkyflowClientBuilder() { - this.vaultConfigMap = new LinkedHashMap<>(); +// this.vaultConfigMap = new LinkedHashMap<>(); this.skyflowCredentials = null; this.logLevel = LogLevel.ERROR; } diff --git a/common/src/main/java/com/skyflow/errors/ErrorMessage.java b/common/src/main/java/com/skyflow/errors/ErrorMessage.java index e1c0eeba..ef7063ff 100644 --- a/common/src/main/java/com/skyflow/errors/ErrorMessage.java +++ b/common/src/main/java/com/skyflow/errors/ErrorMessage.java @@ -21,6 +21,7 @@ public enum ErrorMessage { EmptyClusterId("%s0 Initialization failed. Invalid cluster ID. Specify a valid cluster ID."), EmptyVaultUrl("%s0 Initialization failed. Vault URL is empty. Specify a valid vault URL."), InvalidVaultUrlFormat("%s0 Initialization failed. Vault URL must start with 'https://'."), + EitherVaultUrlOrClusterIdRequired("%s0 Initialization failed. Specify either 'clusterId' or 'vaultURL'."), // Connection config InvalidConnectionId("%s0 Initialization failed. Invalid connection ID. Specify a valid connection ID."), @@ -173,7 +174,7 @@ public enum ErrorMessage { NullTokenGroupNameInTokenGroup("%s0 Validation error. TokenGroupName in TokenGroupRedactions is null or empty. Specify a valid tokenGroupName."), InvalidRecord("%s0 Validation error. InsertRecord object in the list is invalid. Specify a valid InsertRecord object."), ; - ; + private final String message; ErrorMessage(String message) { diff --git a/common/src/main/java/com/skyflow/logs/ErrorLogs.java b/common/src/main/java/com/skyflow/logs/ErrorLogs.java index 64d1c5e6..e8f0a627 100644 --- a/common/src/main/java/com/skyflow/logs/ErrorLogs.java +++ b/common/src/main/java/com/skyflow/logs/ErrorLogs.java @@ -8,6 +8,7 @@ public enum ErrorLogs { EMPTY_VAULT_ID("Invalid vault config. Vault ID can not be empty."), CLUSTER_ID_IS_REQUIRED("Invalid vault config. Cluster ID is required."), EMPTY_CLUSTER_ID("Invalid vault config. Cluster ID can not be empty."), + EITHER_VAULT_URL_OR_CLUSTER_ID_REQUIRED("Invalid vault config. At least one of \"clusterId\" or \"vaultURL\" must be provided."), CONNECTION_CONFIG_EXISTS("Connection config with connection ID %s1 already exists."), CONNECTION_CONFIG_DOES_NOT_EXIST("Connection config with connection ID %s1 doesn't exist."), CONNECTION_ID_IS_REQUIRED("Invalid connection config. Connection ID is required."), diff --git a/common/src/main/java/com/skyflow/utils/validations/BaseValidations.java b/common/src/main/java/com/skyflow/utils/validations/BaseValidations.java index 410b99aa..589f3536 100644 --- a/common/src/main/java/com/skyflow/utils/validations/BaseValidations.java +++ b/common/src/main/java/com/skyflow/utils/validations/BaseValidations.java @@ -1,7 +1,6 @@ package com.skyflow.utils.validations; import com.skyflow.config.Credentials; -import com.skyflow.config.VaultConfig; import com.skyflow.errors.ErrorCode; import com.skyflow.errors.ErrorMessage; import com.skyflow.errors.SkyflowException; @@ -18,27 +17,27 @@ public class BaseValidations { BaseValidations() { } - public static void validateVaultConfig(VaultConfig vaultConfig) throws SkyflowException { - String vaultId = vaultConfig.getVaultId(); - String clusterId = vaultConfig.getClusterId(); - Credentials credentials = vaultConfig.getCredentials(); - if (vaultId == null) { - LogUtil.printErrorLog(ErrorLogs.VAULT_ID_IS_REQUIRED.getLog()); - throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.InvalidVaultId.getMessage()); - } else if (vaultId.trim().isEmpty()) { - LogUtil.printErrorLog(ErrorLogs.EMPTY_VAULT_ID.getLog()); - throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyVaultId.getMessage()); - } else if (clusterId == null) { - LogUtil.printErrorLog(ErrorLogs.CLUSTER_ID_IS_REQUIRED.getLog()); - throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.InvalidClusterId.getMessage()); - } else if (clusterId.trim().isEmpty()) { - LogUtil.printErrorLog(ErrorLogs.EMPTY_CLUSTER_ID.getLog()); - throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyClusterId.getMessage()); - } - else if (credentials != null) { - validateCredentials(credentials); - } - } +// public static void validateVaultConfig(VaultConfig vaultConfig) throws SkyflowException { +// String vaultId = vaultConfig.getVaultId(); +// String clusterId = vaultConfig.getClusterId(); +// Credentials credentials = vaultConfig.getCredentials(); +// if (vaultId == null) { +// LogUtil.printErrorLog(ErrorLogs.VAULT_ID_IS_REQUIRED.getLog()); +// throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.InvalidVaultId.getMessage()); +// } else if (vaultId.trim().isEmpty()) { +// LogUtil.printErrorLog(ErrorLogs.EMPTY_VAULT_ID.getLog()); +// throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyVaultId.getMessage()); +// } else if (clusterId == null) { +// LogUtil.printErrorLog(ErrorLogs.CLUSTER_ID_IS_REQUIRED.getLog()); +// throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.InvalidClusterId.getMessage()); +// } else if (clusterId.trim().isEmpty()) { +// LogUtil.printErrorLog(ErrorLogs.EMPTY_CLUSTER_ID.getLog()); +// throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyClusterId.getMessage()); +// } +// else if (credentials != null) { +// validateCredentials(credentials); +// } +// } public static void validateCredentials(Credentials credentials) throws SkyflowException { int nonNullMembers = 0; diff --git a/v2/src/main/java/com/skyflow/Skyflow.java b/v2/src/main/java/com/skyflow/Skyflow.java index 03e38c3a..1dfd61cc 100644 --- a/v2/src/main/java/com/skyflow/Skyflow.java +++ b/v2/src/main/java/com/skyflow/Skyflow.java @@ -40,6 +40,11 @@ public Skyflow addVaultConfig(VaultConfig vaultConfig) throws SkyflowException { return this; } + public VaultConfig getVaultConfig() { + Object[] array = this.builder.vaultConfigMap.values().toArray(); + return (VaultConfig) array[0]; + } + public VaultConfig getVaultConfig(String vaultId) { return this.builder.vaultConfigMap.get(vaultId); } @@ -141,6 +146,7 @@ public DetectController detect(String vaultId) throws SkyflowException { } public static final class SkyflowClientBuilder extends BaseSkyflowClientBuilder { + private final LinkedHashMap vaultConfigMap; private final LinkedHashMap connectionsMap; private final LinkedHashMap vaultClientsMap; private final LinkedHashMap detectClientsMap; @@ -148,6 +154,7 @@ public static final class SkyflowClientBuilder extends BaseSkyflowClientBuilder public SkyflowClientBuilder() { super(); + this.vaultConfigMap = new LinkedHashMap<>(); this.vaultClientsMap = new LinkedHashMap<>(); this.detectClientsMap = new LinkedHashMap<>(); this.connectionsMap = new LinkedHashMap<>(); diff --git a/common/src/main/java/com/skyflow/config/VaultConfig.java b/v2/src/main/java/com/skyflow/config/VaultConfig.java similarity index 100% rename from common/src/main/java/com/skyflow/config/VaultConfig.java rename to v2/src/main/java/com/skyflow/config/VaultConfig.java diff --git a/v2/src/main/java/com/skyflow/utils/validations/Validations.java b/v2/src/main/java/com/skyflow/utils/validations/Validations.java index ccc1790d..b682ab75 100644 --- a/v2/src/main/java/com/skyflow/utils/validations/Validations.java +++ b/v2/src/main/java/com/skyflow/utils/validations/Validations.java @@ -3,6 +3,8 @@ import com.google.gson.Gson; import com.google.gson.JsonObject; import com.skyflow.config.ConnectionConfig; +import com.skyflow.config.Credentials; +import com.skyflow.config.VaultConfig; import com.skyflow.enums.InterfaceName; import com.skyflow.enums.RedactionType; import com.skyflow.enums.TokenMode; @@ -35,6 +37,27 @@ private Validations() { super(); } + public static void validateVaultConfig(VaultConfig vaultConfig) throws SkyflowException { + String vaultId = vaultConfig.getVaultId(); + String clusterId = vaultConfig.getClusterId(); + Credentials credentials = vaultConfig.getCredentials(); + if (vaultId == null) { + LogUtil.printErrorLog(ErrorLogs.VAULT_ID_IS_REQUIRED.getLog()); + throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.InvalidVaultId.getMessage()); + } else if (vaultId.trim().isEmpty()) { + LogUtil.printErrorLog(ErrorLogs.EMPTY_VAULT_ID.getLog()); + throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyVaultId.getMessage()); + } else if (clusterId == null) { + LogUtil.printErrorLog(ErrorLogs.CLUSTER_ID_IS_REQUIRED.getLog()); + throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.InvalidClusterId.getMessage()); + } else if (clusterId.trim().isEmpty()) { + LogUtil.printErrorLog(ErrorLogs.EMPTY_CLUSTER_ID.getLog()); + throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyClusterId.getMessage()); + } else if (credentials != null) { + validateCredentials(credentials); + } + } + public static void validateConnectionConfig(ConnectionConfig connectionConfig) throws SkyflowException { String connectionId = connectionConfig.getConnectionId(); String connectionUrl = connectionConfig.getConnectionUrl(); diff --git a/common/test/java/com/skyflow/config/VaultConfigTests.java b/v2/test/java/com/skyflow/config/VaultConfigTests.java similarity index 91% rename from common/test/java/com/skyflow/config/VaultConfigTests.java rename to v2/test/java/com/skyflow/config/VaultConfigTests.java index 2c3cb77d..b99f6c9b 100644 --- a/common/test/java/com/skyflow/config/VaultConfigTests.java +++ b/v2/test/java/com/skyflow/config/VaultConfigTests.java @@ -4,7 +4,7 @@ import com.skyflow.errors.ErrorCode; import com.skyflow.errors.ErrorMessage; import com.skyflow.errors.SkyflowException; -import com.skyflow.utils.validations.BaseValidations; +import com.skyflow.utils.validations.Validations; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; @@ -35,7 +35,7 @@ public void testValidVaultConfigWithCredentialsInValidations() { vaultConfig.setClusterId(clusterID); vaultConfig.setEnv(Env.SANDBOX); vaultConfig.setCredentials(credentials); - BaseValidations.validateVaultConfig(vaultConfig); + Validations.validateVaultConfig(vaultConfig); Assert.assertEquals(vaultID, vaultConfig.getVaultId()); Assert.assertEquals(clusterID, vaultConfig.getClusterId()); @@ -53,7 +53,7 @@ public void testValidVaultConfigWithoutCredentialsInValidations() { vaultConfig.setVaultId(vaultID); vaultConfig.setClusterId(clusterID); vaultConfig.setEnv(Env.SANDBOX); - BaseValidations.validateVaultConfig(vaultConfig); + Validations.validateVaultConfig(vaultConfig); Assert.assertEquals(vaultID, vaultConfig.getVaultId()); Assert.assertEquals(clusterID, vaultConfig.getClusterId()); @@ -71,7 +71,7 @@ public void testDefaultEnvInVaultConfigWithCredentialsInValidations() { vaultConfig.setVaultId(vaultID); vaultConfig.setClusterId(clusterID); vaultConfig.setCredentials(credentials); - BaseValidations.validateVaultConfig(vaultConfig); + Validations.validateVaultConfig(vaultConfig); Assert.assertEquals(vaultID, vaultConfig.getVaultId()); Assert.assertEquals(clusterID, vaultConfig.getClusterId()); @@ -89,7 +89,7 @@ public void testDefaultEnvInVaultConfigWithoutCredentialsInValidations() { vaultConfig.setVaultId(vaultID); vaultConfig.setClusterId(clusterID); vaultConfig.setEnv(null); - BaseValidations.validateVaultConfig(vaultConfig); + Validations.validateVaultConfig(vaultConfig); Assert.assertEquals(vaultID, vaultConfig.getVaultId()); Assert.assertEquals(clusterID, vaultConfig.getClusterId()); @@ -106,7 +106,7 @@ public void testNoVaultIdInVaultConfigInValidations() { try { vaultConfig.setClusterId(clusterID); vaultConfig.setEnv(Env.SANDBOX); - BaseValidations.validateVaultConfig(vaultConfig); + Validations.validateVaultConfig(vaultConfig); Assert.fail(EXCEPTION_NOT_THROWN); } catch (SkyflowException e) { Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); @@ -121,7 +121,7 @@ public void testEmptyVaultIdInVaultConfigInValidations() { vaultConfig.setVaultId(""); vaultConfig.setClusterId(clusterID); vaultConfig.setEnv(Env.SANDBOX); - BaseValidations.validateVaultConfig(vaultConfig); + Validations.validateVaultConfig(vaultConfig); Assert.fail(EXCEPTION_NOT_THROWN); } catch (SkyflowException e) { Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); @@ -135,7 +135,7 @@ public void testNoClusterIdInVaultConfigInValidations() { VaultConfig vaultConfig = new VaultConfig(); vaultConfig.setVaultId(vaultID); vaultConfig.setEnv(Env.SANDBOX); - BaseValidations.validateVaultConfig(vaultConfig); + Validations.validateVaultConfig(vaultConfig); Assert.fail(EXCEPTION_NOT_THROWN); } catch (SkyflowException e) { Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); @@ -150,7 +150,7 @@ public void testEmptyClusterIdInVaultConfigInValidations() { vaultConfig.setVaultId(vaultID); vaultConfig.setClusterId(""); vaultConfig.setEnv(Env.SANDBOX); - BaseValidations.validateVaultConfig(vaultConfig); + Validations.validateVaultConfig(vaultConfig); Assert.fail(EXCEPTION_NOT_THROWN); } catch (SkyflowException e) { Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); diff --git a/v3/src/main/java/com/skyflow/Skyflow.java b/v3/src/main/java/com/skyflow/Skyflow.java index ed357bdd..db42fe85 100644 --- a/v3/src/main/java/com/skyflow/Skyflow.java +++ b/v3/src/main/java/com/skyflow/Skyflow.java @@ -31,6 +31,11 @@ public static SkyflowClientBuilder builder() { return new SkyflowClientBuilder(); } + public VaultConfig getVaultConfig() { + Object[] array = this.builder.vaultConfigMap.values().toArray(); + return (VaultConfig) array[0]; + } + public VaultController vault() throws SkyflowException { Object[] array = this.builder.vaultClientsMap.keySet().toArray(); if (array.length < 1) { @@ -48,9 +53,11 @@ public VaultController vault() throws SkyflowException { } public static final class SkyflowClientBuilder extends BaseSkyflowClientBuilder { + private final LinkedHashMap vaultConfigMap; private final LinkedHashMap vaultClientsMap; public SkyflowClientBuilder() { + this.vaultConfigMap = new LinkedHashMap<>(); this.vaultClientsMap = new LinkedHashMap<>(); } diff --git a/v3/src/main/java/com/skyflow/VaultClient.java b/v3/src/main/java/com/skyflow/VaultClient.java index 5765da9c..be266bea 100644 --- a/v3/src/main/java/com/skyflow/VaultClient.java +++ b/v3/src/main/java/com/skyflow/VaultClient.java @@ -80,7 +80,15 @@ protected void setBearerToken() throws SkyflowException { } private void updateVaultURL() throws SkyflowException { - String vaultURL = Utils.getEnvVaultURL(); + // Fetch vaultURL from vault config + String vaultURL = this.vaultConfig.getVaultURL(); + + // If vaultURL from config is null or empty, fetch vaultURL from ENV variable + if (vaultURL == null || vaultURL.isEmpty()) { + vaultURL = Utils.getEnvVaultURL(); + } + + // If vaultURL from ENV variable is also null or empty, construct vaultURL from clusterId passed in vault config if (vaultURL == null || vaultURL.isEmpty()) { vaultURL = Utils.getVaultURL(this.vaultConfig.getClusterId(), this.vaultConfig.getEnv()); } diff --git a/v3/src/main/java/com/skyflow/config/VaultConfig.java b/v3/src/main/java/com/skyflow/config/VaultConfig.java new file mode 100644 index 00000000..23ce7a51 --- /dev/null +++ b/v3/src/main/java/com/skyflow/config/VaultConfig.java @@ -0,0 +1,68 @@ +package com.skyflow.config; + +import com.skyflow.enums.Env; + +public class VaultConfig implements Cloneable { + private String vaultId; + private String clusterId; + private String vaultURL; + private Env env; + private Credentials credentials; + + public VaultConfig() { + this.vaultId = null; + this.clusterId = null; + this.vaultURL = null; + this.env = Env.PROD; + this.credentials = null; + } + + public String getVaultId() { + return vaultId; + } + + public void setVaultId(String vaultId) { + this.vaultId = vaultId; + } + + public String getClusterId() { + return clusterId; + } + + public void setClusterId(String clusterId) { + this.clusterId = clusterId; + } + + public Env getEnv() { + return env; + } + + public void setEnv(Env env) { + this.env = env == null ? Env.PROD : env; + } + + public Credentials getCredentials() { + return credentials; + } + + public void setCredentials(Credentials credentials) { + this.credentials = credentials; + } + + public String getVaultURL() { + return vaultURL; + } + + public void setVaultURL(String vaultURL) { + this.vaultURL = vaultURL; + } + + @Override + public Object clone() throws CloneNotSupportedException { + VaultConfig cloned = (VaultConfig) super.clone(); + if (this.credentials != null) { + cloned.credentials = (Credentials) this.credentials.clone(); + } + return cloned; + } +} diff --git a/v3/src/main/java/com/skyflow/utils/Utils.java b/v3/src/main/java/com/skyflow/utils/Utils.java index aea1e54a..97aa469f 100644 --- a/v3/src/main/java/com/skyflow/utils/Utils.java +++ b/v3/src/main/java/com/skyflow/utils/Utils.java @@ -20,6 +20,8 @@ import io.github.cdimascio.dotenv.Dotenv; import io.github.cdimascio.dotenv.DotenvException; +import java.net.MalformedURLException; +import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -54,7 +56,7 @@ public static List createDetokenizeBatches(DetokenizeRequest // Create a sublist for the current batch List batchTokens = tokens.subList(i, Math.min(i + batchSize, tokens.size())); List tokenGroupRedactions = null; - if (request.getTokenGroupRedactions().isPresent() && !request.getTokenGroupRedactions().get().isEmpty()){ + if (request.getTokenGroupRedactions().isPresent() && !request.getTokenGroupRedactions().get().isEmpty()) { tokenGroupRedactions = request.getTokenGroupRedactions().get(); } // Build a new DetokenizeRequest for the current batch @@ -256,7 +258,7 @@ public static String getEnvVaultURL() throws SkyflowException { if (vaultURL != null && vaultURL.trim().isEmpty()) { LogUtil.printErrorLog(ErrorLogs.EMPTY_VAULT_URL.getLog()); throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyVaultUrl.getMessage()); - } else if (vaultURL != null && !vaultURL.startsWith(BaseConstants.SECURE_PROTOCOL)) { + } else if (vaultURL != null && !isValidURL(vaultURL)) { LogUtil.printErrorLog(ErrorLogs.INVALID_VAULT_URL_FORMAT.getLog()); throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.InvalidVaultUrlFormat.getMessage()); } @@ -266,4 +268,18 @@ public static String getEnvVaultURL() throws SkyflowException { } } + public static boolean isValidURL(String url) { + URL parsedUrl; + try { + parsedUrl = new URL(url); + } catch (MalformedURLException e) { + return false; + } + + if (!parsedUrl.getProtocol().equalsIgnoreCase("https")) { + return false; + } else { + return parsedUrl.getHost() != null && !parsedUrl.getHost().isEmpty(); + } + } } diff --git a/v3/src/main/java/com/skyflow/utils/validations/Validations.java b/v3/src/main/java/com/skyflow/utils/validations/Validations.java index 796cd371..7d9248a3 100644 --- a/v3/src/main/java/com/skyflow/utils/validations/Validations.java +++ b/v3/src/main/java/com/skyflow/utils/validations/Validations.java @@ -182,17 +182,31 @@ public static void validateDetokenizeRequest(DetokenizeRequest request) throws S public static void validateVaultConfiguration(VaultConfig vaultConfig) throws SkyflowException { String vaultId = vaultConfig.getVaultId(); String clusterId = vaultConfig.getClusterId(); + String vaultURL = vaultConfig.getVaultURL(); Credentials credentials = vaultConfig.getCredentials(); + if (vaultId == null) { LogUtil.printErrorLog(ErrorLogs.VAULT_ID_IS_REQUIRED.getLog()); throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.InvalidVaultId.getMessage()); } else if (vaultId.trim().isEmpty()) { LogUtil.printErrorLog(ErrorLogs.EMPTY_VAULT_ID.getLog()); throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyVaultId.getMessage()); + } else if (credentials != null) { + validateCredentials(credentials); + } + + if (vaultURL != null) { + if (vaultURL.trim().isEmpty()) { + LogUtil.printErrorLog(ErrorLogs.EMPTY_VAULT_URL.getLog()); + throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyVaultUrl.getMessage()); + } else if (!Utils.isValidURL(vaultURL)) { + LogUtil.printErrorLog(ErrorLogs.INVALID_VAULT_URL_FORMAT.getLog()); + throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.InvalidVaultUrlFormat.getMessage()); + } } else if (Utils.getEnvVaultURL() == null) { if (clusterId == null) { - LogUtil.printErrorLog(ErrorLogs.CLUSTER_ID_IS_REQUIRED.getLog()); - throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.InvalidClusterId.getMessage()); + LogUtil.printErrorLog(ErrorLogs.EITHER_VAULT_URL_OR_CLUSTER_ID_REQUIRED.getLog()); + throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EitherVaultUrlOrClusterIdRequired.getMessage()); } else if (clusterId.trim().isEmpty()) { LogUtil.printErrorLog(ErrorLogs.EMPTY_CLUSTER_ID.getLog()); throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyClusterId.getMessage()); diff --git a/v3/src/test/java/com/skyflow/config/VaultConfigTests.java b/v3/src/test/java/com/skyflow/config/VaultConfigTests.java new file mode 100644 index 00000000..36738f30 --- /dev/null +++ b/v3/src/test/java/com/skyflow/config/VaultConfigTests.java @@ -0,0 +1,213 @@ +package com.skyflow.config; + +import com.skyflow.enums.Env; +import com.skyflow.errors.ErrorCode; +import com.skyflow.errors.ErrorMessage; +import com.skyflow.errors.SkyflowException; +import com.skyflow.utils.validations.Validations; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +public class VaultConfigTests { + private static final String INVALID_EXCEPTION_THROWN = "Should not have thrown any exception"; + private static final String EXCEPTION_NOT_THROWN = "Should have thrown an exception"; + private static String vaultID = null; + private static String clusterID = null; + private static Credentials credentials = null; + private static String vaultURL = null; + + @BeforeClass + public static void setup() { + vaultID = "vault123"; + clusterID = "cluster123"; + vaultURL = "https://vault.url.com"; + + credentials = new Credentials(); + credentials.setToken("valid-token"); + } + + @Test + public void testValidVaultConfigWithCredentialsInValidations() { + try { + VaultConfig vaultConfig = new VaultConfig(); + vaultConfig.setVaultId(vaultID); + vaultConfig.setClusterId(clusterID); + vaultConfig.setEnv(Env.SANDBOX); + vaultConfig.setCredentials(credentials); + Validations.validateVaultConfiguration(vaultConfig); + + Assert.assertEquals(vaultID, vaultConfig.getVaultId()); + Assert.assertEquals(clusterID, vaultConfig.getClusterId()); + Assert.assertEquals(Env.SANDBOX, vaultConfig.getEnv()); + Assert.assertNotNull(vaultConfig.getCredentials()); + } catch (SkyflowException e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testValidVaultConfigWithoutCredentialsInValidations() { + try { + VaultConfig vaultConfig = new VaultConfig(); + vaultConfig.setVaultId(vaultID); + vaultConfig.setClusterId(clusterID); + vaultConfig.setEnv(Env.SANDBOX); + Validations.validateVaultConfiguration(vaultConfig); + + Assert.assertEquals(vaultID, vaultConfig.getVaultId()); + Assert.assertEquals(clusterID, vaultConfig.getClusterId()); + Assert.assertEquals(Env.SANDBOX, vaultConfig.getEnv()); + Assert.assertNull(vaultConfig.getCredentials()); + } catch (SkyflowException e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testDefaultEnvInVaultConfigWithCredentialsInValidations() { + try { + VaultConfig vaultConfig = new VaultConfig(); + vaultConfig.setVaultId(vaultID); + vaultConfig.setClusterId(clusterID); + vaultConfig.setCredentials(credentials); + Validations.validateVaultConfiguration(vaultConfig); + + Assert.assertEquals(vaultID, vaultConfig.getVaultId()); + Assert.assertEquals(clusterID, vaultConfig.getClusterId()); + Assert.assertEquals(Env.PROD, vaultConfig.getEnv()); + Assert.assertNotNull(vaultConfig.getCredentials()); + } catch (SkyflowException e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testDefaultEnvInVaultConfigWithoutCredentialsInValidations() { + try { + VaultConfig vaultConfig = new VaultConfig(); + vaultConfig.setVaultId(vaultID); + vaultConfig.setClusterId(clusterID); + vaultConfig.setEnv(null); + Validations.validateVaultConfiguration(vaultConfig); + + Assert.assertEquals(vaultID, vaultConfig.getVaultId()); + Assert.assertEquals(clusterID, vaultConfig.getClusterId()); + Assert.assertEquals(Env.PROD, vaultConfig.getEnv()); + Assert.assertNull(vaultConfig.getCredentials()); + } catch (SkyflowException e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } + + @Test + public void testNoVaultIdInVaultConfigInValidations() { + VaultConfig vaultConfig = new VaultConfig(); + try { + vaultConfig.setClusterId(clusterID); + vaultConfig.setEnv(Env.SANDBOX); + Validations.validateVaultConfiguration(vaultConfig); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + Assert.assertEquals(ErrorMessage.InvalidVaultId.getMessage(), e.getMessage()); + } + } + + @Test + public void testEmptyVaultIdInVaultConfigInValidations() { + try { + VaultConfig vaultConfig = new VaultConfig(); + vaultConfig.setVaultId(""); + vaultConfig.setClusterId(clusterID); + vaultConfig.setEnv(Env.SANDBOX); + Validations.validateVaultConfiguration(vaultConfig); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + Assert.assertEquals(ErrorMessage.EmptyVaultId.getMessage(), e.getMessage()); + } + } + + @Test + public void testEmptyClusterIdInVaultConfigInValidations() { + try { + VaultConfig vaultConfig = new VaultConfig(); + vaultConfig.setVaultId(vaultID); + vaultConfig.setClusterId(""); + vaultConfig.setEnv(Env.SANDBOX); + Validations.validateVaultConfiguration(vaultConfig); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + Assert.assertEquals(ErrorMessage.EmptyClusterId.getMessage(), e.getMessage()); + } + } + + @Test + public void testEmptyVaultURLInVaultConfigInValidations() { + try { + VaultConfig vaultConfig = new VaultConfig(); + vaultConfig.setVaultId(vaultID); + vaultConfig.setVaultURL(""); + vaultConfig.setEnv(Env.SANDBOX); + Validations.validateVaultConfiguration(vaultConfig); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + Assert.assertEquals(ErrorMessage.EmptyVaultUrl.getMessage(), e.getMessage()); + } + } + + @Test + public void testNeitherVaultURLNorClusterIdInVaultConfigInValidations() { + try { + VaultConfig vaultConfig = new VaultConfig(); + vaultConfig.setVaultId(vaultID); + vaultConfig.setEnv(Env.SANDBOX); + Validations.validateVaultConfiguration(vaultConfig); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + Assert.assertEquals(ErrorMessage.EitherVaultUrlOrClusterIdRequired.getMessage(), e.getMessage()); + } + } + + @Test + public void testMalformedVaultURLInVaultConfigInValidations() { + try { + VaultConfig vaultConfig = new VaultConfig(); + vaultConfig.setVaultId(vaultID); + vaultConfig.setEnv(Env.SANDBOX); + + String[] malformedUrls = new String[]{"malformed url", "http://www.url.com", "https://"}; + + for (String malformedUrl : malformedUrls) { + try { + System.out.println(malformedUrl); + vaultConfig.setVaultURL(malformedUrl); + Validations.validateVaultConfiguration(vaultConfig); + Assert.fail(EXCEPTION_NOT_THROWN); + } catch (SkyflowException e) { + Assert.assertEquals(ErrorCode.INVALID_INPUT.getCode(), e.getHttpCode()); + Assert.assertEquals(ErrorMessage.InvalidVaultUrlFormat.getMessage(), e.getMessage()); + } + } + } catch (Exception e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void testValidVaultURLInVaultConfigInValidations() { + try { + VaultConfig vaultConfig = new VaultConfig(); + vaultConfig.setVaultId(vaultID); + vaultConfig.setVaultURL(vaultURL); + vaultConfig.setEnv(Env.SANDBOX); + Validations.validateVaultConfiguration(vaultConfig); + } catch (Exception e) { + Assert.fail(INVALID_EXCEPTION_THROWN); + } + } +} From 8384ddd773771ca598e6201946477f3253da28f6 Mon Sep 17 00:00:00 2001 From: skyflow-vivek Date: Wed, 26 Nov 2025 19:20:22 +0530 Subject: [PATCH 2/3] SK-2418 Remove commented code --- .../main/java/com/skyflow/BaseSkyflow.java | 7 ------ .../utils/validations/BaseValidations.java | 22 ------------------- 2 files changed, 29 deletions(-) diff --git a/common/src/main/java/com/skyflow/BaseSkyflow.java b/common/src/main/java/com/skyflow/BaseSkyflow.java index f54c57d9..1626ac12 100644 --- a/common/src/main/java/com/skyflow/BaseSkyflow.java +++ b/common/src/main/java/com/skyflow/BaseSkyflow.java @@ -17,18 +17,11 @@ public LogLevel getLogLevel() { return this.builder.logLevel; } -// public VaultConfig getVaultConfig() { -// Object[] array = this.builder.vaultConfigMap.values().toArray(); -// return (VaultConfig) array[0]; -// } - static class BaseSkyflowClientBuilder { - // protected final LinkedHashMap vaultConfigMap; protected Credentials skyflowCredentials; protected LogLevel logLevel; protected BaseSkyflowClientBuilder() { -// this.vaultConfigMap = new LinkedHashMap<>(); this.skyflowCredentials = null; this.logLevel = LogLevel.ERROR; } diff --git a/common/src/main/java/com/skyflow/utils/validations/BaseValidations.java b/common/src/main/java/com/skyflow/utils/validations/BaseValidations.java index 589f3536..bd6cc636 100644 --- a/common/src/main/java/com/skyflow/utils/validations/BaseValidations.java +++ b/common/src/main/java/com/skyflow/utils/validations/BaseValidations.java @@ -17,28 +17,6 @@ public class BaseValidations { BaseValidations() { } -// public static void validateVaultConfig(VaultConfig vaultConfig) throws SkyflowException { -// String vaultId = vaultConfig.getVaultId(); -// String clusterId = vaultConfig.getClusterId(); -// Credentials credentials = vaultConfig.getCredentials(); -// if (vaultId == null) { -// LogUtil.printErrorLog(ErrorLogs.VAULT_ID_IS_REQUIRED.getLog()); -// throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.InvalidVaultId.getMessage()); -// } else if (vaultId.trim().isEmpty()) { -// LogUtil.printErrorLog(ErrorLogs.EMPTY_VAULT_ID.getLog()); -// throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyVaultId.getMessage()); -// } else if (clusterId == null) { -// LogUtil.printErrorLog(ErrorLogs.CLUSTER_ID_IS_REQUIRED.getLog()); -// throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.InvalidClusterId.getMessage()); -// } else if (clusterId.trim().isEmpty()) { -// LogUtil.printErrorLog(ErrorLogs.EMPTY_CLUSTER_ID.getLog()); -// throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyClusterId.getMessage()); -// } -// else if (credentials != null) { -// validateCredentials(credentials); -// } -// } - public static void validateCredentials(Credentials credentials) throws SkyflowException { int nonNullMembers = 0; String path = credentials.getPath(); From bb08a913670263e2c8f38fc9bf72940a6edd566a Mon Sep 17 00:00:00 2001 From: skyflow-vivek Date: Thu, 27 Nov 2025 12:55:14 +0530 Subject: [PATCH 3/3] SK-2418 Changes priority order as per feedback - New priority order is: vaultURL (env) > vaultURL (config) > clusterId (config) --- v3/src/main/java/com/skyflow/VaultClient.java | 10 +++++----- .../com/skyflow/utils/validations/Validations.java | 2 -- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/v3/src/main/java/com/skyflow/VaultClient.java b/v3/src/main/java/com/skyflow/VaultClient.java index be266bea..464f2efe 100644 --- a/v3/src/main/java/com/skyflow/VaultClient.java +++ b/v3/src/main/java/com/skyflow/VaultClient.java @@ -80,15 +80,15 @@ protected void setBearerToken() throws SkyflowException { } private void updateVaultURL() throws SkyflowException { - // Fetch vaultURL from vault config - String vaultURL = this.vaultConfig.getVaultURL(); + // Fetch vaultURL from ENV + String vaultURL = Utils.getEnvVaultURL(); - // If vaultURL from config is null or empty, fetch vaultURL from ENV variable + // If vaultURL from ENV is null or empty, fetch vaultURL from vault config if (vaultURL == null || vaultURL.isEmpty()) { - vaultURL = Utils.getEnvVaultURL(); + vaultURL = this.vaultConfig.getVaultURL(); } - // If vaultURL from ENV variable is also null or empty, construct vaultURL from clusterId passed in vault config + // If vaultURL from vault config is also null or empty, construct vaultURL from clusterId passed in vault config if (vaultURL == null || vaultURL.isEmpty()) { vaultURL = Utils.getVaultURL(this.vaultConfig.getClusterId(), this.vaultConfig.getEnv()); } diff --git a/v3/src/main/java/com/skyflow/utils/validations/Validations.java b/v3/src/main/java/com/skyflow/utils/validations/Validations.java index 7d9248a3..ace0cec7 100644 --- a/v3/src/main/java/com/skyflow/utils/validations/Validations.java +++ b/v3/src/main/java/com/skyflow/utils/validations/Validations.java @@ -211,8 +211,6 @@ public static void validateVaultConfiguration(VaultConfig vaultConfig) throws Sk LogUtil.printErrorLog(ErrorLogs.EMPTY_CLUSTER_ID.getLog()); throw new SkyflowException(ErrorCode.INVALID_INPUT.getCode(), ErrorMessage.EmptyClusterId.getMessage()); } - } else if (credentials != null) { - validateCredentials(credentials); } } }