Azure Managed Identity Kullanımı ve En İyi Uygulamalar

Azure üzerinde uygulama geliştirirken en sık karşılaşılan güvenlik açıklarından biri, servis hesabı şifrelerini veya API anahtarlarını kod içine gömmektir. Bir arkadaşım geçen ay bunu yaptığı için GitHub’a push ettiği repo’da production veritabanı bağlantı dizesini sızdırdı ve az kalsın işini kaybediyordu. İşte tam bu noktada Azure Managed Identity devreye giriyor ve “credential yönetimi” denen baş ağrısını büyük ölçüde ortadan kaldırıyor.

Managed Identity Nedir ve Neden Önemli?

Azure Managed Identity, Azure Active Directory (AAD) tarafından yönetilen, otomatik olarak döndürülen kimlik bilgilerini kullanarak Azure kaynaklarının birbirini doğrulamasını sağlayan bir mekanizmadır. Kısaca şöyle düşün: Azure VM’in, bir Azure Key Vault’a erişmesi gerekiyor. Normalde bunu yapmak için bir service principal oluşturur, client ID ve secret alır, bunları bir yerlere kaydersin. Managed Identity ile VM’e “sen zaten Azure’sun, sana güveniyorum” diyorsun ve iş bitiyor.

İki temel türü var:

  • System-assigned Managed Identity: Bir Azure kaynağına doğrudan atanır. Kaynak silindiğinde identity de silinir. Birebir ilişki vardır.
  • User-assigned Managed Identity: Bağımsız bir Azure kaynağı olarak oluşturulur. Birden fazla kaynağa atanabilir. Yaşam döngüsü bağımsızdır.

Hangisini kullanacağın senaryoya göre değişiyor. Tek bir VM veya App Service için basit bir senaryo varsa system-assigned yeterli. Ama aynı kimliğin birden fazla kaynakta kullanılması gerekiyorsa user-assigned tercih ediliyor.

System-Assigned Identity Nasıl Aktifleştirilir?

Azure CLI ile bir VM’e system-assigned identity eklemek son derece basit:

# Mevcut bir VM'e system-assigned identity ekle
az vm identity assign 
  --resource-group myResourceGroup 
  --name myVM

# Sonucu kontrol et
az vm identity show 
  --resource-group myResourceGroup 
  --name myVM

Çıktıda principalId alanını göreceksin. Bu, AAD’deki kimliğin benzersiz ID’si. Bu ID’yi rol atamaları için kullanacaksın.

App Service için de benzer şekilde:

# App Service'e system-assigned identity ekle
az webapp identity assign 
  --resource-group myResourceGroup 
  --name myWebApp

# Identity bilgilerini görüntüle
az webapp identity show 
  --resource-group myResourceGroup 
  --name myWebApp

User-Assigned Identity Oluşturma ve Atama

Birden fazla kaynağın aynı kimliği kullanması gereken senaryolarda user-assigned identity çok daha pratik:

# User-assigned identity oluştur
az identity create 
  --resource-group myResourceGroup 
  --name myManagedIdentity 
  --location eastus

# Oluşturulan identity'nin bilgilerini al
IDENTITY_ID=$(az identity show 
  --resource-group myResourceGroup 
  --name myManagedIdentity 
  --query id 
  --output tsv)

PRINCIPAL_ID=$(az identity show 
  --resource-group myResourceGroup 
  --name myManagedIdentity 
  --query principalId 
  --output tsv)

# VM'e user-assigned identity ata
az vm identity assign 
  --resource-group myResourceGroup 
  --name myVM 
  --identities $IDENTITY_ID

# Farklı bir App Service'e aynı identity'yi ata
az webapp identity assign 
  --resource-group myResourceGroup 
  --name myOtherWebApp 
  --identities $IDENTITY_ID

Buradaki güzelliğe dikkat et: Aynı myManagedIdentity‘yi hem VM’e hem de App Service’e atadık. İkisi de aynı Azure kaynaklarına erişim hakkına sahip olacak. Rol yönetimi tek noktadan yapılıyor.

Rol Atama: RBAC ile Yetkilendirme

Identity oluşturduktan sonra asıl iş başlıyor. Bu identity’ye hangi kaynaklara ne kadar erişim hakkı vereceğini tanımlaman gerekiyor. Azure RBAC (Role-Based Access Control) burada devreye giriyor.

