Pobieranie informacji o uid i gid użytkownika z bazy danych MySQL

Czy można pobierać dane o użytkownikach systemu z bazy danych, np. MySQL? Oczywiście!

Instalacja potrzebnych plików

W przypadku Debiania należy zainstalować następujący pakiet: libnss-mysql

apt-get install libnss-mysql

Struktura tabel obsługujących zapytania

Strukture potrzebnych tabel znajdziesz w pliku examples.sql w katalogu /usr/share/doc/libnss-mysql/examples. Dokumentacja ta jest instalowana razem z pakietem libnss-mysql.

Ogólnie sprawę ujmując potrzebujesz 3 tabel, które przechowują informację o użytkownikach, grupach oraz powiązaniach między grupami i użytkownikami.

mysql> desc user;
+---------------+--------------+------+-----+---------+----------------+
| Field         | Type         | Null | Key | Default | Extra          |
+---------------+--------------+------+-----+---------+----------------+
| user_id       | int(11)      |      | PRI | NULL    | auto_increment |
| user_name     | varchar(50)  |      |     |         |                |
| realname      | varchar(120) |      |     |         |                |
| shell         | varchar(20)  |      |     | /bin/sh |                |
| password      | varchar(40)  |      |     |         |                |
| status        | char(1)      |      |     | N       |                |
| uid           | int(11)      |      |     | 65534   |                |
| gid           | int(11)      |      |     | 65534   |                |
| homedir       | varchar(32)  |      |     | /bin/sh |                |
| owner         | int(11)      |      |     | 0       |                |
| lastchange    | varchar(50)  | YES  |     | NULL    |                |
| min           | int(11)      | YES  |     | 0       |                |
| max           | int(11)      | YES  |     | 0       |                |
| warn          | int(11)      | YES  |     | 7       |                |
| inact         | int(11)      | YES  |     | -1      |                |
| expire        | int(11)      | YES  |     | -1      |                |
+---------------+--------------+------+-----+---------+----------------+

mysql> desc user_group;
+----------+---------+------+-----+---------+-------+
| Field    | Type    | Null | Key | Default | Extra |
+----------+---------+------+-----+---------+-------+
| user_id  | int(11) |      |     | 0       |       |
| group_id | int(11) |      |     | 0       |       |
+----------+---------+------+-----+---------+-------+
2 rows in set (0.01 sec)

mysql> desc groups;
+----------------+--------------+------+-----+---------+----------------+
| Field          | Type         | Null | Key | Default | Extra          |
+----------------+--------------+------+-----+---------+----------------+
| group_id       | int(11)      |      | PRI | NULL    | auto_increment |
| group_name     | varchar(30)  |      |     |         |                |
| status         | char(1)      | YES  |     | A       |                |
| group_password | varchar(64)  |      |     | x       |                |
| gid            | int(11)      |      |     | 0       |                |
| members        | varchar(255) | YES  |     | NULL    |                |
+----------------+--------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)

Kod tworzący te tabele można pobrać stąd.

Modyfikacja plików konfiguracyjnych Linuksa

 

cat /etc/nss-mysql.conf | grep -v "#"
conf.version = 2;
users.host = inet:localhost:3306;
users.database = webadmin;
users.db_user = root;
users.db_password = tygrysekdupa;
users.backup_host =
users.table = user;
users.where_clause = user.status = 'A';
users.user_column = user.user_name;
users.password_column = user.password;
users.userid_column = user.user_id;
users.uid_column = user.uid;
users.gid_column = user.gid;
users.realname_column = user.realname;
users.homedir_column = user.homedir;
users.shell_column = user.shell;
groups.group_info_table = groups;
groups.where_clause = groups.status = 'A';
groups.group_name_column = groups.group_name;
groups.groupid_column = groups.group_id;
groups.gid_column = groups.gid;
groups.password_column = groups.group_password;
groups.members_table = user_group;
groups.member_userid_column = user_group.user_id;
groups.member_groupid_column = user_group.group_id;
cat /etc/nss-mysql-root.conf | grep -v "#"
conf.version = 2;
shadow.host = inet:localhost:3306;
shadow.database = webadmin;
shadow.db_user = root;
shadow.db_password = tygrysekdupa;
shadow.table = user;
shadow.where_clause = user.status = 'A';
shadow.userid_column = user.user_id;
shadow.user_column = user.user_name;
shadow.password_column = user.password;
shadow.lastchange_column = user.lastchange;
shadow.min_column = user.min;
shadow.max_column = user.max;
shadow.warn_column = user.warn;
shadow.inact_column = user.inact;
shadow.expire_column = user.expire;

Poinformowanie systemu by korzystał z informacji zawartych również w bazie danych

cat /etc/nsswitch.conf
# /etc/nsswitch.conf
#
# Example configuration of GNU Name Service Switch functionality.
# If you have the `glibc-doc' and `info' packages installed, try:
# `info libc "Name Service Switch"' for information about this file.

passwd:         compat mysql
group:          compat mysql
shadow:         compat mysql

hosts:          files dns
networks:       files

protocols:      db files
services:       db files
ethers:         db files
rpc:            db files

netgroup:       nis

Zauważmy, że taka konfiguracja pozwala najpierw wyszukać informacje o użytkownikach w plikach systemowych a później dopiero (jeżeli tam nie znajdzie informacji) w bazie danych. Umożliwia to dodanianie systemowych użytkowników przez system pakietów bez potrzeby ręcznego modyfikowania informacji o użytkownikach w bazie danych (o ile nie wymagają oni logowania do systemu 😉 ).

Sprawdzenie poprawności konfiguracji

Sprawdzenie poprawności konfiguracji możemy wykonać wydając polecenie id nazwa_uzytkownika_w_bazie:

debian:/usr/share/doc# debian:/etc# id kjozwiak
uid=1119(kjozwiak) gid=100(users) groups=100(users)

W przypadku logowania zapytań do bazy danych w pliku logów pojawi się wpis świadczący o wykonaniu operacji na bazie danych:

44 Query       select groups.group_name,groups.gid,groups.group_password,
 user.user_name from groups LEFT JOIN user_group on groups.group_id=user_group.group_id 
 LEFT JOIN user on user_group.user_id=user.user_id and user.status = 'A' 
 where 1 = 1 and groups.status = 'A'

Bezpieczeństwo rozwiązania

Podstawowym problemem jest bezpieczeństwo bazy danych, w której przechowywane są dane o użytkownikach, jest to jednak bardziej problem bezpieczeństwa MySQLa. Inna sprawa to fakt, iż hasła dostępowe do bazy danych są w plikach konfiguracyjnych podane w sposób niezakodowany, należy więc ograniczyć dostęp do nich tylko do superużytkownika:

chmod 600 /etc/nss-mysql-root.conf
chmod 600 /etc/nss-mysql.conf

Hasła w bazie danych są zaszyfrowane więc nie ma obawy co do szybkiego ich wykorzystania nawet gdy hasła zostaną wykradzione.

Dodaj komentarz