Bir imajı çalıştırmadan önce üç soruya cevap verebilmelisiniz: İçinde ne var? (SBOM) Nasıl ve nerede üretildi? (provenance) Gerçekten bizim ürettiğimiz imaj bu mu? (imza). Bunlar yazılım tedarik zinciri güvenliğinin üç temel taşıdır ve Docker’ın modern araçlarıyla bugün birkaç komutla elde edilebilir. Zafiyet taraması (bkz. Container Image Güvenliği) “içindeki paketlerde bilinen açık var mı?” sorusunu yanıtlar; bu yazı onun tamamlayıcısıdır.

i

Neyi test ettik, neyi etmedik? Provenance üretimini Docker 29.4 + Buildx 0.33 üzerinde gerçekten çalıştırdık. SBOM üretimi ve cosign adımlarını bu ortamda deneyemedik (SBOM tarayıcı imajı için Docker Hub erişimi, cosign için de ağ erişimi gerekiyor); bu bölümler resmi Docker ve Sigstore dokümantasyonuna dayanır. Komutları kendi ortamınızda önce deneme imajında çalıştırın.

1. SBOM: imajın malzeme listesi

SBOM (Software Bill of Materials), bir imajın içindeki paketlerin, kütüphanelerin ve sürümlerin envanteridir. Yeni bir zafiyet açıklandığında (örneğin “şu kütüphanenin 2.3 sürümünde kritik açık var”) imajlarınızı tek tek yeniden taramak yerine SBOM’lara bakarak etkilenen imajları hemen bulabilirsiniz.

Buildx, SBOM’u build sırasında üretip imaja attestation olarak ekleyebilir:

docker buildx build --sbom=true --tag kullanici/uygulama:1.0 --push .

# ya da push etmeden dosya olarak doğrulayın
docker buildx build --sbom=true --output type=local,dest=out .
# out/sbom.spdx.json dosyası oluşur

Dokümantasyona göre SBOM, SPDX standardında JSON olarak üretilir. Registry’deki bir imajın SBOM’unu görmek için:

docker buildx imagetools inspect kullanici/uygulama:1.0 --format "{{ json .SBOM }}"

Varsayılan olarak yalnızca son aşama taranır. Multi-stage build’de ara aşamaların da (örneğin derleme araçlarının) listelenmesini istiyorsanız Dockerfile’a ARG BUILDKIT_SBOM_SCAN_STAGE=true ekleyebilirsiniz (bkz. Multi-Stage Build).

Denemeye çalıştığımızda BuildKit’in SBOM’u docker/buildkit-syft-scanner adlı bir tarayıcı imajı çekerek ürettiğini gördük; yani build ortamınızın bu imaja (registry’ye) erişebilmesi gerekir. Kapalı bir ağda çalışıyorsanız tarayıcı imajını önceden kendi registry’nize aynalamanız gerekir.

2. Provenance: imaj nasıl üretildi?

Provenance, bir imajın kim tarafından, hangi kaynaktan, hangi komutlarla üretildiğini kaydeder (SLSA çerçevesiyle uyumlu). Mod seçeneği vardır: mode=min temel bilgiyi, mode=max build argümanları, komutlar gibi ayrıntıları da içerir.

docker buildx build --provenance=mode=max --output type=local,dest=out .

Bu komutu çalıştırdığımızda çıktı dizininde provenance.json oluştu ve içindeki predicateType alanı https://slsa.dev/provenance/v1 idi; yani standart bir SLSA provenance belgesi. Bir imajın --provenance=mode=max ile registry’ye gönderilmiş halini incelemek için:

docker buildx imagetools inspect kullanici/uygulama:1.0 --format "{{ json .Provenance }}"
!

Önemli ön koşul: Attestation’lar imaj indeksinin (image index) içinde saklanır. Docker dokümantasyonuna göre klasik imaj deposu bu yapıyı tutamaz; docker sürücüsüyle attestation için containerd imaj deposu gerekir. Docker 29.4 kurulumumuzda docker info çıktısında driver-type: io.containerd.snapshotter.v1 görünüyordu; sizinki farklıysa docker-container sürücülü bir builder kullanın. Ayrıca varsayılan davranış (hangi attestation’ın otomatik eklendiği) sürüme ve çıktı biçimine göre değişebilir — beklentiye bırakmayıp --sbom ve --provenance bayraklarını açıkça yazın. Biz type=oci çıktısını bayraksız aldığımızda attestation eklenmediğini gördük.

