Auditer les connexions sur la base de données MySQL

11

Existe-t-il un moyen de vérifier les connexions à MySQL? Je voudrais pouvoir créer un nom d'utilisateur pour chaque employé et ainsi créer une piste d'audit des connexions. Cependant, la recherche sur Google n'a donné aucun bon résultat.

Plus nous pouvons auditer, mieux c'est. À tout le moins, ce serait bien de savoir qui s'est connecté quand. Il serait encore mieux de voir qui a exécuté quelle requête et quand. Les journaux sont là principalement pour indiquer aux clients que nous les avons car il existe des informations potentiellement sensibles dans la base de données.

Évidemment, la possibilité d'auditer les requêtes exécutées par chaque utilisateur (et quand) nous donnerait également la possibilité de mieux identifier qui est la cause d'un problème de sécurité, le cas échéant.

statichippo
la source
1
Que cherchez-vous exactement à auditer? Je suppose que vous voulez dire que vous utiliserez les noms d'utilisateur MySQL, pas les noms d'utilisateur système? Comment comptez-vous utiliser les données d'audit plus tard (ce qui signifie que les détails sont importants ici, la journalisation du système serait-elle suffisante au lieu de la journalisation MySQL). Plus vous pouvez fournir d'informations dans votre question, plus précisément nous pouvons vous donner une réponse, et rapidement pour démarrer. J'imagine que vous voulez une meilleure réponse que "demandez à votre application de faire un appel sproc spécifique avant chaque autre opération" ~ En bref, quels détails auriez-vous besoin de moi si je demandais cela?
jcolebrand

Réponses:

6

Vous voudrez probablement utiliser le journal général des requêtes .

Le journal général des requêtes est un enregistrement général de ce que fait mysqld. Le serveur écrit des informations dans ce journal lorsque les clients se connectent ou se déconnectent, et il enregistre chaque instruction SQL reçue des clients.

Une chose importante avec la journalisation pour des raisons de sécurité est qu'un attaquant ne peut pas accéder au journal pour effacer les traces de sa présence, alors envisagez d' ajouter des fichiers uniquement .

FWIW dans Oracle, nous pouvons envoyer automatiquement des journaux à un syslog distant , mais je ne pense pas que MySQL dispose encore de cette fonctionnalité. Peut-être pourriez-vous le simuler avec SNMP mais je ne l'ai pas essayé.

Gaius
la source
Oh cool, apprends quelque chose de nouveau chaque jour :-)
Gaius
5

La réponse de @Gauis est excellente. Pour en ajouter davantage, vous pouvez:

MySQL 5.1 permet désormais de stocker le journal général et le journal des requêtes lentes sous forme de tables SQL.

Ajoutez ceci à /etc/my.cnf:

[mysqld]
log-output=TABLE
log

Redémarrez mysql

Ensuite, lorsque mysqld crée le journal général, au lieu d'un fichier texte, il crée la table en tant que table CSV dans le dossier / var / lib / mysql / mysql (base de données de schéma mysql).

Faites juste ceci pour le voir:

SHOW CREATE TABLE mysql.general_log\G

Toutes les connexions s'y accumuleront.

Pour vous, cela n'est pas très utile pour l'interroger. Ce serait juste une analyse complète de la table à chaque fois.

Que faire ??? CONVERTIR À MyISAM et INDEXER LA TABLE !!!!

SET @old_log_state = @@global.general_log;
SET GLOBAL general_log = 'OFF';
ALTER TABLE mysql.general_log ENGINE = MyISAM;
ALTER TABLE mysql.general_log ADD INDEX (event_time);
SET GLOBAL general_log = @old_log_state;

Vous pouvez éventuellement mettre un index de texte intégral sur le champ d'argument.

Je viens de configurer MySQL 5.5.9 sur un serveur et je l'ai essayé. Voici le résultat:

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.5.9-log MySQL Community Server (GPL)

Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

iml-db10:3306 (DB (none)) :: show create table mysql.general_log\G
*************************** 1. row ***************************
       Table: general_log
