Kapitel 4. Sicherheit

Diese Arbeit wurde mithilfe von KI übersetzt. Wir freuen uns über dein Feedback und deine Kommentare: translation-feedback@oreilly.com

Sicherheit ist ein unglaublich weites Feld und kann definitiv mehrere Bücher für sich allein beanspruchen. Tatsächlich gibt es bereits viele gute Bücher über Kubernetes-Sicherheit. Der Betrieb von OpenShift-Clustern kann jedoch nicht ohne Sicherheitsaspekte erfolgen. Die Kosten von Fehlern bei sicherheitsrelevanten Aufgaben sind höher als in den meisten anderen Bereichen des Clusterbetriebs. Die jüngsten Datenschutzverletzungen und Hacks haben Unternehmen Hundertevon Millionen Dollar gekostet, und das selbst ohne potenziell noch nicht aufgedeckte Probleme.

Dieses Kapitel befasst sich mit den grundlegenden Konzepten zur Sicherung deines Clusters und deiner Workloads. Dabei bleibt es abstrakter als andere Kapitel und konzentriert sich mehr auf Konzepte als auf die Implementierung.

Cluster Zugang

Wenn du deinen Cluster eingerichtet hast, hast du mit dem kubeadmin-Konto Zugriff darauf, aber das ist nicht sehr sicher und skaliert auch nicht wirklich, denn du müsstest jedem, der den Cluster nutzen will, das Passwort geben und ihn zum Admin machen. Dafür gibt es verschiedene Methoden, angefangen bei der einfachsten: einen Benutzer von Hand über die CLI anlegen. Auch das lässt sich nicht gut skalieren. Deshalb bietet OpenShift die Möglichkeit, Benutzer mit Hilfe von Identitätsprovidern (IdP) automatisch zu provisionieren. Derzeit können die folgenden Identitätsanbieter mit OpenShift verwendet werden:

  • HTPasswd
  • Keystone
  • LDAP
  • Grundlegende Authentifizierung
  • Kopfzeile anfordern
  • GitHub
  • GitLab
  • Google
  • OpenID Connect

Die Umsetzung kann ein wenig variieren, aber im Allgemeinen sind die Schritte:

  • Oauth-App mit Identity Provider erstellen

  • Client-Geheimnis zu OpenShift hinzufügen

  • Client-ID zu OpenShift hinzufügen

  • Füge optional eine Zertifizierungsstelle (CA) für deine IdP-Instanz zu OpenShift hinzu

Nachdem du die Oauth-App mit dem Identitätsanbieter deiner Wahl erstellt hast, werden dir die Client ID und Client Secret angezeigt. Normalerweise kannst du das Geheimnis nicht noch einmal sehen, also solltest du es in einem Passwortspeicher speichern, sonst musst du es später neu generieren.

Jetzt musst du die Informationen, die du hast, in OpenShift-Objekten ablegen. Das Client Secret wird mit dem folgenden Befehl in ein Secret verwandelt:

$ oc create secret generic github-client-secret \
--from-literal=clientSecret=superSecretClientSecret -n openshift-config
secret/github-client-secret created

Jetzt, wo OpenShift darauf zugreifen kann, kannst du die erforderliche Custom Resource erstellen, die in etwa wie in Beispiel 4-1 aussieht. Du musst deine Kunden-ID sowie die Organisation und die Teams angeben. So stellst du sicher, dass nur Benutzer, die Teil dieser Organisationen und Teams sind, Zugang haben.

Beispiel 4-1. Oauth-Konfiguration
apiVersion: config.openshift.io/v1
kind: OAuth
metadata:
  name: cluster
spec:
  identityProviders:
  - name: githubidp
    mappingMethod: claim
    type: GitHub
    github:
      ca:
        name: ca-config-map
      clientID: 1234ClientID5678
      clientSecret:
        name: github-client-secret
      hostname: ...
      organizations:
      - myorganization
      teams:
      - myorganization1/team-a