3. İmzalama: bu imaj gerçekten bizim mi?

SBOM ve provenance imajın ne olduğunu anlatır; imza ise kim tarafından yayımlandığını ve sonradan değiştirilmediğini kanıtlar. Açık kaynak dünyasında yaygın araç Sigstore’un cosign‘ıdır. İki mod vardır: anahtar tabanlı ve anahtarsız (keyless).

# Anahtarsız (OIDC ile; Google/GitHub/Microsoft hesabıyla doğrular)
cosign sign kullanici/uygulama@sha256:ABC...

# Anahtar çifti ile
cosign generate-key-pair
cosign sign --key cosign.key kullanici/uygulama@sha256:ABC...

İmzayı etiket yerine digest ile atmak önemlidir: etiket sonradan başka bir imajı işaret edebilir (bkz. İmaj ve Container Farkı), digest ise içeriğe bağlıdır. Doğrulama:

# Anahtarsız imza: kimin imzaladığını açıkça belirtin
cosign verify kullanici/uygulama@sha256:ABC... \
  [email protected] \
  --certificate-oidc-issuer=https://accounts.google.com

# GitHub Actions ile imzalandıysa
cosign verify kullanici/uygulama@sha256:ABC... \
  --certificate-identity-regexp=https://github.com/kuruluş/depo \
  --certificate-oidc-issuer=https://token.actions.githubusercontent.com

# Anahtar çiftiyle
cosign verify --key cosign.pub kullanici/uygulama@sha256:ABC...

Doğrulamada --certificate-identity ve --certificate-oidc-issuer değerlerini mutlaka belirtin; bu olmadan “birisi imzalamış” demenin güvenlik değeri çok düşüktür. Önemli olan, “herhangi bir imza” değil, “beklediğim kimliğin imzası” olmasıdır. cosign’ın bayrakları ve çıktı biçimi sürümler arasında değişebildiği için kullandığınız sürümün cosign sign --help çıktısına bakın.

Hepsini bir arada: örnek CI akışı

  1. İmajı --sbom=true --provenance=mode=max ile build edip registry’ye gönderin.
  2. Push sonrası digest’i alın.
  3. cosign sign ile digest’i imzalayın (CI’da anahtarsız imza için pipeline’a OIDC kimliği verilir).
  4. Dağıtım öncesi (admission kontrolü ya da dağıtım betiğinde) cosign verify ile kimliği doğrulayın; doğrulanamayan imajı çalıştırmayın.

CI/CD tarafı için CI/CD ile Docker yazısına bakın; tarama adımını da pipeline’a eklemeyi unutmayın.

SBOM’u tarama ile birleştirmek

SBOM yalnızca envanter değil, sürekli bir tarama girdisidir: SBOM’dan zafiyet taraması yapan araçlar vardır (Trivy ve Grype gibi), böylece imajı yeniden çekmeden “bugün açıklanan zafiyetten hangi imajlarımız etkileniyor?” sorusunu yanıtlarsınız. Bu sitedeki Güvenlik Merkezi‘nde Docker Bench ve Falco konularıyla birlikte düşünün: SBOM “ne var”, tarama “açık var mı”, imza “doğru imaj mı”, Falco “çalışırken ne yapıyor” sorularının cevabıdır.

Hızlı kontrol listesi

  • İmajlarınız --sbom=true ve --provenance=mode=max ile mi build ediliyor?
  • Builder attestation destekliyor mu (containerd imaj deposu veya docker-container sürücüsü)?
  • İmajları etiketle değil digest ile imzalıyor ve doğruluyor musunuz?
  • Doğrulamada beklenen kimlik (--certificate-identity) ve sağlayıcı (--certificate-oidc-issuer) belirtiliyor mu?
  • Dağıtım hattınız imzasız imajı reddediyor mu?