Chapter sebelumnya menutup dengan pertanyaan yang sengaja dibiarkan terbuka: tanda tangan membuktikan siapa penulis sebuah commit, tetapi tidak mengatakan apa yang boleh dilakukan penulis itu. Prinsip least privilege — hak akses minimal — menjawabnya: setiap kredensial, kunci, dan akun hanya diberi izin paling sempit yang masih memungkinkan pemegangnya menyelesaikan pekerjaannya, tidak satu poin lebih. Git inti sama sekali tidak punya model izin — seluruh penerapan terjadi di sisi yang menerima push. Kita buktikan dulu, lalu naik lapis demi lapis sampai demo nyata satu mesin dengan dua kunci berbeda izin.

Git Inti Tidak Menguji Izin #

Git menjalankan git push untuk siapa pun yang memegang kredensial yang diterima server — sisi klien tidak punya konsep “dilarang”. Sandbox membuktikannya dengan dua klon pada repository yang sama, latihan-hak, yang memakai identitas dan username kredensial berbeda; keduanya berhasil mendorong commit ke pusat.git. Konfigurasi klon pertama milik Budi:

ini
[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[user]
        name = Budi Santoso
        email = [email protected]
[credential]
        username = budi-laptop
[remote "origin"]
        url = ../pusat.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
        remote = origin
        merge = refs/heads/main

Klon kedua diperuntukkan bagi bot CI — konfigurasinya memuat identitas dan username kredensial yang berbeda untuk repository yang sama:

ini
[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote "origin"]
        url = /home/z/my-project/tutorial-extracted/work/sandbox/keamanan-dan-akses/part-b/latihan-hak/pusat.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
        remote = origin
        merge = refs/heads/main
[user]
        name = Bot CI
        email = [email protected]
[credential]
        username = bot-toko-ci

Konfigurasi credential.username menentukan nama pengguna yang diajukan saat Git meminta kredensial HTTPS — dua klon pada repository yang sama mengajukan dua identitas. Jalur remote klon-bot absolut karena lahir dari git clone; remote klon-budi relatif karena ditambahkan manual. Setelah keduanya push, riwayat pusat memuat dua penulis:

bash
git log --pretty=format:'%an <%ae>'
text
Bot CI <[email protected]>
Budi Santoso <[email protected]>

Pada sandbox lokal, siapa pun yang menjangkau direktori bisa mendorong apa pun. Pada platform sungguhan, server-lah yang memutuskan: kredensial yang autentik diperiksa terhadap izin yang melekat padanya, dan push ditolak bila izinnya kurang. Kolom author tetap teks bebas yang bisa dipalsukan (dibuktikan di Signed Commits ); izin sejatinya melekat pada kredensial — least privilege = memutuskan kredensial macam apa ditanamkan ke tangan mana.

Deploy Key: Satu Repository, Satu Kunci #

Untuk mesin — server deploy, runner CI, skrip backup — pilihan paling sempit bukan token milik akun, melainkan deploy key: pasangan kunci SSH yang publiknya didaftarkan pada satu repository tertentu, bukan pada sebuah akun. Saat menambahkannya di Settings → Deploy keys, tersedia opsi Allow write access; tanpa dicentang, kunci itu hanya bisa membaca — bawaannya memang read-only, sebagaimana didokumentasikan di panduan deploy keys GitHub .

Bentuk deploy keyIzin pada repo ituKapan tepat
read-onlyclone, pull, fetchCI yang hanya build, skrip backup, server deploy
read-writejuga pushpipeline yang menerbitkan rilis/hasil build ke repo

Deploy key read-write bukan kenaikan kecil: aksinya setara anggota dengan akses admin pada repository itu — berikan hanya bila mesin benar-benar harus push. Kuncinya dibuat dengan ssh-keygen biasa — sandbox menamainya sesuai peruntukannya:

bash
ssh-keygen -t ed25519 -C "deploy-toko-ci" -f toko-deploy -N ""
cat toko-deploy.pub
text
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKk6fZ3lUwOuvydBlmP7yL4eTA60/dmMVD6soOwKp+CA deploy-toko-ci

Kunci acak per pembuatan, jadi nilainya berbeda di mesin pembaca. Baris itulah yang ditempelkan ke kolom Key; comment deploy-toko-ci membuat kunci mudah dikenali di daftar deploy key. Tiga sifatnya perlu dipegang: deploy key hanya membuka satu repository — pasangan kunci yang sama tidak bisa didaftarkan ke repo kedua; izinnya tidak terikat keanggotaan organisasi — pembuatnya keluar dari tim, kunci tetap hidup; dan tidak punya masa kedaluwarsa. Bila satu mesin butuh banyak repository, dua jalur lebih sehat daripada mengulurkan token pribadi: machine user — akun khusus otomatisasi, satu kunci per server cukup — atau GitHub App untuk integrasi resmi yang izinnya paling granular.

PAT Fine-Grained: Dua Sumbu Pembatasan #

Untuk jalur HTTPS, padanan tersempitnya adalah fine-grained personal access token, yang membatasi di dua sumbu: repository mana saja yang terbuka, dan permission apa per kategori. Keduanya dipilih saat pembuatan token — alurnya di dokumentasi pembuatan token :

PilihanSumbu repositoryPermission ContentsKapan tepat
fine-grained, 1 repoOnly select repositories: satuRead-onlyskrip backup, alat analisis
fine-grained, 1 repoOnly select repositories: satuRead and writepekerjaan harian pada proyek
fine-grained, beberapa reporepo terpilihper kebutuhanalat lintas 2-3 repo
fine-grained, seluruh repoAll repositoriesminimalalat organisasi lintas repo
klasik, scope reposeluruh repo akunpenuhhanya bila alat lama belum mendukung fine-grained

Kategori permission dipilih satu per satu — Contents, Issues, Pull requests, dan seterusnya — tiap kategori bisa Read-only atau Read and write. Satu batas kerasnya: token tidak pernah bisa memberi izin melebihi yang dimiliki pemiliknya — token hanya mempersempit, bukan memperluas. Kebiasaan merawatnya — nama jujur, umur pendek, rotasi, pencabutan — dibahas tuntas di Mengelola Token .

Permission Level untuk Manusia #

Mesin terlayani kunci dan token; manusia terlayani level permission. GitHub membagi akses repository dalam lima level, dari paling sempit ke paling lebar:

LevelYang bisa dilakukan pemegangnya
readmelihat kode, membuka dan mengomentari issues/PR
triagemenambah label, assign, menutup issues/PR — tanpa menulis kode
writemendorong commit, membuka dan merge pull request
maintainmengelola repository — termasuk sebagian pengaturannya — tanpa aksi sensitif atau destruktif
adminakses penuh: keamanan, pengaturan, anggota, menghapus repository

Deskripsi resmi kelima level GitHub dirinci di dokumentasi repository roles . GitLab memakai lima role yang peta tanggung jawabnya serupa:

Role GitLabYang bisa dilakukan pemegangnya
guestmelihat dan berkomentar pada issue; tanpa akses repository (proyek privat)
reportermelihat kode dan membuka issue; tanpa push
developerpush ke branch non-protected, membuka merge request, menjalankan pipeline
maintainermengelola branch, merge, pengaturan CI, dan anggota
ownerpenuh, termasuk menghapus proyek

Aturan memilihnya: level terendah yang masih menyelesaikan pekerjaannya — kontributor kode cukup di write/developer, koordinator tanpa kode cukup di triage/reporter, admin hanya untuk pemilik yang benar-benar mengelola repository-nya.

Dua Kebiasaan yang Membuka Semua Pintu #

Dua kebiasaan menghapus semua lapisan di atas sekaligus. Pertama, token akun pribadi dipakai bot atau CI: token mewarisi seluruh izin manusianya, jejak audit jadi kacau — aktivitas bot tercatat atas nama manusia — dan hidupnya terikat karir pemilik: orangnya pindah, pipeline ikut mati. Gantinya sudah dibahas: deploy key, machine user, atau GitHub App. Kedua, berbagi akun: dua orang satu kredensial berarti riwayat aktivitas tidak bisa menunjuk siapa pun, 2FA kehilangan maknanya, dan pencabutan tidak bisa setengah-setengah — akunnya dimatikan untuk semua orang sekaligus.

Kebalikan kedua larangan itu dirangkum tabel berikut — skenario dan kredensial paling sempit yang menyelesaikannya:

SkenarioKredensial tepatAlasannya
bot CI hanya build (pull)deploy key read-only pada repo itubocor sekalipun, pelakunya tidak bisa menulis
rekan tim push kodekolaborator write dengan akun + kunci SSH sendiriizin manusia atas nama sendiri, bisa diaudit
kontributor eksternalfork + pull request, tanpa akses langsungpekerjaan masuk lewat review, seperti di Fork dan Pull Request
pelapor bugread / Guest, atau cukup issues publikmelapor tidak butuh menulis kode
skrip backup malam harideploy key read-only / fine-grained Contents: Read-onlysearah — cukup membaca, tidak pernah menulis

Demo: Satu Mesin, Dua Kunci, Dua Izin #

Semua tabel di atas berhenti di kebijakan platform; bagian yang hidup di mesin lokal berikut ini. Laptop Budi membawa dua kunci: id_ed25519 (akun pribadi) dan toko-deploy (deploy key read-only untuk repository toko-buku). Berkas konfigurasi SSH memisahkan keduanya lewat alias:

ini
# Kunci pribadi Budi — akses akun penuh
Host github-budi
  HostName github.com
  User git
  IdentityFile /home/z/my-project/tutorial-extracted/work/sandbox/keamanan-dan-akses/part-b/latihan-hak/ssh/id_ed25519

# Kunci deploy toko-buku — read-only, terdaftar per repository
Host github-toko-ro
  HostName github.com
  User git
  IdentityFile /home/z/my-project/tutorial-extracted/work/sandbox/keamanan-dan-akses/part-b/latihan-hak/ssh/toko-deploy

Jalur IdentityFile di sandbox absolut menuju direktori latihan; di mesin kita cukup ~/.ssh/id_ed25519 dan ~/.ssh/toko-deploy. Tiap alias diperiksa tanpa koneksi — ssh -G mencetak opsi teratasi:

bash
ssh -G github-toko-ro | grep -E '^(hostname|user|identityfile) '
text
user git
hostname github.com
identityfile /home/z/my-project/tutorial-extracted/work/sandbox/keamanan-dan-akses/part-b/latihan-hak/ssh/toko-deploy
bash
ssh -G github-budi | grep -E '^(hostname|user|identityfile) '
text
user git
hostname github.com
identityfile /home/z/my-project/tutorial-extracted/work/sandbox/keamanan-dan-akses/part-b/latihan-hak/ssh/id_ed25519

Dua alias menuju host yang sama dengan kunci berbeda — dan di sinilah least privilege benar-benar bekerja: alamat remote memilih alias, alias memilih kunci, kunci menentukan izin. Klon untuk skrip cadangan memakai github-toko-ro; pekerjaan harian memakai github-budi:

bash
git remote add cadangan github-toko-ro:budi/toko-buku.git
git remote -v
text
cadangan  github-toko-ro:budi/toko-buku.git (fetch)
cadangan  github-toko-ro:budi/toko-buku.git (push)
origin  ../pusat.git (fetch)
origin  ../pusat.git (push)

Audit Berkala #

Akses yang tidak pernah diperiksa membusuk diam-diam: orang pindah peran, kontrak habis, bot dilupakan — sementara kunci dan tokennya tetap hidup. Audit akses membandingkan dua daftar — siapa yang punya akses versus siapa yang masih membutuhkannya. Kedua daftar hidup di platform: GitHub menyediakan Settings → Collaborators per repository, halaman outside collaborators untuk organisasi, dan daftar token dengan waktu pemakaian terakhirnya (dokumentasi pengelolaan token ); GitLab menempatkannya di Project → Members.

Dari terminal, peta manusianya ditarik dari riwayat — git log --pretty=format:'%an <%ae>' | sort -u mencantumkan semua penulis yang pernah menyentuh repository. Nama di riwayat tanpa akses saat ini adalah kontributor lama, wajar; akses tanpa satu pun jejak kontribusi adalah kandidat pencabutan. Jadwalkan perbandingan ini tiap kuartal, dan segera setiap ada anggota keluar dari tim.

Kredensial yang ukurannya tepat hari ini bisa menjadi terlalu besar esok — karena itu keamanan repository bukan pemasangan sekali jadi, melainkan pemeriksaan berulang. Chapter penutup section ini menyusun seluruh pembahasan menjadi satu checklist audit yang bisa dijalankan langsung dari terminal.