Create Table: CREATE TABLE `general_log` (
  `event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `user_host` mediumtext NOT NULL,
  `thread_id` int(11) NOT NULL,
  `server_id` int(10) unsigned NOT NULL,
  `command_type` varchar(64) NOT NULL,
  `argument` mediumtext NOT NULL
) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log'
1 row in set (0.01 sec)

iml-db10:3306 (DB (none)) :: SET @old_log_state = @@global.general_log;
Query OK, 0 rows affected (0.00 sec)

iml-db10:3306 (DB (none)) :: SET GLOBAL general_log = 'OFF';
Query OK, 0 rows affected (0.00 sec)

iml-db10:3306 (DB (none)) :: ALTER TABLE mysql.general_log ENGINE = MyISAM;
Query OK, 9 rows affected (0.02 sec)
Records: 9  Duplicates: 0  Warnings: 0

iml-db10:3306 (DB (none)) :: ALTER TABLE mysql.general_log ADD INDEX (event_time);
Query OK, 9 rows affected (0.00 sec)
Records: 9  Duplicates: 0  Warnings: 0

iml-db10:3306 (DB (none)) :: SET GLOBAL slow_query_log = @old_log_state;
Query OK, 0 rows affected (0.00 sec)

iml-db10:3306 (DB (none)) :: select * from mysql.general_log;
+---------------------+-----------------------------+-----------+-----------+--------------+-------------------------------------------+
| event_time          | user_host                   | thread_id | server_id | command_type | argument                                  |
+---------------------+-----------------------------+-----------+-----------+--------------+-------------------------------------------+
| 2011-02-24 14:42:18 | [lwdba] @  [127.0.0.1]      |         3 | 106451130 | Connect      | lwdba@127.0.0.1 on                        |
| 2011-02-24 14:42:18 | lwdba[lwdba] @  [127.0.0.1] |         3 | 106451130 | Query        | select @@version_comment limit 1          |
| 2011-02-24 14:42:18 | lwdba[lwdba] @  [127.0.0.1] |         3 | 106451130 | Query        | SHOW VARIABLES LIKE 'hostname'            |
| 2011-02-24 14:42:18 | lwdba[lwdba] @  [127.0.0.1] |         3 | 106451130 | Quit         |                                           |
| 2011-02-24 14:42:18 | [lwdba] @  [127.0.0.1]      |         4 | 106451130 | Connect      | lwdba@127.0.0.1 on                        |
| 2011-02-24 14:42:18 | lwdba[lwdba] @  [127.0.0.1] |         4 | 106451130 | Query        | select @@version_comment limit 1          |
| 2011-02-24 14:42:30 | lwdba[lwdba] @  [127.0.0.1] |         4 | 106451130 | Query        | show create table mysql.general_log       |
| 2011-02-24 14:43:54 | lwdba[lwdba] @  [127.0.0.1] |         4 | 106451130 | Query        | SET @old_log_state = @@global.general_log |
| 2011-02-24 14:44:00 | lwdba[lwdba] @  [127.0.0.1] |         4 | 106451130 | Query        | SET GLOBAL general_log = 'OFF'            |
+---------------------+-----------------------------+-----------+-----------+--------------+-------------------------------------------+
9 rows in set (0.00 sec)

iml-db10:3306 (DB (none)) :: show create table mysql.general_log\G
*************************** 1. row ***************************
       Table: general_log
Create Table: CREATE TABLE `general_log` (
  `event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `user_host` mediumtext NOT NULL,
  `thread_id` int(11) NOT NULL,
  `server_id` int(10) unsigned NOT NULL,
  `command_type` varchar(64) NOT NULL,
  `argument` mediumtext NOT NULL,
  KEY `event_time` (`event_time`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='General log'
1 row in set (0.00 sec)

Maintenant, vous pouvez interroger par horodatage et rechercher des jetons spécifiques dans le champ d'argument.

Par exemple, notez la ligne 4 du SELECT que j'ai fait. Ma connexion a été enregistrée dans le champ d'argument en tant que [email protected] on. Vous pouvez les suivre.

Et si le général devient trop grand (croyez-moi, il deviendra trop grand très rapidement)

Que faire ???

  1. arrêter mysql
  2. déplacez general_log.frm, general_log.MYD et general_log.MYI vers un montage de disque différent (et, espérons-le, plus grand).
  3. Créez trois liens symboliques vers general_log.frm, general_log.MYD et general_log.MYI à partir de / var / lib / mysql / mysql
  4. chown mysql: mysql general_log.frm general_log.MYD general_log.MYI sur le nouveau montage de disque
  5. chown mysql: mysql general_log.frm general_log.MYD general_log.MYI liens symboliques dans / var / lib / mysql / mysql
  6. démarrer mysql back up

BTW Une fois que vous avez mis le journal général hors ligne, vous pouvez les exécuter pour collecter les connexions distinctes qui ont fait quelque chose dans mysqld:

SET SQL_LOG_BIN=0;
use mysql
DROP TABLE IF EXISTS audit_user_host;
CREATE TABLE audit_user_host
(
    user_host VARCHAR(32),
    PRIMARY KEY (user_host)
) ENGINE=MyISAM;
SHOW CREATE TABLE audit_user_host\G
INSERT IGNORE INTO mysql.audit_user_host SELECT user_host FROM mysql.general_log;
SELECT COUNT(1) FROM mysql.audit_user_host;

J'ai un client avec 3 serveurs DB. Eeach avec DB Server contient plus de 1 000 000 000 (1 milliard [milliers de millions]) de lignes. Le script ci-dessus a pris environ 2,5 heures. La table audit_user_host s'est terminée avec 27 connexions distinctes.

Vous devriez être prêt à partir.

Amusez-vous avec celui-ci, tout le monde !!!

RolandoMySQLDBA
la source
Excellent article! Je partage juste mes tests. J'ai essayé de renommer la table mysql.general_log et de partitionner la table à des fins de purge, mais je ne me connecterai pas à la table. Je le ramène donc à la table MyIsam non partitionnée. Merci!
1

Au lieu de faire tant de choses manuellement, installez simplement le plug-in Audit qui donne plus d'informations au niveau de l'utilisateur

http://www.mysql.com/products/enterprise/audit.html

Il est disponible sur certaines éditions commerciales MySQL, mais cela aurait été génial si une fourchette MySQL ajoute également dans l'édition communautaire afin que la plupart des gens bénéficient de cette fonctionnalité, sinon nous devons compter sur la solution fournie par @RolandoMySQLDBA.

Mahesh Patil
la source
0

@statichippo
Comment installer la journalisation d'audit sur MySQL.
+ La journalisation d'audit ne prend en charge que MySQL Enterprise
+ Vous pouvez installer la journalisation d'audit sur la communauté MySQL:
1. Copiez le fichier audit_log.so par Vous pouvez installer MySQL Enterprise Trial, puis copiez le fichier audit_log.so dans la communauté MySQL.
2. Copiez audit_log.so dans plugin_dir sous / usr / lib64 / mysql / plugin ou vous pouvez afficher le plugin dir en:
Accédez à la console mysql: mysql> affichez les variables globales comme '% plugin%';
3. Installez la journalisation d'audit comme:
mysql> INSTALLER LE PLUGIN audit_log SONAME 'audit_log.so';
mysql> AFFICHER LES VARIABLES COMME 'audit_log%';
4.
Journalisation d' audit de sortie: tail -f /var/lib/mysql/audit.log

Merci beaucoup.

Binh Nguyen
la source