---
title: "cert-manager and Exoscale DNS - Manage SSL certificates with ease"
description: "Manage certifications in a K8s environment easily with cert-manager. Learn how to simply set up cert-manager on Exoscale in our blog post."
date: 2022-11-22
author: "Predrag Janosevic"
tags: ["security","devops","kubernetes","ecosystem"]
url: https://www.exoscale.com/blog/cert-manager-webhook-exoscale/
---
# cert-manager and Exoscale DNS - Manage SSL certificates with ease

[cert-manager](https://cert-manager.io/) is a powerful and extensible X.509 certificate controller for Kubernetes. It can manage certificates in the SKS environment and in combination with our [cert-manager-webhook](https://github.com/exoscale/cert-manager-webhook-exoscale) it integrates with Exoscale DNS for issuing certificates using [ACME DNS01](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge) challenge.

In this short article we will show you how to add a cert-manager to an [Exoscale Scalable Kubernetes Service] (https://www.exoscale.com/sks/) cluster and configure it to generate a *Let's Encrypt* certificate for a domain managed by [Exoscale DNS service](https://www.exoscale.com/dns/).

<br/>

Prerequisites:

- SKS cluster (check our [SKS Quick Start Guide](https://community.exoscale.com/documentation/sks/quick-start/) for instructions on how to create a new cluster using Exoscale CLI)
- [kubectl](https://kubernetes.io/docs/tasks/tools/)
- [helm](https://helm.sh/docs/intro/install/)
- A [valid Exoscale DNS domain](https://community.exoscale.com/documentation/dns/)
- An [Exoscale API access key](https://community.exoscale.com/documentation/iam/quick-start/)

## Installing cert-manager and cert-manager-webhook

The easiest way to add cert-manager to an SKS cluster is using static manifest as described in the [official cert-manager installation page](https://cert-manager.io/docs/installation/):

```
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.10.0/cert-manager.yaml
```

By default cert-manager will be in its own namespace inside a cluster:

```
$ kubectl get pods -n cert-manager
NAME                                     READY   STATUS    RESTARTS   AGE
cert-manager-646dddd544-sxz24            1/1     Running   0          22s
cert-manager-cainjector-8676c4b7-q7s9w   1/1     Running   0          22s
cert-manager-webhook-557fb758cf-989db    1/1     Running   0          22s
```

cert-manager-webhook is installed using Helm and a Helm Chart in the [official cert-manager webhook repository](https://github.com/exoscale/cert-manager-webhook-exoscale):

```
git clone https://github.com/exoscale/cert-manager-webhook-exoscale.git
cd cert-manager-webhook-exoscale
helm install exoscale-webhook ./deploy/exoscale-webhook
```

Now we can see cert-manager-webhook running in the `default` namespace:

```
$ kubectl get pods
NAME                                            READY   STATUS    RESTARTS        AGE
cert-manager-webhook-exoscale-d7dccb674-9czqw   1/1     Running   0               31s
```

## Issuing a certificate for a domain

With cert-manager and cert-manager-webhook in place, we can proceed to create a new certificate for our domain. In this example we will generate a certificate for `example.com`.

cert-manager-webhook requires Exoscale API credentials to manage a DNS record used in the ACME DNS01 challenge. We can generate a *restricted* access key using [Exoscale CLI](https://github.com/exoscale/cli):

```
 $ exo iam access-key create \
	--operation list-dns-domains \
	--operation list-dns-domain-records \
	--operation  get-dns-domain-record \
	--operation get-operation \
	--operation create-dns-domain-record \
	--operation delete-dns-domain-record \
	cert-manager-webhook-key
┼────────────────┼─────────────────────────────────────────────┼
│ IAM ACCESS KEY │                                             │
┼────────────────┼─────────────────────────────────────────────┼
│ Name           │ cert-manager-webhook-key                    │
│ Type           │ restricted                                  │
│ API Key        │ EXOabcdefghijklmnopqrstuvwx                 │
│ API Secret     │ ABCDEFGIJKLMNOPQRSTUVWXYZabcdefgijklmnopqrs │
│ Operations     │ list-dns-domain-records                     │
│                │ get-dns-domain-record                       │
│                │ get-operation                               │
│                │ list-dns-domains                            │
│                │ create-dns-domain-record                    │
│                │ delete-dns-domain-record                    │
┼────────────────┼─────────────────────────────────────────────┼
```

The recommended way to provide API credentials to cert-manager-webhook is using the Kubernetes secret resource. We can create a `secret.yaml` file with the following content:

```yaml
apiVersion: v1
stringData:
  EXOSCALE_API_KEY: EXOabcdefghijklmnopqrstuvwx
  EXOSCALE_API_SECRET: ABCDEFGIJKLMNOPQRSTUVWXYZabcdefgijklmnopqrs
kind: Secret
metadata:
  name: exoscale-secret
type: Opaque
```

Adding the resource is as simple as running:

```
kubectl create -f secret.yaml
```

Now we can reference our secret when creating an `Issuer` resource (`issuer.yaml`):

```yaml
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: exoscale-issuer
spec:
  acme:
    email: my-user@example.com
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: exoscale-private-key-secret
    solvers:
    - dns01:
        webhook:
          groupName: acme.exoscale.com
          solverName: exoscale
          config:
            apiKeyRef:
              key: EXOSCALE_API_KEY
              name: exoscale-secret
            apiSecretRef:
              key: EXOSCALE_API_SECRET
              name: exoscale-secret
```

`Issuers` are *Kubernetes* resources representing certificate authorities (CAs), that are able to generate signed certificates by honoring certificate signing requests. We can add the resource as before:

```
kubectl create -f issuer.yaml
```

The final piece of the puzzle is the `Certificate` resource. A `Certificate` resource specifies fields that are used to generate certificate signing requests, including domain name and which issuer they want to obtain the certificate from. Our new resource (`certificate.yaml`) will look like this:

```yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: example-com
spec:
  dnsNames:
  - example.com
  issuerRef:
    name: exoscale-issuer
  secretName: example-com-tls
```

And to add a resource:

```
kubectl create -f certificate.yaml
```

It may take a minute or two but eventually we will see our new certificate in the ready state:

```
$ kubectl get certificate example-com
NAME          READY   SECRET            AGE
example-com   True    example-com-tls   0m52s
```

That's it, now we have a valid certificate in our cluster! 

<br/>

Head over to [cert-manager documentation](https://cert-manager.io/docs/usage/) for further use cases like [Securing Ingress Resources](https://cert-manager.io/docs/usage/ingress/).

