HashiCorp Vault Backend Penyimpanan Aman dalam Ekosistem Apache APISIX
API7.ai
January 24, 2022
Dengan meningkatnya arsitektur berbasis mikrolayanan, menjaga keamanan menjadi jauh lebih menantang daripada sebelumnya. Kita sudah jauh melampaui titik di mana 100 instance server backend mengakses server database dengan satu kredensial rahasia statis karena jika terjadi kebocoran kredensial, seluruh sistem akan terancam dan pencabutan kredensial tersebut dapat menyebabkan gangguan layanan besar-besaran (sekarang tidak ada yang bisa mengakses apa pun kecuali instance dikonfigurasi ulang). Kita tidak bisa menghilangkan kemungkinan terjadinya pelanggaran keamanan karena terkadang hal yang tidak terduga terjadi. Sebaliknya, sepenuhnya tergantung pada kita untuk mengontrol radius dampak dalam situasi seperti ini. Untuk mengatasi skenario seperti ini, solusi populer seperti HashiCorp Vault hadir dalam lingkungan produksi untuk bertindak sebagai sistem manajemen rahasia dan enkripsi berbasis identitas. Dalam artikel ini, saya telah mendemonstrasikan cara mengintegrasikan Vault dengan Apache APISIX (sebuah API Gateway cloud-native) jwt-auth plugin untuk secara efektif menggunakan keunggulan dari kedua dunia.
Apa itu Vault
HashiCorp Vault dirancang untuk membantu organisasi mengelola akses ke rahasia dan mengirimkannya dengan aman dalam suatu organisasi. Rahasia didefinisikan sebagai segala bentuk kredensial sensitif yang perlu dikontrol dan dipantau dengan ketat dan dapat digunakan untuk membuka informasi sensitif. Rahasia bisa berupa kata sandi, kunci API, kunci SSH, token RSA, atau OTP. Di dunia nyata, sangat umum terjadi penyebaran rahasia di mana rahasia disimpan ke dalam file konfigurasi atau sebagai variabel dalam kode program yang terkadang bahkan berakhir di sistem kontrol versi seperti GitHub, BitBucket, atau GitLab, yang menimbulkan ancaman keamanan besar. Vault menyelesaikan masalah ini dengan memusatkan rahasia. Ini menyediakan penyimpanan terenkripsi untuk rahasia statis, pembuatan rahasia dinamis dengan sewa TTL, autentikasi pengguna (mesin atau manusia) untuk memastikan mereka berwenang mengakses rahasia tertentu, dan banyak lagi. Sehingga bahkan dalam kasus pelanggaran keamanan, radius dampaknya jauh lebih kecil dan terkendali.
Vault memudahkan untuk mengontrol dan mengelola akses dengan menyediakan antarmuka unilateral untuk mengelola setiap rahasia dalam infrastruktur Anda. Tidak hanya itu, ini juga memberikan fleksibilitas untuk membuat log audit terperinci dan melacak siapa yang mengakses apa.

