Spring Boot Property’lerini Jasypt ile Şifrelemek

Bir Spring Boot projemiz var. Projemize ait application.properties dosyasının içerisinde veritabanına bağlanırken kullandığımız kullanıcı adı/şifre gibi hassas bir veri var. Bu verinin açık olarak dosyada durması bir problem, güvenlik açığı teşkil ediyor. Bugünkü yazımız böyle hassas bilgilerin encrypted bir şekilde saklanabilmesi için Jasypt kütüphanesi ile Spring Boot properties’i birlikte nasıl kullanabileceğimiz hakkında olacak.

Jasypt, “Java Simplified Encrpytion” projesi aslında başlangıcı çok çok eski tarihlere dayanan bir proje. Henüz Acegi dünyası Spring Security altında birleşmeden öncesinde Jasypt’in Acegi ile uyumlu çalışan versiyonları mevcuttu. 2014ten bu yana temel fonksiyon setinde bir değişikliği olmamasına rağmen farklı popüler teknolojilerle entegre çalışabilmesi için geliştirilen farklı projeler de mevcut. Biz bugün Jasypt-Spring-Boot projesini kullanarak örneklerimizi gerçekleştireceğiz.

İlk olarak boş bir Spring Boot projesi yaratıyorum. İçerisine loglamada yardımcı olması için Lombok haricinde hiçbir ek bağımlılık eklemeyeceğim. Application.yml dosyasından aldığım bir değeri console’a basan basit bir kod yazıyorum.

Application.yml içeriği de aşağıdaki şekilde;

Bu şekilde kodumu çalıştırdığımda console’da aşağıdaki çıktıyı görüyorum.

...
INFO 6532 — — [ main] com.mcy.SimpleController : welcome cem
...

Bu durumda iken mcy.person property’sini dosyada açık olarak tutmamayı tercih edersem ne yapmalıyım? http://www.jasypt.org/download.html adresinden en yeni versiyonu indirip sıkıştırılmış paketi extract ediyoruz. ../bin/encrypt.bat çalıştırılabilir dosyası aracılığıyla encrypt etmek istediğimiz değeri kendi belirlediğimiz ve hiçbir yere yazmayacağımız bir key ile şifreleyeceğiz. Dosyayı çalıştırmaya çalışalım.

λ C:\dvlp\tools\jasypt-1.9.2\bin\encrypt.bat
USAGE: encrypt.bat [ARGUMENTS]
* Arguments must apply to format:
“arg1=value1 arg2=value2 arg3=value3 …”
* Required arguments:
input
password
* Optional arguments:
verbose
algorithm
keyObtentionIterations
saltGeneratorClassName
providerName
providerClassName
stringOutputType

İki argüman geçilmesini istedi. Input’ta şifrelemek istediğimiz değerimizi, password’de de bu şifrelemenin yapılacağı anahtarı istiyor. Aşağıdaki şekilde tekrar çalıştırdığımızda bize bir output verecek.

λ C:\dvlp\tools\jasypt-1.9.2\bin\encrypt.bat input=cem password=anyPrivateKey 

— — ENVIRONMENT — — — — — — — — —

Runtime: Oracle Corporation Java HotSpot(TM) 64-Bit Server VM 25.191-b12


— — ARGUMENTS — — — — — — — — — —

input: cem
password: anyPrivateKey


— — OUTPUT — — — — — — — — — — —

9w7d1xtySqiqozS/MmHw5g==

Bu output bizim kullanacağımız değer. cem içeriğine sahip değişkenimizi anyPrivateKey şifresiyle şifreleyerek 9w7d1xtySqiqozS/MmHw5g== şifreli değerimizi oluşturmuş olduk. Artık application.yml’daki açık değerimizi bu değerle değiştirebiliriz. Ancak Spring Boot’un bunun encrypted bir değer olduğunu anlayabilmesi için başına ve sonuna eklememiz gereken ufak ayrıntılar var. Application.yml’ımızın son durumu:

Kodumuzu bu haliyle tekrar çalıştırdığımızda karşımıza bir hata geliyor.

… 16 common frames omitted
Caused by: java.lang.IllegalStateException: Required Encryption configuration property missing: jasypt.encryptor.password
….

Spring’in demeye çalıştığı şu; sen properties dosyasında encrpyted bir değer kullanmışsın ve ben bunu decrypt ederek kullanmanı sağlamaya çalışıyorum. Ancak anahtarlama yaptığın key’i bana da vermezsen ben bu şifreyi açamam!

Biliyorsunuz ki encoding/decoding’in bir hash algoritması. Bcrpyt gibi Spring Boot kütüphanelerinin aksine encryption yapacaksanız güvenilir simetrik/asimetrik algoritmalardan birisini seçmeniz gereklidir. Ve bu şifreleme algoritmalarında şifrelenmiş değerin geri döndürülebilmesi için şifrelerken kullanılan anahtarın veya o anahtarla eşleşmiş başka bir anahtarın(public/private keys) decrpytion işlemine dahil olması gerekir. İşte bu sebeple uygulamamıza bir VM argümanı geçmemiz gerekiyor. Uygulamamızın Run Configurations>>Arguments sekmesi altında VM argümanları kısmına aşağıdaki argümanımızı geçiyoruz.

-Djasypt.encryptor.password=anyPrivateKey

Bu şekilde kodumuzu tekrar çalıştırdığımızda konsol çıktımız aşağıdaki gibi oluyor.

...
INFO 6532 — — [ main] com.mcy.SimpleController : welcome cem
...

Dilerseniz kullanılan şifreleme algoritmasını, argüman alma şeklini aşağıdaki gibi custom encryptor tanımlayarak tamamen kontrolünüze de alabilirsiniz.

Bu noktada belirtmemde fayda olan bir konu var. Bu property’ler sadece Spring Boot startup sonrasındaki argümanlarda kullanılmak zorunda değil. Örneğin startup esnasında AutoConfigurable bean’leriniz ayağa kalkacak ve burada gerekli parametreleriniz var ise bunlar da decrpyted olarak bean yaratılma anında kodunuza dahil oluyorlar. Yani daha somut örneğiyle Spring Data JPA kullanıyorsunuz ve DB connection bilgileri size Configuration sınıfınız içerisinde decrpyted olarak lazım ize EncryptablePropertySourceConverter bu configuration sınıfınız çalışmadan gerekli argümanların decryption işlemlerini tamamlayıp size değerlerinizin kullanılabilir hallerini sunuyor.

Eğer daha detaylı kullanım örneklerine,customization’lara ihtiyacınız olursa projeyi Github adresinde inceleyebilirsiniz. Şu an itibariyle Spring Boot’un 1.4.x, 1.5.x, 2.0.x versiyonları ile uyumlu çalışabiliyor.

Bu yazımız da burada sona erdi. Projenin kodlarına buradan ulaşabilirsiniz.

Her pazar yeni bir yazı ile görüşmek üzere!

En yalın haliyle…

Mehmet Cem Yücel