GCP IAM ile En Az Yetki Prensibini Uygulamak
Bulut ortamlarında güvenliğin temeli tek bir prensibe dayanır: kimseye ihtiyacından fazla yetki verme. Bu kulağa basit gelir, ama pratikte GCP ortamlarına baktığımda çoğu zaman “editor” veya “owner” rolleri dağıtılmış servis hesapları, gerekenden geniş IAM binding’ler ve hiç kullanılmayan ama aktif kalmaya devam eden izinler görüyorum. En az yetki prensibi (Principle of Least Privilege – PoLP) sadece bir güvenlik best practice değil, bir kültür meselesi. Bu yazıda GCP IAM’i gerçek dünya senaryolarıyla nasıl doğru yapılandıracağını, hangi araçları kullanacağını ve mevcut ortamı nasıl temizleyeceğini anlatacağım.
GCP IAM Temel Kavramları
Önce zemin oluşturalım. GCP IAM üç temel kavram üzerine kuruludur:
- Principal (Özne): Kim? Google hesabı, servis hesabı, grup veya domain.
- Role (Rol): Ne yapabilir? Primitive, predefined veya custom roller.
- Resource (Kaynak): Nerede? Organizasyon, klasör, proje veya spesifik servis kaynakları.
Bu üçünün kesişimi bir “binding” oluşturur ve IAM politikası bu binding’lerin toplamından ibaredir.
Primitive roller (Owner, Editor, Viewer) neredeyse her zaman fazla geniştir. Bir geliştiriciye Cloud Storage bucket’ına yazma yetkisi vermek için Editor rolü vermek, aynı zamanda o kişiye Compute Engine instance’larını yönetme, IAM politikalarını görme ve daha onlarca başka şeyi yapma yetkisi de verir. Bu tam olarak kaçınmamız gereken durum.
Mevcut IAM Durumunu Analiz Etmek
Bir şeyi düzeltemeden önce mevcut durumu anlamalısın. gcloud CLI ile mevcut IAM binding’leri çekip analiz etmekle başla.
# Proje seviyesindeki tüm IAM binding'leri listele
gcloud projects get-iam-policy PROJECT_ID
--format="json" > current_iam_policy.json
# Belirli bir üyenin hangi rollere sahip olduğunu filtrele
gcloud projects get-iam-policy PROJECT_ID
--format="json" | jq '.bindings[] | select(.members[] | contains("user:[email protected]"))'
# Owner rolüne sahip tüm üyeleri listele - bunlar kritik!
gcloud projects get-iam-policy PROJECT_ID
--format="json" | jq '.bindings[] | select(.role == "roles/owner")'
Bu komutları çalıştırdığında çıktıya dikkatli bak. Primitive roller (roles/owner, roles/editor) atanmış hesaplar, özellikle servis hesapları varsa alarm zilleri çalmalı.
Organizasyon seviyesinde analiz yapıyorsan:
# Organizasyon genelinde IAM politikası
gcloud organizations get-iam-policy ORG_ID
--format="json" > org_iam_policy.json
# Tüm projelerdeki IAM politikalarını toplu çek
for project in $(gcloud projects list --format="value(projectId)"); do
echo "=== $project ==="
gcloud projects get-iam-policy $project
--format="table(bindings.role,bindings.members)" 2>/dev/null
done
Servis Hesaplarını Doğru Yönetmek
Gerçek dünyada en büyük sorun servis hesaplarında yaşanır. Bir uygulama “çalışsın yeter” mantığıyla Editor rolüyle deploy edilir, yıllar geçer, kimse dokunmaz. Sonra bir güvenlik açığı çıkar ve o servis hesabının token’ını ele geçiren saldırgan projedeki her şeye erişim kazanır.
Servis hesabı oluşturmanın doğru yolu şu:
# Minimal yetkili servis hesabı oluştur
gcloud iam service-accounts create app-backend-sa
--display-name="Backend Uygulama Servis Hesabı"
--description="Sadece Cloud Storage okuma ve Pub/Sub yayımlama yetkisi"
# Sadece ihtiyaç duyulan rolleri ver
# Cloud Storage için sadece okuma
gcloud projects add-iam-policy-binding PROJECT_ID
--member="serviceAccount:app-backend-sa@PROJECT_ID.iam.gserviceaccount.com"
--role="roles/storage.objectViewer"
# Pub/Sub için sadece yayımlama
gcloud projects add-iam-policy-binding PROJECT_ID
--member="serviceAccount:app-backend-sa@PROJECT_ID.iam.gserviceaccount.com"
--role="roles/pubsub.publisher"
Burada önemli nokta: roles/storage.admin yerine roles/storage.objectViewer, roles/pubsub.admin yerine roles/pubsub.publisher veriyoruz. Proje seviyesi yerine kaynak seviyesinde binding yapmak daha da iyidir:
# Proje geneli yerine sadece belirli bucket için izin ver
gsutil iam ch
serviceAccount:app-backend-sa@PROJECT_ID.iam.gserviceaccount.com:objectViewer
gs://uygulama-data-bucket
# Sadece belirli Pub/Sub topic için yetki
gcloud pubsub topics add-iam-policy-binding uygulama-events
--member="serviceAccount:app-backend-sa@PROJECT_ID.iam.gserviceaccount.com"
--role="roles/pubsub.publisher"
Bu yaklaşımla servis hesabı sadece ihtiyaç duyduğu bucket’ı okuyabilir, diğer bucket’lara erişemez. Bu çok daha temiz bir güvenlik profili.
Custom Roller Oluşturmak
Bazen predefined roller bile fazla geniş gelir. Bir monitoring uygulamasının sadece Compute Engine instance’larının durumunu okuması gerekiyorsa roles/compute.viewer bile fazla olabilir çünkü bu rol network konfigürasyonunu, disk bilgilerini ve çok daha fazlasını görme yetkisi de içerir.
Custom rol oluşturmak için önce ihtiyaç duyulan izinleri tanımla:
# Custom rol tanımı için YAML dosyası oluştur
cat > monitoring-reader-role.yaml << 'EOF'
title: "Monitoring Okuyucu"
description: "Sadece instance durum bilgisi okuma yetkisi"
stage: "GA"
includedPermissions:
- compute.instances.get
- compute.instances.list
- monitoring.timeSeries.list
- monitoring.metricDescriptors.list
EOF
# Custom rolü oluştur
gcloud iam roles create monitoringReader
--project=PROJECT_ID
--file=monitoring-reader-role.yaml
# Oluşturulan rolü bir servis hesabına ata
gcloud projects add-iam-policy-binding PROJECT_ID
--member="serviceAccount:monitoring-sa@PROJECT_ID.iam.gserviceaccount.com"
--role="projects/PROJECT_ID/roles/monitoringReader"
Custom rollerin bakımını da düşünmek lazım. İzin setini zaman içinde güncellemen gerekebilir:
# Mevcut custom rolün izinlerini listele
gcloud iam roles describe monitoringReader --project=PROJECT_ID
# Role yeni izin ekle
gcloud iam roles update monitoringReader
--project=PROJECT_ID
--add-permissions=logging.logEntries.list
# Role'den izin kaldır
gcloud iam roles update monitoringReader
--project=PROJECT_ID
--remove-permissions=monitoring.metricDescriptors.list
Koşullu IAM Binding’ler (Conditional IAM)
GCP’nin güzel özelliklerinden biri koşullu IAM binding’lerdir. Bir kullanıcıya sadece belirli saatlerde, sadece belirli kaynak etiketleri için veya belirli bir tarihe kadar yetki verebilirsin. Bu özellik geçici erişim ihtiyaçlarında ve zaman sınırlı production erişimlerinde çok işe yarar.
# Sadece iş saatlerinde (09:00-18:00 UTC) erişim
gcloud projects add-iam-policy-binding PROJECT_ID
--member="user:[email protected]"
--role="roles/compute.instanceAdmin.v1"
--condition='expression=request.time.getHours("Europe/Istanbul") >= 9 && request.time.getHours("Europe/Istanbul") < 18,title=Mesai Saati Erisimi,description=Sadece mesai saatlerinde gecerli'
# Belirli bir tarihe kadar geçerli erişim (geçici proje erişimi)
gcloud projects add-iam-policy-binding PROJECT_ID
--member="user:[email protected]"
--role="roles/viewer"
--condition='expression=request.time < timestamp("2024-06-01T00:00:00Z"),title=Gecici Danisman Erisimi,description=Proje bitis tarihi'
# Sadece "env=prod" etiketine sahip kaynaklara erişim engeli
# (Bu örnek resource.name ile filtreleme yapar)
gcloud projects add-iam-policy-binding PROJECT_ID
--member="user:[email protected]"
--role="roles/compute.viewer"
--condition='expression=resource.name.startsWith("projects/PROJECT_ID/regions/europe-west1"),title=Sadece EU West,description=Sadece Europe West 1 regionu'
Danışman ya da geçici çalışan erişimlerinde bu koşullu binding’ler hayat kurtarır. “Ah bu erişimi kaldırmayı unuttum” dramalarının sonu gelir.
IAM Policy Analyzer ile Güvenlik Açığı Tespiti
Google Cloud’un Policy Analyzer aracı mevcut izinleri analiz etmek için çok değerlidir. Kimin belirli bir kaynağa erişebildiğini ve bu erişimin nereden geldiğini gösterir.
# Belirli bir kaynağa kimlerin erişebildiğini analiz et
gcloud asset analyze-iam-policy
--organization=ORG_ID
--resource="//cloudresourcemanager.googleapis.com/projects/PROJECT_ID"
--identity="user:[email protected]"
# Tüm servis hesaplarının sahip olduğu owner/editor rolleri tara
gcloud asset analyze-iam-policy
--project=PROJECT_ID
--roles="roles/owner,roles/editor"
--format="json" | jq '.analysisResults[].iamBinding'
# Kullanılmayan izinleri bulmak için IAM recommender
gcloud recommender recommendations list
--project=PROJECT_ID
--location=global
--recommender=google.iam.policy.Recommender
--format="json"
IAM Recommender özellikle değerli. Google, son 90 gün içinde kullanılmayan izinleri tespit eder ve daha kısıtlayıcı roller önerir. Öneriyi kabul etmek de oldukça basit:
# Recommender önerilerini listele
gcloud recommender recommendations list
--project=PROJECT_ID
--location=global
--recommender=google.iam.policy.Recommender
# Belirli bir öneriyi uygula (recommendation ID'yi çıktıdan al)
gcloud recommender recommendations mark-claimed
RECOMMENDATION_ID
--project=PROJECT_ID
--location=global
--recommender=google.iam.policy.Recommender
--etag=ETAG
Gerçek Dünya Senaryosu: Startup’tan Enterprise’a
Somut bir senaryo üzerinden gidelim. Diyelim ki bir e-ticaret şirketinde çalışıyorsun. Başlangıçta küçük bir ekip vardı, herkes aynı projeyi kullanıyordu ve kolaylık olsun diye geliştiricilere Editor rolü verilmişti. Şimdi ekip büyüdü, PCI DSS uyumluluğu gerekiyor ve bu durumu düzeltmen lazım.
Mevcut sorunlu durum:
- 5 geliştirici:
roles/editor - CI/CD servis hesabı:
roles/owner - Analytics ekibi:
roles/editor - 3 eski çalışan hesabı hala aktif
Temizleme stratejisi:
#!/bin/bash
# Eski çalışanların erişimini kaldır
OLD_USERS=("[email protected]" "[email protected]" "[email protected]")
for user in "${OLD_USERS[@]}"; do
echo "Kullanici kaldiriliyor: $user"
# Önce mevcut rollerini listele
gcloud projects get-iam-policy PROJECT_ID
--format="json" | jq --arg user "user:$user"
'.bindings[] | select(.members[] == $user) | .role'
# Editor rolünü kaldır
gcloud projects remove-iam-policy-binding PROJECT_ID
--member="user:$user"
--role="roles/editor" 2>/dev/null || echo "$user icin editor rolu bulunamadi"
done
# CI/CD servis hesabından owner rolünü kaldır
gcloud projects remove-iam-policy-binding PROJECT_ID
--member="serviceAccount:cicd-sa@PROJECT_ID.iam.gserviceaccount.com"
--role="roles/owner"
# CI/CD için minimal gerekli rolleri ver
# Container Registry'ye push edebilmek için
gcloud projects add-iam-policy-binding PROJECT_ID
--member="serviceAccount:cicd-sa@PROJECT_ID.iam.gserviceaccount.com"
--role="roles/artifactregistry.writer"
# Cloud Run deployment için
gcloud projects add-iam-policy-binding PROJECT_ID
--member="serviceAccount:cicd-sa@PROJECT_ID.iam.gserviceaccount.com"
--role="roles/run.developer"
# Cloud Build için
gcloud projects add-iam-policy-binding PROJECT_ID
--member="serviceAccount:cicd-sa@PROJECT_ID.iam.gserviceaccount.com"
--role="roles/cloudbuild.builds.editor"
Geliştiriciler için rol ataması şöyle olmalı:
# Geliştirici grupları için Google Groups kullan (bireysel atama yerine)
# Grup oluştur: [email protected]
# Geliştiriciler: Compute ve GKE erişimi (sadece nonprod)
gcloud projects add-iam-policy-binding DEV-PROJECT-ID
--member="group:[email protected]"
--role="roles/container.developer"
gcloud projects add-iam-policy-binding DEV-PROJECT-ID
--member="group:[email protected]"
--role="roles/logging.viewer"
gcloud projects add-iam-policy-binding DEV-PROJECT-ID
--member="group:[email protected]"
--role="roles/monitoring.viewer"
# Analytics ekibi: Sadece BigQuery ve Storage okuma
gcloud projects add-iam-policy-binding PROJECT_ID
--member="group:[email protected]"
--role="roles/bigquery.dataViewer"
gcloud projects add-iam-policy-binding PROJECT_ID
--member="group:[email protected]"
--role="roles/bigquery.jobUser"
Organizasyon Politikaları ile IAM’i Güçlendirmek
IAM tek başına yeterli değil. Organizasyon politikaları (Org Policies) IAM’in üzerine ek kısıtlamalar koyar. Örneğin, IAM ile servis hesabı key oluşturma yetkisi vermiş olsan bile bir org policy bu işlemi tamamen engelleyebilir.
# Servis hesabı key oluşturmayı engelle (çok önemli güvenlik kontrolü)
gcloud resource-manager org-policies set-policy
--project=PROJECT_ID
- << 'EOF'
name: projects/PROJECT_ID/policies/iam.disableServiceAccountKeyCreation
spec:
rules:
- enforce: true
EOF
# Domain restricted sharing - sadece kendi domainin üyelerine erişim
gcloud resource-manager org-policies set-policy
--organization=ORG_ID
- << 'EOF'
name: organizations/ORG_ID/policies/iam.allowedPolicyMemberDomains
spec:
rules:
- values:
allowedValues:
- "C0xxxxxx" # Organizasyon müşteri ID'si
EOF
IAM Değişikliklerini Audit Log ile İzlemek
En az yetki prensibini uygulamak yeterli değil, devam eden değişiklikleri de izlemek gerekiyor. Cloud Audit Logs bu konuda temel araç.
# Son 24 saatte yapılan IAM değişikliklerini listele
gcloud logging read
'logName="projects/PROJECT_ID/logs/cloudaudit.googleapis.com%2Factivity"
AND protoPayload.serviceName="iam.googleapis.com"'
--freshness=24h
--format="json" | jq '.[] | {timestamp: .timestamp, user: .protoPayload.authenticationInfo.principalEmail, method: .protoPayload.methodName}'
# Başarısız IAM işlemlerini izle (yetkisiz erişim denemeleri)
gcloud logging read
'protoPayload.authorizationInfo[].granted=false
AND severity>=WARNING'
--freshness=1h
--project=PROJECT_ID
--format="json" | jq '.[] | {time: .timestamp, principal: .protoPayload.authenticationInfo.principalEmail, resource: .resource.type, denied_permission: .protoPayload.authorizationInfo[].permission}'
Bu sorguları bir Cloud Scheduler job’ına bağlayıp günlük mail ya da Slack bildirimi almak için Cloud Functions ile entegre edebilirsin. Production ortamda beklenmedik IAM değişikliklerini anında tespit etmek kritik önem taşır.
Workload Identity ile Servis Hesabı Key’lerinden Kurtulmak
GKE veya Cloud Run kullanıyorsan servis hesabı key dosyalarından tamamen kurtulabilirsin. Workload Identity, uygulamaların key dosyası olmadan Google Cloud servislerine erişmesini sağlar.
# GKE cluster için Workload Identity etkinleştir
gcloud container clusters update CLUSTER_NAME
--workload-pool=PROJECT_ID.svc.id.goog
--region=europe-west1
# Kubernetes servis hesabı oluştur
kubectl create serviceaccount app-ksa
--namespace=production
# GCP servis hesabını Kubernetes servis hesabıyla bağla
gcloud iam service-accounts add-iam-policy-binding
app-backend-sa@PROJECT_ID.iam.gserviceaccount.com
--role roles/iam.workloadIdentityUser
--member "serviceAccount:PROJECT_ID.svc.id.goog[production/app-ksa]"
# Kubernetes servis hesabına annotation ekle
kubectl annotate serviceaccount app-ksa
--namespace=production
iam.gke.io/gcp-service-account=app-backend-sa@PROJECT_ID.iam.gserviceaccount.com
Bu yapıyla pod’ların içinde artık hiçbir JSON key dosyası yok. Uygulama metadata sunucusu üzerinden otomatik olarak kimlik doğrulama yapıyor. Key sızıntısı riski sıfırlanıyor.
Düzenli IAM Temizliği: Bir Rutinin Parçası Olsun
En az yetki prensibi tek seferlik bir uygulama değil, süregelen bir pratik. Şu rutini öneririm:
Haftalık:
- IAM Recommender önerilerini incele
- Yeni oluşturulan servis hesaplarını gözden geçir
Aylık:
- Aktif olmayan hesapları tespit et ve kaldır
- Koşullu binding’lerin son kullanma tarihlerini kontrol et
- Primitive rol atamalarını tara
Çeyreklik:
- Tüm custom rollerin hala gerekli olup olmadığını sorgula
- Organizasyon politikalarını gözden geçir
- Ekipten ayrılan kişilerin erişimlerini doğrula
#!/bin/bash
# Basit IAM sağlık kontrolü scripti - cron'a ekle
echo "=== IAM Saglik Kontrolu - $(date) ==="
echo "--- Primitive Rol Atamalari ---"
for role in "roles/owner" "roles/editor" "roles/viewer"; do
echo "### $role ###"
gcloud projects get-iam-policy PROJECT_ID
--format="json" |
jq --arg r "$role"
'.bindings[] | select(.role == $r) | .members[]'
done
echo "--- Anahtar Dosyasi Olan Servis Hesaplari ---"
for sa in $(gcloud iam service-accounts list
--project=PROJECT_ID
--format="value(email)"); do
keys=$(gcloud iam service-accounts keys list
--iam-account=$sa
--filter="keyType=USER_MANAGED"
--format="value(name)" 2>/dev/null | wc -l)
if [ "$keys" -gt 0 ]; then
echo "UYARI: $sa - $keys adet kullanici anahtari var"
fi
done
Sonuç
GCP IAM’de en az yetki prensibini uygulamak bir sprint değil, bir maraton. Primitive rolleri temizlemek, servis hesaplarını minimize etmek, Workload Identity’ye geçmek, koşullu binding’leri kullanmak ve düzenli audit yapmak bir kültür haline gelmeli.
Uygulamak istediğin ilk adımları önceliklendirecek olsam şunu söylerdim: önce Owner ve Editor rol atamalarını tespit et ve mümkün olanı predefined rollerle değiştir. Ardından CI/CD servis hesaplarının yetkilerini kıs, çünkü bunlar ele geçirildiğinde en fazla hasar verir. Sonra Workload Identity’ye geç ve key dosyalarını ortadan kaldır. IAM Recommender’ı bir rutin haline getir.
Güvenlik mükemmel olmak zorunda değil, ama sürekli iyileşiyor olmalı. Her geçen gün biraz daha temiz bir IAM konfigürasyonu, potansiyel bir saldırı yüzeyini küçültür. Ve günün sonunda “en az yetki prensibi” sadece teknik bir kural değil; sisteme olan güvensizliği yapısal hale getirmek demek. Doğru olan bu.
