Akses ke server MySQL dikendalikan melalui akun pengguna yang dilengkapi sekumpulan hak (privilege), yaitu izin untuk menjalankan operasi tertentu pada objek tertentu. Topik ini membahas pembuatan akun dengan CREATE USER, pemberian hak dengan GRANT, pencabutan hak dengan REVOKE, serta penerapan prinsip hak seminimal mungkin (least privilege): setiap akun hanya diberi hak yang benar-benar dibutuhkan tugasnya, tidak lebih. Setelah membacanya, pembuatan akun kerja terbatas yang aman untuk aplikasi maupun operator dapat dilakukan tanpa menyentuh akun root.
Akun dan autentikasi#
Akun MySQL dinyatakan dalam bentuk 'nama'@'host', sehingga identitasnya mencakup dua bagian sekaligus: nama pengguna dan asal koneksi yang diperbolehkan. Akun 'pustakawan'@'localhost' hanya dapat dipakai dari komputer server itu sendiri, sedangkan 'pustakawan'@'%.perpustakaan.id' dapat dipakai dari mesin mana pun pada domain tersebut. Kata sandi disimpan sebagai hash, bukan sebagai teks biasa, dan pemeriksaannya dilakukan oleh plugin autentikasi bawaan bernama caching_sha2_password sejak MySQL 8.0.
Pernyataan berikut membuat akun kerja untuk operator perpustakaan. DROP USER IF EXISTS diletakkan lebih dahulu agar urutan perintah dapat dijalankan ulang dari keadaan apa pun tanpa menimbulkan error akun ganda.
-- tidak-dijalankan
DROP USER IF EXISTS 'nama'@'localhost';
CREATE USER 'nama'@'localhost' IDENTIFIED BY 'kata-sandi';# membuat akun pustakawan yang baru
mysql -u root <<'SQL'
DROP USER IF EXISTS 'pustakawan'@'localhost';
CREATE USER 'pustakawan'@'localhost' IDENTIFIED BY 'RahasiaKuat123';
SQLAkun yang baru dibuat belum memiliki hak apa pun. Kondisi itu dapat diverifikasi dengan SHOW GRANTS, dan hasilnya hanya memuat satu hak bernama USAGE, yaitu hak “tanpa hak” yang sekadar menandai keberadaan akun.
# memeriksa hak akun yang baru dibuat
mysql -u root -e "SHOW GRANTS FOR 'pustakawan'@'localhost';"Grants for pustakawan@localhost
GRANT USAGE ON *.* TO `pustakawan`@`localhost`Percobaan masuk dengan kata sandi yang salah langsung ditolak oleh server. Pesan errornya menyebut bagian host dari akun dan memberitahukan bahwa kata sandi memang dikirim, sehingga kegagalan terjadi pada tahap autentikasi.
# percobaan masuk dengan kata sandi yang salah
mysql -u pustakawan -p'SalahTebakan' -e "SELECT 1;"mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'pustakawan'@'localhost' (using password: YES)Memberi hak dengan GRANT#
Hak diberikan melalui GRANT dengan pola GRANT hak ON objek TO akun. Lingkup objeknya bertingkat: *.* mencakup seluruh server, perpustakaan.* mencakup satu basis data, dan perpustakaan.buku mencakup satu tabel saja. Semakin sempit lingkupnya, semakin sedikit pintu yang terbuka bagi akun tersebut.
Sebagai sasaran pemberian hak, basis data perpustakaan beserta tabel buku disiapkan terlebih dahulu oleh root.
# menyiapkan basis data perpustakaan beserta isinya
mysql -u root <<'SQL'
DROP DATABASE IF EXISTS perpustakaan;
CREATE DATABASE perpustakaan;
USE perpustakaan;
CREATE TABLE buku (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
judul VARCHAR(120) NOT NULL,
penulis VARCHAR(80) NOT NULL,
stok TINYINT UNSIGNED NOT NULL DEFAULT 0
);
INSERT INTO buku (judul, penulis, stok) VALUES
('Dasar Basis Data Relasional', 'Dewi Sartika', 4),
('Jaringan Komputer Dasar', 'Ali Rahman', 2),
('Pengantar Statistika', 'Budi Hartono', 7);
SQLAkun pustakawan kemudian diberi tiga hak pada level basis data: SELECT untuk membaca, INSERT untuk menambah, dan UPDATE untuk mengubah. Hak DELETE sengaja tidak diberikan karena tugas operator tidak meliputi penghapusan data.
# memberi tiga hak pada basis data perpustakaan
mysql -u root -e "GRANT SELECT, INSERT, UPDATE ON perpustakaan.* TO 'pustakawan'@'localhost'; SHOW GRANTS FOR 'pustakawan'@'localhost';"Grants for pustakawan@localhost
GRANT USAGE ON *.* TO `pustakawan`@`localhost`
GRANT SELECT, INSERT, UPDATE ON `perpustakaan`.* TO `pustakawan`@`localhost`Sesi berikut membuktikan bahwa hak tersebut benar-benar berlaku. Pustakawan menyisipkan satu baris baru lalu membaca seluruh tabel tanpa hambatan.
# bekerja sebagai pustakawan: menyisipkan dan membaca
mysql -t -u pustakawan -p'RahasiaKuat123' perpustakaan <<'SQL'
INSERT INTO buku (judul, penulis, stok)
VALUES ('Pemrograman SQL untuk Pemula', 'Citra Lestari', 3);
SELECT id, judul, stok FROM buku ORDER BY id;
SQLmysql: [Warning] Using a password on the command line interface can be insecure.
+----+------------------------------+------+
| id | judul | stok |
+----+------------------------------+------+
| 1 | Dasar Basis Data Relasional | 4 |
| 2 | Jaringan Komputer Dasar | 2 |
| 3 | Pengantar Statistika | 7 |
| 4 | Pemrograman SQL untuk Pemula | 3 |
+----+------------------------------+------+Sesuai rencana, operasi yang berada di luar hak akan ditolak. Percobaan penghapusan baris berakhir dengan error 1142 yang menyebut perintah, akun, dan tabelnya.
# percobaan penghapusan yang tidak dilindungi hak apa pun
mysql -u pustakawan -p'RahasiaKuat123' -e "DELETE FROM perpustakaan.buku WHERE id = 1;"mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1142 (42000) at line 1: DELETE command denied to user 'pustakawan'@'localhost' for table 'buku'Penolakan juga terjadi pada objek yang tidak pernah disebutkan dalam GRANT. Basis data sistem mysql berada di luar lingkup perpustakaan.*, sehingga percobaan membukanya menghasilkan error 1044, yaitu error akses ditolak pada tingkat basis data.
# percobaan membuka basis data sistem yang tidak diizinkan
mysql -u pustakawan -p'RahasiaKuat123' -e "USE mysql;"mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1044 (42000) at line 1: Access denied for user 'pustakawan'@'localhost' to database 'mysql'Mencabut hak dengan REVOKE#
REVOKE bekerja berlawanan dengan GRANT dan memakai pola yang sama: hak yang dicabut, objeknya, lalu akunnya. Pernyataan berikut mencabut hak INSERT, sehingga sisa hak akun hanya SELECT dan UPDATE.
# mencabut hak INSERT dari akun pustakawan
mysql -u root -e "REVOKE INSERT ON perpustakaan.* FROM 'pustakawan'@'localhost'; SHOW GRANTS FOR 'pustakawan'@'localhost';"Grants for pustakawan@localhost
GRANT USAGE ON *.* TO `pustakawan`@`localhost`
GRANT SELECT, UPDATE ON `perpustakaan`.* TO `pustakawan`@`localhost`Dampaknya langsung terasa pada koneksi berikutnya. Penyisipan yang sebelumnya berhasil kini ditolak dengan error 1142.
# penyisipan kembali ditolak setelah hak dicabut
mysql -u pustakawan -p'RahasiaKuat123' -e "INSERT INTO perpustakaan.buku (judul, penulis, stok) VALUES ('Uji', 'Rina Kartika', 1);"mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1142 (42000) at line 1: INSERT command denied to user 'pustakawan'@'localhost' for table 'buku'Prinsip hak seminimal mungkin dijalankan dengan pola tiga langkah yang sama pada setiap akun baru: buat akun tanpa hak, beri hak sesuai daftar tugas yang tertulis, lalu audit daftar haknya dengan SHOW GRANTS secara berkala. Akun aplikasi web, misalnya, biasanya cukup dengan SELECT, INSERT, UPDATE, dan DELETE pada satu basis data aplikasi saja, tanpa hak administratif apa pun.
Kesalahan umum#
Kesalahan pertama adalah memakai akun root untuk aplikasi atau untuk pekerjaan sehari-hari. Root melewati seluruh pemeriksaan hak, sehingga satu kesalahan query, misalnya UPDATE tanpa klausa WHERE, langsung menimpa data tanpa penahan apa pun. Akun kerja terbatas membuat kesalahan semacam itu tetap terkandung pada lingkup haknya.
Kesalahan kedua adalah menganggap GRANT otomatis membuat akun. Perilaku lama itu sudah dimatikan sejak MySQL 8.0: GRANT yang ditujukan pada akun yang belum ada berakhir dengan error, dan akun memang harus dibuat lewat CREATE USER terlebih dahulu. Pemisahan ini membuat daftar akun dan daftar hak dapat diaudit secara terpisah.
Kesalahan ketiga adalah menjalankan FLUSH PRIVILEGES setelah setiap GRANT atau REVOKE. Perintah itu hanya diperlukan apabila tabel hak pada basis data mysql diubah langsung dengan INSERT atau UPDATE, sebuah praktik yang sebaiknya ditinggalkan. Pernyataan CREATE USER, GRANT, dan REVOKE sudah menyesuaikan hak yang berlaku seketika.
Ringkasan#
- Akun MySQL terdiri atas nama dan asal host,
'nama'@'host', dan dibuat dengan CREATE USER sebelum menerima hak apa pun. - GRANT memberi hak pada lingkup bertingkat dari
*.*, satu basis data, hingga satu tabel, sedangkan REVOKE mencabutnya dengan pola yang sama. - Penolakan akses muncul sebagai error 1045 pada kegagalan autentikasi, error 1044 pada tingkat basis data, dan error 1142 pada tingkat tabel, lengkap dengan akun dan objeknya.
- Prinsip hak seminimal mungkin diterapkan dengan memberi hak sesuai daftar tugas dan memeriksa hasilnya dengan SHOW GRANTS.
Referensi#
- CREATE USER Statement — Oracle — Sintaks CREATE USER, aturan penamaan akun, dan plugin autentikasi bawaan MySQL 8.0.
- GRANT Statement — Oracle — Daftar hak yang dapat diberikan dan aturan lingkup objek pada GRANT.
- REVOKE Statement — Oracle — Cara mencabut hak dari akun beserta perilaku hak yang sedang dipakai.