Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

Asp.NET Core İle AWS Secrets Manager’ı Keşfedelim

Merhaba,

Bu içeriğimizde AWS Secrets Manager ile Asp.NET Core’da gizli verilerin güvenliğini sağlamayı tartışacak ve secret verilerin yönetiminin çeşitli yönlerini ve kavramlarını inceleyeceğiz.

Biliyorsunuz ki, her yazılımın mutlaka API anahtarları, mail şifreleri, veritabanı bağlantı cümlecikleri vs. gibi bazı gizli ve hassas bilgileri barındırması gerekmektedir. Yazılım için işlevselliği sürdürülebilir kılmanın ana damarı bu bilgiler üzerinden geçmektedir. Ancak bizler, bu tür hassas bilgileri sabit koda eklemekten, kod kalitesi ve olası güvenlik açıklarından kaynaklı katiyen kaçınıyoruz. Ee kaçınıyoruz kaçınmasına ama ne yapıyoruz da bu bilgileri yazılımlara işliyoruz? İşte tam da burada akıllara appsettings.json gelebilir 🙂 Evet, bu dosya bir yapılandırma dosyasıdır ama kritik arz eden hassas veriler için hiçte güvenli değildir. Hele hele production verileri için hiç mi hiç güvenli değildir!

Ee peki ne yapacağız hocam? dediğinizi duyar gibiyim…

Bu güne kadar Asp.NET Core’un Secret Manager Tool‘unu duymuşsunuzdur. Evet, bu tool tam da bu amaç için tasarlanmıştır. Ancak bunda da şöyle bir sıkıntı vardır ki; hassas verileri depolamak için dosya sistemine dayalı bir çözüm getirmektedir ve bu da yalnızca development ortamı için güven sağlayacaktır. Bizlere ise production ortamı için bu hassas verileri güvenilir ve merkezi bir yerde depolayabileceğimiz alan lazımdır. Bunun için internette yapacağımız aramalar neticesinde karşılaşacağımız çeşitli teknolojiler arasından en göze batan seçenek AWS Secrets Manager‘dır diyebiliriz.

AWS Secrets Manager

Uygulamalarınızın gizli ve hassas verilerini son derece güvenli bir şekilde depolamak ve yapılandırmak için özel olarak tasarlanmıştır. Ayrıca secret rotation, replication vs. gibi davranışları da barındırmaktadır.

AWS Secrets Manager, test edilebilmesi için 30 günlük bir deneme süresi sunmaktadır. Sonrasında saklanan her gizli veri için aylık 0,40 ABD doları (replikasyonlar dahil) ödenmesi gerekecektir. Bunun dışında, her 10.000 API request’e karşılık hassas verilerin sunulması veya yeni yapılandırmaların gerçekleştirilmesi için aylık yaklaşık 0,05 ABD doları tutarında bir ücretlendirme söz konusu olacaktır.

AWS Secrets Manager Dashboard’unu Keşfedelim

İlk olarak AWS Secrets Manager’ın dashboard’unu keşfederek başlayalım… Bunun için AWS Management Console üzerinden aşağıdaki gibi ilgili servisi aratalım;Asp.NET Core İle AWS Secrets Manager'ı KeşfedelimArdından açılan sayfada Store a new secret butonuna tıklayarak test amaçlı bazı yapılandırmalarda bulunmak için kurcalamaya başlayalım. Bunun için bir sonraki sayfada ‘Other type of secret’ sekmesini seçerek herhangi bir yapılandırma değerini key/value formatında girelim.Asp.NET Core İle AWS Secrets Manager'ı KeşfedelimTabi yapılandırmayı bu şekilde oluşturmamız bizim için yeterli olacaktır. Ancak, çalışma sürecinde bu hassas veriyi çok daha kolay bir şekilde elde edebilmek için bir sonraki adımda secret name değeri ve bir yandan da yanında isteğe bağlı olarak kısa bir açıklama tanımlıyor olacağız.Asp.NET Core İle AWS Secrets Manager'ı KeşfedelimAyrıca yüksek erişilebilirlik sağlamak için aşağıdaki gibi Replicate secret kısmında yapılandırmada bulunabilir ve böylece diğer AWS region’larında hassas verilerin read-only kopyalarını oluşturabilirsiniz.Asp.NET Core İle AWS Secrets Manager'ı KeşfedelimTabi bu özelliğin ekstradan ücretlendirileceğini de hatrınızdan çıkarmamanızı öneririm… Ve son olarak bir sonraki bölümde de aşağıdaki gibi automatic rotation yapılandırmasında bulunabilirsiniz. Ancak bu kısmı şimdilik atlayacak ve makalemizin ilerleyen bölümlerinde ayrıca ele alıyor olacağız.Asp.NET Core İle AWS Secrets Manager'ı KeşfedelimEvet, böylece dashboard üzerinden AWS Secrets Manager servisinde yapılandırılmış bir değerimiz mevcuttur diyebiliriz. Şimdi gelin bu yapılandırmaya Asp.NET Core Web API üzerinden nasıl erişebileceğimizi teknik olarak inceleyelim…

