KeyCloak mit WebAuthn
Ziel dieser Reihe soll es werden Anwendungen über WebAuthn zu schützen. Dazu wird ein K3S Cluster mit K3D aufgesetzt. Diese soll über .cluster.local erreichbar sein.
-
Im Ersten Teil beschäftige ich mich mit der Installation einer KeyCloak Instanz in einem K3S Cluster.
-
Im zweiten Teil wird die Demoanwendung (Gitea) deployt
-
Im dritte Teil geht es um die Konfiguration von KeyCloak, sodass die Anwendung von WebAuthn gescchützt wird
K3D Setup
Um den Cluster aufzusetzen werde ich K3D verwenden.
K3D installieren
Die Installation habe ich für Manjaro/Arch Linux bereits in dem Artikel K3D Cluster ausfsetzen beschrieben. Anmerkung: Die aktuelle Version kann nun mit yay bereits aus AUR gezogen werden.
K3D Cluster erstellen
Für diese Reihe erstelle ich einen kleinen Demo Cluster mit 2 Knoten und öffne den Port 8080 für den LoadBalancer. D.h. der NginX Reverse Proxy muss später auf den Host und Port 8080 verweisen, so dass die Anfragen vom KeyCloak dann beantwortet werden können.
k3d cluster create demo -a2 -p 8080:80@loadbalancer -p 8443:443@loadbalancer
Achtung: Die Syntax von K3D hat sich seit Version 3.0.0 geändert und folgt nun den anderen K8S Anwendungen, in dem es Nomen und Verb als Parameter verlangt. Bsp: aus k3d create cluster wurde nun k3d cluster create.
Namespace
Wie immer sollte mna einen eigenen Namespace für die Trennung der Anwendung verwenden. Diesen legen wir zuerst mit:
k create namespace keycloak
an.
Hinweis: K ist bei mir immer ein Alias für kubectl.
Self Signed Certificate ausstellen
Installation Cert-Manager
Die Installation von Cert-Manager wird hier beschrieben.
Selbst Signiertes Zertifikat ausstellen
Zunächst müssen wir ein Manifest erstellen, das einen Issuer und ein Certificate beschreibt. Die Domain wird hier auf *.clouster.local festgelegt.
apiVersion: cert-manager.io/v1alpha2
kind: Issuer
metadata:
name: selfsigned-issuer
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
name: first-tls
spec:
secretName: first-tls
dnsNames:
- "*.cluster.local"
issuerRef:
name: selfsigned-issuer
Jetzt muss das Manifest angewendet werden und der Cert-Manager erstellt für uns das selbst signierte Zertifikat, welches wir in dem Ingress später referenzieren werden.
k apply -n keycloak -f keycloak-cert.yaml
Überprüfung der Ausstellung
Ein paar Schnelltests geben auskunft über die erfolgreiche Erstellung der Zertifikate:
# Zertifikat überprüfen
k -n keycloak get certificate
# Secret überprüfen
k -n keycloak get secret first-tls
Nun zum Abschluss noch mit OpenSSL überprüfen…
openssl x509 -in <(kubectl -n keycloak get secret first-tls -o jsonpath='{.data.tls\.crt}' | base64 -d) -text -noout
…in der Ausgabe erhält man dann die Informationen…
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
2e:df:ae:86:5c:27:f9:25:bf:77:ca:d1:7a:3a:48:c6
Signature Algorithm: sha256WithRSAEncryption
Issuer:
Validity
Not Before: Sep 2 08:14:52 2020 GMT
Not After : Dec 1 08:14:52 2020 GMT
Subject:
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:c5:e0:f9:be:a6:b9:41:cb:38:e9:11:57:0a:1b:
b5:2b:c2:7e:78:87:5f:43:dc:22:c3:7d:8b:a7:f3:
c0:d4:f9:bc:75:4e:96:93:66:17:67:f7:e2:02:96:
37:19:90:64:6f:fa:c3:1f:c5:21:80:de:e0:aa:76:
12:d6:24:a0:f2:7b:37:14:34:a8:eb:9c:1a:17:b0:
4f:d8:a4:9b:3a:51:fe:18:30:3e:81:f5:20:01:85:
c1:af:61:cf:2e:30:fd:42:3c:00:c0:28:f9:60:37:
84:80:84:85:54:33:6c:0f:cb:c2:7e:5f:50:ee:82:
a1:4a:35:c3:5b:fe:8a:47:21:75:c5:0e:03:08:f2:
2d:fa:98:e8:d6:16:d6:fb:af:97:d8:86:3a:c6:84:
63:5d:bd:f1:1b:72:0f:73:f5:09:33:26:aa:bc:8f:
8c:9b:fa:a6:11:53:19:69:33:bc:68:47:c3:74:6a:
70:86:c5:19:93:83:cc:9e:07:11:0d:6e:9f:f8:5b:
67:d7:d8:ef:ca:37:4e:7c:1b:a2:f5:ee:70:eb:55:
2f:86:45:02:b4:4d:6d:9a:1b:20:3b:c4:d5:db:f3:
66:8c:22:e1:da:94:c4:e6:20:9f:c4:ff:79:b9:26:
b6:ae:d0:8f:f2:45:d5:7d:eb:88:7f:39:36:7d:ef:
f6:85
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Alternative Name: critical
DNS:*.cluster.local
Signature Algorithm: sha256WithRSAEncryption
39:b5:cf:d7:08:b1:9d:07:44:ef:79:f3:13:46:11:f9:07:96:
f3:db:cb:8d:5e:df:14:5f:2f:74:ff:4a:c8:58:af:57:fa:35:
fb:19:1e:73:af:f5:d2:eb:ec:b9:d1:60:f5:28:c1:39:ba:a1:
0c:4e:0d:3c:10:83:ba:0f:ef:4f:7a:1c:68:25:3a:3c:bf:de:
04:24:f0:ca:15:34:6d:66:8f:3b:69:96:fe:b8:03:54:98:a6:
fe:b8:0f:d4:6f:1b:7a:87:6a:5a:c6:57:ff:62:ee:0f:24:ff:
e9:e8:e9:b5:4d:ca:ec:27:7c:03:7b:63:2e:ff:4d:3a:c8:5e:
d8:b4:f5:8a:e8:0c:2c:62:f1:00:c6:4d:fe:cf:45:e2:5b:74:
55:0a:fe:f7:5a:b4:c0:5a:2c:04:4c:ae:b2:5a:d3:d7:26:ca:
63:2c:69:2b:81:cd:6e:39:c4:66:5f:67:47:2d:f4:ea:eb:9b:
31:17:5d:4c:5b:77:26:d4:a4:4c:f1:52:ae:92:84:e9:f4:01:
7e:f1:f5:cf:1d:54:a5:8c:6b:58:b2:35:b3:44:0d:81:b6:da:
4e:0b:02:fe:21:21:75:59:53:15:17:67:7e:37:00:59:00:11:
67:47:4e:5f:0b:1d:c4:1e:4b:5c:d2:80:57:7f:2b:58:01:ba:
83:fc:c9:ce
Download Kubernetes Manifest
Wir laden das Manifest keycloak.yaml mit wget runter und modifizieren die Defaultwerte für den Namespace und setzen ein neues Passwort. Der Namespace wird auf den zuvor erstellten Namespace keycloak gesetzt. Das Passwort wird auf 123 gesetzt.
wget -q -O - https://raw.githubusercontent.com/keycloak/keycloak-quickstarts/latest/kubernetes-examples/keycloak.yaml | sed "s/namespace: default/namespace: keycloak/" > keycloak.yaml
Achtung: Username und Passwort sind hier admin. Wer es sicherer mag, der sollte das YAML bearbeiten und die Werte ersetzen.
k apply -n keycloak -f keycloak.yaml
Das hochfahre der Pods kan mit
watch kubectl -n keycloak get pods
überwacht werden.
Ingress
Da K3S in der Defaulteinstellung Traefik als Ingress Controller verwendet, nutze ich hier nicht die von KeyCloak Team bereitgestelltes Kubernetes Manifest für Ingress.
HTTPS Anfragen für die FQDN keycloak.cluster.local an den Cluster werden werden so an den Service keycloak an Port 8443 weitergeleitet.
apiVersion: cert-manager.io/v1alpha2
kind: Issuer
metadata:
name: selfsigned-issuer
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
name: first-tls
spec:
secretName: first-tls
dnsNames:
- "*.cluster.local"
# - "*.keyclaok"
issuerRef:
name: selfsigned-issuer
Hosts Datei Vorbereiten
Damit das Ganze funtkioniert, muss der FQDN keycloak.cluster.local in die /etc/hosts Datei eingetragen werden:
192.168.2.XXX keycloak.cluster.local
Erster Test mit CURL
curl -k https://keycloak.cluster.local:8443
<!--
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
~ and other contributors as indicated by the @author tags.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="refresh" content="0; url=/auth/" />
<meta name="robots" content="noindex, nofollow">
<script type="text/javascript">
window.location.href = "/auth/"
</script>
</head>
<body>
If you are not redirected automatically, follow this <a href='/auth'>link</a>.
</body>
</html>
Aufruf mit dem Browser
Nun kann nach dem ersten erfolgreichen Test der KeyCloak über https://keycloak.cluster.local:8443/auth/ bzw. die Admin-Console über https://keycloak.cluster.local:8443/auth/admin/master/console/ aufgerufen werden. Die Credentials für die Admin-Console sind im Kubernetes Manifest (siehe oben) festgelegt worden.
Standard ist hier Username admin und Passwort admin.