Gerçek dünya senaryosu: Bir Azure VM’in Key Vault’taki sırları okuması ve Blob Storage’a yazması gerekiyor.

# Key Vault için secret okuma yetkisi ver
az role assignment create 
  --assignee $PRINCIPAL_ID 
  --role "Key Vault Secrets User" 
  --scope "/subscriptions/<subscription-id>/resourceGroups/myResourceGroup/providers/Microsoft.KeyVault/vaults/myKeyVault"

# Blob Storage için contributor yetkisi ver
STORAGE_ID=$(az storage account show 
  --resource-group myResourceGroup 
  --name mystorageaccount 
  --query id 
  --output tsv)

az role assignment create 
  --assignee $PRINCIPAL_ID 
  --role "Storage Blob Data Contributor" 
  --scope $STORAGE_ID

Burada least privilege prensibine dikkat et. “Storage Blob Data Contributor” rolü verirken “Contributor” vermek yerine sadece blob işlemleri için gerekli rolü seçtim. Bu küçük ayrıntı güvenlik açısından büyük fark yaratıyor.

Uygulama Kodunda Managed Identity Kullanımı

Peki uygulamanın kodunda bu identity’yi nasıl kullanacaksın? Azure SDK’ları bu konuda çok kolaylık sağlıyor. DefaultAzureCredential sınıfı önce ortam değişkenlerine bakıyor, sonra managed identity’yi deniyor, sonra Azure CLI credentials’ını deniyor. Geliştirme ortamında Azure CLI ile login olmuşken aynı kod production’da managed identity kullanıyor.

Python örneği:

from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient
from azure.storage.blob import BlobServiceClient

# Credential oluştur - ortama göre otomatik seçim yapıyor
credential = DefaultAzureCredential()

# Key Vault'tan secret oku
key_vault_url = "https://myKeyVault.vault.azure.net"
secret_client = SecretClient(vault_url=key_vault_url, credential=credential)

db_password = secret_client.get_secret("database-password").value
print(f"Secret başarıyla alındı, uzunluk: {len(db_password)}")

# Blob Storage'a yaz
storage_account_url = "https://mystorageaccount.blob.core.windows.net"
blob_client = BlobServiceClient(account_url=storage_account_url, credential=credential)

container_client = blob_client.get_container_client("mycontainer")
container_client.upload_blob(
    name="test-file.txt",
    data=b"Managed Identity ile yukluyor!",
    overwrite=True
)

Dikkat: Bu kodda hiçbir şifre, API anahtarı veya connection string yok. Kod GitHub’a gitse de sızdırılacak bir şey yok.

Azure Functions ile Managed Identity

Serverless dünyasında da managed identity hayat kurtarıyor. Bir Azure Function’ın Service Bus’a mesaj göndermesi ve SQL veritabanına bağlanması gerektiğini düşün:

# Function App'e system-assigned identity ekle
az functionapp identity assign 
  --resource-group myResourceGroup 
  --name myFunctionApp

# Service Bus üzerinde mesaj gönderme yetkisi ver
SERVICE_BUS_ID=$(az servicebus namespace show 
  --resource-group myResourceGroup 
  --name myServiceBusNamespace 
  --query id 
  --output tsv)

FUNC_PRINCIPAL_ID=$(az functionapp identity show 
  --resource-group myResourceGroup 
  --name myFunctionApp 
  --query principalId 
  --output tsv)

az role assignment create 
  --assignee $FUNC_PRINCIPAL_ID 
  --role "Azure Service Bus Data Sender" 
  --scope $SERVICE_BUS_ID

Azure SQL için managed identity kullanımı biraz farklı çalışıyor. SQL tarafında da AAD authentication’ı aktifleştirmen ve SQL kullanıcısı oluşturman gerekiyor:

# SQL Server için AAD admin ayarla
az sql server ad-admin create 
  --resource-group myResourceGroup 
  --server-name mySqlServer 
  --display-name "AAD Admin" 
  --object-id <your-aad-user-object-id>

SQL’de ise şunu çalıştırman gerekiyor:

-- Azure SQL'de managed identity için kullanıcı oluştur
CREATE USER [myFunctionApp] FROM EXTERNAL PROVIDER;
ALTER ROLE db_datareader ADD MEMBER [myFunctionApp];
ALTER ROLE db_datawriter ADD MEMBER [myFunctionApp];

Ardından uygulama kodundaki connection string şöyle görünüyor:

Server=mySqlServer.database.windows.net;Database=myDatabase;Authentication=Active Directory Managed Identity;

