diff --git a/config-vault/src/main/java/io/scalecube/config/vault/KubernetesVaultTokenSupplier.java b/config-vault/src/main/java/io/scalecube/config/vault/KubernetesVaultTokenSupplier.java index b3877ea..f4bf5f4 100644 --- a/config-vault/src/main/java/io/scalecube/config/vault/KubernetesVaultTokenSupplier.java +++ b/config-vault/src/main/java/io/scalecube/config/vault/KubernetesVaultTokenSupplier.java @@ -15,38 +15,23 @@ public class KubernetesVaultTokenSupplier implements VaultTokenSupplier { private static final EnvironmentLoader ENVIRONMENT_LOADER = new EnvironmentLoader(); - private String vaultRole = ENVIRONMENT_LOADER.loadVariable("VAULT_ROLE"); + private final String vaultRole; + private final String vaultJwtProvider; + private final String serviceAccountTokenPath; - private String vaultJwtProvider = - Optional.ofNullable( - Optional.ofNullable(ENVIRONMENT_LOADER.loadVariable("VAULT_JWT_PROVIDER")) - .orElse(ENVIRONMENT_LOADER.loadVariable("VAULT_MOUNT_POINT"))) - .orElse("kubernetes"); - - private String serviceAccountTokenPath = - Optional.ofNullable(ENVIRONMENT_LOADER.loadVariable("SERVICE_ACCOUNT_TOKEN_PATH")) - .orElse("/var/run/secrets/kubernetes.io/serviceaccount/token"); - - public KubernetesVaultTokenSupplier vaultRole(String vaultRole) { - this.vaultRole = vaultRole; - return this; + private KubernetesVaultTokenSupplier(Builder builder) { + this.vaultRole = Objects.requireNonNull(builder.vaultRole, "vault role"); + this.vaultJwtProvider = Objects.requireNonNull(builder.vaultJwtProvider, "jwt provider"); + this.serviceAccountTokenPath = + Objects.requireNonNull(builder.serviceAccountTokenPath, "k8s service account token path"); } - public KubernetesVaultTokenSupplier vaultJwtProvider(String vaultJwtProvider) { - this.vaultJwtProvider = vaultJwtProvider; - return this; - } - - public KubernetesVaultTokenSupplier serviceAccountTokenPath(String serviceAccountTokenPath) { - this.serviceAccountTokenPath = serviceAccountTokenPath; - return this; + public static Builder builder() { + return new Builder(); } @Override public String getToken(VaultConfig config) { - Objects.requireNonNull(vaultRole, "vault role"); - Objects.requireNonNull(vaultJwtProvider, "jwt provider"); - Objects.requireNonNull(serviceAccountTokenPath, "k8s service account token path"); try (Stream stream = Files.lines(Paths.get(serviceAccountTokenPath))) { String jwt = stream.collect(Collectors.joining()); return Objects.requireNonNull( @@ -59,4 +44,40 @@ public String getToken(VaultConfig config) { throw ThrowableUtil.propagate(e); } } + + public static class Builder { + + private String vaultRole = ENVIRONMENT_LOADER.loadVariable("VAULT_ROLE"); + + private String vaultJwtProvider = + Optional.ofNullable( + Optional.ofNullable(ENVIRONMENT_LOADER.loadVariable("VAULT_JWT_PROVIDER")) + .orElse(ENVIRONMENT_LOADER.loadVariable("VAULT_MOUNT_POINT"))) + .orElse("kubernetes"); + + private String serviceAccountTokenPath = + Optional.ofNullable(ENVIRONMENT_LOADER.loadVariable("SERVICE_ACCOUNT_TOKEN_PATH")) + .orElse("/var/run/secrets/kubernetes.io/serviceaccount/token"); + + private Builder() {} + + public Builder vaultRole(String vaultRole) { + this.vaultRole = vaultRole; + return this; + } + + public Builder vaultJwtProvider(String vaultJwtProvider) { + this.vaultJwtProvider = vaultJwtProvider; + return this; + } + + public Builder serviceAccountTokenPath(String serviceAccountTokenPath) { + this.serviceAccountTokenPath = serviceAccountTokenPath; + return this; + } + + public KubernetesVaultTokenSupplier build() { + return new KubernetesVaultTokenSupplier(this); + } + } } diff --git a/config-vault/src/main/java/io/scalecube/config/vault/VaultClientTokenSupplier.java b/config-vault/src/main/java/io/scalecube/config/vault/VaultClientTokenSupplier.java new file mode 100644 index 0000000..045fd00 --- /dev/null +++ b/config-vault/src/main/java/io/scalecube/config/vault/VaultClientTokenSupplier.java @@ -0,0 +1,101 @@ +package io.scalecube.config.vault; + +import com.bettercloud.vault.VaultConfig; +import com.bettercloud.vault.VaultException; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Future; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class VaultClientTokenSupplier { + + private static final Logger LOGGER = LoggerFactory.getLogger(VaultClientTokenSupplier.class); + + private final String vaultAddress; + private final String vaultToken; + private final String vaultRole; + + /** + * Constructor. + * + * @param vaultAddress vaultAddress + * @param vaultToken vaultToken (must not set be together with vaultRole) + * @param vaultRole vaultRole (must not set be together with vaultToken) + */ + public VaultClientTokenSupplier(String vaultAddress, String vaultToken, String vaultRole) { + this.vaultAddress = vaultAddress; + this.vaultToken = vaultToken; + this.vaultRole = vaultRole; + if (isNullOrNoneOrEmpty(vaultAddress)) { + throw new IllegalArgumentException("Vault address is required"); + } + if (isNullOrNoneOrEmpty(vaultToken) && isNullOrNoneOrEmpty(vaultRole)) { + throw new IllegalArgumentException( + "Vault auth scheme is required (specify either vaultToken or vaultRole)"); + } + } + + /** + * Returns new instance of {@link VaultClientTokenSupplier}. + * + * @param vaultAddress vaultAddress + * @param vaultToken vaultToken + * @return new instance of {@link VaultClientTokenSupplier} + */ + public static VaultClientTokenSupplier supplierByToken(String vaultAddress, String vaultToken) { + return new VaultClientTokenSupplier(vaultAddress, vaultToken, null); + } + + /** + * Returns new instance of {@link VaultClientTokenSupplier}. + * + * @param vaultAddress vaultAddress + * @param vaultRole vaultRole + * @return new instance of {@link VaultClientTokenSupplier} + */ + public static VaultClientTokenSupplier supplierByRole(String vaultAddress, String vaultRole) { + return new VaultClientTokenSupplier(vaultAddress, null, vaultRole); + } + + /** + * Obtains vault client token. + * + * @return future result + */ + public Future getToken() { + return CompletableFuture.supplyAsync(this::getToken0); + } + + private String getToken0() { + try { + VaultTokenSupplier vaultTokenSupplier; + VaultConfig vaultConfig; + + if (!isNullOrNoneOrEmpty(vaultRole)) { + if (!isNullOrNoneOrEmpty(vaultToken)) { + LOGGER.warn( + "Taking KubernetesVaultTokenSupplier by precedence rule, " + + "ignoring EnvironmentVaultTokenSupplier " + + "(specify either vaultToken or vaultRole, not both)"); + } + vaultTokenSupplier = KubernetesVaultTokenSupplier.builder().vaultRole(vaultRole).build(); + vaultConfig = new VaultConfig().address(vaultAddress).build(); + } else { + vaultTokenSupplier = new EnvironmentVaultTokenSupplier(); + vaultConfig = new VaultConfig().address(vaultAddress).token(vaultToken).build(); + } + + return vaultTokenSupplier.getToken(vaultConfig); + } catch (VaultException e) { + throw new RuntimeException(e); + } + } + + private static boolean isNullOrNoneOrEmpty(String value) { + return Objects.isNull(value) + || "none".equalsIgnoreCase(value) + || "null".equals(value) + || value.isEmpty(); + } +} diff --git a/pom.xml b/pom.xml index fda894c..4fc8729 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,7 @@ - + 4.0.0 @@ -38,15 +40,15 @@ + 5.1.0 2.0.7 - 2.20.0 + 2.20.0 2.27.0 5.1.1 1.3 - 5.1.0 - 1.17.4 - 32.0.0-jre + 1.20.1 + 33.3.0-jre https://maven.pkg.github.com/scalecube/scalecube-config