Kubernetes Dashboard mit Keycloak OIDC: Unterschied zwischen den Versionen

Aus RT-Wiki - IT-Notizbuch
Zur Navigation springen Zur Suche springen
KKeine Bearbeitungszusammenfassung
 
(14 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
__NOINDEX__
{{Infobox
{{Infobox
| Titel      = Testumgebung
| Titel      = Testumgebung
Zeile 6: Zeile 4:
| Bildbreite =  
| Bildbreite =  
| Bildtext  =  
| Bildtext  =  
| Stil            = 1
| Stil            = 2
| Titelfarbe      = 6
| Titelfarbe      = 6
| Abschnittsfarbe =  
| Abschnittsfarbe =  
Zeile 21: Zeile 19:


=== API-Server konfigurieren ===
=== API-Server konfigurieren ===
 
<syntaxhighlight lang="bash">
 
vi /etc/kubernetes/manifests/kube-apiserver.yaml
'# /etc/kubernetes/manifests/kube-apiserver.yaml
</syntaxhighlight><syntaxhighlight lang="yaml" line="1">
<syntaxhighlight lang="yaml" line="1">
spec:
spec:
   containers:
   containers:
Zeile 39: Zeile 36:
'''Hinweis:'''
'''Hinweis:'''


''Wenn <code>oidc-username-claim</code> NICHT 'email' ist, wird standardmäßig die 'issuer-url' als Prefix benutzt (z.B. https://<my.keycloak.server>/realms/<Realm-Name>:<username>).''
''Wenn <code>oidc-username-claim</code> '''NICHT''' 'email' ist, wird standardmäßig die 'issuer-url' als Präfix vor den Benutzer gestellt (z.B. https://<my.keycloak.server>/realms/<Realm-Name>:<username>).''


''Um den Prefix zu dekativieren muss als Wert '-' angegeben werden.''
''Um den Präfix zu deaktivieren muss bei <code>oidc-username-prefix</code> der Wert '-' angegeben werden.''


=== Load Balancer installieren ===
=== Load Balancer installieren ===
Zeile 49: Zeile 46:


==== Ports in der Firewall öffnen ====
==== Ports in der Firewall öffnen ====
<syntaxhighlight lang="bash">
Sowohl auf dem Controller als auch den Worker-Nodes<syntaxhighlight lang="bash">
firewall-cmd --permanent --add-port=7472/tcp
firewall-cmd --permanent --add-port=7946/tcp
firewall-cmd --permanent --add-port=7946/tcp
firewall-cmd --permanent --add-port=7946/udp
firewall-cmd --permanent --add-port=7946/udp
Zeile 87: Zeile 85:
</syntaxhighlight>
</syntaxhighlight>


=== Reverse Proxy installieren ===
=== Reverse Proxy installieren (ingress-nginx) ===
Reverse Proxy um mehrere Domains auf einer IP erreichbar zu machen.
Reverse Proxy um mehrere Domains auf einer IP erreichbar zu machen.


Zeile 100: Zeile 98:
</syntaxhighlight>'''Hinweise:'''
</syntaxhighlight>'''Hinweise:'''


''Wenn Header zu groß dann 502 Fehler. Deswegen auf 8k erhöhen''
''Bei Keycloak kann es vorkommen, dass mehr als 4 kb Daten über den Header gesendet werden.''


''Für TLS benötigen wir ein 'Secret" mit dem Privat Key und dem Public Certificate für die Domain, die später für das Dahsboard genutzt werden soll.''
''Wenn der Header zu groß wird, bekommt man einen Fehler (502).''  


''Dieses kann man als Standard direkt in der Config für Ingress-Nginx hinerlegen oder später im Ingress.''
''Deswegen erhöhen wir diesen direkt während der Installation auf 8 kb.''
 
 
 
''Für TLS benötigen wir ein 'Secret" mit dem "Privat Key" und dem "Public Certificate" für die Domain, die später für das Dashboard genutzt werden soll.''
 
''Dieses kann man als Standard, direkt in der Config für Ingress-Nginx hinerlegen oder später im Ingress definieren.''
 
 
'''Tipp:'''
 
Wenn man bei <code>default-ssl-certificate</code> ein Wildcard-Zertifikat (z.B. *.my-cluster.host) für den Cluster hinterlegt,
 
kann für jeden Ingress einfach eine Sub-Domain vergeben, die dann automatisch ein gültiges Zertifikat hat.
 
 
 
Installation starten:
<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
helm upgrade --install ingress-nginx ingress-nginx \
helm upgrade --install ingress-nginx ingress-nginx \
Zeile 115: Zeile 130:
=== OAUTH2 Proxy installieren ===
=== OAUTH2 Proxy installieren ===
Authentifizierung gegen Keyclok und Token Weiterleitung an Dashboard
Authentifizierung gegen Keyclok und Token Weiterleitung an Dashboard
values.yaml
values.yaml
<syntaxhighlight lang="yaml" line="1">
<syntaxhighlight lang="yaml" line="1">
Zeile 145: Zeile 161:


''Der Parameter <code>cookie-refresh</code> sollte kleiner als die "Access Token Lifespan" in Keycloak sein ("Realm Settings->Token").''
''Der Parameter <code>cookie-refresh</code> sollte kleiner als die "Access Token Lifespan" in Keycloak sein ("Realm Settings->Token").''
Installation starten:


<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
Zeile 151: Zeile 170:
   --namespace kubernetes-dashboard \
   --namespace kubernetes-dashboard \
   -f values.yaml
   -f values.yaml
</syntaxhighlight>''
</syntaxhighlight>


=== Dem Keycloak Benutzer die Admin Rolle zuweisen ===
===Dem Keycloak Benutzer die Admin Rolle zuweisen===
oidc-role.yaml
oidc-role.yaml
<syntaxhighlight lang="yaml">
<syntaxhighlight lang="yaml">
Zeile 170: Zeile 189:
</syntaxhighlight>'''''Hinweis:'''''
</syntaxhighlight>'''''Hinweis:'''''


Der Benutzername (subjects.name) entspricht dem <code>oidc-username-claim</code> aus der "kube-apiserver.yaml".
''Der Benutzername (subjects.name) entspricht dem'' <code>oidc-username-claim</code> ''aus der "kube-apiserver.yaml".''
<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
kubectl apply -f oidc-role.yaml
kubectl apply -f oidc-role.yaml
</syntaxhighlight>
</syntaxhighlight>


=== Ingress erstellen ===
===Ingress erstellen===
<syntaxhighlight lang="yaml" line="1">
<syntaxhighlight lang="yaml" line="1">
apiVersion: networking.k8s.io/v1
apiVersion: networking.k8s.io/v1
Zeile 185: Zeile 204:
     nginx.ingress.kubernetes.io/auth-signin: "https://$host/oauth2/start?rd=$escaped_request_uri"
     nginx.ingress.kubernetes.io/auth-signin: "https://$host/oauth2/start?rd=$escaped_request_uri"
     nginx.ingress.kubernetes.io/auth-response-headers: "authorization"
     nginx.ingress.kubernetes.io/auth-response-headers: "authorization"
   name: dashboard
   name: k8s-dashboard
   namespace: kubernetes-dashboard
   namespace: kubernetes-dashboard
spec:
spec:
Zeile 207: Zeile 226:
kind: Ingress
kind: Ingress
metadata:
metadata:
   name: dashboard-oidc
   name: k8s-dashboard-oauth
   namespace: oauth2-proxy
   namespace: oauth2-proxy
spec:
spec:
Zeile 225: Zeile 244:
         path: /oauth2
         path: /oauth2
         pathType: Prefix
         pathType: Prefix
</syntaxhighlight><syntaxhighlight lang="bash">
kubectl apply -f ingress.yaml
</syntaxhighlight>
</syntaxhighlight>

Aktuelle Version vom 7. Januar 2023, 23:52 Uhr

Testumgebung
OS AlmaLinux 8.7
Keycloak 20.0.2
Kubernetes 1.26.0
MetalLB 0.13.7
Ingress-Nginx 1.5.1
OAUTH2-Proxy 7.4.0

API-Server konfigurieren

vi /etc/kubernetes/manifests/kube-apiserver.yaml
spec:
  containers:
  - command:
    - kube-apiserver
... 
	- --oidc-issuer-url=https://<my.keycloak.server>/realms/<Realm-Name>
    - --oidc-client-id=k8s-cluster
    - --oidc-username-claim=email
    #- --oidc-ca-file=/path/to/oidc-ca.pem
	#- --oidc-username-prefix=-

Hinweis:

Wenn oidc-username-claim NICHT 'email' ist, wird standardmäßig die 'issuer-url' als Präfix vor den Benutzer gestellt (z.B. https://<my.keycloak.server>/realms/<Realm-Name>:<username>).

Um den Präfix zu deaktivieren muss bei oidc-username-prefix der Wert '-' angegeben werden.

Load Balancer installieren

'# MetalLB installieren / Aktiviert den Service Typ "LoadBalancer" der sonst nur in Cloud Umgebungen verfügbar ist

'# Bildet IPs aus dem Cluster in einen physischen Adressbereich des LANs

Ports in der Firewall öffnen

Sowohl auf dem Controller als auch den Worker-Nodes

firewall-cmd --permanent --add-port=7472/tcp
firewall-cmd --permanent --add-port=7946/tcp
firewall-cmd --permanent --add-port=7946/udp
firewall-cmd --reload

Installieren

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.7/config/manifests/metallb-native.yaml

address_pool.yaml

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: first-pool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.1.240-192.168.1.250

l2_advert.yaml

apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: example
  namespace: metallb-system
  #- first-pool

IPAddressPools können explizit ausgewählt werden. Ohne Angabe werden alle Pools dem L2Advertisement zugeordnet.

kubectl apply -f address_pool.yaml
kubectl apply -f l2_advert.yaml

Reverse Proxy installieren (ingress-nginx)

Reverse Proxy um mehrere Domains auf einer IP erreichbar zu machen.

values.yaml

controller:
  config:
    proxy-buffer-size: "8k"
    
    #extraArgs:
        #default-ssl-certificate: "default/my-tls-secret"

Hinweise:

Bei Keycloak kann es vorkommen, dass mehr als 4 kb Daten über den Header gesendet werden.

Wenn der Header zu groß wird, bekommt man einen Fehler (502).

Deswegen erhöhen wir diesen direkt während der Installation auf 8 kb.


Für TLS benötigen wir ein 'Secret" mit dem "Privat Key" und dem "Public Certificate" für die Domain, die später für das Dashboard genutzt werden soll.

Dieses kann man als Standard, direkt in der Config für Ingress-Nginx hinerlegen oder später im Ingress definieren.


Tipp:

Wenn man bei default-ssl-certificate ein Wildcard-Zertifikat (z.B. *.my-cluster.host) für den Cluster hinterlegt,

kann für jeden Ingress einfach eine Sub-Domain vergeben, die dann automatisch ein gültiges Zertifikat hat.


Installation starten:

helm upgrade --install ingress-nginx ingress-nginx \
  --repo https://kubernetes.github.io/ingress-nginx \
  --namespace ingress-nginx --create-namespace \
  -f values.yaml


OAUTH2 Proxy installieren

Authentifizierung gegen Keyclok und Token Weiterleitung an Dashboard

values.yaml

extraArgs:
  provider: keycloak-oidc
  #provider-display-name: OIDC Login
  #http-address: "0.0.0.0:4180"
  #skip-provider-button: true
  #skip-jwt-bearer-tokens: true
  #ssl-insecure-skip-verify: true
  #ssl-upstream-insecure-skip-verify: true
  #pass-access-token: true
  #pass-authorization-header: true
  set-authorization-header: true
  #set-xauthrequest: true
  client-id: XXX # Change XXX to your client_id
  client-secret: XXX # Change XXX to your client_secret
  cookie-secret: XXX # Generate with 'openssl rand -base64 32 | head -c 32 | base64'
  #cookie-secure: false
  #cookie-httponly: false
  cookie-refresh: 4m # Zeit nach der ein neuer Access Token über den Refresh Token bezogen wird
  oidc-issuer-url: "https://<my.keycloak.server>/realms/<Realm-Name>"
  redirect-url: "https://<my.dashboard.url>/oauth2/callback"
  #whitelist-domain: ["*"]
  #allowed-group: ["*"]
  #allowed-role: ["*"]
  #email-domain: ["*"]

Hinweis:

Der Parameter cookie-refresh sollte kleiner als die "Access Token Lifespan" in Keycloak sein ("Realm Settings->Token").


Installation starten:

helm upgrade --install oauth2-proxy oauth2-proxy \
  --repo https://oauth2-proxy.github.io/manifests \
  --namespace kubernetes-dashboard \
  -f values.yaml

Dem Keycloak Benutzer die Admin Rolle zuweisen

oidc-role.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: oidc-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: User
  name: user@keycloak.com
  namespace: kube-system

Hinweis:

Der Benutzername (subjects.name) entspricht dem oidc-username-claim aus der "kube-apiserver.yaml".

kubectl apply -f oidc-role.yaml

Ingress erstellen

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
    nginx.ingress.kubernetes.io/auth-url: "https://$host/oauth2/auth"
    nginx.ingress.kubernetes.io/auth-signin: "https://$host/oauth2/start?rd=$escaped_request_uri"
    nginx.ingress.kubernetes.io/auth-response-headers: "authorization"
  name: k8s-dashboard
  namespace: kubernetes-dashboard
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - my.dashboard.url
  rules:
  - host: my.dashboard.url
    http:
      paths:
      - backend:
          service:
            name: kubernetes-dashboard
            port:
              number: 443
        path: /
        pathType: Prefix
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: k8s-dashboard-oauth
  namespace: oauth2-proxy
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - my.dashboard.url
  rules:
  - host: my.dashboard.url
    http:
      paths:
      - backend:
          service:
            name: oauth2-proxy
            port:
              number: 80
        path: /oauth2
        pathType: Prefix
kubectl apply -f ingress.yaml