Closed iamlothian closed 3 years ago
SpEL support follows Spring conventions for SpEL evaluation by using #{…}
. The Spring Data SpEL context has no access to Spring's Environment
for property expansion (${…}
) but rather makes use of the target object and contextual extensions. You can find an example at BasicVaultPersistentEntityUnitTests
.
You're totally right! Let me see if I can rework my solution to make a spring property exposed via contextual expression.
For clarity, the secret path I want to use can be constructed from "/secret/${spring.application.name}/${env}/".
Context extensions are regular beans. You could build an extension that holds Environment
and exposes both properties similar to the sample.
Thanks, @mp911de that's how I did it.
For those who find this and want more examples than the test:
application.yaml
credentials:
backend: "secret"
path: "/dev/credentials/"
CredentialProperties.java
@AllArgsConstructor
public class CredentialProperties implements EvaluationContextExtension {
private final String backend;
private final String path;
@Override
public String getExtensionId() {
return "credentialProperties";
}
@Override
public Map<String, Object> getProperties() {
Map<String, Object> properties = new LinkedHashMap<>();
properties.put("credentialBackend", backend);
properties.put("credentialPath", path);
return properties;
}
}
ApplicationConfig.java
@Configuration
public class ApplicationConfig {
@Bean
CredentialProperties credentialProperties(
@Value("${spring.application.name}") String context,
@Value("${credentials.backend}") String backend,
@Value("${credentials.path}") String path
) {
return new VaultEnvironmentCredentialProperties(backend, context + path);
}
}
CredentialSecret.java
@Data
@Secret(value = "#{credentialPath}", backend = "#{credentialBackend}")
public class CredentialSecret {
@Id
private String id;
private String secretId;
}
As an alternative you can create a ConfigurationProperties
and call the fields in the @Secret
@Component("fooProp")
@ConfigurationProperties("foo")
public class FooProperties{
Stirng name;
String backend;
}
@Secret( value="#{@fooProp.name}", backend="#{@fooProp.backend}" )
public class VaultTest{..... }
versions: org.springframework.boot:spring-boot-starter-web:2.3.0.RELEASE org.springframework.boot:spring-boot-starter-actuator:2.3.0.RELEASE org.springframework.boot:spring-boot-starter-security:2.3.0.RELEASE org.springframework.boot:spring-boot-starter-test:2.3.0.RELEASE org.springframework.cloud:spring-cloud-starter-vault-config:2.2.2.RELEASE org.springframework.cloud:spring-cloud-vault-config-databases:2.2.2.RELEASE org.springframework.data:spring-data-keyvalue:2.2.3.RELEASE
The
@Secret
annotation's documentation states:But when I try to use property templates I get an error from the rest template used to build the request to vault.
It seems that the value SpEL template is not being interpolated before the value is provided to the
restTemplate
which is assuming the{..}
values are uri template values.Have I misunderstood this feature?
My alternative is writing my own repository using the
vaultTemplate
.