Read secrets as files using spring.cloud.kubernetes.secrets.paths property

2.8k Views Asked by At

Is there an example of howto use spring.cloud.kubernetes.secrets.paths=/mnt/secrets-store property to read secrets as files (mounted as a volume)?

My Pod.yaml


kind: Pod
apiVersion: v1
metadata:
  name: nginx-mounted-secrets
  namespace: default
  labels:
    aadpodidbinding: pod-mi
spec:
  containers:
    - name: nginx
      image: nginx
      volumeMounts:
        - name: foo
          mountPath: "/mnt/secrets-store"
          readOnly: true
  volumes:
    - name: foo
      csi:
        driver: secrets-store.csi.k8s.io
        readOnly: true
        volumeAttributes:
          secretProviderClass: spc

When I run the Pod the secrets are mounted

kubectl -n default exec -it nginx-mounted-secrets -- bash
root@nginx-mounted-secrets:/# ls /mnt/secrets-store
service-one-secret
service-two-secret

I've tried the following but the fields do not get populated:

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConfigurationProperties
@Data
public class ApplicationSecrets {

    private String serviceOneSecret;
    private String serviceTwoSecret;

}

I'm using

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-kubernetes-config</artifactId>
            <version>1.1.6.RELEASE</version>
        </dependency>
2

There are 2 best solutions below

2
On

In a general spring application ConfigurationProperties properties are build with prefixes in mind for separation of concerns(i.e spring properties vs application properties..).

Following your yml structure, there are some different concerns of your properties: metadata, spec (split up into containers and volumes)

So for your implementation to work either:

  1. Define @ConfigurationProperties with correct prefixes for each sub-tree and use them accordingly

2.[OR] Load the yml properties and look them up via @Value, using a custom propertyPlaceholder as in this answer: How to use YamlPropertiesFactoryBean to load YAML files using Spring Framework 4.1? and them autowire all properties in a map for example (this solution with the @Value("#{${propertyname}}") private Map<String,String> propertyname;

3
On

I think what might have been missing in your case is letting spring know where the secrets are mounted. I've done this via bootstrap.yaml file (mounted next to application jar).

spring:
  cloud:
    kubernetes:
      secrets:
        # this would be "/mnt/secrets-store" in your case
        paths: /etc/secrets
        enabled: true
      config:
        name: "config-map-name"
        enabled: true
...

Notes:

  1. bootstrap.yaml mounted next to the jar completely overwrites the content of a bootstrap.yaml bundled inside the app (there is no cascading like in case of application.yaml.
  2. I'm running 2.0.1

I can post more configuration bits if you need it.