From spring
Integrate Spring applications with HashiCorp Vault for KV secret reads and writes, AppRole or token authentication, property-source loading, and transit encryption. Use this skill when integrating Spring applications with HashiCorp Vault for KV secret reads and writes, AppRole or token authentication, property-source loading, or transit encryption.
npx claudepluginhub ririnto/sinon --plugin springThis skill uses the workspace's default tool permissions.
Use this skill when integrating Spring applications with HashiCorp Vault for KV secret reads and writes, AppRole or token authentication, property-source loading, or transit encryption.
Mandates invoking relevant skills via tools before any response in coding sessions. Covers access, priorities, and adaptations for Claude Code, Copilot CLI, Gemini CLI.
Share bugs, ideas, or general feedback.
Use this skill when integrating Spring applications with HashiCorp Vault for KV secret reads and writes, AppRole or token authentication, property-source loading, or transit encryption.
The latest released Spring Vault line is 4.0.2. Keep the frontmatter docs URL unversioned, but pin the concrete artifact example in this skill to 4.0.2 because this skill documents the current released standalone client path rather than a Spring BOM-managed path.
Use spring-vault for application-side Vault access, authentication setup, KV engine access, transit operations, and Spring configuration import from Vault.
| Surface | Start here when | Open a reference when |
|---|---|---|
| Token or AppRole auth | one application reads or writes secrets in an imperative path | stay in SKILL.md |
| Property import from Vault | startup configuration must come from Vault | stay in SKILL.md |
| Transit encrypt/decrypt | the app needs Vault-managed crypto without raw key material | stay in SKILL.md |
| Kubernetes auth | pod identity and service-account token are the real auth boundary | open references/kubernetes-authentication.md |
| Reactive secret access | secret reads are already on a reactive request path | open references/reactive-vault-access.md |
| KV v2 versioning and CAS | multiple writers or explicit secret versions matter | open references/kv-versioning-and-cas.md |
The ordinary Spring Vault job is:
VaultTemplate or loads configuration from Vault during bootstrap.SKILL.md for the ordinary token-or-AppRole path: direct VaultTemplate access, KV read or write operations, property import, KV v1 versus KV v2 path awareness, transit encrypt or decrypt, and fail-fast handling for missing secrets.ReactiveVaultTemplate.Use spring-vault-core for direct client access. Add Spring Boot config integration only when Vault-backed property loading is the actual requirement.
<dependencies>
<dependency>
<groupId>org.springframework.vault</groupId>
<artifactId>spring-vault-core</artifactId>
<version>4.0.2</version>
</dependency>
</dependencies>
| Need | Artifact or module |
|---|---|
Imperative Vault client access with VaultTemplate | spring-vault-core |
Reactive secret access with ReactiveVaultTemplate | spring-vault-core |
| KV v2 version-aware access and CAS | spring-vault-core |
| Spring Boot property import from Vault | Spring Boot config import plus Vault environment support in the active runtime |
| Tests that prove the secret boundary | the project test stack plus focused Vault integration tests |
spring:
cloud:
vault:
uri: https://vault.example.com:8200
token: ${VAULT_TOKEN}
kv:
enabled: true
backend: secret
application-name: app
spring:
cloud:
vault:
uri: https://vault.example.com:8200
authentication: approle
app-role:
role-id: ${VAULT_ROLE_ID}
secret-id: ${VAULT_SECRET_ID}
kv:
enabled: true
backend: secret
application-name: app
Keep these keys explicit in the active profile:
| Property | Purpose |
|---|---|
spring.cloud.vault.uri | Vault endpoint |
spring.cloud.vault.authentication | auth mode such as token or approle |
spring.cloud.vault.kv.enabled | enable KV property access |
spring.cloud.vault.kv.backend | backend mount such as secret |
spring.cloud.vault.kv.application-name | application path segment |
Prefer one auth mode per runtime profile so startup and renewal behavior stay obvious.
./mvnw test -Dtest=SecretServiceTests
./gradlew test --tests SecretServiceTests
@SpringBootTest
class SecretServiceTests {
@Autowired
SecretService secretService;
@Test
void databaseSecretReturnsRequiredData() {
Map<String, Object> secret = secretService.readDatabaseSecret();
assertAll(
() -> assertNotNull(secret),
() -> assertTrue(secret.containsKey("username"))
);
}
}
secret/data/app/{env}/database for KV v2.VaultTemplate into a narrow boundary service.opsForKeyValue(...) for ordinary KV access instead of teaching raw data/ path handling as the main integration shape.getRequiredData() when the read path must fail fast instead of silently tolerating a missing payload.VaultTemplate@Service
class SecretService {
private final VaultKeyValueOperations keyValue;
SecretService(VaultTemplate vault) {
this.keyValue = vault.opsForKeyValue("secret", KeyValueBackend.KV_2);
}
Map<String, Object> readDatabaseSecret() {
Versioned<Map<String, Object>> version = keyValue.get("app/prod/database");
return version.getRequiredData();
}
}
@Service
class SecretWriter {
private final VaultKeyValueOperations keyValue;
SecretWriter(VaultTemplate vault) {
this.keyValue = vault.opsForKeyValue("secret", KeyValueBackend.KV_2);
}
void writeFeatureFlag(String environment, String value) {
keyValue.put("app/%s/feature".formatted(environment), Map.of("enabled", value));
}
}
@Service
class TransitEncryptionService {
private final VaultTransitOperations transit;
TransitEncryptionService(VaultTemplate vault) {
this.transit = vault.opsForTransit();
}
String encrypt(String plaintext) {
return transit.encrypt("app-key", plaintext);
}
}
spring:
config:
import: vault://
Use config import only when application startup should fail if Vault configuration is unavailable.
Return:
{
"username": "app",
"password": "secret-value"
}
vault:v1:8sd7f6...
Vault secret missing at secret/app/prod/database
ReactiveVaultTemplate.