Tipps und Tricks von Kubernetes: Zugriff auf Entwickler-Websites

Wir setzen unsere Reihe von Artikeln fort, in denen erläutert wird, wie Wartung und Entwicklern bei ihrer täglichen Arbeit mit Kubernetes das Leben erleichtert werden können. Alle von ihnen stammen aus unserer Erfahrung bei der Lösung von Kundenproblemen und wurden im Laufe der Zeit verbessert, erheben jedoch keinen Anspruch auf Ideal - betrachten Sie sie eher als Ideen und Leerzeichen, schlagen Sie Ihre Lösungen und Verbesserungen in den Kommentaren vor.


Dieses Mal werden zwei Themen betrachtet, die bedingt mit einem Thema zusammenhängen: Benutzerzugriff auf die Entwicklungsumgebung.

1. Wie schließen wir Entwicklungskreise von unnötigen Benutzern?


Wir stehen oft vor der Aufgabe, den gesamten Entwicklungskreis (Dutzende / Hunderte von Anwendungen) hinter der grundlegenden Authentifizierung oder Whitelist zu schließen, damit Such-Bots oder nur sehr Drittanbieter nicht dorthin gelangen können.

Um den Zugriff einzuschränken, müssen normalerweise jeder Ingress und jede Anwendung separate grundlegende Authentifizierungsgeheimnisse erstellen. Ihre Verwaltung ist sehr problematisch, wenn Sie mit einem Dutzend Anwendungen tippen. Deshalb haben wir eine zentrale Zugangskontrolle organisiert.

Zu diesem Zweck wurde nginx mit einer Konfiguration dieses Typs erstellt:

location / { satisfy any; auth_basic "Authentication or whitelist!"; auth_basic_user_file /etc/nginx/htpasswd/htpasswd; allow 10.0.0.0/8; allow 175.28.12.2/32; deny all; try_files FAKE_NON_EXISTENT @return200; } location @return200 { return 200 Ok; } 

Weiter in den Ingresss der Anwendung fügen wir einfach die Anmerkung hinzu:

ingress.kubernetes.io/auth-url: "http://dev-auth.dev-auth-infra.svc.cluster.local"

Wenn Sie auf die Anwendung zugreifen, geht die Anforderung an den dev-auth , der prüft, ob die richtige Basisauthentifizierung eingegeben wurde oder der Client die Whitelist eingibt. Wenn eine der Bedingungen erfüllt ist, wird die Anfrage bestätigt und an den Antrag weitergeleitet.



Bei Verwendung eines solchen Dienstes reicht ein Repository aus, in dem eine Liste aller Zugriffe gespeichert ist und über das wir unser „Single Authorization Center“ bequem konfigurieren können. Die Verteilung auf neue Anwendungen erfolgt durch elementares Hinzufügen von Anmerkungen.

2. Wie bieten wir Zugriff auf Anwendungen in Kubernetes in einer Entwicklungsumgebung?


... sei es Redis, RabbitMQ, PostgreSQL oder Xdebugs Lieblings-PHP-Entwickler.

Sehr oft müssen wir bei der Übersetzung von Anwendungen in Kubernetes den Zugriff von außen und vollständig blockieren, um eine bessere Sicherheit zu gewährleisten. Und dann haben Entwickler, die es gewohnt sind, ihre IDE in die Datenbank oder in Xdebug zu verschieben, ernsthafte Schwierigkeiten.

Um dieses Problem zu lösen, verwenden wir ein VPN direkt im Kubernetes-Cluster. Das allgemeine Schema sieht so aus, dass bei der Verbindung mit einem VPN-Server, der in K8s ausgeführt wird, in der OpenVPN-Konfigurationsdatei die Adresse des DNS-Servers angegeben wird, der auch in K8s ausgeführt wird. OpenVPN konfiguriert das VPN so, dass beim Anfordern einer Ressource in Kubernetes zunächst der DNS-Server von Kubernetes redis.production.svc.cluster.local - beispielsweise hinter der Adresse des Dienstes redis.production.svc.cluster.local . DNS in Kubernetes löst es in 10.244.1.15 auf und Anforderungen für diese IP-Adresse gehen über OpenVPN direkt an den Kubernetes-Cluster.

