Belajar Kubernetes (Sealed Secret — Cara Mudah Menyimpan Credentials dengan Aman)
Kubernetes, sebagai platform orkestrasi kontainer yang populer, memungkinkan pengembang untuk dengan mudah mendeploy dan mengelola aplikasi dalam lingkungan yang terkendali. Namun, salah satu tantangan yang sering dihadapi adalah bagaimana menyimpan dan mengelola informasi rahasia seperti kredensial API, token, atau kunci enkripsi secara aman di dalam cluster Kubernetes.
Kubernetes menyediakan fitur secrets yang dapat digunakan untuk menyimpan informasi rahasia diatas, akan tetapi informasi yang disimpan tersebut disediakan dalam bentuk base64 sehingga sangat mudah untuk dilakukan decode ke plain text.
Berikut contoh manifest secret kubernetes.
apiVersion: v1
kind: Secret
metadata:
name: my-secret
type: Opaque
data:
password: ZjR0NG0wcmc0bjQK # Ini adalah nilai yang telah dienkripsi menjadi base64
Pada file diatas, dapat dilihat bahwa nilai password merupakan sebuah value dari hasil base64 encode, dan jika dilakukan decode maka hasilnya seperti ini.
echo "ZjR0NG0wcmc0bjQK" | base64 -d
f4t4m0rg4n4
Nah, hal ini jika disimpan pada version control repositori seperti git ataupun gitlab, maka user yang memiliki akses ke repositori tersebut dapat dengan mudah mengetahui informasi rahasia dari sebuah aplikasi.
Apa itu Sealed Secrets?
Sealed Secrets adalah solusi yang memungkinkan pengembang untuk menyimpan dan mengelola secret Kubernetes secara aman dalam repositori Git. Konsep dasar dari Sealed Secrets adalah mengenkripsi secret dan kemudian menyimpannya dalam repositori Git. Hanya cluster Kubernetes yang memiliki kunci pribadi yang sesuai yang dapat membuka dan membaca informasi rahasia tersebut.
Bagaimana Sealed Secrets Bekerja?
- Secrets Asli (Original Secrets): Mulai dengan membuat secret Kubernetes seperti yang Anda lakukan biasanya. Ini bisa berisi informasi sensitif seperti username, password, atau kunci API.
- Sealed Secrets: Sealed Secrets adalah versi terenkripsi dari secret asli. Ini diciptakan menggunakan kunci publik yang sesuai dengan kunci pribadi yang dimiliki oleh cluster Kubernetes.
- Sealed Secrets Controller: Sealed Secrets Controller, yang berjalan di dalam cluster Kubernetes, bertanggung jawab untuk membuat dan memelihara Sealed Secrets. Ketika secret asli diperbarui, Controller secara otomatis menciptakan versi terenkripsi baru.
kubeseal
Command Line Tool: Untuk membuat Sealed Secrets dari secret asli, pengembang menggunakan perintahkubeseal
. Ini mengambil secret asli dan menghasilkan Sealed Secret yang dapat disimpan dengan aman dalam repositori Git.
Instal Sealed Secret Controller
Sealed secret controller dapat diinstall menggunakan helm.
helm repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets
helm install sealed-secrets sealed-secrets/sealed-secrets --namespace kube-system
Pada perintah diatas kita memasang sealed secret controller pada namespace kube-system. Status pod dari sealed secret controller dapat dilihat dengan perintah berikut:
kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-5dd5756b68-9rc7t 1/1 Running 0 5m4s
etcd-minikube 1/1 Running 0 5m19s
kube-apiserver-minikube 1/1 Running 0 5m17s
kube-controller-manager-minikube 1/1 Running 0 5m17s
kube-proxy-hvchp 1/1 Running 0 5m4s
kube-scheduler-minikube 1/1 Running 0 5m17s
sealed-secrets-5557bf4fb4-zzjjr 1/1 Running 0 21s
storage-provisioner 1/1 Running 1 (4m34s ago) 5m14s
Instal Kubeseal Client
Setelah berhasil memasang sealed secret controller, maka user dapat memasang kubeseal pada PC atau laptop dengan cara berikut:
# wget https://github.com/bitnami-labs/sealed-secrets/releases/download/<release-tag>/kubeseal-<version>-linux-amd64.tar.gz
Example:
# wget https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.19.4/kubeseal-0.19.4-linux-amd64.tar.gz
# tar -xvzf kubeseal-<version>-linux-amd64.tar.gz kubeseal
# install -m 755 kubeseal /usr/local/bin/kubeseal
atau menggunakan brew.
brew install kubeseal
Membuat Sealed Secret Berdasarkan Secret
Untuk melakukan pengujian terhadap sealed secret kita perlu untuk mengetahui kunci publik yang digunakan oleh kubernetes cluster.
kubeseal --fetch-cert --controller-name sealed-secrets --controller-namespace kube-system
-----BEGIN CERTIFICATE-----
MIIEzDCCArSgAwIBAgIQRRYvbEGWm2w3HaSlPNHdLzANBgkqhkiG9w0BAQsFADAA
MB4XDTIzMTEyNTE2MzYwM1oXDTMzMTEyMjE2MzYwM1owADCCAiIwDQYJKoZIhvcN
AQEBBQADggIPADCCAgoCggIBAMftqwYL+nA1aXOulzCXN2Y2Tf1Shh31JbraRa3q
USSlxpZsA5ojvUoPETEf2z7wm2DBfGvrDw8jTA14Dw8H+IjhP1nghxOMswz3EslE
Zap1WY0zmNfIGyzljDY2fvcLMajs1oQ1A4Txprkdyi+CkzPB9EH/Zdi2wJaOywU0
sHQyRcVj2NYKKX2TQNm07J9U5/3iNmqkKTrqPEcSWYMn9eTbOxTtWcMKmAL3uFBU
5voqA3dw59QXaOE4xJmGjCDyjVaFx6MrIA0bc3pvCdJmYOquAR+usx8T3rkhAxjT
7ZykEj268jcd3wccDf/Vt3EyXP3v8HArCpeeWBgioTQ16z1Q2p/KeEZzHjthtSF4
UlOlXPRKgMNfVARqx6f1tt80ZdxYPrFF9TkPO/1jZI6C685t0P/coJNMh7Yn94D2
bbxI7dVRLfhXP0mr9BmShsMHg+P5oaqXHc1vT1uV713iSBvuYDX6HUnGziaQTXQ+
D8MEiQtZHs3X/qGfkuz+qBm5gJ2JTTe0W6eOln2dAaJ7dGszLEl19Q9GASu9ng36
rWtBnqAK3pxbD3j4FAMVOgo3Ve+PBoS2GjbHbLrwhtA7qBXJqzr7fly8zk8ASWaP
dyLcqq6l8H/gqOgZ0KgOVFgRwCkl71iGGQYWQirb6S+Bd9GtM6b1FdehiacKcEd9
Pc8XAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIAATAPBgNVHRMBAf8EBTADAQH/MB0G
A1UdDgQWBBS78X5/8Vze99SNMrs3xpMahnPSGDANBgkqhkiG9w0BAQsFAAOCAgEA
BrFsnAHMv0ofUKsdRvU/ptZnNK9YpuJZ4lz6f+TwtkKNTVTZsrRj2hj/yvr6tayi
Ppy7IueMZF/Q0fV1Io8UlEJ++zDLXTlkhb8oQXbVDsalemVFgw5Ec+6Dw2MfvdoC
rZxjHliIRoescrUtpC1wcirUhxN4J33dWo5XpUMxN/qrf47CiR4JNJRcuJijNX1Y
tfGPfgNXzcaWEVbUypCAhydP7iPot28+NYA0fopf8oziqy16tyxuHORNlPDFNC5x
4bf8skLeHyhvkMJhOM+2wengK551Qrzy5GV7AXUVw51rtW29QxNmk57J5wyVdxFE
0W7zXSTubfGWptK5Z16S76a16KGo/FQ1ObX9vut0HzXWSf6i7eTP/J+relzayNKI
G3N6PJzMc9EaCH3G06xH6druPuwk3QKoN/ra45o/g3sRwMRcdHCZKnHqqQXTeAjo
5eY/KgH9WYN89P8G3S5Wy1jzxUNLu47hyqWc/9GvyNE3WkUZykcxF3D7Vg91R67H
g+rFInnn6bt46CV45wqIV0B0Zx+jMFcvNjM62j5/tD8avwub3G0UT4tZLylyKH3Y
9hFYWlIR/5U5b858txVuzJu7xTqVBXWtJ4lata6ZKSInlp2kGqio8w/CO0X65DEL
wOB1ITr1diCqkK18zeb6QrHSurmbvs6sZMIpEtpvGF8=
-----END CERTIFICATE-----
Flag --controller-name
dapat menggunakan nama service maupun deployment dari sealed secret controller.
kubectl get service -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 18m
sealed-secrets ClusterIP 10.104.140.191 <none> 8080/TCP 13m
Selanjutnya kita akan membuat sebuah secret yang menggunakan value secret berbasis base64 encode.
kubectl create secret generic database -n default --from-literal=password=f4t4m0rg4n4 --dry-run=client -o yaml > secret.yaml
cat secret.yaml
apiVersion: v1
data:
password: ZjR0NG0wcmc0bjQ=
kind: Secret
metadata:
creationTimestamp: null
name: database
namespace: default
Sekarang kita akan melakukan sealed secret berdasarkan secret yang telah dibuat sebelumnya.
kubeseal --controller-name sealed-secrets --controller-namespace kube-system --format yaml < secret.yaml > sealed-secret.yaml
Dan hasilnya bisa dilihat sebagai berikut.
cat sealed-secret.yaml
---
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
creationTimestamp: null
name: database
namespace: default
spec:
encryptedData:
password: AgBkmeFXmYhAK4Zekujt3Q0w0H72suyH/eqY4t1KxfRR2WXliydE9/gzmCXQaumdVRbAuXUoo6WyIY2oe+aSetKTLMjalug6wWgDNT5k95NcCv3sZzpoOnvRBhY8Ur4PlG7ViySglWGMos7rf8axj5GCVbQ8+ZMj/jtoD2WsA9K0BZXxHw36/DYTWbGsJCNBc3ngFH9zwnn87BF+c3nlMIYedVQrQqDopF6g8Ccjb4IXCZKN8Jf3EAc93cPlvqtil9N0w4LeDKt450zmHquIQg46wLAhS/fA6NBUj4jIAKEB+1t7qbCsi4WtRZ6IZbLDnRwjA6Yyn6aW5He4fcSLha74w+pnMAsxIMxFWcvIGw2WVwRCBtQaUhjQhxKDFfpvTnIY78deMbJQlKm1c97yeIk7+2Av/UWHrWuq6UsilxZHfJBJ8E2RTU4TYd8RE5FV4qZMD3hKmxdRbhhFdY8mvfeehW2SOoSis+dNEj48AYlPgJc+OvMNyunShAmvSa8KmEHJeKkB95iarlVz5E6WCjZPfRCzl45X0fNEB039nHjU1jj5aXQ+IjH3pqfDGgpYLYKTwssDtSD8IKzxzV8WT1ijrwhOkXTUgbyoVGTQjhSSABFy8YyW1ucOr5N1ONQsg1xyyp5Fnv71Emlrx6rT1GMp4FjNkiQyr8o+19wst6GAf0k1jtIz9D2pnfG6ZowMKW0KutMbI4mM+bt0sw==
template:
metadata:
creationTimestamp: null
name: database
namespace: default
Pada file sealed-secret.yaml diatas dapat dilihat bahwa value dari password merupakan hasil enkripsi yang dilakukan oleh sealed secret dan bukan merupakan base64 encode lagi. File inilah yang akan di push ke repositori version control seperti github atau yang lainnya, sehingga walaupun ada user yang dapat mengakses repositori tersebut, dia tidak akan bisa membaca value yang sudah terenkripsi oleh sealed secret.
Menggunakan Sealed Secret di Kubernetes
Untuk meng-apply file sealed-secret.yaml yang telah dibuat, dapat menggunakan perintah berikut:
➜ kubectl apply -f sealed-secret.yaml -n default
sealedsecret.bitnami.com/database created
➜ kubectl get secret -n default
NAME TYPE DATA AGE
database Opaque 1 4s
Sealed secret controller akan membuat sealedsecret dan secret resource dengan nama yang sama.
➜ kubectl get secret -n default
NAME TYPE DATA AGE
database Opaque 1 6m14s
➜ kubectl get sealedsecret -n default
NAME STATUS SYNCED AGE
database True 6m23s
Jika ingin melihat isi dari secret maupun sealed-sercret, dapat menggunakan perintah berikut:
➜ kubectl get secret database -o yaml -n default
apiVersion: v1
data:
password: ZjR0NG0wcmc0bjQ=
kind: Secret
metadata:
creationTimestamp: "2023-11-25T17:03:30Z"
name: database
namespace: default
ownerReferences:
- apiVersion: bitnami.com/v1alpha1
controller: true
kind: SealedSecret
name: database
uid: dc3da9bd-971e-4c0c-b4f3-e402e47b3616
resourceVersion: "1965"
uid: 27aff44d-39b0-42ac-8491-aa1b0ae2f3d6
type: Opaque
➜ kubectl get sealedsecret database -o yaml -n default
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"bitnami.com/v1alpha1","kind":"SealedSecret","metadata":{"annotations":{},"creationTimestamp":null,"name":"database","namespace":"default"},"spec":{"encryptedData":{"password":"AgBkmeFXmYhAK4Zekujt3Q0w0H72suyH/eqY4t1KxfRR2WXliydE9/gzmCXQaumdVRbAuXUoo6WyIY2oe+aSetKTLMjalug6wWgDNT5k95NcCv3sZzpoOnvRBhY8Ur4PlG7ViySglWGMos7rf8axj5GCVbQ8+ZMj/jtoD2WsA9K0BZXxHw36/DYTWbGsJCNBc3ngFH9zwnn87BF+c3nlMIYedVQrQqDopF6g8Ccjb4IXCZKN8Jf3EAc93cPlvqtil9N0w4LeDKt450zmHquIQg46wLAhS/fA6NBUj4jIAKEB+1t7qbCsi4WtRZ6IZbLDnRwjA6Yyn6aW5He4fcSLha74w+pnMAsxIMxFWcvIGw2WVwRCBtQaUhjQhxKDFfpvTnIY78deMbJQlKm1c97yeIk7+2Av/UWHrWuq6UsilxZHfJBJ8E2RTU4TYd8RE5FV4qZMD3hKmxdRbhhFdY8mvfeehW2SOoSis+dNEj48AYlPgJc+OvMNyunShAmvSa8KmEHJeKkB95iarlVz5E6WCjZPfRCzl45X0fNEB039nHjU1jj5aXQ+IjH3pqfDGgpYLYKTwssDtSD8IKzxzV8WT1ijrwhOkXTUgbyoVGTQjhSSABFy8YyW1ucOr5N1ONQsg1xyyp5Fnv71Emlrx6rT1GMp4FjNkiQyr8o+19wst6GAf0k1jtIz9D2pnfG6ZowMKW0KutMbI4mM+bt0sw=="},"template":{"metadata":{"creationTimestamp":null,"name":"database","namespace":"default"}}}}
creationTimestamp: "2023-11-25T17:03:30Z"
generation: 1
name: database
namespace: default
resourceVersion: "1966"
uid: dc3da9bd-971e-4c0c-b4f3-e402e47b3616
spec:
encryptedData:
password: AgBkmeFXmYhAK4Zekujt3Q0w0H72suyH/eqY4t1KxfRR2WXliydE9/gzmCXQaumdVRbAuXUoo6WyIY2oe+aSetKTLMjalug6wWgDNT5k95NcCv3sZzpoOnvRBhY8Ur4PlG7ViySglWGMos7rf8axj5GCVbQ8+ZMj/jtoD2WsA9K0BZXxHw36/DYTWbGsJCNBc3ngFH9zwnn87BF+c3nlMIYedVQrQqDopF6g8Ccjb4IXCZKN8Jf3EAc93cPlvqtil9N0w4LeDKt450zmHquIQg46wLAhS/fA6NBUj4jIAKEB+1t7qbCsi4WtRZ6IZbLDnRwjA6Yyn6aW5He4fcSLha74w+pnMAsxIMxFWcvIGw2WVwRCBtQaUhjQhxKDFfpvTnIY78deMbJQlKm1c97yeIk7+2Av/UWHrWuq6UsilxZHfJBJ8E2RTU4TYd8RE5FV4qZMD3hKmxdRbhhFdY8mvfeehW2SOoSis+dNEj48AYlPgJc+OvMNyunShAmvSa8KmEHJeKkB95iarlVz5E6WCjZPfRCzl45X0fNEB039nHjU1jj5aXQ+IjH3pqfDGgpYLYKTwssDtSD8IKzxzV8WT1ijrwhOkXTUgbyoVGTQjhSSABFy8YyW1ucOr5N1ONQsg1xyyp5Fnv71Emlrx6rT1GMp4FjNkiQyr8o+19wst6GAf0k1jtIz9D2pnfG6ZowMKW0KutMbI4mM+bt0sw==
template:
metadata:
creationTimestamp: null
name: database
namespace: default
status:
conditions:
- lastTransitionTime: "2023-11-25T17:03:30Z"
lastUpdateTime: "2023-11-25T17:03:30Z"
status: "True"
type: Synced
observedGeneration: 1
Dengan menggunakan Sealed Secrets, Anda dapat menyimpan secret dalam repositori Git tanpa harus khawatir tentang keamanannya. Saat diterapkan di cluster Kubernetes, Sealed Secrets Controller akan membuat instance Sealed Secret dari secret asli, yang hanya dapat dibaca oleh cluster yang memiliki kunci pribadi yang sesuai.
Penting untuk dicatat bahwa Sealed Secrets tidak mengatasi semua masalah keamanan, tetapi memberikan lapisan tambahan keamanan saat menyimpan rahasia dalam repositori Git.