Ein anderer interessanter und wichtiger Wert ist mappingMethod. Er legt fest, wie Benutzer im Cluster angelegt werden. Die Optionen sind hier:

  • Anspruch

  • Nachschlagen

  • erzeugen

  • hinzufügen

Nicht alle von ihnen sind für alle Identitätsanbieter verfügbar, aber im Fall von GitHub als Identitätsanbieter sind sie es.

Logischerweise tun sie alle etwas anderes, und claim ist für die meisten Nutzer die gebräuchlichste Variante. Wenn die Zuordnung auf claim gesetzt wird, versucht OpenShift, einen neuen Benutzer auf dem Cluster zu erstellen, wenn sich jemand zum ersten Mal über den Identitätsanbieter anmeldet, und schlägt fehl, wenn es bereits einen Benutzer auf diesem Cluster gibt, der sich über eine andere Methode authentifiziert hat.

Die Methode lookup prüft, ob ein bestimmter Benutzer für die Identität, mit der er sich anzumelden versucht, existiert. Dies erfordert einen zusätzlichen Prozess, da die Benutzer nicht automatisch in den Clustern bereitgestellt werden.

Die etwas großzügigere Alternative zum Claim ist generate. Sie funktioniert ähnlich wie claim, aber wenn ein bestimmter Benutzer bereits mit einer anderen Identität im Cluster existiert, versucht OpenShift, einen neuen Benutzer bereitzustellen. Wenn sich beispielsweise manuel über den ebenfalls bereitgestellten Google-Identitätsprovider angemeldet hat und nun versucht, sich über GitHub einzuloggen, versucht generate mappingMethods, einen neuen Benutzer zu erstellen: manuel2 oder ähnlich.

Wenn du das vermeiden willst, musst du die Methode add verwenden. Hier fügt OpenShift die neue Identität zum bestehenden Benutzer hinzu.

Rollenbasierte Zugriffskontrolle

Neben brauchst du für den Zugang zu deinem Cluster auch bestimmte Rechte, wenn du Aktionen auf dem Cluster durchführen willst. Kubernetes verfügt über das Konzept der rollenbasierten Zugriffskontrolle (RBAC), das auch von OpenShift verwendet wird.

In den folgenden Abschnitten werden die Feinheiten von RBAC genauer erläutert.

Rollen und ClusterRollen

Eine Rolle ist ein bestimmter Satz von Berechtigungen. Die Berechtigungen fangen bei Null an und summieren sich dann auf. Es wird nichts explizit verweigert, vor allem, weil eine Verweigerung bestimmter Rechte nur dann erforderlich ist, wenn sie zuvor gewährt wurden, was nicht passieren sollte, da du mit null Rechten beginnst. Es ist daher entscheidend, das Prinzip des geringsten Privilegs zu befolgen: Vergebe nur die Rechte, die unbedingt erforderlich sind.

Um bestimmte Rechte zu vergeben, musst du verstehen, wie OpenShift-Ressourcen funktionieren: Jede API hat Ressourcen, auf denen du bestimmte Aktionen ausführen kannst. Diese Aktionen sind als Verben definiert. Das folgende Beispiel zeigt eine Interaktion mit der Core-API unter Verwendung des Verbs GET für alle Ressourcen des Typs pod:

$ oc get pods

Alle Interaktionen mit einer OpenShift-Ressource folgen diesem Konzept, und obwohl du OpenShift mit Custom Resource Definitions erweitern und dadurch neue Ressourcen und APIs hinzufügen kannst, ist die Liste der Verben auf die folgenden festgelegt:

  • GET

  • CREATE

  • ANMELDEN

  • UPDATE

  • PATCH

  • DELETE

  • ANTRAG

  • LIST

  • WATCH

  • DELETECOLLECTION

Wenn du anfängst, eine Rolle zu erstellen, musst du dich fragen: "Was will ich mit welcher Ressource für welche API machen?" Von dort aus erstellst du eine Rollendefinition. Das folgende Beispiel zeigt eine Rollendefinition, die den Beispielbefehl oc get pods erlauben würde:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
  resources: ["pods"]
  verbs: ["get", "list"]