Während des Betriebs dieser Lösung ist es uns gelungen, sie wiederholt zu erweitern. Insbesondere:

  1. Da wir kein einfaches und für unseren Fall angemessenes Admin-Panel für die Abrechnung des Zugriffs auf das VPN gefunden haben , mussten wir eine eigene einfache Schnittstelle erstellen - das offizielle Diagramm bietet nur die Möglichkeit, Konsolenbefehle zum Ausstellen von Zertifikaten zu starten.

    Das resultierende Admin-Panel (siehe auch Docker Hub ) sieht sehr asketisch aus:


    Sie können neue Benutzer erstellen oder alte Zertifikate widerrufen:


    Sie können auch die Konfiguration für diesen Client anzeigen:

  2. Wir haben eine Autorisierung in VPN hinzugefügt , die auf Benutzern in GitLab basiert , wobei das Kennwort überprüft wird und der Benutzer in GitLab aktiv ist. Dies ist in Fällen der Fall, in denen der Client Benutzer verwalten möchte, die nur auf der Basis von GitLab und ohne die Verwendung zusätzlicher Administratoren eine Verbindung zu dev VPN herstellen können. In gewissem Sinne stellt sich heraus, dass es sich um "SSO für die Armen" handelt. Als Grundlage nahmen sie das bereits erwähnte fertige Diagramm .

    Zu diesem Zweck haben wir ein Python-Skript geschrieben, das beim Verbinden eines Benutzers mit OpenVPN unter Verwendung des Benutzernamens und des Kennworts den Hash in der GitLab-Datenbank vergleicht und seinen Status überprüft (ob er aktiv ist).



    Hier ist das Skript selbst:

     #!/usr/bin/env python3 # pip3 install psycopg2-binary bcrypt import bcrypt import sys import os import psycopg2 import yaml with open("/etc/openvpn/setup/config.yaml", 'r') as ymlfile: cfg = yaml.load(ymlfile) def get_user_info(username=''): try: connect_str = "dbname=%s user=%s host=%s password=%s" % (cfg['db'], cfg['user'], cfg['host'], cfg['pass']) # use our connection values to establish a connection conn = psycopg2.connect(connect_str) # create a psycopg2 cursor that can execute queries cursor = conn.cursor() # create a new table with a single column called "name" cursor.execute("""SELECT encrypted_password,state FROM users WHERE username='%s';""" % username) # run a SELECT statement - no data in there, but we can try it rows = cursor.fetchall() print(rows) return(rows[0]) except Exception as e: print("Uh oh, can't connect. Invalid dbname, user or password?") print(e) def check_user_auth(): username = os.environ['username'] password = bytes(os.environ['password'], 'utf-8') # hashed = bcrypt.hashpw(password, bcrypt.gensalt()) user_info = get_user_info(username=username) user_encrypted_password = bytes(user_info[0], 'utf-8') user_state = True if user_info[1] == 'active' else False if bcrypt.checkpw(password, user_encrypted_password) and user_state: print("It matches!") sys.exit(0) else: print("It does not match :(") sys.exit(1) def main(): check_user_auth() if __name__ == '__main__': main() 

    Und in der OpenVPN-Konfiguration geben Sie einfach Folgendes an:

    auth-user-pass-verify /etc/openvpn/auth-user.py via-env
    script-security 3
    client-cert-not-required


    Wenn ein Mitarbeiter den Client verlassen hat, hat er ihn einfach in GitLab deaktiviert. Danach kann er keine Verbindung zum VPN herstellen.

Anstelle einer Schlussfolgerung


In Fortsetzung einer Reihe von Artikeln mit praktischen Flant-Rezepten für den Betrieb von Kubernetes werde ich Themen wie das Hervorheben einzelner Knoten für bestimmte Aufgaben (warum und wie?) Und das Konfigurieren von Diensten wie php-fpm / gunicorn, die in Containern für schwere Lasten ausgeführt werden, behandeln. Abonnieren Sie unseren Blog, um keine Updates zu verpassen!

PS


Andere aus dem K8s Tipps & Tricks-Zyklus:


Lesen Sie auch in unserem Blog:

Source: https://habr.com/ru/post/de427745/


All Articles