Vault Kullanarak Secret Depolama ve Spring Boot Hashicorp Entegrasyonu
Merhabalar,
Bu yazımda vault kullanarak web uygulamalarında gizli bilgiler nasıl depolanır, alternatif ve mevcut kullanım senaryoları nelerdir, neden önemlidir gibi konulara değineceğim. Ardından vault alternatiflerininden HashiCorp Vault’un nasıl kullanılacağını anlatmaya çalışacağım. Keyifli okumalar. 🙂
Secret Saklama
Yazılım geliştiriciler olarak, programlarımızın birçok değere ihtiyacı oluyor ve bu değerlerin bazılarını gizli tutmamız gerekiyor. Örneğin, veritabanı bağlantı bilgileri (kullanıcı adı, şifre, port vb.), sunucu adresleri, SSH anahtarları ve yönetici bilgileri gibi hassas bilgileri açığa çıkarmak istemiyoruz. Peki gizli bilgilerimizi sıklıkla nerede ve nasıl depoluyoruz ? Gelin bunlara, avantaj ve dezavantajlarına bakalım.
Kaynak Kod İçerisinde Secret Saklama
Basitlik, yazılım geliştirme aşamasında arzu edilen bir özelliktir. Secret bilgileri direkt olarak kaynak koda koymakta bu basitliğin en iyi hali sayılabilir. Ama bu yöntem güvenlik açısından durumu tam tersine çevirebilir. Mesela uygulamamızın istemci tarafında çalıştığı bir senaryo düşünelim. Bazı gizli bilgilerin bir js dosyasında tutulduğunu varsayalım. Bu durumda gizli bilginin ifşa olması için bir saldırganın sadece sayfayı inspect etmesi yeterli olur. Bunun yaşanmayacak kötü bir örnek olarak gördüyseniz web arşivde yer alan weather.com’un kaynak kodunu inceleyin 🙂 (SECRET_KEY araması yapabilirsiniz.)
İkinci senaryo, private bir repoda çalıştığınız durumdur. Bu, biraz daha güvenli görünse de Apiiro’nun “Yazılım Tedarik Zincirinde Gizli Bilgiler Raporu”na göre, 25.000'den fazla repository üzerinde yapılan incelemede private repolardaki gizli bilgilerin %50'sinin, saldırganların ağa erişim sağlaması durumunda hemen ulaşılabilir olduğu bulunmuştur. Bu gizli bilgilerin %38'i Kişisel Tanımlayıcı Bilgiler (PII) içeriyor. Ayrıca, ifşa edilen tüm gizli bilgilerin %42'si düz metin olarak saklanan şifrelerdir.
Yapılandırma Dosyalarında Secret Saklama
Yapılandırma dosyaları, ortamlar arasında dağıtımları hızlı ve sorunsuz hale getirir. Örneğin, prod ve test ortamlarımız farklı veritabanları kullanıyorsa, bu ayarları yapılandırma dosyalarında kolayca özelleştirebiliriz. İlk bakışta, yapılandırma dosyaları gizli bilgileri saklamak için uygun görünebilir. Ancak, güvenlik açısından yapılandırma dosyalarında gizli bilgi saklamak, kaynak kodunda saklamak kadar risklidir. Bunun nedeni, yapılandırma dosyalarının da repository’e gönderilebilmesidir. Bu riski azaltmak için .gitignore gibi yöntemler kullanılabilir, fakat küçük bir ihmal veya dikkatsizlikle gizli bilgiler repository’e dahil edilebilir. Özellikle büyük ekiplerde bu olasılık daha yüksektir. Ayrıca, bir saldırgan ağa erişim sağladığında, yapılandırma dosyalarına da hızla ulaşabilir.
Vault Nasıl Çalışır ?
Vault, sırları yönetme sorununu çözmek çıkarılmış uygulamalardır. Kullanıcı kimliklerini ve gerçekliğini doğrulayabilir, bireysel bir kullanıcın erişebileceği öğeleri tanımlayan politikaları uygulayabilir, izin verilen işlem kümesini belirleyebilir, şifreleri güvenli bir şekilde saklayabilir. Vault’u kişisel bir şifre yöneticisinin tüm kuruluşa hizmet etmek üzere uyarlanmış versiyonu olarak düşünebiliriz.
Alternatif Vault Uygulamaları
Vault uygulamarı arasıda, özellikleri, kurulum yöntemleri ve kaynak kodu erişimleri açısından farklılık gösteren birçok alternatif bulunmaktadır. Gartner PAM(Privileged Access Managemet) grafiği aşağıdaki gibidir.
- CyberArk Conjur
- BeyondTrust
- Delinea
- Arcon
- WALLIX
- Broadcom
- One Identity
- Netwrix
- GCP Secret Manager
- Akeyless
- Saviynt
- Hashicorp Vault
HashiCorp ve CyberArk, yukarıdaki çözümlerden açık kaynaklı olanlardır. Eğer büyük ölçekli bir proje yerine bireysel projeler üzerinde çalışıyorsanız, 1Password CLI ‘uda alternatif olarak tercih edebilirsiniz.
Vault İle İletişim
Genel olarak vaultlar, kullanıcıların istekte bulunabilmesi için herkese açık bir HTTP API sunar. Bu sayede, kullanıcılar ister web uygulaması, ister doğrudan API çağrısı, isterse de bir programlama kütüphanesi ile vault işlemlerini gerçekleştirebilir.
Şimdi, vault’un nasıl kullanıldığını göstermek için HashiCorp Vault kullanarak yukarıdaki diyagramdaki senaryo üzerinde çalışalım. Bir Spring Boot projesine sahip olduğumuzu ve vault’a yazdığımız secret’ları basit CRUD işlemleriyle konsolda görmek istediğimizi varsayalım. Bu şekilde, Vault’un nasıl çalıştığını daha iyi anlayabiliriz ve programlarımızda nasıl kullanabileceğimizi görebiliriz.
Spring Uygulaması Başlatmak
Yukarıda gerekli bağımlılıkları ekledik. Bu bağımlılıklar arasında Vault bağlantımızı sağlayacak olan Vault Configuration da bulunuyor.
Vault Kurulumu
Şimdi HashiCorp’un Vault’unu kurmaya geçelim. Linkteki bağlantıyı kullanarak, istediğiniz yöntemle Vault’u kurabilirsiniz. Kurulumu tamamladıktan sonra, vault -h
komutunu kullanarak kurulumun doğrulamasını yapabiliriz.
Dev Server Mod
“Vault’u geliştirme modunda başlatmak için vault server -dev
komutunu kullanabiliriz. Bu şekilde, ek bir kurulum gerektirmeden Vault'u deneyebilir veya geliştirme amaçlı örnek bir Vault oluşturabiliriz. Geliştirme modunda Vault'un tüm özellikleri mevcuttur.
Önemli Not: Geliştirme modu kesinlikle production ortamında kullanılmamalıdır. Güvenlik açısından risklidir ve verileri RAM’de depoladığı için her yeniden başlatmada veriler sıfırlanır. Bu nedenle, yalnızca geliştirme ortamı için tasarlanmış bir moddur.
Yukarıda görüldüğü gibi, terminalimize vault server -dev
komutunu yazdığımızda, yerel bir sunucu başlatılır. Bu işlem, bize arayüze erişim sağlayabileceğimiz bir link ve giriş yapabileceğimiz bir token verir. (Bu token, spring yapılandırmasında da kullanılacaktır.)
Terminalden aldığımız root token’ı girdikten sonra aşağıdaki gibi arayüze erişebiliriz. Buradan secrets engines menüsüne tıklayarak var olan secrets engine’leri görebilir ve yeni bir tane oluşturabiliriz. Secrets engine’ler, verileri depolayan, üreten veya şifreleyen bileşenlerdir.
Bu aşamada yeni bir engine oluşturabiliriz. Şimdilik var olan secret/ (key-value) engine ile devam edeceğiz. Buna tıklayıp yeni secret oluşturabiliriz. Örneğin, veritabanı bağlantımız için değerleri burada oluşturalım.
Arayüzden Secret Oluşturmak
Terminal’den Secret Oluşturmak
Veritabanı bilgilerimizi sakladığımız secret’ı oluşturduk. Eğer bu değerleri arayüz yerine terminal üzerinden oluşturmak istersek, aşağıdaki komutu kullanabiliriz:
vault kv put secret/vaultAppDemo example=abdullah
Bu komut, secret/vaultAppDemo
adında bir secret oluşturur ve içine example=abdullah
şeklinde bir anahtar-değer çifti ekler. Doğrulamak için arayüzden baktığımız zaman aşağıdaki gibi oluşturulan değeri görebiliriz.
Terminalden Secret’a Erişmek
vault kv get
komutu ile tanımlanan key-value secretlere erişebiliriz. Örneğin, ilk oluşturduğumuz db secret'ine erişmek için vault kv get secret/db
komutunu yazabiliriz. Aşağıdaki gibi secret bilgilerini görebiliriz:
Şimdi uygulamamızdan oluşturmuş olduğumuz secret’a erişelim ve bu değerleri kullanalım.
Spring Boot Vault Configuration
Uygulamamızı açalım ve application.properties
dosyamızda Vault bağlantı bilgilerini girelim.
spring.application.name=db
: Bu, secret'e verdiğimiz isimdir. Secret oluştururken db
olarak isimlendirdiğimiz için db
yazıyoruz.
spring.cloud.vault.token=hvs.9QGeqfMoccVeAzFC5dDdYzKW
: Vault'a giriş yapabilmek için kullanacağınız özel erişim anahtarını (token) ifade eder. Bu token, vault server -dev
komutunun çıktısında yer almaktadır.
spring.cloud.vault.url=127.0.0.1:8200
: Vault servisinin nerede çalıştığını belirtir. Biz default değerleri girerek devam ediyoruz.
spring.config.import=vault://
: Bu ayar, uygulamamızın yapılandırma ayarlarını Vault'tan otomatik olarak almasını sağlar. Yani, uygulamanızı başlatırken gerekli olan yapılandırmaları doğrudan Vault üzerinden çekebilmemize olanak tanır.
Şimdi gerekli konfigürasyonlarımızı yapalım. Aşağıdaki gibi Vault’a girdiğimiz değerleri alabiliriz.
Şimdi uygulamamıza bir REST API yazalım. API’a istek atıldığı zaman Vault’taki verileri konsola loglayalım. Bu sayede Vault’a düzgün bir şekilde bağlandığımızı ve secret’ları okuyabildiğimizi doğrulayabiliriz.
Yukarıda görüldüğü gibi, curl http://localhost:8080/api/getDataFromVault
isteğini attığımızda, Vault'a yazdığımız secret'lar başarılı bir şekilde konsola yazıldı. Bu sayede, uygulamamızın içinde konfigürasyon veya ortam dosyalarında belirtmediğimiz gizli bilgileri Vault üzerinde saklayarak, çalışma sırasında erişilebilir hale getirdik. Bu aşamada, basit bir uygulama ile HashiCorp Vault'a nasıl secret girileceğini ve mevcut secret'lara Spring Boot üzerinden nasıl erişileceğini öğrendik. Kullanım senaryolarımıza göre Vault'un kullanımını özelleştirebiliriz.
Ne Kazandık ?
Secretlarımızı saklamak için bir vault kullandık. Ama vault’ ile iletişime geçmek için yine bir token kullandık. Bu mantıksız gelebilir ama vaultlar secretları ortadan kaldırmak yerine onları daha sistematik yönetebilmeyi sağlar. Sistemde authantication için kullanılan bir tokenın olması bir çok secret’ın kaynak kodunda olmasından çok daha güvenli bir senaryodur. Çünkü authantication token belirlenen politikalara göre iptal edilebilir, yenilenmeye zorlanabilir ve yönetilmesi kolaydır. Ek olarak büyük bir mimari içerisinde çalışıldığı ve mikroservislerinde sisteme dahil olduğu durumlarda secretlar tek bir uygulamada kalmaz ve bir çok servise yayılması gerekir. Buda yine secret güvenliği açısından sorunlu ve güvensiz bir senaryodur. Vault kullanarak bu durumdada güvenli şekilde yönetebiliriz.
Bu yazıda Vault’un önemine ve Hashicorp Vault’un Spring Boot entegrasyonuna değinmeye çalıştım. Github’dan örnek projeye ulaşabilirsiniz. Umarım keyif aldığınız ve yeni bir şeyler öğrendiğiniz bir yazı olmuştur. Bir sonraki yazımda görüşmek üzere, hoşça kalın! 👋🏼