diff --git a/spring-vault/pom.xml b/spring-vault/pom.xml
index 7b89db2302..60a5ee18f2 100644
--- a/spring-vault/pom.xml
+++ b/spring-vault/pom.xml
@@ -51,10 +51,36 @@
spring-boot-starter-test
test
+
+
+ ch.qos.logback
+ logback-classic
+
+
+ ch.qos.logback
+ logback-core
+
+
+
+ org.slf4j
+ slf4j-api
+
+
+
+ software.amazon.awssdk
+ auth
+ 2.20.140
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-vault-config
+ 3.1.3
+
- 3.0.2
+ 2.3.4
17
diff --git a/spring-vault/src/main/java/com/baeldung/springcloudvault/SpringCloudVaultTestApplication.java b/spring-vault/src/main/java/com/baeldung/springcloudvault/SpringCloudVaultTestApplication.java
new file mode 100644
index 0000000000..cea416005d
--- /dev/null
+++ b/spring-vault/src/main/java/com/baeldung/springcloudvault/SpringCloudVaultTestApplication.java
@@ -0,0 +1,25 @@
+package com.baeldung.springcloudvault;
+
+
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.core.env.Environment;
+import org.springframework.util.Assert;
+
+@SpringBootApplication
+public class SpringCloudVaultTestApplication {
+ public static void main(String... args) {
+ SpringApplication.run(SpringCloudVaultTestApplication.class, args);
+ }
+
+ @Bean
+ CommandLineRunner listSecrets(Environment env) {
+ return args -> {
+ var foo = env.getProperty("foo");
+ Assert.notNull(foo, "foo must have a value");
+ System.out.println("foo=" + foo);
+ };
+ }
+}
diff --git a/spring-vault/src/main/java/com/baeldung/springvaultk8s/VaultConfig.java b/spring-vault/src/main/java/com/baeldung/springvaultk8s/VaultConfig.java
new file mode 100644
index 0000000000..407e324a87
--- /dev/null
+++ b/spring-vault/src/main/java/com/baeldung/springvaultk8s/VaultConfig.java
@@ -0,0 +1,25 @@
+package com.baeldung.springvaultk8s;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.core.env.Environment;
+import org.springframework.vault.authentication.ClientAuthentication;
+import org.springframework.vault.authentication.KubernetesAuthentication;
+import org.springframework.vault.authentication.KubernetesAuthenticationOptions;
+import org.springframework.vault.client.VaultEndpoint;
+import org.springframework.vault.config.AbstractVaultConfiguration;
+import org.springframework.vault.config.EnvironmentVaultConfiguration;
+import org.springframework.web.client.RestOperations;
+import org.springframework.web.client.RestTemplate;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+@Configuration
+@PropertySource("vault-config-k8s.properties")
+@Import(EnvironmentVaultConfiguration.class)
+public class VaultConfig {
+
+}
diff --git a/spring-vault/src/main/java/com/baeldung/springvaultk8s/VaultK8SApplication.java b/spring-vault/src/main/java/com/baeldung/springvaultk8s/VaultK8SApplication.java
new file mode 100644
index 0000000000..a61b67bf6e
--- /dev/null
+++ b/spring-vault/src/main/java/com/baeldung/springvaultk8s/VaultK8SApplication.java
@@ -0,0 +1,45 @@
+package com.baeldung.springvaultk8s;
+
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.core.env.Environment;
+import org.springframework.vault.core.VaultKeyValueOperations;
+import org.springframework.vault.core.VaultKeyValueOperationsSupport;
+import org.springframework.vault.core.VaultTemplate;
+
+import java.util.List;
+import java.util.Map;
+
+@SpringBootApplication
+public class VaultK8SApplication {
+
+ public static void main(String... args) {
+ SpringApplication.run(VaultK8SApplication.class, args);
+ }
+
+ @Bean
+ CommandLineRunner listSecrets(VaultTemplate vault) {
+
+ return args -> {
+ VaultKeyValueOperations ops = vault.opsForKeyValue("secrets", VaultKeyValueOperationsSupport.KeyValueBackend.KV_2);
+ List secrets = ops.list("");
+ if (secrets == null) {
+ System.out.println("No secrets found");
+ return;
+ }
+
+ secrets.forEach(s -> {
+ System.out.println("secret=" + s);
+ var response = ops.get(s);
+ var data = response.getRequiredData();
+
+ data.entrySet()
+ .forEach(e -> {
+ System.out.println("- key=" + e.getKey() + " => " + e.getValue());
+ });
+ });
+ };
+ }
+}
diff --git a/spring-vault/src/main/k8s/vault-csi-example.yaml b/spring-vault/src/main/k8s/vault-csi-example.yaml
new file mode 100644
index 0000000000..8136554033
--- /dev/null
+++ b/spring-vault/src/main/k8s/vault-csi-example.yaml
@@ -0,0 +1,51 @@
+---
+apiVersion: secrets-store.csi.x-k8s.io/v1
+kind: SecretProviderClass
+metadata:
+ name: baeldung-csi-secrets
+ namespace: baeldung
+spec:
+ # Vault CSI Provider
+ provider: vault
+ parameters:
+ # Vault role name to use during login
+ roleName: 'baeldung-test-role'
+ objects: |
+ - objectName: 'baeldung.properties'
+ secretPath: "secrets/data/baeldung-test"
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: nginx-csi
+ namespace: baeldung
+spec:
+ selector:
+ matchLabels:
+ app: nginx-csi
+ replicas: 1 # tells deployment to run 2 pods matching the template
+ template:
+ metadata:
+ labels:
+ app: nginx-csi
+ spec:
+ serviceAccountName: vault-test-sa
+ automountServiceAccountToken: true
+ containers:
+ - name: nginx
+ image: nginx:1.14.2
+ ports:
+ - containerPort: 80
+ volumeMounts:
+ - name: vault-secrets
+ mountPath: /vault/secrets
+ readOnly: true
+ volumes:
+ - name: vault-secrets
+ csi:
+ driver: 'secrets-store.csi.k8s.io'
+ readOnly: true
+ volumeAttributes:
+ secretProviderClass: baeldung-csi-secrets
+
+
diff --git a/spring-vault/src/main/k8s/vault-injector-example.yaml b/spring-vault/src/main/k8s/vault-injector-example.yaml
new file mode 100644
index 0000000000..4d0aad70a1
--- /dev/null
+++ b/spring-vault/src/main/k8s/vault-injector-example.yaml
@@ -0,0 +1,32 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: nginx-deployment
+ namespace: baeldung
+spec:
+ selector:
+ matchLabels:
+ app: nginx
+ replicas: 1 # tells deployment to run 2 pods matching the template
+ template:
+ metadata:
+ labels:
+ app: nginx
+ annotations:
+ vault.hashicorp.com/agent-inject: "true"
+ vault.hashicorp.com/agent-inject-secret-baeldung.properties: "secrets/baeldung-test"
+ vault.hashicorp.com/role: "baeldung-test-role"
+ vault.hashicorp.com/agent-inject-template-baeldung.properties: |
+ {{- with secret "secrets/baeldung-test" -}}
+ {{- range $k, $v := .Data.data }}
+ {{$k}}={{$v}}
+ {{- end -}}
+ {{ end }}
+ spec:
+ serviceAccountName: vault-test-sa
+ automountServiceAccountToken: true
+ containers:
+ - name: nginx
+ image: nginx:1.14.2
+ ports:
+ - containerPort: 80
diff --git a/spring-vault/src/main/k8s/vault-operator-example.yaml b/spring-vault/src/main/k8s/vault-operator-example.yaml
new file mode 100644
index 0000000000..a77888905d
--- /dev/null
+++ b/spring-vault/src/main/k8s/vault-operator-example.yaml
@@ -0,0 +1,58 @@
+---
+##
+## Vault Connection
+##
+apiVersion: secrets.hashicorp.com/v1beta1
+kind: VaultConnection
+metadata:
+ namespace: baeldung
+ name: vault-local
+spec:
+ # required configuration
+ # address to the Vault server.
+ address: http://vault.vault.svc.cluster.local:8200
+---
+##
+## Vault Auth
+##
+apiVersion: secrets.hashicorp.com/v1beta1
+kind: VaultAuth
+metadata:
+ namespace: baeldung
+ name: baeldung-test
+spec:
+ # required configuration
+ # VaultConnectionRef of the corresponding VaultConnection CustomResource.
+ # If no value is specified the Operator will default to the `default` VaultConnection,
+ # configured in its own Kubernetes namespace.
+ vaultConnectionRef: vault-local
+ # Method to use when authenticating to Vault.
+ method: kubernetes
+ # Mount to use when authenticating to auth method.
+ mount: kubernetes
+ # Kubernetes specific auth configuration, requires that the Method be set to kubernetes.
+ kubernetes:
+ # role to use when authenticating to Vault
+ role: baeldung-test-role
+ # ServiceAccount to use when authenticating to Vault
+ # it is recommended to always provide a unique serviceAccount per Pod/application
+ serviceAccount: vault-test-sa
+---
+##
+## Vault-backed secret
+##
+apiVersion: secrets.hashicorp.com/v1beta1
+kind: VaultStaticSecret
+metadata:
+ namespace: baeldung
+ name: baeldung-test
+spec:
+ vaultAuthRef: baeldung-test
+ mount: secrets
+ type: kv-v2
+ path: baeldung-test
+ refreshAfter: 60s
+ hmacSecretData: true
+ destination:
+ create: true
+ name: baeldung-test
diff --git a/spring-vault/src/main/resources/vault-config-k8s.properties b/spring-vault/src/main/resources/vault-config-k8s.properties
new file mode 100644
index 0000000000..276d735fcb
--- /dev/null
+++ b/spring-vault/src/main/resources/vault-config-k8s.properties
@@ -0,0 +1,4 @@
+vault.uri=http://localhost:8200
+vault.authentication=KUBERNETES
+vault.kubernetes.role=baeldung-test-role
+vault.kubernetes.service-account-token-file=sa-token.txt
\ No newline at end of file
diff --git a/spring-vault/src/test/java/com/baeldung/springcloudvault/SpringCloudVaultApplicationLiveTest.java b/spring-vault/src/test/java/com/baeldung/springcloudvault/SpringCloudVaultApplicationLiveTest.java
new file mode 100644
index 0000000000..b4ece472a6
--- /dev/null
+++ b/spring-vault/src/test/java/com/baeldung/springcloudvault/SpringCloudVaultApplicationLiveTest.java
@@ -0,0 +1,26 @@
+package com.baeldung.springcloudvault;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.core.env.Environment;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@ActiveProfiles("vault")
+@SpringBootTest(classes = SpringCloudVaultTestApplication.class)
+public class SpringCloudVaultApplicationLiveTest {
+
+ @Autowired
+ Environment env;
+
+ @Test
+ public void whenSpringContextIsBootstrapped_thenNoExceptions() {
+ assertNotNull(env.getProperty("foo"));
+ }
+
+}
diff --git a/spring-vault/src/test/resources/application-vault.properties b/spring-vault/src/test/resources/application-vault.properties
new file mode 100644
index 0000000000..7226a3a6e4
--- /dev/null
+++ b/spring-vault/src/test/resources/application-vault.properties
@@ -0,0 +1,15 @@
+# Vault Properties
+spring.config.import: vault://
+spring.cloud.vault.uri=http://localhost:8200
+spring.cloud.vault.authentication=KUBERNETES
+spring.cloud.vault.kubernetes.role=baeldung-test-role
+
+#
+spring.cloud.vault.kv.backend=secrets
+spring.cloud.vault.kv.application-name=baeldung-test
+#
+
+# NOTICE: the following property is only necessary when running the application
+# outside Kubernetes
+# Please refer to the article for instructions on how to create this file
+spring.cloud.vault.kubernetes.service-account-token-file=sa-token.txt
\ No newline at end of file