Şifre yok, hiçbir credential yok. Sysadmin olarak bunu ilk gördüğümde “bu nasıl çalışıyor?” diye şaşırdığımı itiraf edeyim.

Sorun Giderme: En Sık Karşılaşılan Hatalar

Managed Identity kullanırken çeşitli hatalarla karşılaşabilirsin. İşte en yaygın olanlar ve çözümleri:

“ManagedIdentityCredential authentication unavailable”

Bu hata genellikle local geliştirme ortamında managed identity token endpoint’ine ulaşamadığında çıkar. Çözüm: DefaultAzureCredential kullanıyorsan Azure CLI ile login ol.

# Local geliştirme için Azure CLI ile login
az login

# Doğru subscription seçili mi kontrol et
az account show

# Gerekirse subscription değiştir
az account set --subscription "My Subscription Name"

“The user, group or application does not have secrets get permission on key vault”

Bu hata rol atamasının eksik veya hatalı olduğunu gösteriyor. Key Vault ayrıca kendi access policy mekanizmasına da sahip. RBAC modunu kullanıyorsan roller yeterli, ama eski access policy modundaysan ayrıca izin eklemen gerekiyor:

# Key Vault access policy modunda çalışıyorsa
az keyvault set-policy 
  --name myKeyVault 
  --object-id $PRINCIPAL_ID 
  --secret-permissions get list

# Key Vault'un hangi modda olduğunu kontrol et
az keyvault show 
  --name myKeyVault 
  --query properties.enableRbacAuthorization

Rol Atamasının Geçerli Olması İçin Bekleme

Rol atamaları Azure’da anında geçerli olmayabiliyor. Özellikle yeni oluşturulmuş identity’lerde birkaç dakika beklemek gerekebiliyor. Bu konuda acele etme ve şüpheli durumlarda şunu dene:

# Rol atamalarını listele ve doğrula
az role assignment list 
  --assignee $PRINCIPAL_ID 
  --output table

# Token alarak identity'nin çalışıp çalışmadığını test et
# VM içinden çalıştır:
curl 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://vault.azure.net' 
  -H Metadata:true

Bu curl komutu VM içinden çalıştırılmalı. Başarılı bir yanıt access_token alanı içerecek. Bu token’ı alabiliyorsun demek ki managed identity düzgün çalışıyor.

AKS ve Container Ortamlarında Managed Identity

Kubernetes üzerinde de managed identity kullanmak mümkün. Azure Kubernetes Service (AKS) için Workload Identity özelliği bu işi yapıyor. Eski yöntem olan Pod Identity artık deprecated olduğu için workload identity kullanmanı tavsiye ederim.

# Workload Identity aktif AKS cluster oluştur
az aks create 
  --resource-group myResourceGroup 
  --name myAKSCluster 
  --enable-oidc-issuer 
  --enable-workload-identity 
  --node-count 2 
  --generate-ssh-keys

# OIDC issuer URL'ini al
OIDC_ISSUER=$(az aks show 
  --resource-group myResourceGroup 
  --name myAKSCluster 
  --query "oidcIssuerProfile.issuerUrl" 
  --output tsv)

# User-assigned identity oluştur
az identity create 
  --resource-group myResourceGroup 
  --name myWorkloadIdentity

# Federated identity credential oluştur
az identity federated-credential create 
  --name myFederatedCredential 
  --identity-name myWorkloadIdentity 
  --resource-group myResourceGroup 
  --issuer $OIDC_ISSUER 
  --subject "system:serviceaccount:default:my-service-account" 
  --audiences "api://AzureADTokenExchange"

Kubernetes tarafında service account’a annotation eklemen gerekiyor:

# Service account oluştur ve identity ile ilişkilendir
kubectl create serviceaccount my-service-account --namespace default

CLIENT_ID=$(az identity show 
  --resource-group myResourceGroup 
  --name myWorkloadIdentity 
  --query clientId 
  --output tsv)

kubectl annotate serviceaccount my-service-account 
  --namespace default 
  azure.workload.identity/client-id=$CLIENT_ID

Terraform ile Managed Identity Yönetimi

Infrastructure as Code kullanıyorsan Terraform’da managed identity yönetimi şöyle görünüyor:

# Terraform ile managed identity ve rol atama - main.tf
# Önce terraform plan ile kontrol et
terraform plan -var="resource_group=myResourceGroup" -out=tfplan

