Mengonfigurasi Konteks Keamanan untuk Pod atau Container

Konteks keamanan (security context) menentukan wewenang (privilege) dan aturan kontrol akses untuk sebuah Pod atau Container. Aturan konteks keamanan meliputi hal-hal berikut ini namun tidak terbatas pada hal-hal tersebut:

  • Kontrol akses bersifat diskresi: Izin untuk mengakses objek, seperti sebuah berkas, yang didasarkan pada ID pengguna atau user ID (UID) dan ID grup atau group ID (GID).

  • Security Enhanced Linux (SELinux): Di mana objek diberi label keamanan.

  • Menjalankan dengan wewenang (privileged) atau tanpa wewenang (unprivileged).

  • Kapabilitas Linux (Linux Capabilities): Memberi sebuah proses beberapa wewenang, namun tidak semua wewenang dari pengguna root.

  • AppArmor: Menggunakan profil program untuk membatasi kemampuan dari masing-masing program.

  • Seccomp: Menyaring panggilan sistem (system calls) dari suatu proses.

  • AllowPrivilegeEscalation: Mengontrol apakah suatu proses dapat memperoleh lebih banyak wewenang daripada proses induknya. Pilihan ini mengontrol secara langsung apakah opsi no_new_privs diaktifkan pada proses dalam Container. AllowPrivilegeEscalation selalu aktif (true) ketika Container: 1) berjalan dengan wewenang ATAU 2) memiliki CAP_SYS_ADMIN.

  • readOnlyRootFilesystem: Menambatkan (mount) sistem berkas (file system) root dari sebuah Container hanya sebatas untuk dibaca saja (read-only).

Poin-poin di atas bukanlah sekumpulan lengkap dari aturan konteks keamanan - silakan lihat SecurityContext untuk daftar lengkapnya.

Untuk informasi lebih lanjut tentang mekanisme keamanan pada Linux, silahkan lihat ikhtisar fitur keamanan pada Kernel Linux

Sebelum kamu memulai

Kamu harus memiliki klaster Kubernetes, dan perangkat baris perintah kubectl juga harus dikonfigurasikan untuk berkomunikasi dengan klastermu. Jika kamu belum memiliki klaster, kamu dapat membuatnya dengan menggunakan minikube, atau kamu juga dapat menggunakan salah satu dari tempat mencoba Kubernetes berikut ini:

Untuk melihat versi, tekan kubectl version.

Mengatur konteks keamanan untuk Pod

Untuk menentukan aturan keamanan pada Pod, masukkan bagian securityContext dalam spesifikasi Pod. Bagian securityContext adalah sebuah objek PodSecurityContext. Aturan keamanan yang kamu tetapkan untuk Pod akan berlaku untuk semua Container dalam Pod tersebut. Berikut sebuah berkas konfigurasi untuk Pod yang memiliki volume securityContext dan emptyDir:

apiVersion: v1
kind: Pod
metadata:
  name: security-context-demo
spec:
  securityContext:
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
  volumes:
  - name: sec-ctx-vol
    emptyDir: {}
  containers:
  - name: sec-ctx-demo
    image: busybox
    command: [ "sh", "-c", "sleep 1h" ]
    volumeMounts:
    - name: sec-ctx-vol
      mountPath: /data/demo
    securityContext:
      allowPrivilegeEscalation: false

Dalam berkas konfigurasi ini, bagian runAsUser menentukan bahwa dalam setiap Container pada Pod, semua proses dijalankan oleh ID pengguna 1000. Bagian runAsGroup menentukan grup utama dengan ID 3000 untuk semua proses dalam setiap Container pada Pod. Jika bagian ini diabaikan, maka ID grup utama dari Container akan berubah menjadi root(0). Berkas apa pun yang dibuat juga akan dimiliki oleh pengguna dengan ID 1000 dan grup dengan ID 3000 ketika runAsGroup ditentukan. Karena fsGroup ditentukan, semua proses milik Container juga merupakan bagian dari grup tambahan dengan ID 2000. Pemilik volume /data/demo dan berkas apa pun yang dibuat dalam volume tersebut adalah grup dengan ID 2000.

Buatlah Pod tersebut:

