CI/CD pipeline'larında sızan sırlar çoğunlukla bir güvenlik ekibinin öğrendiği son şey olur. Sızıntının yolu genelde bir saldırı değildir; pipeline'ın normal işleyişi sırasında değerin yanlış yere yazılmasıdır. Sırayla dört tipik noktayı ve her birinde nasıl davranılması gerektiğini ele alıyoruz.
Sızıntının dört tipik noktası
Birincisi git deposu. Bir .env dosyası, bir servis hesabı
anahtarı ya da kod içine hardcode edilmiş bir token'ın commit'lenmesi
en görünür ama en zor düzeltilen sızıntıdır. Commit geçmişi tüm klonlarda
ve fork'larda kalır; değeri sildiğiniz commit onu geçmişten çıkarmaz.
Doğru refleks önce sırrı devre dışı bırakmak, sonra repo'yu temizlemektir.
İkincisi build log'u. Runner'lar çıktıyı satır satır saklar; bir shell satırı sırrı ekrana yazdığında o değer log'a düşer. Log'un maskelenmesi güvenilir bir katman değildir çünkü yalnızca birebir eşleşen değerleri gizler; base64 encode edilen ya da parçalanmış bir değer maskelenmez.
Üçüncüsü environment değişkeni miras hakkı. Bir üst pipeline adımına tanımlanan bir sır, alt süreçlere kendiliğinden geçer; bu alt süreç üçüncü taraf bir Docker imajı ise sırrınız artık sizin kontrolünüzde değildir. Dördüncüsü artifact ve cache: build sırasında oluşturulan bir dosyaya sırrın yazılıp artifact olarak yayınlanması, sırrı repo'ya koymanın uzun yoludur.
Kısa ömürlü kimlik: OIDC federation
Statik bir access key, sızmadığı sürece güvenlidir; sızdığı anda ne kadar sürelik pencere açtığı da belirsizdir. Bu asimetriyi kırmanın yolu, sırrın kendisini pipeline'a hiç vermemektir. OIDC federation tam olarak bunu yapar: pipeline runner, çalıştığı akış hakkında bir JWT üretir, bulut sağlayıcısı bu token'ı doğrular ve karşılığında yalnızca dakikalar süren geçici bir kimlik döner.
Bu modelde sızacak kalıcı bir sır kalmaz. Log'a düşen token birkaç dakika içinde geçersiz olur; ele geçirilen imaj, geçici kimliği artık çıkarılamayacak bir şeye çeviremez. Kendi ürettiğimiz iş yükleri için CI/CD pipeline hizmetimizde statik anahtar taşınmasını varsayılan olarak kapatıyor, bulut tarafı erişimi OIDC üzerinden veriyoruz.
Secret manager, rotasyon ve erişim kaydı
OIDC ile karşılanamayan sırlar (bir üçüncü taraf servisin API anahtarı, bir eski sistemin şifresi) merkezi bir secret manager üzerinden dağıtılmalıdır. Secret manager'ın işlevi yalnızca depolama değildir; erişim kaydını tutar, sırra kimin ne zaman baktığını gösterir ve rotasyonu programatik yapar.
Rotasyon adımının sık atlanan yanı uygulama tarafıdır. Sır secret manager'da güncellendi ama uygulama değeri başlangıçta okuyup bellekte tuttuysa, bir sonraki yeniden başlatmaya kadar eski değerle çalışır. Rotasyon politikası ile yeniden yükleme mekanizması aynı anda yazılmalıdır; biri diğerinin yerini tutmaz. Erişim kaydı ise zafiyet yönetimi tarafında bir sızıntı şüphesinde ilk bakılacak kaynaktır.
Fork PR'ları ve self-hosted runner
Açık projelerde en sinsi sızıntı, fork'tan gelen bir PR'ın pipeline içinde secret'a ulaşmasıdır. Fork sahibi kendi kodunu ekleyip pipeline'ın çalıştığı iş yükü içinde secret'ı okuyup dışarı gönderebilir. Fork PR'larında secret'ları varsayılan olarak kısıtlamak ve gerekli hallerde açık onay adımı zorunlu kılmak temel bir savunmadır.
Self-hosted runner tarafında ise izolasyon meselesi bir kat daha önemlidir. Aynı runner üzerinde arka arkaya çalışan iki iş, ilkinin bıraktığı dosyaları ve önbelleği görebilir. Runner'ın her iş için taze bir konteynerde çalışması ve iş bitiminde imajın silinmesi gerekir. Ağ tarafında da runner'ın yalnızca gerçekten ihtiyaç duyduğu dış hedeflere ulaşabilmesi, bir sızıntı denemesini zorlaştıran ek bir katmandır. Bu ağ segmentasyonunu daha geniş biçimde zero-trust ve mikro segmentasyon yazısında ele almıştık.
Sık sorulan sorular
Repo'ya kaçmış bir secret'ı silmek yeterli mi?
Hayır. Commit geçmişi ve fork'lar hâlâ o değeri taşır. Doğru refleks önce sızmış kimliği devre dışı bırakmak ve yenisini oluşturmaktır. Repo temizliği ikinci adımdır ve zaten döndürülmüş bir sırra karşı savunma değildir.
Environment değişkeni secret için güvenli mi?
Kısıtlı bir güvence sağlar. Değişken pipeline log'una kolayca sızabilir, alt süreçlere miras kalır ve dump alan hata mesajlarında görünür. Runner'ın maskeleme işlevi tam bir garanti değildir; yalnızca birebir eşleşen değerleri gizler.
OIDC federation nedir ve neden statik token'dan iyidir?
Pipeline'ın kimliğini bulut sağlayıcısına imzalı bir token ile kanıtlar; sağlayıcı da karşılığında dakikalar süren geçici kimlik verir. Uzun ömürlü bir access key gerekmez, dolayısıyla sızacak kalıcı bir sır da kalmaz.
Secret manager kullanınca döndürmeyi bırakabilir miyim?
Hayır. Secret manager yalnızca depolamayı ve erişimi merkezileştirir. Rotasyon politikası ayrıca yazılmalı, uygulama tarafında değeri yeniden okuyacak akış hazır olmalıdır. Yoksa sır uzun ömürlü olarak kalmaya devam eder.
Fork PR'larından gelen build'lere secret vermek riskli mi?
Evet, ciddi biçimde. Fork'tan gelen kod pipeline içinde çalıştığında secret'a erişebilir ve dışarı yazabilir. Fork PR'larında secret'a erişimi kapatmak ya da onay adımı zorunlu kılmak temel bir savunmadır.
