Frage Postgres-Rollen-Best-Practice-Implementierung


Leute,

Ich könnte Ihre Hilfe nutzen, um mein Design für Benutzerzugriffskontrollen von Postgres besser und besser auf Best Practices abzustimmen. Ich helfe bei der Einführung eines kleinen Postgres-Servers, aber ich bin kein DB-Administrator, daher weiß ich gerade genug, um gefährlich zu sein.

Es gibt einen Server mit einer Installation von Postgres v9.2. Diese Installation hostet mehrere Datenbanken, von denen jede einen anderen "Kunden" bedient. Mit anderen Worten, customer1 wird nicht, sollte nicht Datenbank2 verwenden und so weiter. Während des normalen Betriebs werden die Datenbanken von einer übereinstimmenden Instanz von CakePHP abgerufen, die sich alle auf demselben Server wie Postgres befindet. Während es bei dieser Bereitstellung möglicherweise Optimierungen gibt, interessiere ich mich hauptsächlich für Psql-Rollen.

Basierend auf dem, was ich gelesen habe, scheinen drei Arten von Rollen sinnvoll zu sein:

  • Superuser postgres mit nicht standardmäßigen Passwort
  • Eine Administratorrolle, die keine Superuser-Berechtigungen für die routinemäßige Wartung, Datenbankerstellung, Sicherung und Wiederherstellung besitzt. Sollte alles mit allen Kundendatenbanken machen können.
  • Benutzerrollen mit der Möglichkeit, CRUD in ihrer jeweiligen Datenbank zu verwenden. Mehr Rechte an ihrer eigenen Datenbank könnten toleriert werden, wenn sie die Implementierung bereinigt.

Die Umsetzung dieses Designs ist, wo ich viel weniger zuversichtlich bin. Ownership von DB gegen Tisch und gut, wer von wem etwas matschig erben soll. Unten sind meine Datenbanken und meine Benutzer. Reicht das zur Auswertung der Implementierung aus?

     Role name |                   Attributes                   |     Member of     
    -----------+------------------------------------------------+-------------------
     admin     | Create role, Create DB                         | {user1, user2}
     postgres  | Superuser, Create role, Create DB              | {}
     user1     |                                                | {}
     user2     |                                                | {}

    postgres=# \l
                                 List of databases
       Name    |  Owner   | Encoding | Collate | Ctype |   Access privileges   
    -----------+----------+----------+---------+-------+-----------------------
     admin     | postgres | UTF8     | en_US   | en_US | =Tc/postgres         +
               |          |          |         |       | postgres=CTc/postgres+
               |          |          |         |       | admin=CTc/postgres
     postgres  | postgres | UTF8     | en_US   | en_US | 
     template0 | postgres | UTF8     | en_US   | en_US | =c/postgres          +
               |          |          |         |       | postgres=CTc/postgres
     template1 | postgres | UTF8     | en_US   | en_US | =c/postgres          +
               |          |          |         |       | postgres=CTc/postgres
     user1     | admin    | UTF8     | en_US   | en_US | =Tc/admin            +
               |          |          |         |       | admin=CTc/admin      +
               |          |          |         |       | user1=CTc/admin
     user2     | admin    | UTF8     | en_US   | en_US | =Tc/admin            +
               |          |          |         |       | admin=CTc/admin      +
               |          |          |         |       | user2=CTc/admin

Um externe Verbindungen und Passwörter im Klartext zu verhindern, ist pg_hba.conf wie folgt:

local   all             all                                     md5
host    all             all             127.0.0.1/32            md5
host    all             all             ::1/128                 md5

19
2018-03-02 03:44


Ursprung


Nach meiner Erfahrung ist die beste Trennung, die auch eine Menge anderer Vorteile bringt, separate PostGreSQL-Cluster (z. B. Services) für jeden Kunden zu betreiben. Dies ist, was wir derzeit für eine große Produktionsumgebung tun, und ich würde es nicht anders machen, wenn die Anzahl der DBs nicht wirklich groß würde und jeder von ihnen wirklich klein wäre. Natürlich muss die Anwendung auch wissen, wie eine Verbindung zu einer anderen Datenquelle für jeden Mandanten (Kunden) hergestellt wird. - Florin Asăvoaie
Neben @ FlorinAsăvoaie seine Bemerkung. Sollte nicht jede Datenbank einen eigenen Besitzer und Benutzer haben? Dies würde es einfacher machen, bestimmte Benutzer zu Wartungszwecken in einen Passwortspeicher zu setzen. - hspaans


