Dans chaque système informatique où des tâches commerciales importantes ont lieu, il est important d'avoir un ensemble explicite de politiques et de pratiques, et de s'assurer qu'elles sont respectées et suivies.
Introduction à l'audit
Un audit de système de technologie de l'information est l'examen des politiques, processus, procédures et pratiques d'une organisation concernant l'infrastructure informatique par rapport à un certain ensemble d'objectifs. Un audit informatique peut être de deux types génériques :
- Vérification par rapport à un ensemble de normes sur un sous-ensemble limité de données
- Vérification de l'ensemble du système
Un audit informatique peut couvrir certaines parties critiques du système, telles que celles liées aux données financières afin de prendre en charge un ensemble spécifique de réglementations (par exemple, SOX), ou l'ensemble de l'infrastructure de sécurité par rapport à des réglementations telles que la nouvelle réglementation européenne GDPR qui répond au besoin. pour la protection de la vie privée et définit les lignes directrices pour la gestion des données personnelles. L'exemple SOX est du premier type décrit ci-dessus alors que GDPR est du second.
Le cycle de vie de l'audit
Planification
Le portée d'un audit dépend de l'objectif de l'audit. Le champ d'application peut couvrir une application particulière identifiée par une activité commerciale spécifique, telle qu'une activité financière, ou l'ensemble de l'infrastructure informatique couvrant la sécurité du système, la sécurité des données, etc. La portée doit être correctement identifiée à l'avance comme une première étape de la phase de planification initiale. L'organisation est censée fournir à l'auditeur toutes les informations contextuelles nécessaires pour l'aider à planifier l'audit. Il peut s'agir des spécifications fonctionnelles/techniques, des schémas d'architecture du système ou de toute autre information demandée.
Objectifs de contrôle
Sur la base de la portée, l'auditeur forme un ensemble d'objectifs de contrôle à tester par l'audit. Ces objectifs de contrôle sont mis en œuvre via des pratiques de gestion censées être en place afin d'atteindre un contrôle dans la mesure décrite par le périmètre. Les objectifs de contrôle sont associés à des plans de test et ceux-ci constituent ensemble le programme d'audit. Basé sur le programme d'audit l'organisation auditée alloue des ressources pour faciliter l'audit.
Résultats
L'auditeur essaie d'obtenir la preuve que tous les objectifs de contrôle sont atteints. Si, pour un objectif de contrôle, il n'y a pas de telles preuves, l'auditeur essaie d'abord de voir s'il existe une autre manière pour l'entreprise de gérer l'objectif de contrôle spécifique, et dans le cas où une telle manière existe, alors cet objectif de contrôle est marqué comme compensation et l'auditeur considère que l'objectif est atteint. Si toutefois il n'y a aucune preuve qu'un objectif est atteint, cela est alors marqué comme une constatation . Chaque constatation comprend la condition, les critères, la cause, l'effet et la recommandation. Le responsable informatique doit être en contact étroit avec l'auditeur afin d'être informé de toutes les constatations potentielles et s'assurer que toutes les informations demandées sont partagées entre la direction et l'auditeur afin de s'assurer que l'objectif de contrôle est atteint (et ainsi éviter la découverte).
Le rapport d'évaluation
À la fin du processus d'audit, l'auditeur rédige un rapport d'évaluation sous forme de résumé couvrant toutes les parties importantes de l'audit, y compris toutes les constatations potentielles suivies d'une déclaration indiquant si l'objectif est correctement traité et des recommandations pour éliminer l'impact des constatations.
Qu'est-ce que la journalisation d'audit et pourquoi devriez-vous le faire ?
L'auditeur souhaite avoir un accès complet aux modifications apportées aux logiciels, aux données et au système de sécurité. Il souhaite non seulement pouvoir suivre toute modification des données de l'entreprise, mais également suivre les modifications de l'organigramme, de la politique de sécurité, de la définition des rôles/groupes et des modifications de l'appartenance aux rôles/groupes. La façon la plus courante d'effectuer un audit est via la journalisation. Bien qu'il était possible dans le passé de réussir un audit informatique sans fichiers journaux, c'est aujourd'hui la méthode préférée (sinon la seule).
Généralement, le système informatique moyen comprend au moins deux couches :
- Base de données
- Application (éventuellement au-dessus d'un serveur d'applications)
L'application maintient ses propres journaux couvrant l'accès et les actions des utilisateurs, et la base de données et éventuellement les systèmes de serveur d'applications maintiennent leurs propres journaux. Des informations propres et facilement utilisables dans les fichiers journaux qui ont une réelle valeur commerciale du point de vue de l'auditeur sont appelées une piste d'audit . Les pistes d'audit diffèrent des fichiers journaux ordinaires (parfois appelés journaux natifs) en ce que :
- Les fichiers journaux sont inutiles
- Les pistes d'audit doivent être conservées plus longtemps
- Les fichiers journaux ajoutent une surcharge aux ressources du système
- Le but des fichiers journaux est d'aider l'administrateur système
- Le but des pistes d'audit est d'aider l'auditeur
Nous résumons ce qui précède dans le tableau suivant :
Type de journal | Application/Système | Compatible avec la piste d'audit |
---|---|---|
Journaux des applications | Application | Oui |
Journaux du serveur d'applications | Système | Non |
Journaux de la base de données | Système | Non |
Les journaux d'application peuvent être facilement adaptés pour être utilisés comme pistes d'audit. Le système se connecte pas si facilement car :
- Ils sont limités dans leur format par le logiciel système
- Ils agissent globalement sur l'ensemble du système
- Ils n'ont aucune connaissance directe du contexte commercial spécifique
- Ils nécessitent généralement un logiciel supplémentaire pour l'analyse/le traitement hors ligne ultérieurs afin de produire des pistes d'audit utilisables et conviviales.
Cependant, d'un autre côté, les journaux d'application placent une couche logicielle supplémentaire au-dessus des données réelles, ainsi :
- Rendre le système d'audit plus vulnérable aux bogues/mauvaises configurations de l'application
- Création d'un trou potentiel dans le processus de journalisation si quelqu'un tente d'accéder aux données directement sur la base de données en contournant le système de journalisation de l'application, comme un utilisateur privilégié ou un administrateur de base de données
- Rendre le système d'audit plus complexe et plus difficile à gérer et à maintenir dans le cas où nous avons de nombreuses applications ou de nombreuses équipes logicielles.
Donc, idéalement, nous recherchons le meilleur des deux :avoir des pistes d'audit utilisables avec la plus grande couverture sur l'ensemble du système, y compris la couche de base de données, et configurables en un seul endroit, de sorte que la journalisation elle-même puisse être facilement auditée au moyen d'autres ( système) journaux.
Journalisation d'audit avec PostgreSQL
Les options que nous avons dans PostgreSQL concernant la journalisation d'audit sont les suivantes :
- En utilisant une journalisation exhaustive ( log_statement =all )
- En écrivant une solution de déclencheur personnalisée
- En utilisant les outils PostgreSQL standard fournis par la communauté, tels que
- audit-trigger 91plus (https://github.com/2ndQuadrant/audit-trigger)
- Extension pgaudit (https://github.com/pgaudit/pgaudit)
La journalisation exhaustive, au moins pour une utilisation standard dans les charges de travail OLTP ou OLAP, doit être évitée car :
- Produit des fichiers volumineux, augmente la charge
- N'a aucune connaissance interne des tables consultées ou modifiées, imprime simplement l'instruction qui pourrait être un bloc DO avec une instruction concaténée cryptique
- Nécessite des logiciels/ressources supplémentaires pour l'analyse et le traitement hors ligne (afin de produire les pistes d'audit) qui, à leur tour, doivent être inclus dans la portée de l'audit, pour être considérés comme dignes de confiance
Dans la suite de cet article nous allons essayer les outils fournis par la communauté. Supposons que nous ayons ce tableau simple que nous voulons auditer :
myshop=# \d orders
Table "public.orders"
Column | Type | Collation | Nullable | Default
------------+--------------------------+-----------+----------+------------------------------------
id | integer | | not null | nextval('orders_id_seq'::regclass)
customerid | integer | | not null |
customer | text | | not null |
xtime | timestamp with time zone | | not null | now()
productid | integer | | not null |
product | text | | not null |
quantity | integer | | not null |
unit_price | double precision | | not null |
cur | character varying(20) | | not null | 'EUR'::character varying
Indexes:
"orders_pkey" PRIMARY KEY, btree (id)
déclencheur d'audit 91plus
La documentation sur l'utilisation du déclencheur peut être trouvée ici :https://wiki.postgresql.org/wiki/Audit_trigger_91plus. Nous téléchargeons et installons d'abord le DDL fourni (fonctions, schéma) :
$ wget https://raw.githubusercontent.com/2ndQuadrant/audit-trigger/master/audit.sql
$ psql myshop
psql (10.3 (Debian 10.3-1.pgdg80+1))
Type "help" for help.
myshop=# \i audit.sql
Ensuite, nous définissons les déclencheurs pour nos commandes de table en utilisant l'utilisation de base :
myshop=# SELECT audit.audit_table('orders');
Cela créera deux déclencheurs sur les commandes de table :un déclencheur de ligne insert_update_delere et un déclencheur d'instruction truncate. Voyons maintenant ce que fait le déclencheur :
myshop=# insert into orders (customer,customerid,product,productid,unit_price,quantity) VALUES('magicbattler',1,'some fn skin 2',2,5,2);
INSERT 0 1
myshop=# update orders set quantity=3 where id=2;
UPDATE 1
myshop=# delete from orders where id=2;
DELETE 1
myshop=# select table_name, action, session_user_name, action_tstamp_clk, row_data, changed_fields from audit.logged_actions;
-[ RECORD 1 ]-----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
table_name | orders
action | I
session_user_name | postgres
action_tstamp_clk | 2018-05-20 00:15:10.887268+03
row_data | "id"=>"2", "cur"=>"EUR", "xtime"=>"2018-05-20 00:15:10.883801+03", "product"=>"some fn skin 2", "customer"=>"magicbattler", "quantity"=>"2", "productid"=>"2", "customerid"=>"1", "unit_price"=>"5"
changed_fields |
-[ RECORD 2 ]-----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
table_name | orders
action | U
session_user_name | postgres
action_tstamp_clk | 2018-05-20 00:16:12.829065+03
row_data | "id"=>"2", "cur"=>"EUR", "xtime"=>"2018-05-20 00:15:10.883801+03", "product"=>"some fn skin 2", "customer"=>"magicbattler", "quantity"=>"2", "productid"=>"2", "customerid"=>"1", "unit_price"=>"5"
changed_fields | "quantity"=>"3"
-[ RECORD 3 ]-----+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
table_name | orders
action | D
session_user_name | postgres
action_tstamp_clk | 2018-05-20 00:16:24.944117+03
row_data | "id"=>"2", "cur"=>"EUR", "xtime"=>"2018-05-20 00:15:10.883801+03", "product"=>"some fn skin 2", "customer"=>"magicbattler", "quantity"=>"3", "productid"=>"2", "customerid"=>"1", "unit_price"=>"5"
changed_fields |
Notez la valeur changes_fields sur la mise à jour (RECORD 2). Il existe des utilisations plus avancées du déclencheur d'audit, comme l'exclusion de colonnes ou l'utilisation de la clause WHEN, comme indiqué dans la documentation. Le déclencheur d'audit semble faire le travail de créer des pistes d'audit utiles dans la table audit.logged_actions. Cependant, il y a quelques mises en garde :
- Aucun SELECT (les déclencheurs ne se déclenchent pas sur les SELECT) ou DDL n'est suivi
- Les modifications apportées par les propriétaires de tables et les super utilisateurs peuvent être facilement falsifiées
- Les bonnes pratiques doivent être suivies concernant les utilisateurs de l'application et les propriétaires du schéma et des tables de l'application
Pgaudit
Pgaudit est le dernier ajout à PostgreSQL en ce qui concerne l'audit. Pgaudit doit être installé en tant qu'extension, comme indiqué sur la page github du projet :https://github.com/pgaudit/pgaudit. Pgaudit se connecte au journal PostgreSQL standard. Pgaudit fonctionne en s'enregistrant lors du chargement du module et en fournissant des crochets pour executorStart, executorCheckPerms, processUtility et object_access. Par conséquent, pgaudit (contrairement aux solutions basées sur des déclencheurs telles que audit-trigger discutées dans les paragraphes précédents) prend en charge les READ (SELECT, COPY). Généralement avec pgaudit on peut avoir deux modes de fonctionnement ou les utiliser combinés :
- Journalisation d'audit de SESSION
- Journalisation d'audit OBJECT
La journalisation d'audit de session prend en charge la plupart des commandes DML, DDL, privilège et misc via des classes :
- LIRE (sélectionner, copier depuis)
- WRITE (insérer, mettre à jour, supprimer, tronquer, copier vers)
- FUNCTION (appels de fonction et blocs DO)
- ROLE (accorder, révoquer, créer/modifier/supprimer un rôle)
- DDL (tous les DDL sauf ceux de ROLE)
- MISC (jeter, récupérer, point de contrôle, vide)
La métaclasse "tout" inclut toutes les classes. - exclut une classe. Par exemple, configurons la journalisation d'audit de session pour tous sauf MISC, avec les paramètres GUC suivants dans postgresql.conf :
pgaudit.log_catalog = off
pgaudit.log = 'all, -misc'
pgaudit.log_relation = 'on'
pgaudit.log_parameter = 'on'
En donnant les commandes suivantes (les mêmes que dans l'exemple de déclencheur)
myshop=# insert into orders (customer,customerid,product,productid,unit_price,quantity) VALUES('magicbattler',1,'some fn skin 2',2,5,2);
INSERT 0 1
myshop=# update orders set quantity=3 where id=2;
UPDATE 1
myshop=# delete from orders where id=2;
DELETE 1
myshop=#
Nous obtenons les entrées suivantes dans le journal PostgreSQL :
% tail -f data/log/postgresql-22.log | grep AUDIT:
[local] [55035] 5b03e693.d6fb 2018-05-22 12:46:37.352 EEST psql [email protected] line:7 LOG: AUDIT: SESSION,5,1,WRITE,INSERT,TABLE,public.orders,"insert into orders (customer,customerid,product,productid,unit_price,quantity) VALUES('magicbattler',1,'some fn skin 2',2,5,2);",<none>
[local] [55035] 5b03e693.d6fb 2018-05-22 12:46:50.120 EEST psql [email protected] line:8 LOG: AUDIT: SESSION,6,1,WRITE,UPDATE,TABLE,public.orders,update orders set quantity=3 where id=2;,<none>
[local] [55035] 5b03e693.d6fb 2018-05-22 12:46:59.888 EEST psql [email protected] line:9 LOG: AUDIT: SESSION,7,1,WRITE,DELETE,TABLE,public.orders,delete from orders where id=2;,<none>
Notez que le texte après AUDIT :constitue une piste d'audit parfaite, presque prête à être envoyée à l'auditeur au format csv prêt pour une feuille de calcul. L'utilisation de la journalisation d'audit de session nous donnera des entrées de journal d'audit pour toutes les opérations appartenant aux classes définies par le paramètre pgaudit.log sur all les tables. Cependant, dans certains cas, nous ne souhaitons qu'un petit sous-ensemble de données, c'est-à-dire que quelques tables seulement soient auditées. Dans de tels cas, nous pouvons préférer la journalisation d'audit d'objet qui nous donne des critères précis pour les tables/colonnes sélectionnées via le système de privilèges de PostgreSQL. Pour commencer à utiliser la journalisation d'audit d'objets, nous devons d'abord configurer le paramètre pgaudit.role qui définit le rôle principal que pgaudit utilisera. Il est logique de ne donner aucun droit de connexion à cet utilisateur.
CREATE ROLE auditor;
ALTER ROLE auditor WITH NOSUPERUSER INHERIT NOCREATEROLE NOCREATEDB NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT 0;
Ensuite, nous spécifions cette valeur pour pgaudit.role dans postgresql.conf :
pgaudit.log = none # no need for extensive SESSION logging
pgaudit.role = auditor
La journalisation Pgaudit OBJECT fonctionnera en trouvant si l'utilisateur auditeur reçoit (directement ou hérité) le droit d'exécuter l'action spécifiée effectuée sur les relations/colonnes utilisées dans une instruction. Donc, si nous devons ignorer toutes les tables, mais avoir une journalisation détaillée des ordres de table, voici comment procéder :
grant ALL on orders to auditor ;
Par la subvention ci-dessus, nous activons la journalisation complète SELECT, INSERT, UPDATE et DELETE sur les commandes de table. Reprenons les INSERT, UPDATE, DELETE des exemples précédents et regardons le log postgresql :
% tail -f data/log/postgresql-22.log | grep AUDIT:
[local] [60683] 5b040125.ed0b 2018-05-22 14:41:41.989 EEST psql [email protected] line:7 LOG: AUDIT: OBJECT,2,1,WRITE,INSERT,TABLE,public.orders,"insert into orders (customer,customerid,product,productid,unit_price,quantity) VALUES('magicbattler',1,'some fn skin 2',2,5,2);",<none>
[local] [60683] 5b040125.ed0b 2018-05-22 14:41:52.269 EEST psql [email protected] line:8 LOG: AUDIT: OBJECT,3,1,WRITE,UPDATE,TABLE,public.orders,update orders set quantity=3 where id=2;,<none>
[local] [60683] 5b040125.ed0b 2018-05-22 14:42:03.148 EEST psql [email protected] line:9 LOG: AUDIT: OBJECT,4,1,WRITE,DELETE,TABLE,public.orders,delete from orders where id=2;,<none>
Nous observons que la sortie est identique à la journalisation SESSION décrite ci-dessus, à la différence qu'au lieu de SESSION comme type d'audit (la chaîne à côté de AUDIT :), nous obtenons maintenant OBJECT.
Une mise en garde avec la journalisation OBJECT est que les TRUNCATE ne sont pas journalisés. Nous devons recourir à la journalisation SESSION pour cela. Mais dans ce cas, nous finissons par obtenir toute l'activité WRITE pour toutes les tables. Il y a des discussions entre les pirates impliqués pour faire de chaque commande une classe distincte.
Une autre chose à garder à l'esprit est que dans le cas de l'héritage, si nous accordons l'accès à l'auditeur sur une table enfant, et non au parent, les actions sur la table parent qui se traduisent en actions sur les lignes de la table enfant ne seront pas enregistrées.
En plus de ce qui précède, les informaticiens en charge de l'intégrité des journaux doivent documenter une procédure stricte et bien définie qui couvre l'extraction de la piste d'audit des fichiers journaux PostgreSQL. Ces journaux peuvent être diffusés vers un serveur syslog sécurisé externe afin de minimiser les risques d'interférence ou de falsification.
Résumé
Nous espérons que ce blog vous a aidé à mieux comprendre les meilleures pratiques de journalisation d'audit dans PostgreSQL et pourquoi la création d'une piste d'audit est si importante dans la préparation d'un audit informatique. Une piste d'audit fournira un ensemble d'informations propres et utilisables qui contribueront au bon déroulement de votre audit.
ClusterControl peut aider à automatiser et à gérer la plupart des tâches liées à la base de données tout en garantissant la sécurité, la disponibilité et les performances de la base de données, quel que soit le système choisi. Téléchargez dès aujourd'hui un essai gratuit de ClusterControl pour voir comment votre entreprise peut bénéficier de l'outil et des opérations qu'il effectue. Si vous ne l'avez pas déjà fait, assurez-vous de nous suivre sur Twitter et LinkedIn, et abonnez-vous à notre flux, et nous vous verrons dans le prochain blog.