AWS Secrets Manager’a AWS .NET SDK İle Erişim

Öncelikle boş bir Asp.NET Core Web API uygulaması oluşturalım ve ardından AWS Secrets Manager SDK’ini aşağıdaki talimatlar aracılığıyla projeye kuralım.

Install-Package AWSSDK.Extensions.NETCore.Setup
Install-Package AWSSDK.SecretsManager

Bu kurulumdan sonra ‘Program.cs’ dosyasında aşağıdaki gibi çalışma sergileyebiliriz;

using Amazon.SecretsManager;
using Amazon.SecretsManager.Model;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddDefaultAWSOptions(builder.Configuration.GetAWSOptions());
builder.Services.AddAWSService<IAmazonSecretsManager>();
var app = builder.Build();

app.MapGet("/secret", async (IAmazonSecretsManager amazonSecretsManager) =>
{
    var request = new GetSecretValueRequest()
    {
        SecretId = "prod/XProject/ConnectionString"
    };

    var data = await amazonSecretsManager.GetSecretValueAsync(request);
    return Results.Ok(data.SecretString);
});

app.Run();

Burada görüldüğü üzere 6. ve 7. satırlarda AWS SDK dependency’leri IoC Container’a eklenmekte ve özellikle AWS Secrets Manager’ın servisi olan IAmazonSecretsManager yapılandırılmaktadır. Akabinde, /secret endpoint’i içerisinde prod/XProject/ConnectionString ‘SecretId’ değerini temsil eden bir talep/request nesnesi oluşturulmakta ve GetSecretValueAsync metoduyla bu değere karşılık veri istenmektedir. Bu kadar basit… Bu geliştirme neticesinde uygulamayı derleyip, çalıştırırsak eğer ilgili endpoint’e yapılan isteğe karşın aşağıdaki response’un elde edildiğini görmekteyiz.Asp.NET Core İle AWS Secrets Manager'ı Keşfedelim

AWS Secrets’ı Asp.NET Core İle Runtime’da Entegre Etme

Esasında, Asp.NET Core uygulamalarında AWS Secrets Manager’dan hassas verilerin okunması bu kadar basit. Ancak, gerçek bir uygulamada bu tarz hassas verilerin kullanımı tabi ki de yukarıdaki gibi Get isteği üzerine kurulu olmasa gerek, öyle değil mi? İdeal olarak, bu hassas verilerin builder.Configuration üzerinden yapılandırılması beklenir! Ee bunun içinde bu verilerin appsettings.json dosyasının ya da environment’ın bir parçası olması gerekmektedir.

Bunun için hassas verilere her ihtiyaç durumunda, AWS’ye istek gönderilmeksizin tüm bu verilerin AWS Secrets Manager’dan elde edilebilmesi için uygulama başlatılırken kümülatif bir şekilde çekilmeleri gerekmektedir. Evet, bu işlem için de AWS Secrets Manager’ı Configuration Provider olarak eklememiz gerekecektir. Bunu da yapabilmek için Amazon.Extensions.Configuration.SystemsManager kütüphanesinden istifade edeceğiz.

Install-Package Amazon.Extensions.Configuration.SystemsManager

Burada tek yapmamız gereken aşağıdaki gibi bir yapılandırmada bulunmaktır;

if (!builder.Environment.IsDevelopment())
    builder.Configuration.AddSystemsManager(source =>
    {
        source.Path = $"/aws/reference/secretsmanager/{builder.Environment.EnvironmentName}/XProject/ConnectionString";
        source.Optional = false;
        source.ReloadAfter = TimeSpan.FromMinutes(5);
    });