Du hast vielleicht bemerkt, dass es neben dem reinen GET-Verb auch die LIST-Berechtigung gibt. Wenn du das weglassen würdest, könntest du nur einen bestimmten Pod abrufen, den du bereits kennst, während der Befehl oc get pods alle Pods auflisten muss, um sie zu bekommen.

Du kannst auch sehen, dass es einen namespace Parameter gibt. Das ist der Unterschied zwischen einer Role und einer ClusterRole: Rollen sind mit einem Namensraum versehen, so dass die vorangegangene Definition nur die Aktionen im Namensraum default erlaubt. Das folgende Beispiel für eine ClusterRole gibt die gleichen Berechtigungen, aber für den gesamten Cluster:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pod-reader-cluster
rules:
- apiGroups: [""] # "" indicates the core API group
  resources: ["pods"]
  verbs: ["get", "list"]

Neben der Aufhebung der Namensraumbeschränkung sind ClusterRoles auch das einzige Mittel, um Zugriff auf clusterweite Ressourcen, wie z.B. Knoten, zu gewähren. Das bedeutet, dass du keine Rolle verwenden kannst, um Zugriff auf clusterweite Ressourcen zu gewähren, sondern stattdessen eine ClusterRole verwendenmusst.

RoleBindings und ClusterRoleBindings

du bestimmte Rechte definiert hast, die du brauchst oder haben möchtest, brauchst du eine Möglichkeit, sie einem Benutzer oder einem Systemkonto zuzuweisen. Das ist die Aufgabe von RoleBindings. Eine RoleBinding hat eine Reihe von Subjekten, nämlich die Benutzer. Du kannst dir das so vorstellen: "Ihnen sollen diese Berechtigungen zugewiesen werden." Der andere Teil ist roleRef, die Rolle, die du an die Subjekte binden willst. Im folgenden Beispiel wird unsere Rolle pod-reader dem Benutzer Manuel zugewiesen:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: User
  name: Manuel
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

Nach der Anwendung des Vorstehenden würde Manuel die Berechtigung erhalten, Pods im Standard-Namensraum abzurufen und aufzulisten.

Du kannst die gleiche Rolle mehreren Benutzern im selben RoleBinding zuweisen. Im nächsten Beispiel weisen wir die Rolle pod-reader den Benutzern Manuel und Rick zu:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: User
  name: Manuel
  apiGroup: rbac.authorization.k8s.io
- kind: User
  name: Rick
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

Beachte, dass bei der Namensvariable zwischen Groß- und Kleinschreibung unterschieden wird. Das bedeutet, dass Manuel nicht derselbe Benutzer ist wie manuel und dass man leicht darüber stolpern kann, weil eine IDE dies normalerweise nicht als Problem erkennt.

Das Äquivalent zu einer RoleBinding ist die ClusterRoleBinding. Sie ermöglicht es, den Zugriff auf Ressourcen clusterweit zu gewähren. Im folgenden Beispiel können Rick und Manuel alle Pods in allen Namensräumen abrufen und auflisten:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: read-pods-cluster
subjects:
- kind: User
  name: Manuel
  apiGroup: rbac.authorization.k8s.io
- kind: User
  name: Rick
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader-cluster
  apiGroup: rbac.authorization.k8s.io
Warnung

Jede Berechtigung in deinem OpenShift-Cluster ist auf diese Weise eingerichtet, und du solltest dich davor hüten, zu viele Berechtigungen zu erteilen, auch wenn es irgendwann umständlich werden könnte. Das gilt vor allem dann, wenn du anfängst, Workloads auf deinem Cluster zu platzieren und ServiceAccounts verwenden musst.

CLI

Die Kommandozeilenschnittstelle oc gibt dir die Möglichkeit, einige der oben genannten Aktionen ad hoc auszuführen und einen Überblick über die Rollen und Bindungen zu erhalten, die derzeit in deinem Cluster existieren.

Um zu überprüfen, welche Rollen in deinem aktuellen Namensraum existieren und welche Rechte sie gewähren, führe den folgenden Befehl aus:

$ oc describe role.rbac
Name:         prometheus-k8s
Labels:       app.kubernetes.io/component=prometheus
              app.kubernetes.io/instance=k8s
              app.kubernetes.io/name=prometheus
              app.kubernetes.io/part-of=openshift-monitoring
              app.kubernetes.io/version=2.32.1
Annotations:  <none>
PolicyRule:
Resources                    Non-Resource URLs  Resource Names  Verbs
 ---------                    -----------------  --------------  -----
endpoints                    []                 []              [get list watch]
pods                         []                 []              [get list watch]
services                     []                 []              [get list watch]
ingresses.extensions         []                 []              [get list watch]
ingresses.networking.k8s.io  []                 []              [get list watch]

Derselbe Befehl funktioniert auch für ClusterRoles. Mach dich nur darauf gefasst, dass du angesichts der vielen beweglichen Teile, die sich in einem OpenShift-Cluster befinden, viel mehr ausgeben musst.

Du kannst auch herausfinden, welche RoleBindings sich im aktuellen Namensraum befinden, indem du den folgenden Befehl verwendest:

$ oc describe rolebindings.rbac
Name:         prometheus-k8s
Labels:       app.kubernetes.io/component=prometheus
              app.kubernetes.io/instance=k8s
              app.kubernetes.io/name=prometheus
              app.kubernetes.io/part-of=openshift-monitoring
              app.kubernetes.io/version=2.32.1
Annotations:  <none>
Role:
  Kind:  Role
  Name:  prometheus-k8s
Subjects:
  Kind            Name            Namespace
  ----            ----            ---------
  ServiceAccount  prometheus-k8s  openshift-monitoring

Neben der reinen Anzeige des bestehenden Zustands eines Clusters kannst du die CLI auch verwenden, um Änderungen vorzunehmen. Du kannst zum Beispiel Manuel zu und pod-reader hinzufügen:

$ oc adm policy add-role-to-user pod-reader Manuel -n default
clusterrole.rbac.authorization.k8s.io/pod-reader added: "Manuel"

ServiceAccounts

Wenn du bestimmte Aufgaben zu automatisieren hast, möchtest du vielleicht ein Systemkonto statt eines tatsächlichen Benutzers und dessen Token verwenden. ServiceAccounts gehorchen genau denselben Regeln für Berechtigungen wie jeder andere Benutzer im Cluster, daher ist es hier wichtig zu wissen, wie man einen ServiceAccount erstellt und ihn dann verwendet.

Um ein Dienstkonto zu erstellen, führe den folgenden Befehl aus:

$ oc create sa my-bot
serviceaccount/my-bot created

Du kannst auch einen ServiceAccount und seine Informationen abrufen:

$ oc get sa my-bot -o yaml
apiVersion: v1
imagePullSecrets:
- name: my-bot-dockercfg-bpf5n
kind: ServiceAccount
metadata:
  creationTimestamp: "2022-08-03T13:57:30Z"
  name: my-bot
  namespace: default
  resourceVersion: "25019623"
  uid: f718f7be-abce-47f0-a43b-0dc02b044bcf
secrets:
- name: my-bot-token-zwskx
- name: my-bot-dockercfg-bpf5n

Jetzt kannst du ihm beliebige Berechtigungen hinzufügen. Im folgenden Beispiel fügen wir dem Bot-Konto die Rolle pod-reader hinzu:

$ oc policy add-role-to-user pod-reader system:serviceaccount:default:my-bot
ClusterRole.rbac.authorization.k8s.io/pod-reader added:

"system:serviceaccount:default:my-bot"

Jetzt, wo das my-bot-Konto etwas kann, kannst du es auch von außerhalb des Clusters verwenden. In diesem einfachen Beispiel könnten wir es im folgenden Befehl verwenden, um alle Pods im Standard-Namensraum aufzulisten, ohne selbst authentifiziert zu sein:

$ export TOKEN=$(oc sa get-token my-bot)

$ oc get pods -n default --token $TOKEN
NAMESPACE NAME
grafana   grafana-deployment-787fd449f4-z5vkf
grafana   grafana-operator-controller-manager-5b5d45b9bd-wrnsv

$ oc whoami --token $TOKEN
system:serviceaccount:default:my-bot

Der letzte Befehl wird nicht benötigt, macht aber deutlich, dass der Befehl als ServiceAccount ausgeführt wurde.

Die Anwendungsfälle für ServiceAccounts sind breit gefächert, aber im Allgemeinen solltest du ServiceAccounts verwenden, wenn du eine Aktion von außerhalb des Clusters auf automatisierte Weise durchführen musst.

Für die Bereitstellung kann jede App ihren eigenen ServiceAccount haben, dessen Rechte nur auf das beschränkt sind, was für die Bereitstellung benötigt wird. So gibt es kein Szenario, in dem ein einziger kompromittierter Token oder Account die gesamte Plattform auf einmal beeinträchtigen kann. Diese Trennung bietet einen zusätzlichen rudimentären Schutz, den du in deiner gesamten Infrastruktur aktiviert haben solltest. Du würdest einem Benutzer keine Pseudorechte auf einem Linux-Host gewähren, nur um eine Bereitstellung zu erstellen, oder?

Nachdem du Zugang zu einem Cluster verschafft und anschließend einige Rechte zugewiesen hast, ist es nun an der Zeit, den Standardbenutzer kubeadmin zu entfernen. Du solltest dich nicht mehr alskubeadminanmelden. Das Passwort ist zwar ziemlich komplex und daher nicht leicht zu erraten oder zu erzwingen, aber ein ungenutztes Admin-Konto ist definitiv nicht das, was du willst. Bevor du das tust, überprüfe noch einmal die folgenden Punkte:

  • Du hast einen Identity Provider konfiguriert

  • Du hast einem Benutzer die Rolle des Cluster-Administrators zugewiesen

Beides ist wichtig, da du dich sonst selbst vom Admin-Zugang aussperrst.

Wenn du beides getan hast, kannst du dich jetzt als Benutzer mit der Rolle cluster-admin anmelden und den folgenden Befehl ausführen:

$ oc delete secrets kubeadmin -n kube-system

Bedrohungsmodellierung

Bedrohungsmodellierung bedeutet, dass du dir potenzielle Bedrohungen für dein System ansiehst und deren Wahrscheinlichkeit und Auswirkungen abschätzt. Während dein Sicherheitsteam damit beschäftigt ist, ist es gut, über die Risiken für deine Plattform nachzudenken und zu bewerten, wie du dich am besten vor diesen Risiken schützen kannst.

Stell dir zum Einstieg folgendes Szenario vor: Jemand schreibt alle seine Passwörter auf einen kleinen Notizblock in seiner Wohnung. Ist das gut oder schlecht?

Du würdest vielleicht schnell sagen, dass sie einen sicheren Passwortspeicher oder etwas Ähnliches verwenden sollten, aber ist es ein realistisches Szenario, dass jemand in ihre Wohnung einbricht und den Notizblock stiehlt, um an ihre Passwörter zu kommen? Für den Durchschnittsbürger, nein. Das ist kein wirkliches Problem. Ja, es gibt bessere Methoden, aber im Allgemeinen ist ein Notizblock in Ordnung und auf jeden Fall besser, als überall das gleiche Passwort zu verwenden.

Aber wenn die Person, die einen Notizblock für alle Passwörter benutzt, der CEO eines Fortune-500-Unternehmens ist, ist das etwas anderes, und es besteht tatsächlich eine gewisse Wahrscheinlichkeit, dass jemand versucht, ihren Passwort-Notizblock zu stehlen.

Das Gleiche gilt für deinen OpenShift-Cluster, und das solltest du im Hinterkopf behalten, wenn du deinen Cluster härtest. Wenn du CodeReadContainers auf deinem Laptop verwendest, um OpenShift zu lernen und zu verstehen, ist es wahrscheinlich in Ordnung, einfach den Benutzer kubeadmin zu verwenden. Wenn du einen Produktionscluster für dein Unternehmen betreibst, der dem Internet ausgesetzt ist, willst du ihn wahrscheinlich wie in den vorangegangenen Abschnitten beschrieben mit Zugriffskontrollen und RBAC-Regeln absichern.

Bedrohungsmodelle im Kopf zu haben, bevor du etwas tust, macht dir und deinem Sicherheitsteam das Leben leichter, da du erklären kannst, was du getan hast, um deine Infrastruktur zu schützen, und warum du bestimmte andere Maßnahmen vielleicht nicht ergriffen hast.

Arbeitsbelastungen

Die Sperrung deines Clusters ist eine Sache, aber irgendwann willst du deinen Cluster auch nutzen, und das ist der Zeitpunkt, an dem du anfängst, Workloads zu verteilen, die ebenfalls einige Sicherheitsüberlegungen erfordern. Du willst es einem potenziellen Angreifer so schwer wie möglich machen, einen bestimmten Workload zu kompromittieren, und es ihm noch schwerer machen, von dort aus weiterzugehen. Das bedeutet, dass selbst ein einziger kompromittierter Workload nicht zu einer Kompromittierung deines gesamten Clusters führen sollte.

Eine gängige Art von Workloads, die bereitgestellt werden, sind Webservices und alles andere, was über eine Route zugänglich ist, und wenn es sich nicht um kundenorientierte und für die Welt offene Workloads handelt, solltest du diese auf jeden Fall sperren. Der einfachste Weg, dies zu tun, ist die Nutzung der nativen Funktionen von OpenShift. Mit OpenShift kannst du einen Oauth-Proxy vor deiner Anwendung einrichten und so das RBAC-Berechtigungsmodell nutzen, das du bereits hast, um Zugriffsrechte für deinen exponierten Dienst zu definieren.

Im folgenden Beispiel stellst du ein einfaches Spiel bereit. Da es sich aber noch um einen Prototyp handelt, sollen nur die Nutzer, die daran arbeiten, darauf zugreifen können.

Zuerst brauchst du einen neuen Namensraum:

$ oc create namespace s3e
namespace/s3e created

$ oc project s3e
Now using project "s3e" on server "https://api.crc.testing:6443".

Jetzt, wo du einen Platz für dein Spiel hast, ist es an der Zeit, mit dem Proxy zu beginnen. Du brauchst eine ServiceAccount, damit er benutzt werden kann:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: proxy
  annotations:
    serviceaccounts.openshift.io/oauth-redirectreference.primary: >
      '{"kind":"OAuthRedirectReference",
      "apiVersion":"v1",
      "reference":{"kind":"Route","name":"proxy"}}'

Als Nächstes bereitest du deine App-Bereitstellung vor, die den Proxy enthält:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: proxy
spec:
  replicas: 1
  selector:
    matchLabels:
      app: proxy
  template:
    metadata:
      labels:
        app: proxy
    spec:
      serviceAccountName: proxy
      containers:
      - name: oauth-proxy
        image: openshift/oauth-proxy:latest
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8443
          name: public
        args:
        - --https-address=:8443
        - --provider=openshift
        - --openshift-service-account=proxy
        - --upstream=http://localhost:8080
        - --tls-cert=/etc/tls/private/tls.crt
        - --tls-key=/etc/tls/private/tls.key
        - --cookie-secret=SECRET
        volumeMounts:
        - mountPath: /etc/tls/private
          name: proxy-tls
      - name: app
        image: quay.io/operatingopenshift/s3e-game:latest
      volumes:
      - name: proxy-tls
        secret:
          secretName: proxy-tls

Wenn du ein anderes Bild verwendest, stelle sicher, dass die Variable upstream immer noch richtig funktioniert. In diesem Fall meldet sich das Spiel auf Port 8080, also ist das völlig in Ordnung.

Du kannst den Proxy weiter konfigurieren, indem du das Argument --openshift-sar= verwendest, um ihn speziell auf Basis von RBAC-Berechtigungen zu sperren. Wenn du dieses Argument nicht setzt, wie in diesem Fall, kann jeder Benutzer, der sich bei OpenShift anmelden kann, auch auf alles zugreifen, was sich hinter dem Proxy befindet, was für dieses Szenario vernünftig erscheint.

