web-dev-qa-db-fra.com

Quelle est la meilleure façon de stocker le certificat X509 dans la base de données PostgreSQL?

Je travaille sur le système d'authentification Web où les utilisateurs signeront numériquement des jetons aléatoires et que ceci sera vérifié avec des certificats X509 stockés sur le serveur.

Par conséquent, je dois stocker plusieurs certificats X509 (format PEM ou DER) dans la base de données PostgreSQL. Cela semble facile, mais je souhaite avoir la possibilité de rechercher des certificats avec sujet, émetteur, notedavre, novateur et critères similaires.

Mon idée est d'avoir des colonnes suivantes dans la base de données: x509Data, notabilter, notefore, sujet, émetteur, etc. que je ne créerai d'objet (dans SQL Alchemy) représentant X509 Certificat avec des méthodes telles que Add_new_x509 (), Find_x509 (Critères de recherche), etc. Je vais ajouter un nouveau certificat avec la méthode add_new_x509 () Il lit automatiquement du certificat toutes les données et remplira le repos des colonnes et placez le certificat brut dans la colonne X509Data.

Malheureusement, cette solution a deux inconvénients:

  1. Je stockerai les mêmes informations deux fois (Certificat X509 lui-même et dans des colonnes séparées pour une recherche facile)
  2. Chaque fois que je souhaite lire un certificat X509, ma demande devra recourir à CrossCheck NotAfter, NotBefrefore, sujet, émetteur des informations stockées dans un certificat d'origine (ceci est pour des raisons de sécurité, au cas où quelqu'un essaierait de modifier ces champs).

Alors .. Tout le monde a une meilleure idée ou une meilleure suggestion? Peut-être que quelqu'un voit une autre question de sécurité pouvant survenir avec cette solution?

5
Marek

La duplication n'est pas idéale, mais dans ce cas est probablement le meilleur choix. Définissez les autorisations de la table de sorte que le propriétaire de la table ne soit pas le jour de la base de données de jour de la journée de travail que votre application fonctionne, et seulement GRANT votre application La possibilité d'écrire dans la colonne Données de certificat, pas des colonnes "cache" avec Expiration, etc. Ayez une interception de la fonction de déclenchement SECURITY DEFINER __Contrée d'interception du certificat et à la mise à jour de l'utilisateur privilégié, les colonnes de cache indexées à l'aide d'une bibliothèque X.509 pour extraire les champs du certificat après la vérification de la vérification.

Alternativement, vous pouvez écrire un PL/Python, Pl/Perl, ou même une fonction C SQL C appelant une bibliothèque d'analyseurs de certificats X.509 pour extraire les champs et les renvoyer. Donc, vous diriez que extract_x509_field(cert, 'subject'). Ou peut-être même une forme de retour à la ligne comme SELECT subject, issuerName FROM (SELECT extract_x509_fields(cert) FROM the_table)extract_x509_fields renvoie une ligne de toutes les données certificat pertinentes. Avec cette approche, vous pouvez créer des index fonctionnels tels que CREATE INDEX cert_issuer ON certificate_table( extract_x509_field(cert,'issuer') ); pouvant être utilisée pour correspondre aux expressions WHERE. Vous n'avez pas besoin d'avoir des colonnes de table pour les données extraites du tout. L'inconvénient est que cela serait probablement plus lent, car le certificateur serait analysé plusieurs fois lors de la création d'index, lors de la vérification de l'index, etc.

De toute façon, il est essentiel que votre application fonctionne comme un utilisateur PostgreSQL qui n'est pas le propriétaire de la base de données, pas un superutilisateur, et non le propriétaire des tables et des indices de préoccupation. Il devrait être GRANTdé les droits minimum nécessaires et plus. Si vous avez des tâches assez séparées (disons, en lecture seule VS Write-and-Update) envisagez d'utiliser différents utilisateurs de base de données afin que même si la partie "Lire" de votre application est tracée à essayer d'écrire un champ/mise à jour un cert/etc, il n'a pas la permission.

5
Craig Ringer

J'ai abordé un problème similaire dans mon blog stocker des certificats numériques x.509 (et d'autres choses désordonnées) et quelques commentaires antérieurs. (Il est trop long pour couper et coller ici.) Plusieurs des points faits ici sont beaucoup plus faciles si vous pouvez créer une fonction définie par l'utilisateur qui extrait les champs dont vous avez besoin pour cache.

