Linux : Praktikum Membangun Skema Nilai dan Audit Hak Akses Database MariaDB
Artikel pagi menjelaskan bagaimana database server bekerja: layanan yang menunggu, dua lapis identitas, dan datadir yang tidak boleh disalin sembarangan. Artikel ini melanjutkannya dengan praktik.
Kamu akan membangun skema nilai sekolah yang rapi, memberi akun aplikasi hak minimum, lalu membuktikan batas hak itu satu per satu. Semua latihan dilakukan di VM sendiri, bukan server produksi.
π― Tujuan
Setelah mengikuti latihan ini, kamu bisa:
- membangun skema relasional sederhana dengan kunci primer, kunci unik, dan foreign key;
- membuat akun aplikasi yang hanya bisa melakukan pekerjaannya, bukan seluruh pekerjaan server;
- membaca bukti hak akses dari tiga sumber:
SHOW GRANTS, tabelinformation_schema, dan uji perintah langsung; - membedakan kegagalan hak akses tingkat database, tabel, dan kolom;
- menemukan view yang diam-diam memberi hak lebih besar dari yang terlihat.
π Konteks nyata
Bayangkan lemari arsip di ruang guru. Ada kunci pintu ruang guru, kunci loker per kelas, dan kunci lemari nilai. Guru wali kelas memegang kunci lokernya sendiri, bukan kunci seluruh lemari.
Database bekerja dengan cara yang sama. Satu akun aplikasi tidak perlu bisa menghapus database, membaca tabel pengguna lain, atau mengubah struktur tabel. Ia hanya perlu membaca dan menulis di meja kerjanya.
Masalahnya, banyak aplikasi sekolah memakai akun root karena "biar tidak ada error hak akses". Itu sama seperti membagikan kunci induk gedung ke setiap petugas kebersihan: praktis, sampai ada satu perintah salah yang menghapus data satu angkatan.
π₯ Kasus nyata: Sebuah SMK memakai akun root untuk aplikasi nilai karena pengembangnya tidak mau repot mengurus GRANT. Suatu sore, menu "bersihkan kelas" dijalankan tanpa filter dan menghapus seluruh baris nilai satu tingkat. Karena akun itu juga bisa membaca mysql.user, berkas dump yang dibagikan ke vendor ikut memuat hash sandi semua akun. Sekolah harus mereset seluruh akun dan merekap nilai manual selama dua minggu.
π§ Konsep singkat
πΉ Hak akses itu tangga, bukan saklar
Hak di MariaDB diberikan pada tingkat tertentu. Makin ke bawah, makin sempit, dan makin aman.
| Tingkat | Contoh penulisan | Arti |
|---|---|---|
| Global | ON *.* |
semua database di server |
| Database | ON lab_nilai.* |
semua objek dalam satu database |
| Tabel | ON lab_nilai.nilai |
satu tabel saja |
| Kolom | ON lab_nilai.siswa (nama) |
satu kolom saja |
Aturan praktisnya: beri hak paling sempit yang masih membuat aplikasi berjalan. Kalau aplikasi hanya membaca daftar mapel, cukup SELECT pada tabel itu.
β οΈ Hati-hati: GRANT ALL ON *.* terlihat seperti satu baris yang menyelesaikan semua masalah. Kenyataannya kamu memberi akun itu kemampuan membaca tabel sistem, mengubah akun lain, dan mematikan server.
πΉ Satu akun, dua nama
Akun MariaDB selalu ditulis sebagai 'nama'@'host'. Host adalah pola alamat asal koneksi, bukan nama komputer.
'app_nilai'@'localhost'β hanya untuk koneksi lewat socket lokal.'app_nilai'@'192.168.100.%'β untuk koneksi TCP dari jaringan itu.'app_nilai'@'%'β dari mana saja, termasuk internet kalau port terbuka.
Saat klien tersambung, server memilih tepat satu akun: nama yang cocok persis, lalu pola host paling spesifik. Setelah itu, pemeriksaan hak di tingkat database dan tabel memakai nama akun tadi bersama host asal koneksi yang sebenarnya.
π‘ Tips: Dua fungsi ini menjawab dua pertanyaan berbeda. USER() adalah nama yang kamu ketik saat login, sedangkan CURRENT_USER() adalah akun yang benar-benar dipakai server. Kalau keduanya beda, ada pola host lain yang menang.
πΉ Skema yang menjaga diri sendiri
Hak akses mengatur siapa boleh menyentuh tabel. Skema mengatur data seperti apa yang boleh masuk. Dua-duanya harus ada.
PRIMARY KEYmencegah baris kembar.UNIQUEmencegah NIS yang sama dipakai dua siswa.FOREIGN KEYmencegah nilai menunjuk siswa yang tidak ada.INDEXmembuat pencarian per kelas tidak memindai seluruh tabel.
π Angka penting: Foreign key bertipe RESTRICT menolak penghapusan induk dengan kode 1451. Penyisipan anak tanpa induk ditolak dengan kode 1452.
πΉ View punya kunci sendiri
View adalah jendela ke tabel. Secara bawaan, view dibuat dengan SQL SECURITY DEFINER β artinya hak yang dipakai adalah hak pembuat view, bukan hak orang yang membukanya.
Kalau root membuat view di atas tabel rahasia lalu memberi SELECT pada view itu, penerima bisa membaca isi tabel rahasia tanpa pernah diberi hak ke tabelnya. Ini bukan bug; ini fitur yang sering dipakai tanpa sadar.
π§© Istilah penting
- Privilege β izin melakukan satu jenis tindakan, misalnya
SELECTatauDROP. - GRANT β perintah memberi izin. REVOKE mencabutnya.
- Akun β pasangan nama dan pola host, misalnya
'app_nilai'@'localhost'. - Skema β kumpulan tabel, view, dan aturan di dalam satu database.
- Foreign key β aturan yang menyatakan nilai kolom harus ada di tabel induk.
- Orphan row β baris anak yang induknya sudah tidak ada; biasanya lahir dari pemeriksaan foreign key yang dimatikan.
- Definer β akun yang haknya dipakai saat view atau routine dijalankan.
- SQL SECURITY β pilihan
DEFINERatauINVOKERuntuk menentukan hak siapa yang dipakai. - Collation β aturan membandingkan huruf, misalnya besar-kecil dianggap sama atau tidak.
- Lock wait β waktu tunggu saat baris yang sama sedang diubah transaksi lain.
- Dump β berkas teks berisi perintah untuk membangun ulang isi database.
π§ Praktik: membangun skema nilai dan mengaudit hak akses
Siapkan VM Debian atau Ubuntu dengan MariaDB terpasang. Semua perintah administrator memakai sudo mariadb; perintah aplikasi memakai akun terbatas.
πΉ Langkah 0: potret keadaan awal
Catat dulu kenyataan server, jangan menebak dari ingatan:
systemctl is-active mariadb
mariadb --version
sudo mariadb -e "SELECT @@version, @@sql_mode, @@character_set_server, @@innodb_lock_wait_timeout;"
sudo mariadb -e "SELECT user, host, plugin FROM mysql.user ORDER BY user;"
Di VM uji penulis, hasilnya MariaDB 10.11.14, sql_mode memuat STRICT_TRANS_TABLES, charset server utf8mb4, dan innodb_lock_wait_timeout bernilai 50 detik.
π Angka penting: Catat empat angka ini di lembar kerja: versi, sql_mode, charset, dan lock timeout. Banyak masalah "data aneh" berakar di salah satu dari empat angka itu.
πΉ Langkah 1: bangun skema nilai
Buat database baru dengan charset yang benar sejak awal:
sudo mariadb <<'SQL'
DROP DATABASE IF EXISTS lab_nilai;
CREATE DATABASE lab_nilai
CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
USE lab_nilai;
CREATE TABLE siswa (
id INT PRIMARY KEY AUTO_INCREMENT,
nis CHAR(8) NOT NULL UNIQUE,
nama VARCHAR(80) NOT NULL,
kelas VARCHAR(10) NOT NULL,
INDEX idx_kelas (kelas)
) ENGINE=InnoDB;
CREATE TABLE mapel (
id TINYINT PRIMARY KEY,
nama VARCHAR(40) NOT NULL
) ENGINE=InnoDB;
CREATE TABLE nilai (
id INT PRIMARY KEY AUTO_INCREMENT,
siswa_id INT NOT NULL,
mapel_id TINYINT NOT NULL,
skor DECIMAL(5,2) NOT NULL,
dicatat DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uq_nilai (siswa_id, mapel_id),
CONSTRAINT fk_nilai_siswa FOREIGN KEY (siswa_id)
REFERENCES siswa(id) ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT fk_nilai_mapel FOREIGN KEY (mapel_id)
REFERENCES mapel(id) ON DELETE RESTRICT
) ENGINE=InnoDB;
SQL
Perhatikan uq_nilai: satu siswa hanya punya satu nilai per mapel. Tanpa kunci unik itu, input ganda akan lolos dan rata-rata kelas jadi salah tanpa error.
sudo mariadb lab_nilai -e "SHOW CREATE TABLE nilai\G"
sudo mariadb -e "SELECT CONSTRAINT_NAME, TABLE_NAME, REFERENCED_TABLE_NAME
FROM information_schema.REFERENTIAL_CONSTRAINTS
WHERE CONSTRAINT_SCHEMA='lab_nilai';"
πΉ Langkah 2: isi data dan buktikan charset
Masukkan data yang sengaja memuat huruf beraksen dan emoji:
sudo mariadb lab_nilai <<'SQL'
INSERT INTO mapel VALUES (1,'Matematika'), (2,'Bahasa Indonesia');
INSERT INTO siswa (nis, nama, kelas) VALUES
('24250001','Ayu NirΓ‘ha','X TKJ 1'),
('24250002','Bagas Pratama','X TKJ 1'),
('24250003','Rizky π Nugraha','X TKJ 2');
INSERT INTO nilai (siswa_id, mapel_id, skor) VALUES
(1,1,88.50), (1,2,91.00), (2,1,74.25), (3,2,80.00);
SQL
sudo mariadb lab_nilai -e "SELECT s.nama, m.nama AS mapel, n.skor
FROM nilai n
JOIN siswa s ON s.id = n.siswa_id
JOIN mapel m ON m.id = n.mapel_id
ORDER BY s.kelas, s.nama;"
Kalau emoji tampil sebagai tanda tanya, jangan langsung menyalahkan aplikasi. Periksa charset di tiga tempat:
sudo mariadb -e "SHOW VARIABLES LIKE 'character_set%';"
sudo mariadb lab_nilai -e "SHOW FULL COLUMNS FROM siswa LIKE 'nama';"
πΉ Langkah 3: buat akun aplikasi dengan hak minimum
Akun ini hanya boleh membaca daftar mapel, serta membaca dan menulis siswa dan nilai. Tidak ada DELETE, tidak ada hak membuat tabel.
sudo mariadb <<'SQL'
CREATE USER 'app_nilai'@'localhost'
IDENTIFIED BY 'SandiLab-Nilai-2026';
GRANT SELECT ON lab_nilai.mapel TO 'app_nilai'@'localhost';
GRANT SELECT, INSERT, UPDATE ON lab_nilai.siswa TO 'app_nilai'@'localhost';
GRANT SELECT, INSERT, UPDATE ON lab_nilai.nilai TO 'app_nilai'@'localhost';
SQL
CREATE USER dan GRANT langsung berlaku. Kamu tidak perlu FLUSH PRIVILEGES; perintah itu hanya untuk perubahan langsung pada tabel hak akses.
πΉ Langkah 4: uji tangga hak satu per satu
Jalankan sebagai akun aplikasi, bukan sebagai root:
mariadb -u app_nilai -p lab_nilai -e "SELECT COUNT(*) FROM siswa;"
mariadb -u app_nilai -p lab_nilai -e "DELETE FROM nilai WHERE id = 1;"
mariadb -u app_nilai -p lab_nilai -e "CREATE TABLE uji_hak (id INT);"
mariadb -u app_nilai -p -e "SELECT user, host FROM mysql.user;"
mariadb -u app_nilai -p -e "DROP DATABASE lab_nilai;"
Empat perintah terakhir harus gagal. Perhatikan kode dan namanya, karena tiap kode menunjuk lapis yang berbeda:
1142β perintah ditolak pada objek tertentu, misalnyaDELETE command denied.1044β akun tidak punya hak pada database itu, misalnya saatDROP DATABASE.1045β akun atau sandi tidak cocok saat menyambung.
πΉ Langkah 5: audit dari sisi server
Aplikasi bisa berbohong tentang haknya; tabel sistem tidak. Mulai dari yang paling ringkas:
sudo mariadb -e "SHOW GRANTS FOR 'app_nilai'@'localhost';"
Lalu periksa ketiga tingkat hak secara terpisah:
sudo mariadb -e "SELECT GRANTEE, PRIVILEGE_TYPE
FROM information_schema.USER_PRIVILEGES
WHERE GRANTEE LIKE \"'app_nilai'%\";"
sudo mariadb -e "SELECT GRANTEE, TABLE_SCHEMA, PRIVILEGE_TYPE
FROM information_schema.SCHEMA_PRIVILEGES
WHERE GRANTEE LIKE \"'app_nilai'%\";"
sudo mariadb -e "SELECT GRANTEE, TABLE_SCHEMA, TABLE_NAME, PRIVILEGE_TYPE
FROM information_schema.TABLE_PRIVILEGES
WHERE GRANTEE LIKE \"'app_nilai'%\";"
Di latihan ini, USER_PRIVILEGES hanya berisi USAGE β arti harfiahnya "boleh login, belum boleh apa-apa". Hak sebenarnya ada di TABLE_PRIVILEGES. Kalau kamu hanya melihat USAGE lalu menyimpulkan akun tidak punya hak, kamu membaca tabel yang salah.
πΉ Langkah 6: buktikan isolasi antar database
Buat database kedua dengan akun berbeda, lalu coba saling menembus:
sudo mariadb <<'SQL'
CREATE DATABASE lab_kasir CHARACTER SET utf8mb4;
CREATE TABLE lab_kasir.transaksi (
id INT PRIMARY KEY AUTO_INCREMENT,
total DECIMAL(12,2) NOT NULL
) ENGINE=InnoDB;
INSERT INTO lab_kasir.transaksi (total) VALUES (150000), (275000);
CREATE USER 'app_kasir'@'localhost'
IDENTIFIED BY 'SandiLab-Kasir-2026';
GRANT SELECT, INSERT ON lab_kasir.* TO 'app_kasir'@'localhost';
SQL
mariadb -u app_nilai -p -e "SELECT COUNT(*) FROM lab_kasir.transaksi;"
mariadb -u app_kasir -p -e "SELECT COUNT(*) FROM lab_nilai.nilai;"
Keduanya harus ditolak dengan 1142. Ini bukti bahwa hak ON lab_nilai.* bukan hak global.
πΉ Langkah 7: temukan view yang membocorkan hak
Sekarang bagian yang paling sering terlewat. Buat tabel catatan guru dan view di atasnya:
sudo mariadb lab_nilai <<'SQL'
CREATE TABLE catatan_guru (
id INT PRIMARY KEY AUTO_INCREMENT,
siswa_id INT NOT NULL,
catatan VARCHAR(200),
CONSTRAINT fk_catatan_siswa FOREIGN KEY (siswa_id)
REFERENCES siswa(id) ON DELETE RESTRICT
) ENGINE=InnoDB;
INSERT INTO catatan_guru (siswa_id, catatan) VALUES
(1,'Perlu pendampingan matematika'),
(3,'Aktif di praktikum');
CREATE SQL SECURITY DEFINER VIEW v_catatan AS
SELECT id, siswa_id, catatan FROM catatan_guru;
GRANT SELECT ON lab_nilai.v_catatan TO 'app_nilai'@'localhost';
SQL
Uji dari sisi aplikasi:
mariadb -u app_nilai -p lab_nilai -e "SELECT * FROM catatan_guru;"
mariadb -u app_nilai -p lab_nilai -e "SELECT * FROM v_catatan;"
Perintah pertama ditolak, perintah kedua berhasil. Aplikasi tidak pernah diberi hak ke catatan_guru, tetapi tetap bisa membaca seluruh isinya lewat view.
Cari view seperti ini di server nyata:
sudo mariadb -e "SELECT TABLE_SCHEMA, TABLE_NAME, SECURITY_TYPE, DEFINER
FROM information_schema.VIEWS
WHERE SECURITY_TYPE='DEFINER';"
Perbaiki dengan mengubah sifat view, lalu uji ulang:
sudo mariadb lab_nilai -e "ALTER ALGORITHM=UNDEFINED
SQL SECURITY INVOKER VIEW v_catatan
AS SELECT id, siswa_id, catatan FROM catatan_guru;"
mariadb -u app_nilai -p lab_nilai -e "SELECT * FROM v_catatan;"
Sekarang perintah terakhir ikut ditolak, karena hak yang dipakai adalah hak pemanggil.
πΉ Langkah 8: uji rusak terkendali AβH
Jalankan satu per satu, lalu kembalikan keadaan sebelum lanjut. Tujuannya bukan merusak server, tetapi mengenali gejala.
- Uji A β hak tabel, bukan hak database. Cabut hak tabel lalu beri hak satu tabel saja:Baris pertama sukses, baris kedua
sudo mariadb -e "REVOKE ALL PRIVILEGES ON lab_nilai.* FROM 'app_nilai'@'localhost';" sudo mariadb -e "GRANT SELECT ON lab_nilai.nilai TO 'app_nilai'@'localhost';" mariadb -u app_nilai -p lab_nilai -e "SELECT COUNT(*) FROM nilai;" mariadb -u app_nilai -p lab_nilai -e "SELECT COUNT(*) FROM siswa;"
1142. Artinya hak tabel tidak menular ke tabel tetangga.
- Uji B β pola host terlalu sempit. Buat akun untuk jaringan lain, lalu sambung dari lokal:Hasilnya
sudo mariadb -e "CREATE USER 'app_pindah'@'192.168.100.%' IDENTIFIED BY 'SandiPindah-2026';" sudo mariadb -e "GRANT SELECT ON lab_nilai.* TO 'app_pindah'@'192.168.100.%';" mariadb -u app_pindah -p -e "SELECT COUNT(*) FROM lab_nilai.siswa;" sudo mariadb -e "SELECT user, host FROM mysql.user WHERE user='app_pindah';"
1045 Access denied ... 'app_pindah'@'localhost'. Pesannya menyebutlocalhost, bukan alamat yang kamu kira. Itu petunjuk bahwa pola host tidak cocok.
- Uji C β sandi benar, akun salah. Buat dua akun bernama sama dengan pola host dan sandi berbeda:Percobaan pertama ditolak walau sandinya "ada di server". Yang dicek adalah sandi akun yang menang saat pencocokan host.
sudo mariadb <<'SQL' CREATE USER 'app_dua'@'localhost' IDENTIFIED BY 'SandiLokal-2026'; CREATE USER 'app_dua'@'%' IDENTIFIED BY 'SandiJaringan-2026'; GRANT SELECT ON lab_nilai.* TO 'app_dua'@'localhost'; GRANT SELECT ON lab_nilai.* TO 'app_dua'@'%'; SQL mariadb -u app_dua -p -e "SELECT CURRENT_USER();" # pakai sandi jaringan mariadb -u app_dua -p -e "SELECT CURRENT_USER();" # pakai sandi lokal
- Uji D β foreign key dimatikan. Lihat apa yang terjadi pada data:Percobaan pertama
sudo mariadb lab_nilai -e "INSERT INTO nilai (siswa_id, mapel_id, skor) VALUES (99, 1, 70);" sudo mariadb lab_nilai <<'SQL' SET foreign_key_checks = 0; INSERT INTO nilai (siswa_id, mapel_id, skor) VALUES (99, 1, 70); SET foreign_key_checks = 1; SQL sudo mariadb lab_nilai -e "SELECT n.id, n.siswa_id FROM nilai n LEFT JOIN siswa s ON s.id = n.siswa_id WHERE s.id IS NULL;"
1452. Percobaan kedua berhasil dan meninggalkan baris yatim. Artinya pemeriksaan foreign key bisa dimatikan per sesi, jadi aplikasi tetap perlu memvalidasi.
- Uji E β charset yang salah sejak lahir. Bandingkan dua tabel:Baris pertama masuk, baris kedua
sudo mariadb lab_nilai <<'SQL' CREATE TABLE uji_latin (nama VARCHAR(20)) CHARSET=latin1; INSERT INTO uji_latin VALUES ('Ayu NirΓ‘ha'); INSERT INTO uji_latin VALUES ('Rizky π'); SQL1366 Incorrect string value. Huruf beraksen muat dilatin1, emoji butuh 4 byte dan tidak muat. Perbaikannya bukan menambal aplikasi, tetapi membuat ulang kolom denganutf8mb4.
- Uji F β sql_mode longgar memotong data diam-diam.Dengan mode ketat, penyisipan ditolak
sudo mariadb lab_nilai -e "CREATE TABLE uji_potong (nama VARCHAR(10)) CHARSET=utf8mb4;" sudo mariadb lab_nilai -e "INSERT INTO uji_potong VALUES ('Muhammad Rizky Pratama');" sudo mariadb lab_nilai -e "SET SESSION sql_mode=''; INSERT INTO uji_potong VALUES ('Muhammad Rizky Pratama');" sudo mariadb lab_nilai -e "SELECT nama, CHAR_LENGTH(nama) FROM uji_potong;" sudo mariadb -e "SHOW WARNINGS;"1406 Data too long. Tanpa mode ketat, data dipotong menjadi 10 karakter dan hanya muncul peringatan. Aplikasi yang tidak membaca peringatan akan menyimpan nama yang salah tanpa sadar.
- Uji G β lock wait pada baris yang sama. Buka dua terminal. Terminal pertama mengunci baris dan tidak commit:Terminal kedua menunggu sebentar lalu menyerah:
sudo mariadb lab_nilai -e "BEGIN; SELECT * FROM nilai WHERE id=1 FOR UPDATE; SELECT SLEEP(60);"
Hasilnyamariadb -u app_nilai -p lab_nilai -e "SET SESSION innodb_lock_wait_timeout=5; UPDATE nilai SET skor=95 WHERE id=1;"
1205 Lock wait timeout exceededsetelah sekitar 5 detik. Di aplikasi, gejala ini terlihat seperti halaman yang menggantung lalu error, bukan seperti masalah hak akses.
- Uji H β akun aplikasi dipakai untuk mengubah struktur. Coba migrasi dari akun aplikasi:Ditolak
mariadb -u app_nilai -p lab_nilai -e "ALTER TABLE nilai ADD COLUMN catatan VARCHAR(50);"
1142. Ini yang diinginkan. Migrasi skema harus dijalankan akun terpisah dengan hakALTER, bukan akun yang dipakai aplikasi setiap hari.
πΉ Langkah 9: dump, restore, dan bukti data utuh
Ambil dump logis, lalu pulihkan ke database uji:
sudo mkdir -p /srv/lab-db
sudo mariadb-dump --single-transaction --routines --triggers \
lab_nilai > /srv/lab-db/nilai-$(date +%F).sql
grep -c "CREATE TABLE" /srv/lab-db/nilai-$(date +%F).sql
sudo mariadb -e "DROP DATABASE IF EXISTS lab_uji;
CREATE DATABASE lab_uji CHARACTER SET utf8mb4;"
sudo mariadb lab_uji < /srv/lab-db/nilai-$(date +%F).sql
Bandingkan jumlah baris dan cari baris yatim:
sudo mariadb -e "SELECT
(SELECT COUNT(*) FROM lab_nilai.nilai) AS asli,
(SELECT COUNT(*) FROM lab_uji.nilai) AS uji;"
sudo mariadb -e "SELECT COUNT(*) FROM lab_uji.nilai n
LEFT JOIN lab_uji.siswa s ON s.id = n.siswa_id
WHERE s.id IS NULL;"
Kedua angka harus sama, dan hasil terakhir harus 0. Kalau jumlah baris sama tetapi ada baris yatim, berarti dump membawa data yang memang sudah rusak sebelum di-dump.
β οΈ Hati-hati: mariadb-dump menyertakan DROP TABLE secara bawaan. Saat memulihkan ke database yang sudah berisi, tabel lama akan diganti. Pastikan nama database tujuan benar sebelum menekan Enter.
πΉ Langkah 10: bersih-bersih
Hapus seluruh bahan latihan supaya VM tidak menumpuk database percobaan:
sudo mariadb <<'SQL'
DROP DATABASE IF EXISTS lab_uji;
DROP DATABASE IF EXISTS lab_kasir;
DROP DATABASE IF EXISTS lab_nilai;
DROP USER IF EXISTS 'app_nilai'@'localhost';
DROP USER IF EXISTS 'app_kasir'@'localhost';
DROP USER IF EXISTS 'app_pindah'@'192.168.100.%';
DROP USER IF EXISTS 'app_dua'@'localhost';
DROP USER IF EXISTS 'app_dua'@'%';
SQL
sudo mariadb -e "SHOW DATABASES;"
sudo mariadb -e "SELECT user, host FROM mysql.user;"
π Dipakai di dunia kerja
- Sekolah: aplikasi nilai dan absensi memakai akun sendiri per modul. Saat guru menemukan data hilang, admin bisa menunjuk modul mana yang terakhir menulis, bukan menebak seluruh aplikasi.
- Kantor distributor: tim sales hanya mendapat view stok, tim gudang mendapat hak tulis, dan akun laporan hanya boleh
SELECT. Kecelakaan "hapus faktur" tidak mungkin datang dari akun laporan. - Klinik: rekam medis dipisahkan per database dan per akun layanan. Ketika ada audit, daftar hak akses menjadi bukti siapa boleh melihat apa.
- ISP dan warnet: data pelanggan dan data billing biasanya tumbuh di server yang sama. Akun terpisah mencegah satu bug di halaman billing membaca seluruh data pelanggan.
- Industri manufaktur: aplikasi lini produksi menulis ke tabel hasil ukur, sementara aplikasi kualitas hanya membaca. Pemisahan ini membuat kesalahan input tidak menyebar ke laporan manajemen.
- Hosting dan pengembangan: setiap aplikasi pelanggan mendapat database dan akun sendiri. Satu akun bersama berarti satu pelanggan bisa membaca data pelanggan lain saat ada celah.
β Verifikasi
Jangan berhenti di "perintahnya tidak error". Kumpulkan bukti yang bisa ditunjukkan ke orang lain.
| Yang diperiksa | Perintah | Bukti yang diharapkan |
|---|---|---|
| Database ada | SHOW DATABASES; |
lab_nilai muncul
|
| Skema utuh | SHOW CREATE TABLE lab_nilai.nilai\G |
dua foreign key dan satu unique |
| Charset benar | SHOW FULL COLUMNS FROM lab_nilai.siswa LIKE 'nama'; |
utf8mb4
|
| Hak akun | SHOW GRANTS FOR 'app_nilai'@'localhost'; |
hanya SELECT/INSERT/UPDATE |
| Isolasi | SELECT * FROM lab_kasir.transaksi; sebagai app_nilai |
1142
|
| View aman | SELECT SECURITY_TYPE FROM information_schema.VIEWS; |
INVOKER
|
| Data utuh | bandingkan jumlah baris asli dan hasil restore | angka sama, yatim 0
|
π§ͺ Uji cepat: Satu perintah untuk melihat semua akun yang punya hak global berlebih:
sudo mariadb -e "SELECT GRANTEE, PRIVILEGE_TYPE
FROM information_schema.USER_PRIVILEGES
WHERE PRIVILEGE_TYPE IN ('SUPER','FILE','PROCESS','CREATE USER')
ORDER BY GRANTEE;"
Kalau akun aplikasi muncul di daftar itu, ada yang perlu dicabut hari ini, bukan minggu depan.
β οΈ Kesalahan umum & troubleshooting
| Kode | Pesan | Penyebab | Perbaikan |
|---|---|---|---|
| 1045 | Access denied for user ... |
akun atau sandi tidak cocok | periksa CURRENT_USER() dan pola host
|
| 1044 | Access denied ... to database |
tidak ada hak di tingkat database | beri hak ON db.* atau pakai akun lain
|
| 1142 | ... command denied to user |
hak objek kurang | tambah hak pada tabel yang benar |
| 1146 | Table ... doesn't exist |
salah database atau tabel belum dibuat | USE database yang benar
|
| 1049 | Unknown database |
nama database salah ketik | SHOW DATABASES;
|
| 1451 | Cannot delete or update a parent row |
anak masih menunjuk induk | hapus anak dulu atau ubah aturan |
| 1452 | Cannot add or update a child row |
induk tidak ada | buat induk atau perbaiki id |
| 1366 | Incorrect string value |
charset kolom tidak muat | ubah ke utf8mb4
|
| 1406 | Data too long for column |
panjang kolom kurang | perlebar kolom, jangan potong data |
| 1205 | Lock wait timeout exceeded |
baris sedang dikunci transaksi lain | cari transaksi menggantung |
β οΈ Hati-hati: Jangan menyelesaikan 1142 dengan GRANT ALL. Itu seperti membuka seluruh lemari karena satu laci macet. Cari dulu perintah mana yang ditolak, lalu beri hak terkecil untuk perintah itu.
π‘ Tips: Saat menulis pesan error ke log aplikasi, sertakan CURRENT_USER(). Tanpa itu, dua akun berbeda dengan nama sama akan terlihat identik di log.
π Angka penting: innodb_lock_wait_timeout bawaan 50 detik. Aplikasi web biasanya menyerah lebih dulu, jadi pengguna melihat halaman error padahal database masih menunggu.
π Catatan keamanan & etika
- Akun aplikasi bukan root. Beri hak hanya pada database dan tabel yang dipakai. Simpan akun administrator terpisah untuk migrasi.
- Password tidak di dalam SQL yang tersimpan. Jangan menaruh sandi di skrip yang ikut masuk repositori. Gunakan berkas environment dengan izin
600. - Audit view secara berkala. View dengan
DEFINER=root@localhostadalah jalan pintas hak yang tidak terlihat diSHOW GRANTSpenerimanya. - Dump berisi data pribadi. Nilai, catatan guru, dan identitas siswa termasuk data pribadi. Simpan dump dengan izin ketat dan jangan dibagikan lewat grup pesan.
- Tabel
mysql.usersetara kunci server. Siapa pun yang bisa membacanya bisa menyusun serangan tebak sandi lebih terarah. - Etika data orang lain. Latihan memakai data palsu. Jangan menyalin data siswa atau pasien asli ke VM latihan hanya karena "hanya untuk belajar".
π Kesimpulan
Hak akses database bukan satu saklar yang dinyalakan sekali. Ia tangga: global, database, tabel, kolom. Akun aplikasi cukup berdiri di anak tangga paling bawah yang masih membuat pekerjaannya selesai.
Skema dan hak akses bekerja berlapis. Kunci unik dan foreign key menjaga isi data, sedangkan GRANT menjaga siapa yang boleh menyentuhnya. Keduanya harus dibuktikan dengan perintah, bukan diasumsikan dari file konfigurasi.
Langkah berikutnya: ulangi latihan ini di server sekolahmu dengan akun aplikasi yang sebenarnya dipakai. Mulai dari SHOW GRANTS, lalu catat satu hak yang bisa dicabut tanpa membuat aplikasi rusak.
π Materi terkait
- Linux : MariaDB Dasar (Cara Kerja Database Server) β artikel pagi: layanan, dua lapis identitas, dan datadir.
- Debian : Database Server β pemasangan MariaDB dan
mysql_secure_installation. - Shell Scripting : Mariadb dan PhpMyAdmin β skrip pemasangan dan antarmuka web.
- Linux : Manajemen User, Group, dan sudo β konsep identitas dan kewenangan di tingkat sistem operasi.
- Linux : Praktikum Audit Akun, Group, dan Hak sudo β pola audit yang sama, tetapi untuk akun Linux.
- Linux : Praktikum Uji Restore dan Verifikasi Arsip Backup β membuktikan arsip benar-benar bisa dipulihkan.
π Referensi
- MariaDB Documentation β GRANT (tingkat hak, pencocokan akun, dan resolusi hak per tingkat).
- MariaDB Documentation β CREATE USER (format nama akun dan pencocokan pola host).
- MariaDB Documentation β CREATE VIEW (
DEFINERdanSQL SECURITY). - MariaDB Documentation β CREATE TABLE (foreign key,
ON DELETE, dan kode1451). - MariaDB Documentation β SQL Mode (arti
STRICT_TRANS_TABLES). - MariaDB Documentation β InnoDB Lock Modes (kunci baris dan
SELECT ... FOR UPDATE). - Debian manpages β mariadbd(8), mariadb(1), mariadb-dump(1).