diff --git a/pom.xml b/pom.xml index 6c18a93..a8b40f8 100644 --- a/pom.xml +++ b/pom.xml @@ -39,10 +39,8 @@ - 0.4.20 - 1.0.24 - 2020.0.32 + 5.1.0 2.15.1 2.0.7 0.11.2 @@ -50,8 +48,7 @@ 4.6.1 5.8.2 1.3 - 5.1.0 - 1.17.4 + 1.20.1 https://maven.pkg.github.com/scalecube/scalecube-security @@ -59,17 +56,11 @@ - - - io.scalecube - scalecube-config-vault - ${scalecube-config.version} - - + - io.scalecube - scalecube-commons - ${scalecube-commons.version} + com.bettercloud + vault-java-driver + ${vault-java-driver.version} diff --git a/vault/pom.xml b/vault/pom.xml index 9316599..5c3e073 100644 --- a/vault/pom.xml +++ b/vault/pom.xml @@ -1,5 +1,7 @@ - + 4.0.0 @@ -12,16 +14,8 @@ - io.scalecube - scalecube-config-vault - - - io.scalecube - scalecube-commons - - - io.projectreactor - reactor-core + com.bettercloud + vault-java-driver org.slf4j diff --git a/vault/src/main/java/io/scalecube/security/vault/VaultClientTokenSupplier.java b/vault/src/main/java/io/scalecube/security/vault/VaultClientTokenSupplier.java deleted file mode 100644 index d4b080b..0000000 --- a/vault/src/main/java/io/scalecube/security/vault/VaultClientTokenSupplier.java +++ /dev/null @@ -1,127 +0,0 @@ -package io.scalecube.security.vault; - -import static io.scalecube.utils.MaskUtil.mask; - -import com.bettercloud.vault.VaultConfig; -import com.bettercloud.vault.VaultException; -import io.scalecube.config.utils.ThrowableUtil; -import io.scalecube.config.vault.EnvironmentVaultTokenSupplier; -import io.scalecube.config.vault.KubernetesVaultTokenSupplier; -import io.scalecube.config.vault.VaultTokenSupplier; -import java.util.Objects; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import reactor.core.publisher.Mono; -import reactor.core.scheduler.Schedulers; - -public final class VaultClientTokenSupplier { - - private static final Logger LOGGER = LoggerFactory.getLogger(VaultClientTokenSupplier.class); - - private String vaultAddress; - private String vaultToken; - private String vaultRole; - - public VaultClientTokenSupplier() {} - - private VaultClientTokenSupplier(VaultClientTokenSupplier other) { - this.vaultAddress = other.vaultAddress; - this.vaultToken = other.vaultToken; - this.vaultRole = other.vaultRole; - } - - private VaultClientTokenSupplier copy() { - return new VaultClientTokenSupplier(this); - } - - private void validate() { - 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 VAULT_ROLE or VAULT_TOKEN)"); - } - } - - /** - * Setter for vaultAddress. - * - * @param vaultAddress vaultAddress - * @return new instance with applied setting - */ - public VaultClientTokenSupplier vaultAddress(String vaultAddress) { - final VaultClientTokenSupplier c = copy(); - c.vaultAddress = vaultAddress; - return c; - } - - /** - * Setter for vaultToken. - * - * @param vaultToken vaultToken - * @return new instance with applied setting - */ - public VaultClientTokenSupplier vaultToken(String vaultToken) { - final VaultClientTokenSupplier c = copy(); - c.vaultToken = vaultToken; - return c; - } - - /** - * Setter for vaultRole. - * - * @param vaultRole vaultRole - * @return new instance with applied setting - */ - public VaultClientTokenSupplier vaultRole(String vaultRole) { - final VaultClientTokenSupplier c = copy(); - c.vaultRole = vaultRole; - return c; - } - - /** - * Obtains vault client token. - * - * @return vault client token - */ - public Mono getToken() { - return Mono.fromRunnable(this::validate) - .then(Mono.fromCallable(this::getToken0)) - .subscribeOn(Schedulers.boundedElastic()) - .doOnSuccess(s -> LOGGER.debug("[getToken][success] result: {}", mask(s))) - .doOnError(th -> LOGGER.error("[getToken][error] cause: {}", th.toString())); - } - - 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 VAULT_ROLE or VAULT_TOKEN, not both)"); - } - vaultTokenSupplier = new KubernetesVaultTokenSupplier().vaultRole(vaultRole); - 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 ThrowableUtil.propagate(e); - } - } - - private static boolean isNullOrNoneOrEmpty(String value) { - return Objects.isNull(value) - || "none".equalsIgnoreCase(value) - || "null".equals(value) - || value.isEmpty(); - } -} diff --git a/vault/src/main/java/io/scalecube/security/vault/VaultServiceRolesInstaller.java b/vault/src/main/java/io/scalecube/security/vault/VaultServiceRolesInstaller.java index 2b1575a..74d3c95 100644 --- a/vault/src/main/java/io/scalecube/security/vault/VaultServiceRolesInstaller.java +++ b/vault/src/main/java/io/scalecube/security/vault/VaultServiceRolesInstaller.java @@ -3,6 +3,8 @@ import com.bettercloud.vault.json.Json; import com.bettercloud.vault.rest.Rest; import com.bettercloud.vault.rest.RestException; +import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; +import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import io.scalecube.security.vault.VaultServiceRolesInstaller.ServiceRoles.Role; @@ -21,11 +23,8 @@ import java.util.function.Supplier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import reactor.core.Exceptions; -import reactor.core.publisher.Mono; -import reactor.core.scheduler.Schedulers; -public final class VaultServiceRolesInstaller { +public class VaultServiceRolesInstaller { private static final Logger LOGGER = LoggerFactory.getLogger(VaultServiceRolesInstaller.class); @@ -34,199 +33,64 @@ public final class VaultServiceRolesInstaller { private static final List> DEFAULT_SERVICE_ROLES_SOURCES = Collections.singletonList(new ResourcesServiceRolesSupplier()); - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(new YAMLFactory()); - - private String vaultAddress; - private Mono vaultTokenSupplier; - private Supplier keyNameSupplier; - private Function roleNameBuilder; - private List> serviceRolesSources = DEFAULT_SERVICE_ROLES_SOURCES; - private String keyAlgorithm = "RS256"; - private String keyRotationPeriod = "1h"; - private String keyVerificationTtl = "1h"; - private String roleTtl = "1m"; - - public VaultServiceRolesInstaller() {} - - private VaultServiceRolesInstaller(VaultServiceRolesInstaller other) { - this.vaultAddress = other.vaultAddress; - this.vaultTokenSupplier = other.vaultTokenSupplier; - this.keyNameSupplier = other.keyNameSupplier; - this.roleNameBuilder = other.roleNameBuilder; - this.serviceRolesSources = other.serviceRolesSources; - this.keyAlgorithm = other.keyAlgorithm; - this.keyRotationPeriod = other.keyRotationPeriod; - this.keyVerificationTtl = other.keyVerificationTtl; - this.roleTtl = other.roleTtl; + private static final ObjectMapper OBJECT_MAPPER = + new ObjectMapper(new YAMLFactory()).setVisibility(PropertyAccessor.FIELD, Visibility.ANY); + + private final String vaultAddress; + private final Supplier vaultTokenSupplier; + private final Supplier keyNameSupplier; + private final Function roleNameBuilder; + private final List> serviceRolesSources; + private final String keyAlgorithm; + private final String keyRotationPeriod; + private final String keyVerificationTtl; + private final String roleTtl; + + private VaultServiceRolesInstaller(Builder builder) { + this.vaultAddress = builder.vaultAddress; + this.vaultTokenSupplier = builder.vaultTokenSupplier; + this.keyNameSupplier = builder.keyNameSupplier; + this.roleNameBuilder = builder.roleNameBuilder; + this.serviceRolesSources = builder.serviceRolesSources; + this.keyAlgorithm = builder.keyAlgorithm; + this.keyRotationPeriod = builder.keyRotationPeriod; + this.keyVerificationTtl = builder.keyVerificationTtl; + this.roleTtl = builder.roleTtl; } - private VaultServiceRolesInstaller copy() { - return new VaultServiceRolesInstaller(this); + public static Builder builder() { + return new Builder(); } /** - * Setter for vaultAddress. - * - * @param vaultAddress vaultAddress - * @return new instance with applied setting + * Builds vault oidc micro-infrastructure (identity roles and keys) to use it for + * machine-to-machine authentication. */ - public VaultServiceRolesInstaller vaultAddress(String vaultAddress) { - final VaultServiceRolesInstaller c = copy(); - c.vaultAddress = vaultAddress; - return c; - } - - /** - * Setter for vaultTokenSupplier. - * - * @param vaultTokenSupplier vaultTokenSupplier - * @return new instance with applied setting - */ - public VaultServiceRolesInstaller vaultTokenSupplier(Mono vaultTokenSupplier) { - final VaultServiceRolesInstaller c = copy(); - c.vaultTokenSupplier = vaultTokenSupplier; - return c; - } - - /** - * Setter for keyNameSupplier. - * - * @param keyNameSupplier keyNameSupplier - * @return new instance with applied setting - */ - public VaultServiceRolesInstaller keyNameSupplier(Supplier keyNameSupplier) { - final VaultServiceRolesInstaller c = copy(); - c.keyNameSupplier = keyNameSupplier; - return c; - } - - /** - * Setter for roleNameBuilder. - * - * @param roleNameBuilder roleNameBuilder - * @return new instance with applied setting - */ - public VaultServiceRolesInstaller roleNameBuilder(Function roleNameBuilder) { - final VaultServiceRolesInstaller c = copy(); - c.roleNameBuilder = roleNameBuilder; - return c; - } - - /** - * Setter for serviceRolesSources. - * - * @param serviceRolesSources serviceRolesSources - * @return new instance with applied setting - */ - public VaultServiceRolesInstaller serviceRolesSources( - List> serviceRolesSources) { - final VaultServiceRolesInstaller c = copy(); - c.serviceRolesSources = serviceRolesSources; - return c; - } - - /** - * Setter for serviceRolesSources. - * - * @param serviceRolesSources serviceRolesSources - * @return new instance with applied setting - */ - public VaultServiceRolesInstaller serviceRolesSources( - Supplier... serviceRolesSources) { - final VaultServiceRolesInstaller c = copy(); - c.serviceRolesSources = Arrays.asList(serviceRolesSources); - return c; - } - - /** - * Setter for keyAlgorithm. - * - * @param keyAlgorithm keyAlgorithm - * @return new instance with applied setting - */ - public VaultServiceRolesInstaller keyAlgorithm(String keyAlgorithm) { - final VaultServiceRolesInstaller c = copy(); - c.keyAlgorithm = keyAlgorithm; - return c; - } - - /** - * Setter for keyRotationPeriod. - * - * @param keyRotationPeriod keyRotationPeriod - * @return new instance with applied setting - */ - public VaultServiceRolesInstaller keyRotationPeriod(String keyRotationPeriod) { - final VaultServiceRolesInstaller c = copy(); - c.keyRotationPeriod = keyRotationPeriod; - return c; - } - - /** - * Setter for keyVerificationTtl. - * - * @param keyVerificationTtl keyVerificationTtl - * @return new instance with applied setting - */ - public VaultServiceRolesInstaller keyVerificationTtl(String keyVerificationTtl) { - final VaultServiceRolesInstaller c = copy(); - c.keyVerificationTtl = keyVerificationTtl; - return c; - } - - /** - * Setter for roleTtl. - * - * @param roleTtl roleTtl - * @return new instance with applied setting - */ - public VaultServiceRolesInstaller roleTtl(String roleTtl) { - final VaultServiceRolesInstaller c = copy(); - c.roleTtl = roleTtl; - return c; - } - - /** - * Reads {@code inputFileName} and builds vault oidc micro-infrastructure (identity roles and - * keys) to use it for machine-to-machine authentication. - */ - public Mono install() { - return Mono.defer(this::install0) - .subscribeOn(Schedulers.boundedElastic()) - .doOnError(th -> LOGGER.error("Failed to install serviceRoles, cause: {}", th.toString())); - } - - private Mono install0() { + public void install() { if (isNullOrNoneOrEmpty(vaultAddress)) { LOGGER.debug("Skipping serviceRoles installation, vaultAddress not set"); - return Mono.empty(); + return; } final ServiceRoles serviceRoles = loadServiceRoles(); if (serviceRoles == null || serviceRoles.roles.isEmpty()) { LOGGER.debug("Skipping serviceRoles installation, serviceRoles not set"); - return Mono.empty(); - } - - return Mono.defer(() -> vaultTokenSupplier) - .doOnSuccess( - token -> { - final Rest rest = new Rest().header(VAULT_TOKEN_HEADER, token); - - final String keyName = keyNameSupplier.get(); - createVaultIdentityKey(rest.url(buildVaultIdentityKeyUri(keyName)), keyName); - - for (Role role : serviceRoles.roles) { - String roleName = roleNameBuilder.apply(role.role); - createVaultIdentityRole( - rest.url(buildVaultIdentityRoleUri(roleName)), - keyName, - roleName, - role.permissions); - } - }) - .doOnSuccess(s -> LOGGER.debug("Installed serviceRoles ({})", serviceRoles)) - .then(); + return; + } + + final String token = vaultTokenSupplier.get(); + final Rest rest = new Rest().header(VAULT_TOKEN_HEADER, token); + + final String keyName = keyNameSupplier.get(); + createVaultIdentityKey(rest.url(buildVaultIdentityKeyUri(keyName)), keyName); + + for (Role role : serviceRoles.roles) { + String roleName = roleNameBuilder.apply(role.role); + createVaultIdentityRole( + rest.url(buildVaultIdentityRoleUri(roleName)), keyName, roleName, role.permissions); + } + + LOGGER.debug("Installed serviceRoles ({})", serviceRoles); } private ServiceRoles loadServiceRoles() { @@ -235,14 +99,9 @@ private ServiceRoles loadServiceRoles() { } for (Supplier serviceRolesSource : serviceRolesSources) { - try { - final ServiceRoles serviceRoles = serviceRolesSource.get(); - if (serviceRoles != null) { - return serviceRoles; - } - } catch (Throwable th) { - LOGGER.warn( - "Failed to load serviceRoles from {}, cause {}", serviceRolesSource, th.getMessage()); + final ServiceRoles serviceRoles = serviceRolesSource.get(); + if (serviceRoles != null) { + return serviceRoles; } } @@ -271,7 +130,7 @@ private void createVaultIdentityKey(Rest rest, String keyName) { try { verifyOk(rest.body(body).post().getStatus(), "createVaultIdentityKey"); } catch (RestException e) { - throw Exceptions.propagate(e); + throw new RuntimeException(e); } } @@ -290,7 +149,7 @@ private void createVaultIdentityRole( try { verifyOk(rest.body(body).post().getStatus(), "createVaultIdentityRole"); } catch (RestException e) { - throw Exceptions.propagate(e); + throw new RuntimeException(e); } } @@ -325,12 +184,13 @@ public static class ServiceRoles { private List roles; - public List getRoles() { + public List roles() { return roles; } - public void setRoles(List roles) { + public ServiceRoles roles(List roles) { this.roles = roles; + return this; } @Override @@ -345,20 +205,22 @@ public static class Role { private String role; private List permissions; - public String getRole() { + public String role() { return role; } - public void setRole(String role) { + public Role role(String role) { this.role = role; + return this; } - public List getPermissions() { + public List permissions() { return permissions; } - public void setPermissions(List permissions) { + public Role permissions(List permissions) { this.permissions = permissions; + return this; } @Override @@ -443,7 +305,7 @@ public String toString() { public static class FileServiceRolesSupplier implements Supplier { - public static final String DEFAULT_FILE = "service_roles.yaml"; + public static final String DEFAULT_FILE = "service-roles.yaml"; private final String file; @@ -459,11 +321,14 @@ public FileServiceRolesSupplier(String file) { public ServiceRoles get() { try { final File file = new File(this.file); - return file.exists() - ? OBJECT_MAPPER.readValue(new FileInputStream(file), ServiceRoles.class) - : null; + if (!file.exists()) { + return null; + } + try (final FileInputStream fis = new FileInputStream(file)) { + return OBJECT_MAPPER.readValue(fis, ServiceRoles.class); + } } catch (Exception e) { - throw Exceptions.propagate(e); + throw new RuntimeException(e); } } @@ -474,4 +339,73 @@ public String toString() { .toString(); } } + + public static class Builder { + + private String vaultAddress; + private Supplier vaultTokenSupplier; + private Supplier keyNameSupplier; + private Function roleNameBuilder; + private List> serviceRolesSources = DEFAULT_SERVICE_ROLES_SOURCES; + private String keyAlgorithm = "RS256"; + private String keyRotationPeriod = "1h"; + private String keyVerificationTtl = "1h"; + private String roleTtl = "1m"; + + private Builder() {} + + public Builder vaultAddress(String vaultAddress) { + this.vaultAddress = vaultAddress; + return this; + } + + public Builder vaultTokenSupplier(Supplier vaultTokenSupplier) { + this.vaultTokenSupplier = vaultTokenSupplier; + return this; + } + + public Builder keyNameSupplier(Supplier keyNameSupplier) { + this.keyNameSupplier = keyNameSupplier; + return this; + } + + public Builder roleNameBuilder(Function roleNameBuilder) { + this.roleNameBuilder = roleNameBuilder; + return this; + } + + public Builder serviceRolesSources(List> serviceRolesSources) { + this.serviceRolesSources = serviceRolesSources; + return this; + } + + public Builder serviceRolesSources(Supplier... serviceRolesSources) { + this.serviceRolesSources = Arrays.asList(serviceRolesSources); + return this; + } + + public Builder keyAlgorithm(String keyAlgorithm) { + this.keyAlgorithm = keyAlgorithm; + return this; + } + + public Builder keyRotationPeriod(String keyRotationPeriod) { + this.keyRotationPeriod = keyRotationPeriod; + return this; + } + + public Builder keyVerificationTtl(String keyVerificationTtl) { + this.keyVerificationTtl = keyVerificationTtl; + return this; + } + + public Builder roleTtl(String roleTtl) { + this.roleTtl = roleTtl; + return this; + } + + public VaultServiceRolesInstaller build() { + return new VaultServiceRolesInstaller(this); + } + } } diff --git a/vault/src/main/java/io/scalecube/security/vault/VaultServiceTokenSupplier.java b/vault/src/main/java/io/scalecube/security/vault/VaultServiceTokenSupplier.java index c7ba25e..2c766b4 100644 --- a/vault/src/main/java/io/scalecube/security/vault/VaultServiceTokenSupplier.java +++ b/vault/src/main/java/io/scalecube/security/vault/VaultServiceTokenSupplier.java @@ -1,7 +1,5 @@ package io.scalecube.security.vault; -import static io.scalecube.utils.MaskUtil.mask; - import com.bettercloud.vault.json.Json; import com.bettercloud.vault.rest.Rest; import com.bettercloud.vault.rest.RestException; @@ -10,124 +8,52 @@ import java.util.Objects; import java.util.StringJoiner; import java.util.function.BiFunction; +import java.util.function.Supplier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import reactor.core.Exceptions; -import reactor.core.publisher.Mono; -import reactor.core.scheduler.Schedulers; -public final class VaultServiceTokenSupplier { +public class VaultServiceTokenSupplier { private static final Logger LOGGER = LoggerFactory.getLogger(VaultServiceTokenSupplier.class); private static final String VAULT_TOKEN_HEADER = "X-Vault-Token"; - private String serviceRole; - private String vaultAddress; - private Mono vaultTokenSupplier; - private BiFunction, String> serviceTokenNameBuilder; - - public VaultServiceTokenSupplier() {} - - private VaultServiceTokenSupplier(VaultServiceTokenSupplier other) { - this.serviceRole = other.serviceRole; - this.vaultAddress = other.vaultAddress; - this.vaultTokenSupplier = other.vaultTokenSupplier; - this.serviceTokenNameBuilder = other.serviceTokenNameBuilder; - } - - private VaultServiceTokenSupplier copy() { - return new VaultServiceTokenSupplier(this); - } - - private void validate() { - Objects.requireNonNull(serviceRole, "VaultServiceTokenSupplier.serviceRole"); - Objects.requireNonNull(vaultAddress, "VaultServiceTokenSupplier.vaultAddress"); - Objects.requireNonNull(vaultTokenSupplier, "VaultServiceTokenSupplier.vaultTokenSupplier"); - Objects.requireNonNull( - serviceTokenNameBuilder, "VaultServiceTokenSupplier.serviceTokenNameBuilder"); - } - - /** - * Setter for serviceRole. - * - * @param serviceRole serviceRole - * @return new instance with applied setting - */ - public VaultServiceTokenSupplier serviceRole(String serviceRole) { - final VaultServiceTokenSupplier c = copy(); - c.serviceRole = serviceRole; - return c; - } - - /** - * Setter for vaultAddress. - * - * @param vaultAddress vaultAddress - * @return new instance with applied setting - */ - public VaultServiceTokenSupplier vaultAddress(String vaultAddress) { - final VaultServiceTokenSupplier c = copy(); - c.vaultAddress = vaultAddress; - return c; - } - - /** - * Setter for vaultTokenSupplier. - * - * @param vaultTokenSupplier vaultTokenSupplier - * @return new instance with applied setting - */ - public VaultServiceTokenSupplier vaultTokenSupplier(Mono vaultTokenSupplier) { - final VaultServiceTokenSupplier c = copy(); - c.vaultTokenSupplier = vaultTokenSupplier; - return c; + private final String vaultAddress; + private final String serviceRole; + private final Supplier vaultTokenSupplier; + private final BiFunction, String> serviceTokenNameBuilder; + + private VaultServiceTokenSupplier(Builder builder) { + this.vaultAddress = Objects.requireNonNull(builder.vaultAddress, "vaultAddress"); + this.serviceRole = Objects.requireNonNull(builder.serviceRole, "serviceRole"); + this.vaultTokenSupplier = + Objects.requireNonNull(builder.vaultTokenSupplier, "vaultTokenSupplier"); + this.serviceTokenNameBuilder = + Objects.requireNonNull(builder.serviceTokenNameBuilder, "serviceTokenNameBuilder"); } - /** - * Setter for serviceTokenNameBuilder. - * - * @param serviceTokenNameBuilder serviceTokenNameBuilder; inputs for this function are {@code - * serviceRole} and {@code tags} attributes - * @return new instance with applied setting - */ - public VaultServiceTokenSupplier serviceTokenNameBuilder( - BiFunction, String> serviceTokenNameBuilder) { - final VaultServiceTokenSupplier c = copy(); - c.serviceTokenNameBuilder = serviceTokenNameBuilder; - return c; + public static Builder builder() { + return new Builder(); } /** * Obtains vault service token (aka identity token or oidc token). * - * @param tags tags attributes; along with {@code serviceRole} will be applied on {@code + * @param tags tags attributes, along with {@code serviceRole} will be applied on {@code * serviceTokenNameBuilder} * @return vault service token */ - public Mono getToken(Map tags) { - return Mono.fromRunnable(this::validate) - .then(Mono.defer(() -> vaultTokenSupplier)) - .subscribeOn(Schedulers.boundedElastic()) - .flatMap( - vaultToken -> { - final String uri = buildServiceTokenUri(tags); - return Mono.fromCallable(() -> rpcGetToken(uri, vaultToken)) - .doOnSuccess( - s -> - LOGGER.debug( - "[getToken][success] uri='{}', tags={}, result: {}", - uri, - tags, - mask(s))) - .doOnError( - th -> - LOGGER.error( - "[getToken][error] uri='{}', tags={}, cause: {}", - uri, - tags, - th.toString())); - }); + public String getToken(Map tags) { + try { + final String vaultToken = vaultTokenSupplier.get(); + final String uri = toServiceTokenUri(tags); + final String token = rpcGetToken(uri, vaultToken); + LOGGER.debug("[getToken][success] uri={}, tags={}, result={}", uri, tags, mask(token)); + return token; + } catch (Exception ex) { + LOGGER.error("[getToken][error] tags={}, cause: {}", tags, ex.toString()); + throw new RuntimeException(ex); + } } private static String rpcGetToken(String uri, String vaultToken) { @@ -144,7 +70,7 @@ private static String rpcGetToken(String uri, String vaultToken) { .get("token") .asString(); } catch (RestException e) { - throw Exceptions.propagate(e); + throw new RuntimeException(e); } } @@ -155,10 +81,52 @@ private static void verifyOk(int status) { } } - private String buildServiceTokenUri(Map tags) { + private String toServiceTokenUri(Map tags) { return new StringJoiner("/", vaultAddress, "") .add("/v1/identity/oidc/token") .add(serviceTokenNameBuilder.apply(serviceRole, tags)) .toString(); } + + private static String mask(String data) { + if (data == null || data.length() < 5) { + return "*****"; + } + return data.replace(data.substring(2, data.length() - 2), "***"); + } + + public static class Builder { + + private String vaultAddress; + private String serviceRole; + private Supplier vaultTokenSupplier; + private BiFunction, String> serviceTokenNameBuilder; + + private Builder() {} + + public Builder vaultAddress(String vaultAddress) { + this.vaultAddress = vaultAddress; + return this; + } + + public Builder serviceRole(String serviceRole) { + this.serviceRole = serviceRole; + return this; + } + + public Builder vaultTokenSupplier(Supplier vaultTokenSupplier) { + this.vaultTokenSupplier = vaultTokenSupplier; + return this; + } + + public Builder serviceTokenNameBuilder( + BiFunction, String> serviceTokenNameBuilder) { + this.serviceTokenNameBuilder = serviceTokenNameBuilder; + return this; + } + + public VaultServiceTokenSupplier builder() { + return new VaultServiceTokenSupplier(this); + } + } }