Adressant un autre point ci-dessus - c'est possible pour écrire un déclencheur qui utilise SPI pour vérifier que l'émetteur du cert est présents dans la base de données. Vous devriez inclure des exceptions pour des certificats racines auto-signés et des certs "de confiance" fournis par d'autres. Ceci, plus d'autres contrôles de santé mentale (par exemple, l'émetteur a-t-il la capacité de base? Existe-t-il? DN restrictions?) Vous donnerait un référentiel beaucoup plus fort.

Est-ce sage de faire cela? Je continue de retourner sur ça. Mes pensées actuelles sont que cela fonctionnerait si vous émettez et gérez vos propres certificats, mais ce sera un mal de tête massif si vous intégrez des certs tiers. Le problème est qu'il y a beaucoup de certs junky là-bas. Si vous êtes strict, vous allez exclure beaucoup de certs utilisés et si vous êtes LAX, alors pourquoi vous déranger avec la logique supplémentaire?

3
bgiles

Je n'ai pas vraiment compris pourquoi vous souhaitez stocker les différents champs sujets/émetteurs séparément, à moins que vous n'auriez interrogé pour les informations de la base de données; Surtout comme vous devrez lire le certificat pour vérifier ses détails (votre deuxième élément de la liste).

Si vous stockiez cela pour expirer automatiquement/invalider les certificats, vous pouvez exécuter une tâche distincte qui le fait.

De plus, puisque PostgreSQL vous permet d'utiliser python comme langage de procédure; vous pouvez écrire un déclencheur ou une vue qui retournera les informations "analysées" pour votre candidature - si vous vouliez vraiment le décharger de votre application.

De plus, je ferais ce qui suit depuis que vous stockez des certificats:

  1. Assurez-vous que la connexion entre les clients et le serveur est cryptée (vous devriez le faire quand même). Voir la section 17.9 dans la documentation.

  2. Assurez-vous que la table/colonne est cryptée. Voir la pycrypto Documentation du module.

1
Burhan Khalid

Ajout à l'excellente réponse de Craig, qu'une fois que vous commencez à tirer des informations d'une bibliothèque X509, vous pouvez effectuer d'autres choses intéressantes avec elle. Je ne sais pas si Sqlalchemy utilise toujours des alias de table ou si vous pouvez le forcer à le faire, mais si vous le pouvez, vous pouvez éviter les informations de double emploi en appelant directement les routines d'analyse sur les certs X509 et vous pouvez même indexer la sortie. Parmi ces fonctions, vous n'avez donc pas à les appeler sur le temps de sélection (c.-à-d. Les fonctions permettent d'exécuter l'heure d'insertion/mise à jour) comme il mentionne.

Une chose que je voudrais souligner, c'est que vous pouvez alors créer des méthodes de table qui, si vous pouvez obtenir votre orj Toujours Utilisez des alias de table, peut alors prendre le lieu de colonnes. Par exemple:

CREATE OR REPLACE FUNCTION issuer(x509table) returns text 
LANGUAGE SQL IMMUTABLE AS $$
    select issuer_cn FROM extract_x509info($1.x509data);
$$;

Cela peut alors être trouvé par:

SELECT x.issuer FROM x509table x;  --works

Notez que ce qui suit n'est pas valide et donc mes commentaires sur l'ormes:

SELECT issuer FROM x509table; --does not work

La raison en est que s'il n'y a pas de colonne d'émetteur, l'analyseur convertira la première instruction à:

SELECT issuer(x) from x509table x;

Notez que l'indexation de nombreuses colonnes Il y aura beaucoup de temps de calcul de la lecture à l'écriture (faire des insertions/mises à jour plus lentes, mais de lire des opérations plus rapidement).

En fin de compte, il est difficile de proposer une recommandation complète sans savoir exactement ce que vous faites, quelles sont vos charges de travail attendues, etc. L'avantage de la duplication est-il séparant les données des fonctions d'extraction pour la lecture et l'écriture, permettant ainsi de plus d'optimisations. être possible. L'avantage de garder tout ce qui fonctionne (en supposant que votre orme prend en charge) est qu'il fournit des garanties supplémentaires de l'intégrité des données.

1
Chris Travers