# Sonra uygula
terraform apply tfplan

# Mevcut identity'leri import et
terraform import azurerm_user_assigned_identity.example 
  /subscriptions/<sub-id>/resourceGroups/myRG/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myIdentity

Terraform’un HCL konfigürasyonu bu script’te değil elbette, ama önemli olan import ve plan workflow’u. Production’da her zaman önce plan çıktısını gözden geçir, doğrudan apply yapma.

Güvenlik En İyi Uygulamaları

Managed identity kullanmak tek başına yeterli değil. Birkaç önemli noktayı aklında tut:

  • Scope’u dar tut: Rol atarken kaynak grubu veya subscription seviyesinde değil, mümkün olan en dar scope’ta yetki ver. Bir Key Vault için yetki veriyorsan sadece o Key Vault’u scope olarak belirt.
  • Audit loglarını takip et: Azure Monitor ve Activity Log üzerinden identity’lerin hangi kaynaklara ne zaman eriştiğini izle.
  • User-assigned identity’leri isimlendir: identity-prod-api-keyvault-reader gibi açıklayıcı isimler ver. Altı ay sonra “bu identity ne işe yarıyor?” sorusundan kurtulursun.
  • Access review yap: Düzenli aralıklarla rol atamalarını gözden geçir. Artık kullanılmayan kaynakları temizle.
  • System-assigned identity’yi silerken dikkatli ol: Kaynağı sildiğinde identity de gidiyor. Bağımlılıkları önceden kontrol et.

Key Vault erişim loglarını aktifleştirmek için:

# Key Vault diagnostic settings aktifleştir
az monitor diagnostic-settings create 
  --resource "/subscriptions/<sub-id>/resourceGroups/myRG/providers/Microsoft.KeyVault/vaults/myKeyVault" 
  --name "keyvault-diagnostics" 
  --logs '[{"category":"AuditEvent","enabled":true}]' 
  --workspace "/subscriptions/<sub-id>/resourceGroups/myRG/providers/microsoft.operationalinsights/workspaces/myLogAnalytics"

Bu ayarla Key Vault’a yapılan her erişim Log Analytics’e gidecek ve sorgulanabilir hale gelecek.

Maliyet ve Operasyonel Avantajlar

Managed Identity’nin bir diğer güzel yanı tamamen ücretsiz olması. Oluşturabileceğin user-assigned identity sayısında subscription başına 1000 adet sınırı var, ama pratikte bu sınıra ulaşmak çok nadir. System-assigned identity’ler için ek sınır yok.

Operasyonel açıdan bakıldığında en büyük kazanım sır rotasyonu sorununu ortadan kaldırması. Eskiden her 90 günde bir service principal şifrelerini döndürmek, bunları ilgili uygulama ayarlarında güncellemek ve süreci takip etmek zorundaydın. Managed identity ile bu döngü otomatik olarak Azure tarafından yönetiliyor.

Compliance açısından da büyük avantaj sağlıyor. Penetrasyon testlerinde ve güvenlik denetimlerinde “hard-coded credentials” bulgusu almak hem stresli hem de raporlamada can sıkıcı. Managed identity kullanımı bu bulgu kategorisini tamamen ortadan kaldırıyor.

Sonuç

Azure Managed Identity, bulut güvenliği konusunda gerçekten paradigma değiştiren bir yaklaşım. “Sırları nereye saklarım?” sorusunun cevabı artık “hiçbir yere, çünkü sıra gerek yok” oluyor. Uygulamak için gereken süre oldukça kısa, kazanım ise büyük.

Eğer hala application.config veya environment variable içinde Azure servis hesabı şifreleri taşıyorsan, bugün başla ve migration planı yap. Önce yeni projelerde managed identity kullanarak başla, sonra mevcut uygulamaları kademeli olarak taşı. En büyük engel genellikle teknik değil, ekibin alışkanlıklarını değiştirmek oluyor. Ama bir kez benimsendikten sonra “eskiden nasıl çalışıyorduk?” diye düşünüyorsun.

Son olarak şunu söyleyeyim: Managed identity her senaryonun çözümü değil. On-premises kaynaklara erişim için hala service principal kullanman gerekebilir. Ama Azure ekosisteminin içinde kalan her entegrasyon için managed identity birinci tercih olmalı. Bunu bir kural olarak benimse, sonrasında credential sızıntısı stresini yaşamazsın.

Bir yanıt yazın

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