Von hier an brauchst du auch einen Dienst und eine Route:

apiVersion: v1
kind: Route
metadata:
  name: proxy
spec:
  to:
    kind: Service
    name: proxy
  tls:
    termination: Reencrypt
apiVersion: v1
kind: Service
metadata:
  name: proxy
  annotations:
    service.alpha.openshift.io/serving-cert-secret-name: proxy-tls
spec:
  ports:
  - name: proxy
    port: 443
    targetPort: 8443
  selector:
    app: proxy

Der Selektor gibt hier an, dass der Proxy das Backend ist, an das der Datenverkehr gesendet wird.

Du kannst alle obigen Angaben in einer einzigen YAML-Datei zusammenfassen und sie dann wie folgt im Cluster verteilen:

kind: List
apiVersion: v1
items:
# Create a proxy service account and ensure it will use the route "proxy"
- apiVersion: v1
  kind: ServiceAccount
  metadata:
    name: proxy
    annotations:
      serviceaccounts.openshift.io/oauth-redirectreference.primary: >
        '{"kind":"OAuthRedirectReference",
        "apiVersion":"v1",
        "reference":{"kind":"Route","name":"proxy"}}'
# Create a secure connection to the proxy via a route
- apiVersion: v1
  kind: Route
  metadata:
    name: proxy
  spec:
    to:
      kind: Service
      name: proxy
    tls:
      termination: Reencrypt
- apiVersion: v1
  kind: Service
  metadata:
    name: proxy
    annotations:
      service.alpha.openshift.io/serving-cert-secret-name: proxy-tls
  spec:
    ports:
    - name: proxy
      port: 443
      targetPort: 8443
    selector:
      app: proxy
# Launch a proxy as a sidecar
- apiVersion: apps/v1
  kind: Deployment
  metadata:
    name: proxy
  spec:
    replicas: 1
    selector:
      matchLabels:
        app: proxy
    template:
      metadata:
        labels:
          app: proxy
      spec:
        serviceAccountName: proxy
        containers:
        - name: oauth-proxy
          image: openshift/oauth-proxy:latest
          imagePullPolicy: IfNotPresent
          ports:
          - containerPort: 8443
            name: public
          args:
          - --https-address=:8443
          - --provider=openshift
          - --openshift-service-account=proxy
          - --upstream=http://localhost:8080
          - --tls-cert=/etc/tls/private/tls.crt
          - --tls-key=/etc/tls/private/tls.key
          - --cookie-secret=SECRET
          volumeMounts:
          - mountPath: /etc/tls/private
            name: proxy-tls

        - name: app
          image: quay.io/operatingopenshift/s3e-game:latest
        volumes:
        - name: proxy-tls
          secret:
            secretName: proxy-tls

Um die Konfiguration anzuwenden, führe den folgenden Befehl aus:

$ oc apply -f deploy-snake-proxy.yaml
serviceaccount/proxy created
route.route.openshift.io/proxy created
service/proxy created
deployment.apps/proxy created

Du kannst jetzt die URL der Route über oc get route wie folgt abrufen:

$ oc get route -o json | jq .items[].spec.host
"proxy-s3e.apps-crc.testing"

Wenn du sie in deinem Browser aufrufst, wird dir jetzt ein Anmeldebildschirm angezeigt. Hier siehst du auch, dass du deine App über einen Oauth-Proxy gesichert hast.

Zusammenfassung

In diesem Kapitel haben wir bewährte Methoden und Überlegungen zur Sicherheit besprochen, die du bei der Planung und dem Betrieb deines OpenShift-Clusters anstellen solltest. Diese geben dir einen Ausgangspunkt. Da sich jedoch sowohl die Cluster als auch die Angreifer ständig weiterentwickeln, ist es von großer Bedeutung, die von dir unternommenen Schritte zu überprüfen.

Get Betrieb von OpenShift now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.