[[secrets-propertysource]]
= Secrets PropertySource

Kubernetes has the notion of https://kubernetes.io/docs/concepts/configuration/secret/[Secrets] for storing
sensitive data such as passwords, OAuth tokens, and so on. This project provides integration with `Secrets` to make secrets
accessible by Spring Boot applications. You can explicitly enable or disable This feature by setting the `spring.cloud.kubernetes.secrets.enabled` property.

When enabled, the `Fabric8SecretsPropertySource` looks up Kubernetes for `Secrets` from the following sources:

. Reading recursively from secrets mounts
. Named after the application (as defined by `spring.application.name`)
. Matching some labels

*Note:* 

By default, consuming Secrets through the API (points 2 and 3 above) *is not enabled* for security reasons. The permission 'list' on secrets allows clients to inspect secrets values in the specified namespace.
Further, we recommend that containers share secrets through mounted volumes.

If you enable consuming Secrets through the API, we recommend that you limit access to Secrets by using an authorization policy, such as RBAC. 
For more information about risks and best practices when consuming Secrets through the API refer to https://kubernetes.io/docs/concepts/configuration/secret/#best-practices[this doc].

If the secrets are found, their data is made available to the application.

Assume that we have a spring boot application named `demo` that uses properties to read its database
configuration. We can create a Kubernetes secret by using the following command:

[source]
----
kubectl create secret generic db-secret --from-literal=username=user --from-literal=password=p455w0rd
----

The preceding command would create the following secret (which you can see by using `kubectl get secrets db-secret -o yaml`):

[source,yaml]
----
apiVersion: v1
data:
  password: cDQ1NXcwcmQ=
  username: dXNlcg==
kind: Secret
metadata:
  creationTimestamp: 2017-07-04T09:15:57Z
  name: db-secret
  namespace: default
  resourceVersion: "357496"
  selfLink: /api/v1/namespaces/default/secrets/db-secret
  uid: 63c89263-6099-11e7-b3da-76d6186905a8
type: Opaque
----

Note that the data contains Base64-encoded versions of the literal provided by the `create` command.

Your application can then use this secret -- for example, by exporting the secret's value as environment variables:

[source,yaml]
----
apiVersion: v1
kind: Deployment
metadata:
  name: ${project.artifactId}
spec:
   template:
     spec:
       containers:
         - env:
            - name: DB_USERNAME
              valueFrom:
                 secretKeyRef:
                   name: db-secret
                   key: username
            - name: DB_PASSWORD
              valueFrom:
                 secretKeyRef:
                   name: db-secret
                   key: password
----

You can select the Secrets to consume in a number of ways:

. By listing the directories where secrets are mapped:
+
[source,bash]
----
-Dspring.cloud.kubernetes.secrets.paths=/etc/secrets/db-secret,etc/secrets/postgresql
----
+
If you have all the secrets mapped to a common root, you can set them like:
+
[source,bash]
----
-Dspring.cloud.kubernetes.secrets.paths=/etc/secrets
----

. By setting a named secret:
+
[source,bash]
----
-Dspring.cloud.kubernetes.secrets.name=db-secret
----

. By defining a list of labels:
+
[source,bash]
----
-Dspring.cloud.kubernetes.secrets.labels.broker=activemq
-Dspring.cloud.kubernetes.secrets.labels.db=postgresql
----

As the case with `ConfigMap`, more advanced configuration is also possible where you can use multiple `Secret`
instances. The `spring.cloud.kubernetes.secrets.sources` list makes this possible.
For example, you could define the following `Secret` instances:

[source,yaml]
----
spring:
  application:
    name: cloud-k8s-app
  cloud:
    kubernetes:
      secrets:
        name: default-name
        namespace: default-namespace
        sources:
         # Spring Cloud Kubernetes looks up a Secret named s1 in namespace default-namespace
         - name: s1
         # Spring Cloud Kubernetes looks up a Secret named default-name in namespace n2
         - namespace: n2
         # Spring Cloud Kubernetes looks up a Secret named s3 in namespace n3
         - namespace: n3
           name: s3
----