kubectl apply -f https://k8s.io/examples/pods/security/security-context.yaml

Periksa apakah Container dari Pod sedang berjalan:

kubectl get pod security-context-demo

Masuk ke shell dari Container yang sedang berjalan tersebut:

kubectl exec -it security-context-demo -- sh

Pada shell kamu, lihat daftar proses yang berjalan:

ps

Keluarannya menunjukkan bahwa proses dijalankan oleh pengguna dengan ID 1000, yang merupakan nilai dari bagian runAsUser:

PID   USER     TIME  COMMAND
    1 1000      0:00 sleep 1h
    6 1000      0:00 sh
...

Pada shell kamu, pindah ke direktori /data, dan lihat isinya:

cd /data
ls -l

Keluarannya menunjukkan bahwa direktori /data/demo memiliki grup dengan ID 2000, yang merupakan nilai dari bagian fsGroup.

drwxrwsrwx 2 root 2000 4096 Jun  6 20:08 demo

Pada shell kamu, pindah ke direktori /data/demo, dan buatlah sebuah berkas didalamnya:

cd demo
echo hello > testfile

Lihatlah daftar berkas dalam direktori /data/demo:

ls -l

Keluarannya menunjukkan bahwa testfile memiliki grup dengan ID 2000, dimana merupakan nilai dari bagian fsGroup.

-rw-r--r-- 1 1000 2000 6 Jun  6 20:08 testfile

Jalankan perintah berikut ini:

$ id
uid=1000 gid=3000 groups=2000

Kamu akan melihat bahwa nilai gid adalah 3000, sama dengan bagian runAsGroup. Jika runAsGroup diabaikan maka nilai gid akan tetap bernilai 0(root) dan proses akan dapat berinteraksi dengan berkas-berkas yang dimiliki oleh grup root(0) dan yang memiliki izin grup untuk grup root(0).

Keluarlah dari shell kamu:

exit

Melakukan konfigurasi izin volume dan kebijakan perubahan kepemilikan untuk Pod

FEATURE STATE: Kubernetes v1.18 [alpha]

Secara bawaan, Kubernetes mengubah kepemilikan dan izin secara rekursif untuk konten masing-masing volume untuk mencocokkan fsGroup yang ditentukan dalam securityContext dari Pod pada saat volume itu ditambatkan (mounted). Untuk volume yang besar, memeriksa dan mengubah kepemilikan dan izin dapat memerlukan waktu yang sangat lama, sehingga memperlambat proses menjalankan Pod. Kamu dapat menggunakan bagian fsGroupChangePolicy dalam sebuah securityContext untuk mengontrol cara Kubernetes memeriksa dan mengelola kepemilikan dan izin untuk sebuah volume.

fsGroupChangePolicy - fsGroupChangePolicy mendefinisikan perilaku untuk mengubah kepemilikan dan izin volume sebelum diekspos di dalam sebuah Pod. Bagian ini hanya berlaku untuk tipe volume yang mendukung fsGroup untuk mengontrol kepemilikan dan izin. Bagian ini memiliki dua nilai yang dapat dimasukkan:

  • OnRootMismatch: Hanya mengubah izin dan kepemilikan jika izin dan kepemilikan dari direktori root tidak sesuai dengan izin volume yang diharapkan. Hal ini dapat membantu mempersingkat waktu yang diperlukan untuk mengubah kepemilikan dan izin sebuah volume.
  • Always: Selalu mengubah izin dan kepemilikan volume ketika volume sudah ditambatkan.

Sebagai contoh:

securityContext:
  runAsUser: 1000
  runAsGroup: 3000
  fsGroup: 2000
  fsGroupChangePolicy: "OnRootMismatch"

Ini adalah fitur alpha. Untuk menggunakannya, silahkan aktifkan gerbang fitur ConfigurableFSGroupPolicy untuk kube-api-server, kube-controller-manager, dan kubelet.

Catatan: Bagian ini tidak berpengaruh pada tipe volume yang bersifat sementara (ephemeral) seperti secret, configMap, dan emptydir.

Mengatur konteks keamanan untuk Container