Tentang APISIX jwt-auth Plugin
Ini adalah plugin autentikasi yang dapat dilampirkan ke rute APISIX mana pun untuk melakukan autentikasi JWT (JSON web token, baca lebih lanjut) sebelum permintaan diteruskan ke URI upstream. Singkatnya, ini adalah mekanisme autentikasi yang aman yang mengarah ke otorisasi untuk sumber daya kritis. Biasanya, kunci pribadi atau rahasia teks digunakan oleh penerbit untuk menandatangani JWT. Penerima JWT akan memverifikasi tanda tangan untuk memastikan bahwa token tidak diubah setelah ditandatangani oleh penerbit. Integritas keseluruhan mekanisme jwt bergantung pada rahasia penandatanganan (baik itu rahasia teks atau pasangan kunci RSA). Hal ini membuat sulit bagi sumber yang tidak terautentikasi untuk menebak kunci penandatanganan dan mencoba mengubah klaim dalam JWT.
Oleh karena itu, penyimpanan kunci-kunci ini dalam lingkungan yang aman sangatlah penting. Jatuh ke tangan yang salah dapat membahayakan keamanan seluruh infrastruktur. Meskipun kami dari sisi APISIX mengambil semua cara untuk mengikuti praktik SecOps standar, sangat wajar dalam lingkungan produksi untuk memiliki solusi manajemen kunci terpusat seperti HashiCorp vault untuk memiliki jejak audit yang rinci, rotasi kunci berkala, pencabutan kunci, dll. Dan akan menjadi masalah yang cukup merepotkan jika setiap kali Anda harus memperbarui konfigurasi Apache APISIX setiap kali terjadi rotasi kunci di seluruh infrastruktur.
Langkah-langkah Menggunakan Vault dengan Apache APISIX
Untuk integrasi dengan Vault, Apache APISIX perlu dimuat dengan konfigurasi vault di config.yaml.
Secara internal, APISIX berkomunikasi dengan server vault KV secret engine v1 HTTP APIs. Karena sebagian besar solusi perusahaan lebih memilih untuk tetap menggunakan KV Secrets Engine - Versi 1 dalam lingkungan produksi mereka, selama fase awal dukungan APISIX-Vault kami hanya menggunakan versi 1. Dalam rilis selanjutnya, kami akan menambahkan dukungan untuk K/V versi 2.
Ide utama menggunakan vault, alih-alih backend etcd APISIX, adalah masalah keamanan dalam lingkungan dengan tingkat kepercayaan rendah. Kami, pengembang APISIX, memahami prioritas Anda dengan serius. Itulah mengapa kami merekomendasikan menggunakan token akses vault yang memiliki cakupan terbatas dan dapat memberikan akses terbatas ke server APISIX.
Mengonfigurasi Vault
Jika Anda sudah memiliki instance Vault yang berjalan dengan hak istimewa yang diperlukan, silakan lewati bagian ini. Bagian ini berbagi praktik terbaik untuk menggunakan Vault dalam ekosistem Apache APISIX. Silakan ikuti langkah-langkah yang disebutkan di bawah ini.
Langkah 1: Menjalankan Server Vault
Di sini Anda memiliki beberapa opsi, silakan pilih antara docker, biner yang telah dikompilasi sebelumnya, atau membangun dari sumber. Karena untuk berkomunikasi dengan server vault, Anda memerlukan klien CLI vault, saya lebih memilih untuk menggunakan biner yang telah dikompilasi sebelumnya daripada pendekatan Docker. Bagaimanapun, itu sepenuhnya terserah Anda (silakan konsultasikan dokumentasi instalasi resmi Vault). Untuk menjalankan server pengembangan, jalankan perintah berikut.
$ vault server -dev -dev-root-token-id=root … PERINGATAN! mode dev diaktifkan! Dalam mode ini, Vault berjalan sepenuhnya di memori dan mulai tidak disegel dengan satu kunci unseal. Token root sudah diautentikasi ke CLI, sehingga Anda dapat segera mulai menggunakan Vault. Anda mungkin perlu mengatur variabel lingkungan berikut: export VAULT_ADDR='http://127.0.0.1:8200' Kunci unseal dan token root ditampilkan di bawah ini jika Anda ingin menyegel/membuka segel Vault atau mengautentikasi ulang. Kunci Unseal: 12hURx2eDPKK1tzK+8TkgH9pPhPNJFpyfc/imCLgJKY= Token Root: root Mode pengembangan TIDAK BOLEH digunakan dalam instalasi produksi!
Atur CLI Anda dengan variabel lingkungan yang benar.
export VAULT_ADDR='http://127.0.0.1:8200' export VAULT_TOKEN='root'
Aktifkan mesin rahasia k/v versi 1 vault dengan prefiks path yang sesuai. Dalam demo ini, kami akan memilih path kv sehingga kami tidak memiliki tabrakan dengan path rahasia default vault untuk kv versi 2.
$ vault secrets enable -path=kv -version=1 kv Sukses! Mengaktifkan mesin rahasia kv di: kv/ # Untuk mengonfirmasi ulang status, jalankan $ vault secrets list Path Type Accessor Description ---- ---- -------- ----------- cubbyhole/ cubbyhole cubbyhole_4eeb394c penyimpanan rahasia pribadi per-token identity/ identity identity_5ca6201e penyimpanan identitas kv/ kv kv_92cd6d37 n/a secret/ kv kv_6dd46a53 penyimpanan rahasia key/value sys/ system system_2045ddb1 endpoint sistem yang digunakan untuk kontrol, kebijakan, dan debugging
Langkah 2: Menghasilkan Token Akses Vault untuk APISIX
Artikel ini berkaitan dengan penggunaan vault dalam perspektif plugin jwt-auth. Jadi, untuk konsumen APISIX (jika Anda tidak familiar dengan konsumen dalam ekosistem APISIX, silakan baca dokumentasi tentang Apache APISIX Consumer) dengan nama pengguna jack, plugin jwt-auth akan mencari (jika diaktifkan dengan konfigurasi vault) rahasia di <vault.prefix di dalam config.yaml>/consumer/<consumer.username>/jwt-auth ke dalam penyimpanan kv vault. Dalam konteks ini, jika Anda menetapkan namespace kv/apisix (path vault) sebagai vault.prefix di dalam config.yaml untuk semua pengambilan data terkait apisix, kami sarankan Anda membuat kebijakan untuk path kv/apisix/consumer/. Tanda bintang tambahan () di akhir memastikan kebijakan mengizinkan pembacaan untuk path apa pun yang memiliki prefiks kv/apisix/consumer.
Buat file kebijakan dalam Bahasa Konfigurasi HashiCorp (HCL).
$ tee apisix-policy.hcl << EOF path "kv/apisix/consumer/*" { capabilities = ["read"] } EOF
Terapkan kebijakan ke instance vault.
$ vault policy write apisix-policy apisix-policy.hcl Sukses! Mengunggah kebijakan: apisix-policy
Hasilkan token dengan kebijakan yang baru ditentukan yang telah dikonfigurasi dengan batas akses yang kecil.
$ vault token create -policy="apisix-policy" Key Value --- ----- token s.KUWFVhIXgoRuQbbp3j1eMVGa token_accessor nPXT3q0mfZkLmhshfioOyx8L token_duration 768h token_renewable true token_policies ["apisix-policy" "default"] identity_policies [] policies ["apisix-policy" "default"]
Dalam demonstrasi ini, s.KUWFVhIXgoRuQbbp3j1eMVGa adalah token akses Anda.
Menambahkan konfigurasi vault ke Apache APISIX
Seperti yang dibahas sebelumnya, Apache APISIX berkomunikasi dengan instance Vault melalui API HTTP Vault. Konfigurasi yang diperlukan harus ditambahkan ke config.yaml. Berikut adalah informasi singkat tentang berbagai bidang yang dapat Anda gunakan:
- host: Alamat host tempat server vault berjalan.
- timeout: Timeout HTTP untuk setiap permintaan.
- token: Token yang dihasilkan dari instance vault yang dapat memberikan akses untuk membaca data dari vault.
- prefix: mengaktifkan prefiks memungkinkan Anda untuk lebih menegakkan kebijakan, menghasilkan token dengan cakupan terbatas, dan mengontrol data yang dapat diakses dari APISIX dengan ketat. Prefiks yang valid adalah (
kv/apisix,secret, dll.)
vault: host: 'http://0.0.0.0:8200' timeout: 10 token: 's.KUWFVhIXgoRuQbbp3j1eMVGa' prefix: 'kv/apisix'
Membuat Konsumen APISIX
APISIX memiliki abstraksi tingkat konsumen yang berjalan seiring dengan skenario autentikasi. Untuk mengaktifkan autentikasi untuk rute APISIX apa pun, diperlukan konsumen dengan konfigurasi yang sesuai untuk jenis layanan autentikasi tertentu. Kemudian hanya APISIX yang dapat meneruskan permintaan ke URI upstream dengan berhasil melakukan autentikasi sesuai dengan konfigurasi konsumen. Konsumen APISIX memiliki dua bidang - satu adalah username (wajib) untuk mengidentifikasi satu konsumen dari yang lain dan yang lainnya adalah plugins yang menyimpan konfigurasi plugin khusus konsumen.
Di sini, dalam artikel ini, kami akan membuat konsumen dengan plugin jwt-auth. Ini melakukan autentikasi JWT untuk rute atau layanan yang sesuai.
Untuk mengaktifkan jwt-auth dengan konfigurasi vault, buat permintaan ke:
$ curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "username": "jack", "plugins": { "jwt-auth": { "key": "test-key", "vault": {} } } }'
Di sini plugin mencari rahasia kunci di dalam path vault (<vault.prefix dari conf.yaml>/consumer/jack/jwt-auth) untuk konsumen jack yang disebutkan dalam konfigurasi konsumen dan menggunakannya untuk penandatanganan dan verifikasi jwt selanjutnya. Jika kunci tidak ditemukan di path yang sama, plugin akan mencatat kesalahan dan gagal melakukan autentikasi jwt.
Menyiapkan Server Upstream Uji
Untuk menguji perilaku, Anda dapat membuat rute untuk upstream (penangan ping sederhana yang mengembalikan pong). Anda dapat menyiapkannya dengan server HTTP-Go sederhana.
// server upstream sederhana package main import "net/http" func ping(w http.ResponseWriter, req *http.Request) { w.Write([]byte("secure/pong\n")) } func main() { http.HandleFunc("/secure/ping", ping) http.ListenAndServe(":9999", nil) }
Membuat Rute APISIX dengan Autentikasi Diaktifkan
Buat rute APISIX dengan server HTTP ping yang aman ini dan plugin autentikasi jwt-auth diaktifkan.
$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "plugins": { "jwt-auth": {} }, "upstream": { "nodes": { "127.0.0.1:9999": 1 }, "type": "roundrobin" }, "uri": "/secure/ping" }'
Menghasilkan Token dari Plugin jwt-auth
Sekarang tanda tangani rahasia jwt dari APISIX yang dapat digunakan dan diteruskan untuk membuat permintaan ke rute proxy [http://localhost:9080/secure/ping](http://localhost:9080/secure/ping) ke server APISIX.
$ curl http://127.0.0.1:9080/apisix/plugin/jwt/sign\?key\=test-key -i HTTP/1.1 200 OK Date: Tue, 18 Jan 2022 07:50:57 GMT Content-Type: text/plain; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Server: APISIX/2.11.0 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ0ZXN0LWtleSIsImV4cCI6MTY0MjU3ODY1N30.nkyev1_KUapVgY_QVYETsSApA6gEkDWS8tsHFV1EpD8
Pada langkah sebelumnya, jika Anda melihat pesan seperti gagal menandatangani jwt, pastikan Anda memiliki kunci rahasia yang disimpan ke path vault kv/apisix/consumers/jack/jwt-auth.
# contoh $ vault kv put kv/apisix/consumer/jack/jwt-auth secret=$ecr3t-c0d3 Sukses! Data ditulis ke: kv/apisix/consumer/jack/jwt-auth
Meminta Server APISIX
Sekarang, buat permintaan ke proxy APISIX untuk rute /secure/ping. Setelah validasi berhasil, itu akan meneruskan permintaan ke server HTTP Go kami.
$ curl http://127.0.0.1:9080/secure/ping -H 'Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ0ZXN0LWtleSIsImV4cCI6MTY0MjU3ODU5M30.IYudBr7FTgRme70u4rEBoYNtGmGByzgfGlt8hctI__Q' -i HTTP/1.1 200 OK Content-Type: text/plain; charset=utf-8 Content-Length: 12 Connection: keep-alive Date: Tue, 18 Jan 2022 08:00:04 GMT Server: APISIX/2.11.0 secure/pong
Setiap permintaan tanpa jwt yang valid akan menghasilkan kesalahan HTTP 401 Unauthorized.
$ curl http://127.0.0.1:9080/secure/ping -i HTTP/1.1 401 Unauthorized Date: Tue, 18 Jan 2022 08:00:33 GMT Content-Type: text/plain; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Server: APISIX/2.11.0 {"message":"Missing JWT token in request"}
Berbagai Kasus Penggunaan di mana Vault Dapat Diintegrasikan dengan Plugin jwt-auth APISIX
Plugin jwt-auth Apache APISIX dapat dikonfigurasi untuk mengambil kunci rahasia teks sederhana serta pasangan kunci publik-privat RS256 dari penyimpanan vault.
:::note Untuk versi awal dukungan integrasi ini, plugin mengharapkan nama kunci rahasia yang disimpan ke path vault adalah di antara [ secret, public_key, private_key] untuk berhasil menggunakan kunci. Dalam rilis mendatang, kami akan menambahkan dukungan untuk merujuk kunci dengan nama kustom. :::
-
Anda telah menyimpan rahasia penandatanganan HS256 di dalam vault dan Anda ingin menggunakannya untuk penandatanganan dan verifikasi jwt.
$ curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "username": "jack", "plugins": { "jwt-auth": { "key": "key-1", "vault": {} } } }'Di sini plugin mencari kunci
secretdi dalam path vault (<vault.prefix dari conf.yaml>/consumer/jack/jwt-auth) untuk konsumen jack yang disebutkan dalam konfigurasi konsumen dan menggunakannya untuk penandatanganan dan verifikasi jwt selanjutnya. Jika kunci tidak ditemukan di path yang sama, plugin akan mencatat kesalahan dan gagal melakukan autentikasi jwt. -
Pasangan kunci RSA RS256, baik kunci publik maupun privat, disimpan di vault.
$ curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "username": "jim", "plugins": { "jwt-auth": { "key": "rsa-keypair", "algorithm": "RS256", "vault": {} } } }'Plugin mencari kunci
public_keydanprivate_keydi dalam path kv vault (<vault.prefix dari conf.yaml>/consumer/jim/jwt-auth) untukjimyang disebutkan di dalam konfigurasi plugin vault. Jika tidak ditemukan, autentikasi gagal.Jika Anda tidak yakin, bagaimana cara menyimpan kunci publik dan privat ke penyimpanan kv vault, gunakan perintah ini
# asumsikan, direktori Anda saat ini berisi file bernama "public.pem" dan "private.pem" $ vault kv put kv/apisix/consumer/jim/jwt-auth public_key=@public.pem private_key=@private.pem Sukses! Data ditulis ke: kv/apisix/consumer/jim/jwt-auth -
Kunci publik dalam konfigurasi konsumen, sementara kunci privat ada di vault.
$ curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "username": "john", "plugins": { "jwt-auth": { "key": "user-key", "algorithm": "RS256", "public_key": "-----BEGIN PUBLIC KEY-----\n……\n-----END PUBLIC KEY-----" "vault": {} } } }'Plugin ini menggunakan kunci publik RSA dari konfigurasi konsumen dan menggunakan kunci privat yang langsung diambil dari vault.
Menonaktifkan Vault dari Plugin
Sekarang, untuk menonaktifkan pencarian vault dari plugin jwt-auth, cukup hapus objek vault kosong dari konfigurasi plugin konsumen (dalam hal ini adalah jack). Ini akan membuat plugin jwt mencari rahasia penandatanganan (baik HS256/HS512 atau pasangan kunci RS512) ke dalam konfigurasi plugin untuk permintaan selanjutnya ke rute URI di mana konfigurasi jwt-auth telah diaktifkan. Bahkan jika Anda memiliki konfigurasi vault yang diaktifkan di APISIX config.yaml, tidak ada permintaan yang akan dikirim ke server vault.
Plugin APISIX dimuat ulang secara otomatis, oleh karena itu tidak perlu me-restart APISIX.
$ curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d ' { "username": "jack", "plugins": { "jwt-auth": { "key": "test-key", "secret": "my-secret-key" } } }'
Ringkasan
Artikel ini membawa Anda ke rilis mendatang integrasi Vault-Apache APISIX dan detail terkait.
Jangan ragu untuk memulai diskusi di GitHub Discussions atau berkomunikasi melalui mailing list.