Polishing.
Simplify file read. Add tests. See gh-609 Original pull request: gh-614
This commit is contained in:
@@ -9,9 +9,8 @@ Spring Cloud Vault supports token and AppId authentication.
|
||||
=== Token authentication
|
||||
|
||||
Tokens are the core method for authentication within Vault.
|
||||
Token authentication requires a static token to be provided using the
|
||||
https://github.com/spring-cloud/spring-cloud-commons/blob/master/docs/src/main/asciidoc/spring-cloud-commons.adoc#the-bootstrap-application-context[Bootstrap Application Context].
|
||||
As a fallback the token may also be retrieved from ~/.vault-token which is the default location used by the Vault CLI to cache a token.
|
||||
Token authentication requires a static token to be provided using the configuration.
|
||||
As a fallback, the token may also be retrieved from `~/.vault-token` which is the default location used by the Vault CLI to cache tokens.
|
||||
|
||||
NOTE: Token authentication is the default authentication method.
|
||||
If a token is disclosed an unintended party gains access to Vault and can access secrets for the intended client.
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.cloud.vault.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
@@ -28,12 +27,12 @@ import com.amazonaws.auth.AWSCredentialsProvider;
|
||||
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.boot.system.SystemProperties;
|
||||
import org.springframework.cloud.vault.config.VaultProperties.AppRoleProperties;
|
||||
import org.springframework.cloud.vault.config.VaultProperties.AwsIamProperties;
|
||||
import org.springframework.cloud.vault.config.VaultProperties.AzureMsiProperties;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StreamUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.vault.authentication.AppIdAuthentication;
|
||||
import org.springframework.vault.authentication.AppIdAuthenticationOptions;
|
||||
@@ -406,24 +405,25 @@ class ClientAuthenticationFactory {
|
||||
}
|
||||
|
||||
private ClientAuthentication tokenAuthentication(VaultProperties vaultProperties) {
|
||||
|
||||
if (StringUtils.hasText(vaultProperties.getToken())) {
|
||||
return new TokenAuthentication(vaultProperties.getToken());
|
||||
}
|
||||
|
||||
Path vaultTokenPath = Paths.get(SystemProperties.get("user.home"), ".vault-token");
|
||||
|
||||
if (Files.exists(vaultTokenPath)) {
|
||||
try {
|
||||
return new TokenAuthentication(new String(Files.readAllBytes(vaultTokenPath), UTF_8));
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException(String.format("Could not retrieve vault token from %s", vaultTokenPath),
|
||||
ex);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Path vaultTokenPath = Paths.get(System.getProperty("user.home"), ".vault-token");
|
||||
if (Files.exists(vaultTokenPath)) {
|
||||
try (InputStream inputStream = Files.newInputStream(vaultTokenPath)) {
|
||||
String token = StreamUtils.copyToString(inputStream, UTF_8);
|
||||
return new TokenAuthentication(token);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException("Could not retrieve vault token from ~/.vault-token", ex);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException(
|
||||
"Cannot create authentication mechanism for TOKEN. This method requires either a Token (spring.cloud.vault.token) or File ~/.vault-token.");
|
||||
}
|
||||
throw new IllegalStateException(
|
||||
"Cannot create authentication mechanism for TOKEN. This method requires either a Token (spring.cloud.vault.token) or a token file at ~/.vault-token.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,16 @@
|
||||
|
||||
package org.springframework.cloud.vault.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.system.SystemProperties;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.vault.authentication.AppRoleAuthenticationOptions;
|
||||
import org.springframework.vault.authentication.AppRoleAuthenticationOptions.RoleId;
|
||||
@@ -25,10 +33,12 @@ import org.springframework.vault.authentication.AppRoleAuthenticationOptions.Sec
|
||||
import org.springframework.vault.authentication.ClientAuthentication;
|
||||
import org.springframework.vault.authentication.ClientCertificateAuthentication;
|
||||
import org.springframework.vault.authentication.PcfAuthentication;
|
||||
import org.springframework.vault.authentication.TokenAuthentication;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
/**
|
||||
@@ -178,4 +188,41 @@ public class ClientAuthenticationFactoryUnitTests {
|
||||
assertThat(clientAuthentication).isInstanceOf(ClientCertificateAuthentication.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSupportTokenFromFile() throws IOException {
|
||||
|
||||
VaultProperties properties = new VaultProperties();
|
||||
properties.setAuthentication(VaultProperties.AuthenticationMethod.TOKEN);
|
||||
|
||||
Path vaultTokenPath = Paths.get(SystemProperties.get("user.home"), ".vault-token");
|
||||
Files.write(vaultTokenPath, "hello".getBytes(StandardCharsets.UTF_8), StandardOpenOption.WRITE,
|
||||
StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE);
|
||||
try {
|
||||
ClientAuthentication clientAuthentication = new ClientAuthenticationFactory(properties, new RestTemplate(),
|
||||
new RestTemplate()).createClientAuthentication();
|
||||
|
||||
assertThat(clientAuthentication).isInstanceOf(TokenAuthentication.class);
|
||||
VaultToken token = clientAuthentication.login();
|
||||
|
||||
assertThat(new String(token.toCharArray())).isEqualTo("hello");
|
||||
}
|
||||
finally {
|
||||
Files.deleteIfExists(vaultTokenPath);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tokenAuthShouldFailIfTokenFileNotExistsAndTokenEmpty() throws IOException {
|
||||
|
||||
VaultProperties properties = new VaultProperties();
|
||||
properties.setAuthentication(VaultProperties.AuthenticationMethod.TOKEN);
|
||||
Path vaultTokenPath = Paths.get(SystemProperties.get("user.home"), ".vault-token");
|
||||
Files.deleteIfExists(vaultTokenPath);
|
||||
|
||||
ClientAuthenticationFactory factory = new ClientAuthenticationFactory(properties, new RestTemplate(),
|
||||
new RestTemplate());
|
||||
|
||||
assertThatIllegalStateException().isThrownBy(factory::createClientAuthentication);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user