Skip to content

Commit f597951

Browse files
feat(infra): add Spring Cloud Vault secrets management (STA-219) (#236)
* feat(infra): add Spring Cloud Vault secrets management across all services (STA-219) Integrate HashiCorp Vault via Spring Cloud Vault 5.0.1 for centralised secrets management. Vault is opt-in (app.vault.enabled=false by default) so existing env-var workflow and all tests continue to work unchanged. - Add spring-cloud-starter-vault-config to platform-infra - Add VaultConfig with @ConditionalOnProperty toggle (matchIfMissing=false) - Add optional:vault:// ConfigData import to all 10 service application.yml - Configure KV v2 backend with per-service and shared (application) contexts - Add vault-init Docker Compose service that seeds dev secrets on startup - Add init-vault.sh script seeding DB creds, API keys, JWT keys per service Closes STA-219 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(infra): add spring.cloud.vault.enabled=false to all integration test configs Fixes duplicate YAML key errors in CI where integration test application.yml files that already had spring.cloud.stream conflicted with the new spring.cloud.vault block from the main application.yml. Also explicitly disables Vault in all IT configs to prevent connection attempts in CI where no Vault instance is running. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(infra): default Vault scheme to HTTPS and remove dev token fallback (STA-219) Addresses CodeRabbit review: scheme defaults to HTTPS for production safety, token has no fallback to prevent accidental auth with dev-root-token. Local dev sets VAULT_SCHEME=http and VAULT_TOKEN=dev-root-token via docker-compose. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 501ebef commit f597951

26 files changed

Lines changed: 516 additions & 88 deletions

File tree

api-gateway-iam/api-gateway-iam/src/main/resources/application-integration-test.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ spring:
2525
port: 6379
2626

2727
cloud:
28+
vault:
29+
enabled: false
2830
stream:
2931
kafka:
3032
binder:

api-gateway-iam/api-gateway-iam/src/main/resources/application.yml

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,27 @@ spring:
22
application:
33
name: api-gateway-iam
44

5+
config:
6+
import: optional:vault://
7+
8+
cloud:
9+
vault:
10+
enabled: ${app.vault.enabled:false}
11+
host: ${VAULT_HOST:localhost}
12+
port: ${VAULT_PORT:8200}
13+
scheme: ${VAULT_SCHEME:https}
14+
authentication: TOKEN
15+
token: ${VAULT_TOKEN:}
16+
kv:
17+
enabled: true
18+
backend: secret
19+
default-context: application
20+
stream:
21+
kafka:
22+
binder:
23+
brokers: ${KAFKA_BROKERS:localhost:9092}
24+
auto-create-topics: false
25+
526
datasource:
627
url: ${DB_URL:jdbc:postgresql://localhost:5432/s10_api_gateway_iam}
728
username: ${DB_USER:sp_user}
@@ -47,13 +68,6 @@ spring:
4768
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
4869
value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
4970

50-
cloud:
51-
stream:
52-
kafka:
53-
binder:
54-
brokers: ${KAFKA_BROKERS:localhost:9092}
55-
auto-create-topics: false
56-
5771
app:
5872
idempotency:
5973
ttl-hours: 24

blockchain-custody/blockchain-custody/src/integration-test/resources/application-integration-test.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
spring:
2+
cloud:
3+
vault:
4+
enabled: false
25
main:
36
allow-bean-definition-overriding: true
47
jpa:

blockchain-custody/blockchain-custody/src/main/resources/application.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,22 @@ spring:
22
application:
33
name: blockchain-custody
44

5+
config:
6+
import: optional:vault://
7+
8+
cloud:
9+
vault:
10+
enabled: ${app.vault.enabled:false}
11+
host: ${VAULT_HOST:localhost}
12+
port: ${VAULT_PORT:8200}
13+
scheme: ${VAULT_SCHEME:https}
14+
authentication: TOKEN
15+
token: ${VAULT_TOKEN:}
16+
kv:
17+
enabled: true
18+
backend: secret
19+
default-context: application
20+
521
datasource:
622
url: ${DB_URL:jdbc:postgresql://localhost:5432/s4_blockchain_custody}
723
username: ${DB_USER:dev}

compliance-travel-rule/compliance-travel-rule/src/integration-test/resources/application-integration-test.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
spring:
2+
cloud:
3+
vault:
4+
enabled: false
25
main:
36
allow-bean-definition-overriding: true
47
jpa:

compliance-travel-rule/compliance-travel-rule/src/main/resources/application.yml

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,32 @@ spring:
22
application:
33
name: compliance-travel-rule
44

5+
config:
6+
import: optional:vault://
7+
8+
cloud:
9+
vault:
10+
enabled: ${app.vault.enabled:false}
11+
host: ${VAULT_HOST:localhost}
12+
port: ${VAULT_PORT:8200}
13+
scheme: ${VAULT_SCHEME:https}
14+
authentication: TOKEN
15+
token: ${VAULT_TOKEN:}
16+
kv:
17+
enabled: true
18+
backend: secret
19+
default-context: application
20+
stream:
21+
kafka:
22+
binder:
23+
brokers: ${KAFKA_BROKERS:localhost:9092}
24+
auto-create-topics: false
25+
bindings:
26+
compliance-result-out-0:
27+
destination: compliance.result
28+
sanctions-hit-out-0:
29+
destination: sanctions.hit
30+
531
datasource:
632
url: ${DB_URL:jdbc:postgresql://localhost:5432/s2_compliance}
733
username: ${DB_USER:sp_user}
@@ -36,18 +62,6 @@ spring:
3662
key-serializer: org.apache.kafka.common.serialization.StringSerializer
3763
value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
3864

39-
cloud:
40-
stream:
41-
kafka:
42-
binder:
43-
brokers: ${KAFKA_BROKERS:localhost:9092}
44-
auto-create-topics: false
45-
bindings:
46-
compliance-result-out-0:
47-
destination: compliance.result
48-
sanctions-hit-out-0:
49-
destination: sanctions.hit
50-
5165
namastack:
5266
outbox:
5367
poll-interval: 2000

docker-compose.dev.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,23 @@ services:
193193
timeout: 5s
194194
retries: 10
195195

196+
# ─────────────────────────────────────────────
197+
# Vault init — seeds KV v2 secrets for local dev
198+
# ─────────────────────────────────────────────
199+
vault-init:
200+
image: hashicorp/vault:latest
201+
container_name: sp-vault-init
202+
depends_on:
203+
vault:
204+
condition: service_healthy
205+
environment:
206+
VAULT_ADDR: http://vault:8200
207+
VAULT_TOKEN: dev-root-token
208+
volumes:
209+
- ./infra/local/vault/init-vault.sh:/vault/init-vault.sh
210+
entrypoint: ["/bin/sh", "/vault/init-vault.sh"]
211+
restart: "no"
212+
196213
# ─────────────────────────────────────────────
197214
# Mailhog — captures outbound email (replaces SendGrid in dev)
198215
# ─────────────────────────────────────────────

fiat-off-ramp/fiat-off-ramp/src/integration-test/resources/application-integration-test.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
spring:
2+
cloud:
3+
vault:
4+
enabled: false
25
main:
36
allow-bean-definition-overriding: true
47
jpa:

fiat-off-ramp/fiat-off-ramp/src/main/resources/application.yml

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,34 @@ spring:
22
application:
33
name: fiat-off-ramp
44

5+
config:
6+
import: optional:vault://
7+
8+
cloud:
9+
vault:
10+
enabled: ${app.vault.enabled:false}
11+
host: ${VAULT_HOST:localhost}
12+
port: ${VAULT_PORT:8200}
13+
scheme: ${VAULT_SCHEME:https}
14+
authentication: TOKEN
15+
token: ${VAULT_TOKEN:}
16+
kv:
17+
enabled: true
18+
backend: secret
19+
default-context: application
20+
stream:
21+
kafka:
22+
binder:
23+
brokers: ${KAFKA_BROKERS:localhost:9092}
24+
auto-create-topics: false
25+
bindings:
26+
fiat-payout-initiated-out-0:
27+
destination: fiat.payout.initiated
28+
fiat-payout-completed-out-0:
29+
destination: fiat.payout.completed
30+
fiat-payout-failed-out-0:
31+
destination: fiat.payout.failed
32+
533
datasource:
634
url: ${DB_URL:jdbc:postgresql://localhost:5432/s5_fiat_off_ramp}
735
username: ${DB_USER:sp_user}
@@ -36,20 +64,6 @@ spring:
3664
key-serializer: org.apache.kafka.common.serialization.StringSerializer
3765
value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
3866

39-
cloud:
40-
stream:
41-
kafka:
42-
binder:
43-
brokers: ${KAFKA_BROKERS:localhost:9092}
44-
auto-create-topics: false
45-
bindings:
46-
fiat-payout-initiated-out-0:
47-
destination: fiat.payout.initiated
48-
fiat-payout-completed-out-0:
49-
destination: fiat.payout.completed
50-
fiat-payout-failed-out-0:
51-
destination: fiat.payout.failed
52-
5367
namastack:
5468
outbox:
5569
poll-interval: 2000

fiat-on-ramp/fiat-on-ramp/src/integration-test/resources/application-integration-test.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
spring:
2+
cloud:
3+
vault:
4+
enabled: false
25
main:
36
allow-bean-definition-overriding: true
47
jpa:

0 commit comments

Comments
 (0)