In the preceding example, if `spring.cloud.kubernetes.secrets.namespace` had not been set,
the `Secret` named `s1` would be looked up in the namespace that the application runs.
See xref:property-source-config/namespace-resolution.adoc[namespace-resolution] to get a better understanding of how the namespace
of the application is resolved.

xref:property-source-config/configmap-propertysource.adoc#config-map-fail-fast[Similar to the `ConfigMaps`]; if you want your application to fail to start 
when it is unable to load `Secrets` property sources, you can set `spring.cloud.kubernetes.secrets.fail-fast=true`.

It is also possible to enable retry for `Secret` property sources xref:property-source-config/configmap-propertysource.adoc#config-map-retry[like the `ConfigMaps`].
As with the `ConfigMap` property sources, first you need to set `spring.cloud.kubernetes.secrets.fail-fast=true`. 
Then you need to add `spring-retry` and `spring-boot-starter-aop` to your classpath. 
Retry behavior of the `Secret` property sources can be configured by setting the `spring.cloud.kubernetes.secrets.retry.*`
properties.

NOTE: If you already have `spring-retry` and `spring-boot-starter-aop` on the classpath for some reason
and want to enable fail-fast, but do not want retry to be enabled; you can disable retry for `Secrets` `PropertySources`
by setting `spring.cloud.kubernetes.secrets.retry.enabled=false`.

Since data coming from Secrets is usually treated as sensitive, endpoints of the actuator `/env` and `/configprops` can be made to sanitize data, so that it is not displayed in plain text. In order to do that, you need to set:

[source]
----
spring.cloud.kubernetes.sanitize.secrets=true
----

This setting is supported since `3.0.6` and upwards.

.Properties:
[options="header,footer"]
|===
| Name                                                     | Type      | Default                      | Description
| `spring.cloud.kubernetes.secrets.enabled`                | `Boolean` | `true`                       | Enable Secrets `PropertySource`
| `spring.cloud.kubernetes.secrets.name`                   | `String`  | `${spring.application.name}` | Sets the name of the secret to look up
| `spring.cloud.kubernetes.secrets.namespace`              | `String`  | Client namespace             | Sets the Kubernetes namespace where to look up
| `spring.cloud.kubernetes.secrets.labels`                 | `Map`     | `null`                       | Sets the labels used to lookup secrets
| `spring.cloud.kubernetes.secrets.paths`                  | `List`    | `null`                       | Sets the paths where secrets are mounted (example 1)
| `spring.cloud.kubernetes.secrets.enableApi`              | `Boolean` | `false`                      | Enables or disables consuming secrets through APIs (examples 2 and 3)
| `spring.cloud.kubernetes.secrets.fail-fast`              | `Boolean` | `false`                      | Enable or disable failing the application start-up when an error occurred while loading a `Secret`
| `spring.cloud.kubernetes.secrets.retry.enabled`          | `Boolean` | `true`                       | Enable or disable secrets retry.
| `spring.cloud.kubernetes.secrets.retry.initial-interval` | `Long`    | `1000`                       | Initial retry interval in milliseconds.
| `spring.cloud.kubernetes.secrets.retry.max-attempts`     | `Integer` | `6`                          | Maximum number of attempts.
| `spring.cloud.kubernetes.secrets.retry.max-interval`     | `Long`    | `2000`                       | Maximum interval for backoff.
| `spring.cloud.kubernetes.secrets.retry.multiplier`       | `Double`  | `1.1`                        | Multiplier for next interval.
|===

Notes:

* The `spring.cloud.kubernetes.secrets.labels` property behaves as defined by
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-Configuration-Binding#map-based-binding[Map-based binding].
* The `spring.cloud.kubernetes.secrets.paths` property behaves as defined by
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-Configuration-Binding#collection-based-binding[Collection-based binding].
* Access to secrets through the API may be restricted for security reasons. The preferred way is to mount secrets to the Pod.

You can find an example of an application that uses secrets (though it has not been updated to use the new `spring-cloud-kubernetes` project) at
https://github.com/fabric8-quickstarts/spring-boot-camel-config[spring-boot-camel-config]

