Benutzer-Werkzeuge

Webseiten-Werkzeuge


computer:linux:mysql_datenbank_mit_luks_und_selinux

Mithilfe von LUKS lassen sich sämtliche Daten in verschlüsselte Container verschiedenster Verschlüsselungsstärken sammeln. In Kombination mit MySQL kann man so eine Datenbank verschlüsseln und so Festplattendieben die Arbeit erschweren. Der Fokus des Artikels liegt auf der Konfiguration von SELinux, sodass diese Umstrukturierung die Funktion der Datenbank nicht beeinträchtigt.

Logisches Volume

Zuerst wird sichergestellt, dass sich in der Root-Volumengruppe noch genügend Speicherplatz für ein weiteres logisches Volume vorhanden ist (natürlich kann auch eine dedizierte Volumengruppe verwendet werden). Anschließend wird ein logisches Volume für den verschlüsselten LUKS-Container erstellt. Bei der Formatierung wird der LUKS-Masterkey definiert:

# vgs
  VG   #PV #LV #SN Attr   VSize  VFree
  vg00   1   2   0 wz--n- 19.51g 9.51g
# lvcreate -L 3G -n lv_database vg00

LUKS-Container

Anschließend wird der LUKS-Container mit den Standardeinstellungen (AES, 256 Bit Schlüsselstärke) formatiert:

# cryptsetup luksFormat /dev/mapper/vg00-lv_database       
WARNING!
========
This will overwrite data on /dev/mapper/vg00-lv_database irrevocably.

Are you sure? (Type uppercase yes): YES
Enter LUKS passphrase:
Verify passphrase:

Der LUKS-Container wird jetzt geöffnet und mit einem ext4-Dateisystem versehen:

# cryptsetup luksOpen /dev/mapper/vg00-lv_database crypt_database
Enter passphrase for /dev/mapper/vg00-lv_database:
# cryptsetup status /dev/mapper/crypt_database
/dev/mapper/crypt_database is active.
  type:  LUKS1
  cipher:  aes-cbc-essiv:sha256
  keysize: 256 bits
  device:  /dev/mapper/vg00-lv_database
  offset:  4096 sectors
  size:    6287360 sectors
  mode:    read/write
# mkfs.ext4 /dev/mapper/crypt_database

Damit der Container beim Booten geöffnet und das enthaltene Dateisystem montiert wird (unterhalb /data), sind Einträge in der /etc/cryptab und /etc/fstab nötig:

# mkdir /data
# vi /etc/crypttab
...
crypt_database  /dev/mapper/vg00-lv_database
ESC ZZ
# vi /etc/fstab
...
/dev/mapper/crypt_database      /data   ext4    defaults        0       0
...
ESC ZZ
# mount -a

Für dedizierte Benutzer können bei Bedarf dedizierte LUKS-Passwörter (bis zu 7, also insgesamt 8 Keys) vergeben werden:

# cryptsetup luksAddKey /dev/mapper/vg00-lv_database
Enter any passphrase: [MASTERKEY]
Enter new passphrase for key slot:
Verify passphrase:

Bei zukünftigen Boot-Vorgängen sollte ein Passwort für den Container abgefragt werden:

# reboot
...
/data is password protected:
....

MySQL-Konfiguration

Anschließend werden der MySQL-Server und SELinux-Tools installiert und ein Ordner für die zukünftige MySQL-Datenbank angelegt:

# mkdir /data/mysql
# yum install policycoreutils-python mysql-server
# chkconfig mysqld on

Die Datenbank wird mit der Standardkonfiguration gestartet, ein Passwort wird festgelegt. Anschließend wird die Datenbank gestoppt und dessen Datenbestand auf den Container kopiert. Dabei werden alle vorhandenen Metadaten (Benutzer, Rechte,..) mitkopiert:

# service mysqld start
# myqsladmin -u root password 'new-password'
# service mysql stop
# cp --preserve=all -R /var/lib/mysql/* /data/mysql/

Die Standardkonfiguration von MySQL wird kopiert und angepasst:

# cp /etc/my.cnf /etc/my.cnf.initial
# vi /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/var/lib/mysql/mysql.sock
...
ESC ZZ

Das Socket sollte idealerweise nicht nach /data/mysql verschoben werden, da das andernfalls zur Folge hätte, dass PHP-Anwendungen nicht auf MySQL zugreifen könnten. Hierfür müssten dann wieder eigene SELinux-Regeln gebaut werden.

SELinux-Konfiguration

Zu diesem Zeitpunkt kann MySQL noch nicht gestartet werden, da SELinux den Dienst aufgrund des neuen Orts der Datenbank abwürgt:

# service mysqld start
MySQL Daemon failed to start.
Starting mysqld:                                           [FAILED]
# audit2why < /var/log/audit/audit.log
type=AVC msg=audit(1352205218.399:44): avc:  denied  { search } for  pid=2478 comm="mysqld" name="/" dev=dm-3 ino=2 scontext=unconfined_u:system_r:mysqld_t:s0 tcontext=system_u:object_r:file_t:s0 tclass=dir

        Was caused by:
                Missing type enforcement (TE) allow rule.

                You can use audit2allow to generate a loadable module to allow this access.

Nun wird eine Ausnahmeregel für diesen Regelverstoß gebaut. Hierzu wird das Audit-Log erst geleert, bevor nochmal versucht wird, den Dienst zu starten. Dieser Regelverstoß wird protokolliert und kann mithilfe von audit2allow zu einer SELinux-Modulvorlage (local.te) umgebaut werden:

# > /var/log/audit/audit.log
# service mysqld start ; audit2allow -m local < /var/log/audit/audit.log > local.te
MySQL Daemon failed to start.
Starting mysqld:                                           [FAILED]
# vi local.te

module local 1.0;

require {
        type file_t;
        type mysqld_t;
        class dir { getattr search };
}

#============= mysqld_t ==============
allow mysqld_t file_t:dir { getattr search };

ESC ZZ

Das Modul wird nun als Binärdatei übersetzt und in ein gültiges Nicht-Standard-Modulpaket umgebaut und installiert:

# checkmodule local.te -M -m -o local.mo
checkmodule:  loading policy configuration from local.te
checkmodule:  policy configuration loaded
checkmodule:  writing binary representation (version 10) to local.mo
# semodule_package -m local.mo -o local.pp
# semodule -i local.pp

Zum Abschluss werden für den neuen Ort der Datenbank-Files die SELinux-Label wiederhergestellt und der Dienst letztendlich gestartet:

# semanage fcontext -a -t mysqld_db_t "/data/mysql(/.*)?"
# restorecon -R /data/mysql
# service mysqld start
Starting mysqld:                                           [  OK  ]

Falls das MySQL-Socket von ihrem Standardplatz /var/lib/mysql/mysql.sock verschoben wurde, kann der MySQL-Client es nicht finden. Hier schafft ein symbolischer Link abhilfe:

# ln -s /data/mysql/mysql.sock /var/lib/mysql/mysql.sock

computer/linux/mysql_datenbank_mit_luks_und_selinux.txt · Zuletzt geändert: 2012/11/24 10:03 von christian