# Install Cert-Manager

Der [Cert-Manager](https://cert-manager.io) ist eine Verwaltungskomponente für
Zertifikate innerhalb eines Kubernetes Clusters.

Erst mit dem Cert-Manager ist es möglich Zertifikate zu erstellen, verwalten und
löschen. Der Cert-Manager bringt über CRDs eigene Objekte für die Verwaltung mit

## Installation

Die einfachste Installation kann direkt über [Helm](https://helm.sh) erfolgen.

Typischerweise wird für den Cert-Manager ein eigener Namespace (`cert-manager`)
angelegt.

```bash

helm repo add jetstack https://charts.jetstack.io
helm install cert-manager jetstack/cert-manager --namespace cert-manager \
  --create-namespace --set installCRDs=true
```

## Beispiel für die Anwendung

Bei einem extern erreichbaren Webserver soll neben der Konfiguration eines
Ingress mit nginx auf Port 80 auch ein Zugang über https (Port 443) ermöglicht
werden.

Dazu bedarf es eines Zertifikats von einer Trusted-CA. Bei extern erreichbaren
Webseiten bietet sich dafür z. B. [Let's Encrypt](https://letsencrypt.org/de/)
an.

### Issuer

Um bei Let's Encrypt Zertifikate abholen zu können bedarf es zunächst eines
_Issuers_ über diese Objekt wir die Anmeldung an Let's Encrypt durchgeführt. Die
gespeicherte Anmeldung dient später auch als Berechtigung die Zertifikate zu
beantragen.

Der Issuer wird im gleichen Namespace wie der spätere Ingress angelegt.

```yaml
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: acme
  namespace: example
spec:
  acme:
    email: user@example.com
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: acme-issuer
    solvers:
      - http01:
          ingress:
            class: nginx
```

Sobald das Objekt erstellt ist, wird die Anmeldung durchgeführt. Der Status ist
im `status` des Ingress Objekts sichtbar.

### Ingress

Um einen Webserver per https erreichbar zu machen, wird zusätzlich zu der
normalen Konfiguration ein Abschnitt `spec.tls` benötigt in dem der SNI
`spec.tls.hosts[]` und der Name eines Secrets für das Zertifikat angegeben wird.

Damit der Cert-Manager sich um das Zertifikat kümmert muss eine Annotation
`cert-manager.io/issuer:` angelegt werden, in die der Name des zu benutztenden
Issuers angegeben wird.

```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/issuer: "acme"
  name: nginx
  namespace: example
spec:
  ingressClassName: nginx
  rules:
    - host: example.com
      http:
        paths:
          - pathType: Prefix
            path: /
            backend:
              service:
                name: nginx
                port:
                  number: 80
  tls:
    - hosts:
        - example.com
      secretName: example.com-tls
```

Nach Anlegen des Objekts sorgt der Cert-Manager für die Erzeugung des Privaten
Schlüssels und eines Certificate Sign Requests (CSR). Den CSR sendet er zur
Validierung an den über den Issuer angegeben Dienst und sorgt sich um die
Kommunikation mit diesem um das Zertifikat zu holen. Sobald es vorliegt wird es
in dem unter `secretName` angegebenen Secret zusammen mit dem Key abgelegt und
steht für den Ingress zu Verfügung. Dieser baut das Zertifikat - sobald es
vorhanden ist - ein und stellt die Domain per https zur Verfügung.

## ClusterIssuer

Der Issuer steht immer nur in dem Namespace in dem er angelegt wurde zur
Verfügung. Um einen Issuer auch über die Namespaces hinweg benutzen zu können
gibt es den ClusterIssuer.

Dieser wird - in der Regel - Im Namespace des Cert-Manager abgelegt, kann aber -
solang es keine RBAC Einschränkungen gibt - aus allen Namespaces benutzt werden.

### Cluster-Issuer

```yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: acme
  namespace: cert-manager
spec:
  acme:
    email: user@example.com
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: acme-issuer
    solvers:
      - http01:
          ingress:
            class: nginx
```

Tatsächlich unterscheidet sich die Konfiguration des ClusterIssuer nur durch den unterschiedlichen
`kind` von dem Issuer (`ClusterIssuer` statt `Issuer`)

### Ingress

Auch beim Ingress ist nur die Annotation zu ändern.

Hier wird dann `cert-manager.io/cluster-issuer:` benutzt.

```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/cluster-issuer: "acme"
  name: nginx
  namespace: example
spec:
  ingressClassName: nginx
  rules:
    - host: example.com
      http:
        paths:
          - pathType: Prefix
            path: /
            backend:
              service:
                name: nginx
                port:
                  number: 80
  tls:
    - hosts:
        - example.com
      secretName: example.com-tls
```
