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.
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
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: ....
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
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 ]
# ln -s /data/mysql/mysql.sock /var/lib/mysql/mysql.sock