# Spring Boot with Cert-Manager

The purpose of this Spring Boot example is to demonstrate how we can configure an HTTPS/TLS microservice using the Cert-Manager Dekorate extension.

Apart from the Dekorate Kubernetes starter dependency, the application must declare the Cert-Manager dekorate dependency part of the pom.xml file:

    <dependency>
      <groupId>io.dekorate</groupId>
      <artifactId>certmanager-annotations</artifactId>
      <version>${project.version}</version>
    </dependency>

## Enable HTTPS transport

To enable the HTTPS/TLS transport in Spring Boot, we need to add the following properties:

```
server.port=8443
server.ssl.enabled=true
```

Next, we need to configure the Java PKCS12 Keystore properties that our Spring Boot application will use to get the Server certificate signed and the private key:

```
server.ssl.key-store-type=PKCS12
server.ssl.key-store=/path/to/keystore.p12
server.ssl.key-store-password=the password
```

Where is the `keystore.p12` Keystore and what is its password? This is where Cert-Manager comes to play. This Java Keystore will be generated by the Cert-Manager on the Kubernetes platform as a secret resource. Then, what we need to do is to mount a volume from this generated secret, so the Spring Boot application can read the generated Keystore by Cert-Manager. In the following sections, we'll see how we can instruct Cert-Manager to generate the Keystore and how to configure the application to mount the secret and use it.

## Generate a Self-Signed Certificate and the Keystore

Let's configure the different properties to request the generation of the Self-Signed certificate and the `keystore.p12` PKCS12 Keystore file:

```
dekorate.certificate.secret-name=tls-secret
dekorate.certificate.self-signed.enabled=true
dekorate.certificate.keystores.pkcs12.create=true
# the secret name of the password:
dekorate.certificate.keystores.pkcs12.passwordSecretRef.name=pkcs12-pass 
dekorate.certificate.keystores.pkcs12.passwordSecretRef.key=password
```

Using this configuration, Dekorate will create the `Certificate` and `Issuer` resources that, once installed on the Kubernetes platform, will be used by the Certificate Manager to generate a self-signed certificate and the Keystore files within the secret `tls-secret`. 

**NOTE**: As the Keystore file (pkcs12, ...) is password protected, this is then the reason why we have to create a secret including the needed password. For that purpose, we are going to create, part of the file `src/main/resources/k8s/common.yml`, a secret named "pkcs12-pass". The data field will include the key password where the string `supersecret` will be encoded in base64:

```yaml
---
apiVersion: v1
kind: Secret
metadata:
  name: pkcs12-pass
data:
  # "supersecret" in base64:
  password: c3VwZXJzZWNyZXQ=
type: Opaque
```

To tell to Dekorate where it can find the file `src/main/resources/k8s/common.yml`, we will then set the property `dekorate.options.input-path` to specify the name folder under `src/main/resources` where they can be found (e.g. k8s):

```
dekorate.options.input-path=k8s
```

At this point, when we install the generated resources by Dekorate on the Kubernetes platform, Certificate Manager will generate the generated PKCS12 Keystore file named `keystore.p12` within the secret `tls-secret`. Also, the Cert-Manager Dekorate extension will configure the Spring Boot application to automatically mount a volume using this secret `tls-secret` at the path `/etc/certs` (it can be configured using `dekorate.certificate.volume-mount-path`). Therefore, what we need to do next is to simply map the Keystore file and password into the Spring Boot properties `server.ssl.key-store` and `server.ssl.key-store-password`:

```
dekorate.kubernetes.env-vars[0].name=SERVER_SSL_KEY_STORE
dekorate.kubernetes.env-vars[0].value=/etc/certs/keystore.p12
dekorate.kubernetes.env-vars[1].name=SERVER_SSL_KEY_STORE_PASSWORD
dekorate.kubernetes.env-vars[1].secret=pkcs12-pass
dekorate.kubernetes.env-vars[1].value=password
```

## Run the application in Kubernetes

First, make sure you have access to a Kubernetes cluster and that the [Cert-Manager](https://cert-manager.io/docs/installation/) is deployed.

Next, we need to generate the manifests and push the application container image to our container registry:

```
mvn clean install -Ddekorate.push=true -Ddekorate.docker.registry=<your container registry. Example: quay.io> -Ddekorate.docker.group=<the container group. Example: user>
```

After executing the above command, the generated manifests, which are available at this path `target/classes/META-INF/dekorate/kubernetes.yml`, can be installed as such:

```
kubectl apply -f target/classes/META-INF/dekorate/kubernetes.yml
```

After a few moments, we should be able to see the secret resource named `tls-secret` that the `Cert-Manager` has created like the pkcs12 keystore file:

```
kubectl get secret/tls-secret -o yaml | grep keystore.p12
```

After some minutes, our application should be up and running:

```
kubectl get pods
```

Output:

```
NAME                                                    READY   STATUS    RESTARTS   AGE
spring-boot-with-certmanager-example-566546987c-nj94n   1/1     Running   0          2m23s
```

Let's try it out by port-forwarding the port 8443:

```
kubectl port-forward spring-boot-with-certmanager-example-566546987c-nj94n 8443:8443
```

Then, if we browse to `https://localhost:8443/`, we should see `Hello world from HTTPS!`!