Untuk menentukan aturan keamanan untuk suatu Container, sertakan bagian securityContext dalam manifes Container. Bagian securityContext adalah sebuah objek SecurityContext. Aturan keamanan yang kamu tentukan untuk Container hanya berlaku untuk Container secara individu, dan aturan tersebut menimpa aturan yang dibuat pada tingkat Pod apabila ada aturan yang tumpang tindih. Aturan pada Container mempengaruhi volume pada Pod.

Berikut berkas konfigurasi untuk Pod yang hanya memiliki satu Container. Keduanya, baik Pod dan Container memiliki bagian securityContext sebagai berikut:

apiVersion: v1
kind: Pod
metadata:
  name: security-context-demo-2
spec:
  securityContext:
    runAsUser: 1000
  containers:
  - name: sec-ctx-demo-2
    image: gcr.io/google-samples/node-hello:1.0
    securityContext:
      runAsUser: 2000
      allowPrivilegeEscalation: false

Buatlah Pod tersebut:

kubectl apply -f https://k8s.io/examples/pods/security/security-context-2.yaml

Periksa jika Container dalam Pod sedang berjalan:

kubectl get pod security-context-demo-2

Masuk ke dalam shell Container yang sedang berjalan tersebut:

kubectl exec -it security-context-demo-2 -- sh

Pada shell kamu, lihat daftar proses yang sedang berjalan:

ps aux

Keluarannya menunjukkan bahwa proses dijalankan oleh user dengan ID 2000, yang merupakan nilai dari runAsUser seperti yang telah ditentukan untuk Container tersebut. Nilai tersebut menimpa nilai ID 1000 yang ditentukan untuk Pod-nya.

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
2000         1  0.0  0.0   4336   764 ?        Ss   20:36   0:00 /bin/sh -c node server.js
2000         8  0.1  0.5 772124 22604 ?        Sl   20:36   0:00 node server.js
...

Keluar dari shell anda:

exit

Mengatur Kapabilitas untuk Container

Dengan menggunakan Kapabilitas Linux (Linux Capabilities), kamu dapat memberikan wewenang tertentu kepada suatu proses tanpa memberikan semua wewenang dari pengguna root. Untuk menambah atau menghapus Kapabilitas Linux pada suatu Container, masukkan bagian capabilities pada securityContext di manifes Container-nya.

Pertama-tama, mari melihat apa yang terjadi ketika kamu tidak menyertakan bagian capabilities. Berikut ini adalah berkas konfigurasi yang tidak menambah atau mengurangi kemampuan apa pun dari Container:

apiVersion: v1
kind: Pod
metadata:
  name: security-context-demo-3
spec:
  containers:
  - name: sec-ctx-3
    image: gcr.io/google-samples/node-hello:1.0

Buatlah Pod tersebut:

kubectl apply -f https://k8s.io/examples/pods/security/security-context-3.yaml

Periksa apakah Container dari Pod tersebut sedang berjalan:

kubectl get pod security-context-demo-3

Masuk ke dalam shell dari Container yang berjalan:

kubectl exec -it security-context-demo-3 -- sh

Dalam shell tersebut, lihatlah daftar proses yang berjalan:

ps aux

Keluarannya menunjukkan ID dari proses atau process IDs (PIDs) untuk Container tersebut:

USER  PID %CPU %MEM    VSZ   RSS TTY   STAT START   TIME COMMAND
root    1  0.0  0.0   4336   796 ?     Ss   18:17   0:00 /bin/sh -c node server.js
root    5  0.1  0.5 772124 22700 ?     Sl   18:17   0:00 node server.js

Dalam shell kamu, lihat status dari proses dengan ID 1:

cd /proc/1
cat status

Keluarannya menunjukkan bitmap dari kapabilitas untuk proses tersebut:

...
CapPrm:	00000000a80425fb
CapEff:	00000000a80425fb
...

Buatlah catatan untuk bitmap dari kapabilitas tersebut, dan keluarlah dari shell kamu:

exit

Berikutnya, jalankan Container yang sama seperti dengan Container sebelumnya, namun Container ini memiliki kapabilitas tambahan yang sudah ditentukan.

