· kaynak dev.to (home feed)
Yanlış yazılan Terraform plan dosyası adı gitignore'u atladı ve tüm sırları sızdırdı
dev.to'da yayımlanan bir yazı, terraform plan -out=out komutunun gitignore ve gizli bilgi tarayıcılarını nasıl atlatığını, tüm Terraform state'inin açığa çıkmasını ve dört ortam ile altı sağlayıcıda sır rotasyonunu zorunlu kıldığını anlatıyor.

dev.to'da yayımlanan birinci ağızdan anlatımda, yanlış yazılan tek bir Terraform komutunun out adında bir plan dosyası ürettiği, bu dosyanın özel bir depoya commit edildiği ve dokuz gün boyunca uzak depoda kaldığı — yanında çalışma alanındaki tüm sırları taşıyarak — anlatılıyor.
Yazar terraform plan -out=tfplan çalıştırmak istedi ama terraform plan -out=out yazdı. Terraform dosya adını hiçbir itiraz olmadan kabul etti ve ardından gelen git add . dosyayı bir sonraki commit'e dahil etti. Yazıya göre her koruma önlemi dosya adına bağlıydı: .gitignore içinde tfplan ve out/ listeleniyordu ve hiçbir desen out adlı bir dosyayla eşleşmiyordu. Yazar ayrıca GitHub'ın kendi Terraform gitignore şablonunun state, tfvars ve override dosyalarını kapsayan on dört desen içerdiğini, ancak plan dosyaları için hiçbir desen bulunmadığını belirtiyor — *tfplan* orada yalnızca bir yorumda geçiyor.
Gizli bilgi tarayıcısı da dosyayı kaçırdı. Tarayıcılar metin okur ve file aracı bu yapıtı Zip arşivi olarak tanımladı, dolayısıyla içindeki bir parola hiçbir zaman bir dosyadaki düz metin dizisi olmadı. Gitleaks 8.27.0 sürümünden itibaren arşivleri inceleyebiliyor, ama yalnızca --max-archive-depth ayarlandığında ve yazıya göre bu seçenek varsayılan olarak kapalı. İnceleyenler ise GitHub'ın "Binary file not shown" yer tutucusunu gördü ve dosyayı artık kullanılmayan bir build yapıtı olarak yorumladı. Deponun özel olması küçük bir teselliydi: klonu olan her mühendis, yüklenici ve CI runner elinde bu dosya taşıyordu.
Plan dosyası gerçekte ne içeriyordu
Yazıya göre bir Terraform plan dosyası beş şey barındıran bir zip arşivi: tfplan (planlanan değişiklikler ve tüm input değişken değerleri), tfstate (refresh sonrası tam önceki state, düz JSON olarak), tfstate-prev (refresh öncesi state, o da düz JSON), kök dizinden ve modüllerden her .tf dosyasının bir kopyası ve provider lock dosyası. Sonuç olarak bir plan dosyasını commit etmek, state'i commit etmek anlamına geliyor. Diff yaklaşık yirmi kaynağı kapsıyordu ama state birkaç yüz kaynak içeriyordu ve hepsi arşivin içindeydi.
İki ayrıntı öne çıkıyor. Targeting işe yaramıyor: tek bir random_pet kaynağına karşı -target ile oluşturulan bir plan bile tam state'i, çalışma alanındaki üretilmiş her parolayı ve her input değişkeni içeriyordu. Ve terraform show'un yazdırdığı "(sensitive value)" yer tutucusu bir şifreleme değil, görüntüleme tercihi — terraform show -json değerleri düz metin olarak yazdırıyor ve yazı bunun belgelenmiş bir davranış olduğuna dikkat çekiyor. Dosyayı okumak için yalnızca unzip yeterli, herhangi bir Terraform binary'si gerekmiyor.
Envanteri hafızadan değil, dosyadan çıkarmak
Yazar bilinen sırları listelemek yerine terraform show -json çıktısını dışa aktardı ve jq sorgularıyla hem önceki state'te hem de planlanan değişikliklerde input değişkenlerini ve Terraform'ın sensitive olarak işaretlediği her kaynağı saydı. Sensitive bayrağı sorunun boyutunu olduğundan küçük gösteriyordu, çünkü sağlayıcılar her şeyi işaretlemiyor: bağlantı dizeleri, monitor HTTP başlıklarındaki bearer token'ları ve Kubernetes secret veri haritalarındaki private key'ler işaretsiz biçimde ortaya çıktı; bu yüzden jq turunun ardından açılmış state üzerinde password, secret, token, key ve BEGIN gibi terimler için düz bir grep yapıldı.
Bulgular beş gruba ayrıldı: doğrudan config'de ayarlanmış parolalar; random_password sonuçları gibi üretilmiş sırlar; Secrets Manager ve Key Vault gibi data source'lar üzerinden okunan sırlar — okumak salt okunur hissettirse de değerleri state'e kopyalıyorlar; CI tarafından geçirilen ve -out tarafından kaydedilen TF_VAR_datadog_api_key gibi input değişkenleri; ve sağlayıcıların geri verdiği kimlik bilgileri, IAM access key sırları ve TLS private key'ler dahil. Datadog anahtarı ve Cloudflare token'ı her ortamın pipeline'ında aynı değişken olduğu için "yalnızca prod planıydı" savunması hiçbir koruma sağlamıyordu.
Rotasyon neden bir öğleden sonraydı değil
Rotasyon dört ortamı ve altı sağlayıcıyı kapsıyordu ve her sır türü farklı şekilde döndürülüyor. Veritabanı master parolaları yerinde değişir ve yeniden dağıtılana kadar eski değeri tutan her tüketiciyi bozar. IAM access key'lerin değeri değişemez, bu yüzden ikinci bir anahtar oluşturulmalı, tüketiciler ona geçirilmeli ve ilki silinmelidir. Storage account anahtarları Terraform dışında yeniden üretilir. random_password rotasyonu keeper'ları güncellemek ve bağımlı her kaynağı yenilemek demektir. Data source sırları kaynakta döndürülür ama state, bir sonraki refresh'e kadar eski kopyayı tutar. Provider token'ları onları tutan her pipeline'da güncellenmelidir ve bir CA private key'inin değiştirilmesi, imzaladığı her şeyin yeniden verilmesi anlamına gelir.
Yazara göre yapısal boşluk şu: Terraform kaynağı bilir, onu okuyanları bilmez. State bir veritabanının parolası olduğunu söyler ama bu değerin bir kopyasını tutan servisler, cron job'lar veya analist defterleri hakkında hiçbir şey söylemez; dolayısıyla her değeri kimin daha elinde tuttuğu sorusu elle yanıtlanmak zorunda kaldı.
Neden önemli
Plan dosyaları atılabilir yerel yapıtlar olarak görülür, ama gerçekte zip içindeki state dosyalarıdır. Dosya adına dayanan savunmalar yazım hatalarında başarısız olur, metin tabanlı tarayıcılar arşivlerde başarısız olur ve sensitive bayrağı yalnızca bir görüntüleme ipucudur. Yazıdan pratik dersler: gitignore ve pre-commit hook'ları plan dosyalarını tam ada göre değil geniş biçimde engellemeli, gizli bilgi tarayıcılarında arşiv taraması etkinleştirilmeli, commit edilen her plan tam bir state sızıntısı olarak ele alınmalı — ve ekipler hangi tüketicinin hangi sırrı tuttuğunun canlı bir haritasını çıkarmalı, çünkü rotasyon günü geldiğinde depodaki hiçbir dosya bu soruyu yanıtlamayacak.
- #terraform
- #devops
- #security
- #secrets-management
- #infrastructure-as-code
İlgili yazılar
- Supabase RLS satırları koruyor ama sütunları korumuyor: kullanıcılar kendilerine admin yetkisi verebiliyor
- TeamViewer, destek teknisyenlerinin makinelerini uzaktan kod çalıştırmaya açık bırakan kritik açığı yamaladı
- Airlock guardrail açığı, Hermes ajan eylemlerinin insan onayını atlamasına izin veriyordu; 0.2.3'te düzeltildi