.Net Core Üzerinde Config, Redis ve ElasticSearch İçin Güvenlik
Selamlar,
Bu makalede, .Net Core üzerinde kullanabileceğiniz çeşitli Tooların configlerini nasıl güvenli bir şekilde saklayabileceğimize ve ElasticSearch, Kibana ve son olarak Redis’e nasıl şifre atayabileceğimizi inceleyeceğiz.
“Güvenlik bir yanılsamadır ama hoş bir tanesidir.” ― James Rozoff
Redis’e Şifre Atama:
Bu işlemi 2 şekilde yapabilirsiniz.
1.Yol, Redisin kurulu olduğu klasör altında, “redis.windows.conf” dosyasında “requirepass foobared” kelimeleri bulunup, başındaki # kaldırılıp, foobared kelimesi yerine istenen password atanır. Uygulama, ilgili makina ya da sunucu üzerinde servis olarak çalıştırılıyor ise, “redis.windows-service.conf” dosyasının değiştirilmesi gerekmektedir.
Örnek: “requirepass flyingcarpet”
2.Yol, “redis-cli” : Redis klasörü altındaki “redis-cli.exe” tıklanarak aşağıdaki komut ile, istenen password atanır.
1 |
CONFIG SET requirepass "mypassword" |
ElasticSearch’e Şifre Atama:
1-) Öncelikle, ElasticSearch’ün kurulu olduğu klasörün altındaki “/config” klasörü içinde, “elasticsearch.yml” dosyası bulunur. Aşağıdaki satır, başında # konmadan eklenir.
1 |
xpack.security.enabled: true |
2-) Yukarıdaki tanımlamadan sonra, ElasticSearch’ün kurulu olduğu klasör altında “bin/elasticsearch.bat” dosyası çalıştırılıp => “http://localhost:9200” adresine browserdan request çekilir ise, karşımıza aşağıdaki gibi bir ekran gelir.
Şu noktada, RabbitMQ’da olduğu gibi herhangi bir default “username” ve “password” değeri atanmamaktadır. Boşuna aramayın :)
3-) ElasticSearch’ün kurulu olduğu klasör altındaki “bin” klasörü içinde, aşağıdaki komut çalıştırılır.
1 |
elasticsearch-setup-passwords interactive |
Aşağıda görüldüğü gibi, yukarıdaki komut çalıştırıldığında elastic, kibana, logstash gibi birçok tool için şifre istenmektedir. Ben hepsi için aynı şifreyi, “borablog123!” şifresini girdim.
Şimdi “http://localhost:9200” adresine gidip, alttaki credentialları girerseniz aşağıdaki gibi bir ekran ile karşılaşırsınız:
Username: “elastic”
Password: “borablog123!”
Şimdi sıra geldi Kibana’yı, atanan bu şifrelemeye göre düzenlemeye.
Kibana’ya Şifre Atama:
1-) Öncelikle Kibana’nın kurulu olduğu klasörün altındak “C:\kibana-7.12.0-windows-x86_64\config/” klasörü altındaki”kibana.yml” içine, aşağıdaki satırlar eklenir. Dikkat edilir ise, “borablog123!” şifresi elasticsearch altında kibana user’ı için atanan şifrenin ta kendisidir.
1 2 3 4 5 |
elasticsearch.username: "elastic" elasticsearch.password: "borablog123!" xpack.security.session.idleTimeout: "1h" xpack.security.session.lifespan: "30d" |
2-) Kibana, “C:\kibana-7.12.0-windows-x86_64\bin\kibana.bat” çalıştırılıp => “http://localhost:5601” adresine request çekildiğinde, aşağıdaki değerler girilerek kibana ana ekranına ulaşılır:
Username: “elastic”
Password: “borablog123!”
Ayrıca istenir ise Elastic Üzerindeki var olan şifre, aşağıda görüldüğü gibi Kibana üzerinden değiştirilebilir. Bunun için, Kibana sayfası üzerinden => Stack Management=>Security=>Users altındaki “elastic” user’ı seçilip, password değiştirilebilir.
Ayrıca user detaya gelindiğinde, aşağıda görüldüğü gibi seçilen user, Username kutucuğunda görülmekte ve “Change Password” buttonuna basılarak var olan ElasticSearch şifresi güncellenebilmektedir.
Son olarak, ElasticSearch üzerinde atanmış olan password, “elasticsearch.yml” üzerindeki “xpack.security.enabled: true” satırının silinmesi ile tekrardan kaldırılabilir.
“Gerçek güvenlik diye bir şey yoktur. Hiç olmamıştı.” ― Germaine Greer
.NET Core Projede Config Dosya Güvenliği :
Şimdi bu şifreleri, .NET Core bir projede “appsettings.json“‘a doğrudan yani okunabilecek şekilde yazmak, kesinlikle güvenli olmaz.
Öncelikle gelin, Encrpt ve Decrpty yapabileceğimiz harici bir .NET Core projesi yazalım.
Encrption adında, “.Net Core WebApi” projesi aşağıdaki gibi yaratılır.
ICipherService.cs: Dosyası aşağıdaki gibi oluşturulur. Bu projede iki method olacaktır. “Encrypt()” ve “Decrypt()“.
1 2 3 4 5 |
public interface ICipherService { string Encrypt(string cipherText); string Decrypt(string cipherText); } |
Security.cs adında bir sınıf, “ICipherService” interface’inden türetilerek oluşturulur:
Aşağıda görüldüğü gibi “Encrypt()” ve “Decrypt()” methodları, belirlenen static bir Key’e göre, two way yani çift yönlü şifreleme yapmaktadır.
Security.cs:
Şimdi gelin bu servisi, SecurityController’da yazacağımız WebServislerinde çağıralım.
Encrypt() ve Decrypt() methodlarında, aşağıda görüldüğü gibi Encryption tipinde bir sınıf, parametre olarak beklemektedir.
1 2 3 4 |
public class Encrption { public string Text { get; set; } } |
Geriye “ActionResult<IEnumerable<string>>” tipinde, şifrelenen keyword’ün hem şifreli hem de şifresiz hali, geri dönülür.
SecurityController.cs:
Postman’den Encrypt() methodu elasticsearch için tanımlı Username ve Password için çağrıldığında, aşağıdaki gibi bir sonuçlar ile karşılaşılır.
UserName Encryption:
Password Encryption:
Şimdi sıra geldi burada şifrelediğimiz UserName ve Password’ü, gerçek projede kullanacağımız appsettings.json’a aşağıdaki gibi atamaya.
Öncelikle ElasticConnectionSettings.cs aşağıdaki gibi tanımlanır.
ElasticConnectionSettings.cs: Amaç, appsettings.json’da tanımlı alanın ilgili class ile eşlenmesidir.
1 2 3 4 5 6 |
public class ElasticConnectionSettings { public string ElasticUsername { get; set; } public string ElasticPassword { get; set; } public string ElasticUrl { get; set; } } |
Startup.cs‘de aşağıdaki tanımlama ile, appsettings.json üzerindeki “ElasticConnectionSettings” node’u ile ElasticConnectionSettings.cs sınıfını matchliyoruz.
1 |
services.Configure<ElasticConnectionSettings>(Configuration.GetSection("ElasticConnectionSettings")); |
Projenin Core katmanında, ElasticClient‘ın tek bir yerden ayağı kaldırıldığı “ElasticClientProvider” sınıfı, aşağıdaki gibi güncellenmiştir. Öncelikle Constructor’ında, aşağıdaki gibi “IEncryption” ve “ElasticConnectionSettings” sınıfları’ı Dependency Injection ile alınmıştır.
ElasticClientProvider.cs(1):
1 2 3 4 5 6 7 |
IEncryption _encryption; Microsoft.Extensions.Options.IOptions<ElasticConnectionSettings> _elasticConfig; public ElasticClientProvider(Microsoft.Extensions.Options.IOptions<ElasticConnectionSettings> elasticConfig, IEncryption encryption) { _encryption = encryption; _elasticConfig = elasticConfig; } |
“Güvenlik bir şeyler ile başa çıkmaktır, bir şeylere sahip olmak değil.” ― Susan Jeffers
ElasticClientProvider.cs(2): Aşağıda görüldüğü gibi, yukarıda makalenin başında tanımlanan “Encryption” sınıfı ile “appsettings.json“‘dan alınan Encrypted “Elastic Username ve Password“, Decrypt edilerek ilgili client ayağa kaldırılmıştır. appsettings.json’dan ilgili config datalar, “ElasticConnectionSettings” sınıfı ile doğrudan şifreli olarak alınır. Daha sonra decrypt edilerek, güvenli bir şekilde kullanılır. “BasicAuthentication()” methodu ile, ElasticSearch için gerekli olan credential bilgileri girilir.
1 2 3 4 5 6 7 8 9 10 11 |
private ElasticClient CreateClient() { var connectionSettings = new ConnectionSettings(new Uri(ElasticSearchHost)) .BasicAuthentication(_encryption.DecryptText(_elasticConfig.Value.ElasticUsername), _encryption.DecryptText(_elasticConfig.Value.ElasticPassword)) .DisablePing() .DisableDirectStreaming(true) .SniffOnStartup(false) .SniffOnConnectionFault(false); return new ElasticClient(connectionSettings); } |
Yapılan tüm bu işlemler, Redis Config için de geçerlidir. Encrypted olarak appsettings.json’a kaydedilen Redis password, RedisProvider’da Encryption sınıfı ile decrypt edilerek kullanılmaktadır.
Bu makalede Redis, ElasticSearch ve ElasticMonitor Tool’u olan Kibana’ya nasıl şifre atayabileceğimizi gördük. Atanan bu şifreleri, yazdığımız bir başka encrption uygulaması ile, okunamaz yani encrypted hale getirip (config)appsettings.json’a yazdık. Daha sonra ilgili Elastic ve Redis Client’a ihtiyaç duyulduğu noktalarda, bu config dosyadan okunan encrypted passwordleri, decrypt ederek kullandık. Esas amaç, tabi ki güvenlikdi.
Son olarak Encrption sınıfında kullanılan private key “private const string Key = “CutTheNightWithTheLight“, kodun içinde değil de, DB’den alınsa ve düzenli olarak değiştirilse, güvenlik bir kat daha arttırılmış olacaktır.
Geldik bir makalenin daha sonuna. Yeni bir makalede görüşmek üzere hepinize hoşçakalın.
Source :
Merhaba Hocam,
IDataProtectionProvider servisini kullanmıyor olmanıza rağmen, Controller’da AddDataProtection metodunu çağırmışsınız, bu noktada faydası nedir ?
Teşekkürler,
İyi Çalışmalar.