Berikut ini adalah berkas konfigurasi untuk Pod yang hanya menjalankan satu Container. Konfigurasi ini menambahkan kapabilitas CAP_NET_ADMIN dan CAP_SYS_TIME:

apiVersion: v1
kind: Pod
metadata:
  name: security-context-demo-4
spec:
  containers:
  - name: sec-ctx-4
    image: gcr.io/google-samples/node-hello:1.0
    securityContext:
      capabilities:
        add: ["NET_ADMIN", "SYS_TIME"]

Buatlah Pod tersebut:

kubectl apply -f https://k8s.io/examples/pods/security/security-context-4.yaml

Masuk ke dalam shell dari Container yang berjalan:

kubectl exec -it security-context-demo-4 -- sh

Di dalam shell kamu, lihatlah kapabilitas dari proses dengan ID 1:

cd /proc/1
cat status

Keluarannya menunjukkan bitmap kapabilitas untuk proses tersebut:

...
CapPrm:	00000000aa0435fb
CapEff:	00000000aa0435fb
...

Bandingkan kemampuan dari kedua Containers tersebut:

00000000a80425fb
00000000aa0435fb

Dalam bitmap kapabilitas pada Container pertama, bit-12 dan ke-25 tidak diatur. Sedangkan dalam Container kedua, bit ke-12 dan ke-25 diatur. Bit ke-12 adalah kapabilitas CAP_NET_ADMIN, dan bit-25 adalah kapabilitas CAP_SYS_TIME. Lihatlah capability.h untuk nilai dari konstanta kapabilitas-kapabilitas yang lainnya.

Catatan: Konstanta kapabilitas Linux memiliki format CAP_XXX. Tetapi ketika kamu memasukkan daftar kemampuan dalam manifes Container kamu, kamu harus menghilangkan bagian CAP_ dari konstantanya. Misalnya, untuk menambahkan CAP_SYS_TIME, masukkan SYS_TIME ke dalam daftar kapabilitas Container kamu.

Memberikan label SELinux pada sebuah Container

Untuk memberikan label SELinux pada sebuah Container, masukkan bagian seLinuxOptions pada bagian securityContext dari manifes Pod atau Container kamu. Bagian seLinuxOptions adalah sebuah objek SELinuxOptions. Berikut ini adalah contoh yang menerapkan sebuah level dari SELinux:

...
securityContext:
  seLinuxOptions:
    level: "s0:c123,c456"
Catatan: Untuk menetapkan label SELinux, modul keamanan SELinux harus dimuat terlebih dahulu pada sistem operasi dari hosnya.

Diskusi

Konteks keamanan untuk sebuah Pod berlaku juga untuk Container yang berada dalam Pod tersebut dan juga untuk volume dari Pod tersebut jika ada. Terkhusus untuk fsGroup dan seLinuxOptions akan diterapkan pada volume seperti berikut:

  • fsGroup: Volume yang mendukung manajemen kepemilikan (ownership) akan dimodifikasi agar dapat dimiliki dan ditulis oleh ID group (GID) yang disebutkan dalam fsGroup. Lihatlah Dokumen Desain untuk Manajemen Kepemilikan untuk lebih lanjut.

  • seLinuxOptions: Volume yang mendukung pelabelan SELinux akan dilabel ulang agar dapat diakses oleh label yang ditentukan pada seLinuxOptions. Biasanya kamu hanya perlu mengatur bagian level. Dimana ini akan menetapkan label Keamanan multi-kategori (Multi-Category Security) (MCS) yang diberikan kepada semua Container dalam Pod serta Volume yang ada didalamnya.

Peringatan: Setelah kamu menentukan label MCS untuk Pod, maka semua Pod dengan label yang sama dapat mengakses Volume tersebut. Jika kamu membutuhkan perlindungan antar Pod, kamu harus menetapkan label MCS yang unik untuk setiap Pod.

Bersih-bersih (Clean Up)

Hapus Pod-Pod tersebut:

kubectl delete pod security-context-demo
kubectl delete pod security-context-demo-2
kubectl delete pod security-context-demo-3
kubectl delete pod security-context-demo-4

Selanjutnya

Last modified July 10, 2020 at 10:24 PM PST : Replace EN links to ID links (0c799ef75)