Polishing.

Simplify file read. Add tests.

See gh-609
Original pull request: gh-614
This commit is contained in:
Mark Paluch
2021-10-04 08:58:31 +02:00
parent a0150aef17
commit 7c215f2c3e
3 changed files with 65 additions and 19 deletions

View File

@@ -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.

View File

@@ -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.");
}
}

View File

@@ -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);
}
}