Antworten:


Ich weiß, dass dies eine alte Frage ist, aber ich werde versuchen, sie auch jetzt zu beantworten, da ich dazu einige Nachforschungen anstellen kann.

Was Sie versuchen zu tun, heißt Mandantenfähigkeit auf Datenbankebene. Dies kann auf zwei Arten erreicht werden:

  1. In einem einzelnen Datenbank-Cluster, so wie das OP es beschreibt, wäre meine persönliche Entscheidung jedoch:

    • postgres-Benutzer verwendet die Peer-Authentifizierung und darf keine Kennwortverbindungen verwenden. MD5-Authentifizierung ist meiner Meinung nach eine schlechte Übung. Wenn Sie Probleme mit der Datenbankkonsistenz oder ähnlichen Problemen haben, können Sie sich dennoch anmelden, wenn Sie Postgren Peer-Auth verwenden.
    • Jeder Kunde sollte seine eigenen bekommen Schema und keine Datenbank. Dafür gibt es mehrere Gründe:
      • Der Besitz der gesamten Datenbank würde viele Privilegien gewähren.
      • Der Besitz nur bestimmter Tabellen würde Probleme für Entwickler mit sich bringen und würde immer erfordern, dass Administratoren aufgefordert werden, Berechtigungen und andere Dinge hinzuzufügen.
      • Als solche würde jeder von ihnen in einem normalen Setup Zugriff bekommen, um Dinge innerhalb ihres Schemas zu erstellen, einschließlich Tabellen, Ansichten, Auslösern usw.
      • Alle verwenden die gleiche Verbindungszeichenfolge außer dem Benutzernamen. Wenn Sie in Postgres ein Schema mit dem Namen Ihres Benutzers haben, befindet es sich automatisch in Ihrem Suchpfad.
    • Ich würde mich dafür entscheiden, keinen Administrator zu haben, der als Sicherheitsmaßnahme auf jedes Schema zugreifen kann. Sie sollten Sicherungskopien erstellen, indem Sie entweder jedes Schema mit einem eigenen Benutzer ablegen oder die PITR-Methode von PostgreSQL verwenden. Sie müssten immer noch den Postgres-Benutzer verwenden, um neue Schemas zu erstellen, ich würde für eine Sudo-Regel und ein Skript dafür gehen.
    • Viele bewährte Sicherheitsmethoden empfehlen, das Standardschema zu löschen.
    • Diese Lösung ist sehr geeignet, wenn die DB für jeden Kunden klein ist und Sie viele Kunden haben.
    • Wenn Ihre Anwendung die Mandantenfähigkeit behandelt, kann sie einen einzigen Verbindungspool für alle Kunden verwenden. Natürlich werden dadurch viele der oben genannten Sicherheitsverbesserungen beseitigt, aber insbesondere bei einer großen Anzahl von Kunden können Leistungsvorteile erzielt werden (wenn Sie 500-1000 separate Datenquellen haben und das Verbindungspooling verwenden, wird es ziemlich überwältigend).
  2. Jeder Kunde erhält seinen eigenen Datenbank-Cluster. Dies ist meine bevorzugte Lösung, besonders weil ich normalerweise mit Anwendungen arbeite, die für jeden Kunden eine große Datenbank haben.

    • Dieser bringt sehr gute Datentrennung. Sie können für jeden Kunden separate Speichervolumes verwenden, CPU- und Speicherbeschränkungen zuweisen (über Andockfenster?).
    • Wirklich gute Flexibilität, was jeder Kunde in seiner Instanz braucht. Sie könnten entweder ähnlich sein oder unterschiedliche Merkmale aufweisen.
    • Sehr einfach in beide Richtungen zu skalieren (nach oben und nach außen).
    • Ich verwende auch separate virtuelle IPs, bei denen jeder Cluster auf Verbindungen wartet, wodurch die Skalierung so erfolgt, dass keine Neukonfiguration der Datenquelle erforderlich ist.
    • PITR-Backups sind pro Kunde, so dass es einfacher wird, einen einzelnen Kunden im Vergleich zu der Multi-Mandantenfähigkeit pro Schema wiederherzustellen.
    • Bei komplexen Setups benötigt jeder Kunde möglicherweise mehrere Datenbanken, Schemas, Benutzer und Rollen usw. In solchen Fällen ist dies eine bessere Lösung.

Sie können auch eine Kombination der oben genannten verwenden und pgBouncer als Router verwenden.


5
2017-12-23 09:24