Kodu incelerseniz eğer development environment’ının dışındaki ortamlarda, AddSystemsManager metoduyla, AWS Secrets Manager’da bulunan uygulamayla ilgili tüm yapılandırma verileri uygulamaya eklenmektedir. Burada source.Optional özelliğine false değerini vererek, belirtilen path’de ki yapılandırma verilerinin kesinlikle uygulamaya katılması gerektiğini aksi taktirde uygulamanın hata fırlatacağını ifade ediyor, source.ReloadAfter özelliğiyle de AWS’den alınan bu hassas verilerin ne kadar periyot aralığında yeniden çekilmesi gerektiğini belirtiyoruz. Böylece uygulamaya dair güncel yapılandırma verilerini sunucuları yeniden başlatmaya gerek kalmaksızın rotasyon edebiliyoruz. Tabi bu rotasyonun ek maliyetler doğuracağını ve belirtilen periyodik süre aşımıyla ters orantılı olacak şekilde AWS faturalarınıza bu maliyetlerin yansıtılacağını unutmayınız.

Şimdi bu çalışmayı test edebilmek için uygulamanın launchSettings.json dosyasındaki profiller üzerinden birinin (ya da yeni oluşturulan bir profilin) ASPNETCORE_ENVIRONMENT değerini ‘prod’ olarak değiştirelim.

{
  "$schema": "https://json.schemastore.org/launchsettings.json",
  "profiles": {
    .
    .
    .,
    "prod": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "applicationUrl": "https://localhost:7155;http://localhost:5097",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "prod"
      }
    }
  }
}

Ve bu işlem neticesinde uygulamayı derleyip, bu profil ile tekrar ayağa kaldıralım.

dotnet run --launch-profile "prod"

https://localhost:7155/connectionstring adresi üzerinden bir istekte bulunduğumuz taktirde aşağıdaki gibi hassas verilerin AWS Secrets Manager’dan sorunsuz bir şekilde yüklendiğini görebilirsiniz.Asp.NET Core İle AWS Secrets Manager'ı Keşfedelim

Version Stages

İçeriğimizin sonlarına doğru AWS Secrets Manager’ın önemli kavramlarından biri olan Versioning‘e de temas etmekte fayda görmekteyim. Bu özellik ile AWS’de tutulan hassas verilere dair bir değişiklik söz konusu olduğunda sürümleme gerçekleştirebilmekte ve böylece kısmi olarak bir güvenlik sağlanabilmektedir. Düşünürseniz bu, ihtiyaç dahilinde oldukça kritik arz edebilen bir özelliktir diyebiliriz. Gizli bir veri güncellenecek, ardından eski sürümlere erişim sağlanması için otomatik versiyonlama gerçekleştirilecektir. Gün gelecek basit bir hatadan kaynaklı bir kriz anında eski yapılandırmaya geri dönüş gerekecek ve bu özellik sayesinde hızlıca hareket edilerek, uygulama korunmuş olacaktır.

Burada unutulmaması gereken husus şudur ki; verinin tüm sürümleri değil, yalnızca güncel (AWSCURRENT) ve önceki (AWSPREVIOUS) versiyonlar tutulmaktadır.

Eğer ki, bir yapılandırmanın bir önceki sürümü elde edilmek isteniyorsa, request’in aşağıdaki gibi AWSPREVIOUS VersionStage değeri ile yapılması yeterli olacaktır.

app.MapGet("/previous-version", async (IAmazonSecretsManager amazonSecretsManager) =>
{
    var request = new GetSecretValueRequest()
    {
        SecretId = "prod/XProject/ConnectionString",
        VersionStage = "AWSPREVIOUS"
    };

    var data = await amazonSecretsManager.GetSecretValueAsync(request);
    return Results.Ok(data.SecretString);
});

Nihai olarak;
Bu içeriğimizde, AWS Secrets Manager servisiyle uygulamalarımızın hassas verilerini güvenli bir şekilde depolamanın farklı bir yolunun farkındalığına erişmiş ve bir yandan da Asp.NET Core ile birlikte AWS SDK’i eşliğinde kullanımını incelemiş olduk. Artık ihtiyaç dahilinde AWS’nin bu nimetinden istifade kaçınılmazdır diyebiliriz 🙂

İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Not: Örnek çalışmaya aşağıdaki GitHub adresinden erişebilirsiniz.
https://github.com/gncyyldz/AWSSecretManagerExample

Bunlar da hoşunuza gidebilir...

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir