Güvenli Derleme & Cloud Build, Artifact Registry ve GKE ile dağıtın

1. Giriş

Container Analysis, container'lar için güvenlik açığı taraması ve meta veri depolama alanı sağlar. Tarama hizmeti, Artifact Registry ve Container Registry'deki görüntülerde güvenlik açığı taramaları gerçekleştirir, ardından ortaya çıkan meta verileri depolar ve bir API aracılığıyla kullanılabilir hale getirir. Meta veri depolama, güvenlik açığı taraması, Google Cloud hizmetleri ve üçüncü taraf sağlayıcılar dahil olmak üzere farklı kaynaklardan gelen bilgileri depolamanıza olanak tanır.

Güvenlik açığı taraması otomatik olarak veya isteğe bağlı olarak gerçekleştirilebilir:

  • Otomatik tarama etkinleştirildiğinde, Artifact Registry veya Container Registry'ye yeni bir görüntü her aktardığınızda tarama otomatik olarak tetiklenir. Yeni güvenlik açıkları keşfedildikçe güvenlik açığı bilgileri sürekli olarak güncellenir.
  • İsteğe Bağlı Tarama etkinleştirildiğinde yerel bir görüntüyü veya Artifact Registry ya da Container Registry'deki bir görüntüyü taramak için bir komut çalıştırmanız gerekir. İsteğe bağlı tarama, container'ları ne zaman tarayacağınız konusunda esneklik sağlar. Örneğin, yerel olarak oluşturulmuş bir görüntüyü tarayabilir ve kayıt defterinde depolamadan önce güvenlik açıklarını düzeltebilirsiniz. Tarama sonuçları, tarama tamamlandıktan sonra 48 saate kadar kullanılabilir. Güvenlik açığı bilgileri, taramadan sonra güncellenmez.

Container Analysis'i CI/CD ardışık düzeninize entegre ederek bu meta verilere dayalı kararlar verebilirsiniz. Örneğin, yalnızca güvenilir kayıt defterlerindeki uyumlu görüntüler için dağıtımlara izin veren dağıtım politikaları oluşturmak üzere İkili Program Yetkilendirmesi'ni kullanabilirsiniz.

Neler öğreneceksiniz?

  • Otomatik tarama nasıl etkinleştirilir?
  • İsteğe bağlı tarama nasıl yapılır?
  • Tarama işlevini derleme işlem hattına entegre etme
  • Onaylanan resimleri imzalama
  • GKE kabul denetleyicilerini kullanarak görüntüleri engelleme
  • GKE'yi yalnızca imzalı onaylı görüntülere izin verecek şekilde yapılandırma

2. Kurulum ve Gereksinimler

Yönlendirmesiz ortam kurulumu

  1. Google Cloud Console'da oturum açın ve yeni bir proje oluşturun veya mevcut bir projeyi yeniden kullanın. Gmail veya Google Workspace hesabınız yoksa hesap oluşturmanız gerekir.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Proje adı, bu projenin katılımcıları için görünen addır. Google API'leri tarafından kullanılmayan bir karakter dizesidir. Dilediğiniz zaman bunu güncelleyebilirsiniz.
  • Proje kimliği, tüm Google Cloud projelerinde benzersizdir ve sabittir (ayarlandıktan sonra değiştirilemez). Cloud Console, benzersiz bir dizeyi otomatik olarak oluşturur. Genellikle bu dizenin ne olduğuyla ilgilenmezsiniz. Çoğu codelab'de proje kimliğine (genellikle PROJECT_ID olarak tanımlanır) başvurmanız gerekir. Oluşturulan kimliği beğenmezseniz başka bir rastgele kimlik oluşturabilirsiniz. Dilerseniz kendi adınızı deneyerek kullanılabilir olup olmadığını kontrol edebilirsiniz. Bu adımdan sonra değiştirilemez ve proje süresince geçerli kalır.
  • Bazı API'lerin kullandığı üçüncü bir değer olan Proje Numarası da vardır. Bu üç değer hakkında daha fazla bilgiyi belgelerde bulabilirsiniz.
  1. Ardından, Cloud kaynaklarını/API'lerini kullanmak için Cloud Console'da faturalandırmayı etkinleştirmeniz gerekir. Bu codelab'i tamamlamak neredeyse hiç maliyetli değildir. Bu eğitimin ötesinde faturalandırma ücreti alınmaması için kaynakları kapatmak üzere oluşturduğunuz kaynakları veya projenin tamamını silebilirsiniz. Google Cloud'un yeni kullanıcıları 300 ABD doları değerinde ücretsiz deneme programından yararlanabilir.

Cloud Shell Düzenleyici'yi başlatma

Bu laboratuvar, Google Cloud Shell Düzenleyici ile kullanılmak üzere tasarlanmış ve test edilmiştir. Düzenleyiciye erişmek için:

  1. https://console.cloud.google.com adresinden Google projenize erişin.
  2. Sağ üst köşedeki Cloud Shell düzenleyici simgesini tıklayın.

8560cc8d45e8c112.png

  1. Pencerenizin alt kısmında yeni bir bölme açılır.

Ortam Kurulumu

Cloud Shell'de projenizin proje kimliğini ve proje numarasını ayarlayın. Bunları PROJECT_ID ve PROJECT_ID değişkenleri olarak kaydedin.

export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID \
    --format='value(projectNumber)')

Hizmetleri etkinleştirme

Gerekli tüm hizmetleri etkinleştirin:

gcloud services enable \
  cloudkms.googleapis.com \
  cloudbuild.googleapis.com \
  container.googleapis.com \
  containerregistry.googleapis.com \
  artifactregistry.googleapis.com \
  containerscanning.googleapis.com \
  ondemandscanning.googleapis.com \
  binaryauthorization.googleapis.com 

Artifact Registry deposu oluşturma

Bu laboratuvarda, resimlerinizi depolamak ve taramak için Artifact Registry'yi kullanacaksınız. Aşağıdaki komutla depoyu oluşturun.

gcloud artifacts repositories create artifact-scanning-repo \
  --repository-format=docker \
  --location=us-central1 \
  --description="Docker repository"

Artifact Registry'ye erişirken gcloud kimlik bilgilerinizi kullanmak için Docker'ı yapılandırın.

gcloud auth configure-docker us-central1-docker.pkg.dev

3. Otomatik Tarama

Yeni bir görüntüyü Artifact Registry veya Container Registry'ye her aktardığınızda yapay ürün taraması otomatik olarak tetiklenir. Yeni güvenlik açıkları keşfedildikçe güvenlik açığı bilgileri sürekli olarak güncellenir. Bu bölümde, Artifact Registry'ye bir görüntü gönderecek ve sonuçları inceleyeceksiniz.

Çalışma dizini oluşturma ve değiştirme

mkdir vuln-scan && cd vuln-scan

Örnek resim tanımlama

Aşağıdaki içeriklere sahip Dockerfile adlı bir dosya oluşturun.

cat > ./Dockerfile << EOF
FROM gcr.io/google-appengine/debian9@sha256:ebffcf0df9aa33f342c4e1d4c8428b784fc571cdf6fbab0b31330347ca8af97a

# System
RUN apt update && apt install python3-pip -y

# App
WORKDIR /app
COPY . ./

RUN pip3 install Flask==1.1.4
RUN pip3 install gunicorn==20.1.0

CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app

EOF

Aşağıdaki içeriklere sahip main.py adlı bir dosya oluşturun.

cat > ./main.py << EOF
import os
from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello_world():
    name = os.environ.get("NAME", "Worlds")
    return "Hello {}!".format(name)

if __name__ == "__main__":
    app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
EOF

Görüntüyü oluşturma ve AR'ye gönderme

Container'ınızı oluşturmak ve otomatik olarak Artifact Registry'ye aktarmak için Cloud Build'i kullanın. Resimdeki bad etiketini not edin. Bu, sonraki adımlarda kimliğinizi belirlemenize yardımcı olur.

gcloud builds submit . -t us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:bad

Resim ayrıntılarını inceleme

Derleme işlemi tamamlandıktan sonra Artifact Registry kontrol panelinde görüntü ve güvenlik açığı sonuçlarını inceleyin.

  1. Cloud Console'da Artifact Registry'yi açın.
  2. İçerikleri görüntülemek için artifact-scanning-repo'yu tıklayın.
  3. Görsel ayrıntılarını tıklayın.
  4. Resminizin en son özetini tıklayın.
  5. Tarama tamamlandıktan sonra, resimle ilgili güvenlik açıkları sekmesini tıklayın.

Güvenlik açıkları sekmesinde, yeni oluşturduğunuz görüntü için otomatik tarama sonuçlarını görürsünüz.

361be7b3bf293fca.png

Otomatik tarama varsayılan olarak etkindir. Otomatik taramayı nasıl devre dışı bırakabileceğinizi/etkinleştirebileceğinizi görmek için Artifact Registry ayarlarını inceleyin.

4. İsteğe Bağlı Tarama

Görüntüyü depoya aktarmadan önce tarama yapmanız gereken çeşitli senaryolar olabilir. Örneğin, bir kapsayıcı geliştiricisi, kodu kaynak denetimine göndermeden önce bir görüntüyü tarayıp sorunları düzeltebilir. Aşağıdaki örnekte, sonuçlara göre işlem yapmadan önce görüntüyü yerel olarak oluşturup analiz edeceksiniz.

Görsel oluşturma

Bu adımda, görüntüyü yerel önbelleğinize oluşturmak için yerel Docker'ı kullanacaksınız.

docker build -t us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image .

Resmi tarama

Görüntü oluşturulduktan sonra görüntünün taranmasını isteyin. Tarama sonuçları bir meta veri sunucusunda saklanır. İş, sonuçların meta veri sunucusundaki konumuyla tamamlanır.

gcloud artifacts docker images scan \
    us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image \
    --format="value(response.scan)" > scan_id.txt

Çıkış Dosyasını İnceleme

scan_id.txt dosyasında saklanan önceki adımın çıktısını inceleyin. Meta veri sunucusundaki tarama sonuçlarının rapor konumuna dikkat edin.

cat scan_id.txt

Ayrıntılı tarama sonuçlarını inceleme

Taramanın gerçek sonuçlarını görüntülemek için çıktı dosyasında belirtilen rapor konumunda list-vulnerabilities komutunu kullanın.

gcloud artifacts docker images list-vulnerabilities $(cat scan_id.txt) 

Çıkış, resimdeki tüm güvenlik açıklarıyla ilgili önemli miktarda veri içeriyor.

Kritik sorunları işaretleme

İnsanlar, raporda saklanan verileri nadiren doğrudan kullanır. Sonuçlar genellikle otomatik bir işlem tarafından kullanılır. Rapor ayrıntılarını okumak ve KRİTİK güvenlik açığı bulunup bulunmadığını günlüğe kaydetmek için aşağıdaki komutları kullanın.

export SEVERITY=CRITICAL

gcloud artifacts docker images list-vulnerabilities $(cat scan_id.txt) --format="value(vulnerability.effectiveSeverity)" | if grep -Fxq ${SEVERITY}; then echo "Failed vulnerability check for ${SEVERITY} level"; else echo "No ${SEVERITY} Vulnerabilities found"; fi

Bu komutun çıkışı şu şekilde olur:

Failed vulnerability check for CRITICAL level

5. Build Pipeline Scanning

Bu bölümde, kapsayıcı görüntünüzü oluşturacak, tarayacak ve ardından sonuçları değerlendirecek otomatik bir derleme ardışık düzeni oluşturacaksınız. CRITICAL (Kritik) düzeyde güvenlik açığı bulunmazsa görüntü depoya gönderilir. CRITICAL (Kritik) güvenlik açıkları bulunursa derleme başarısız olur ve çıkılır.

Cloud Build hizmet hesabına erişim sağlama

Cloud Build'in, isteğe bağlı tarama API'sine erişim haklarına sahip olması gerekir. Aşağıdaki komutlarla erişim sağlayın.

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
        --member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
        --role="roles/iam.serviceAccountUser"
        
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
        --member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
        --role="roles/ondemandscanning.admin"

Cloud Build ardışık düzenini oluşturma

Aşağıdaki komut, dizininizde otomatik işlem için kullanılacak bir cloudbuild.yaml dosyası oluşturur. Bu örnekte adımlar, kapsayıcı derleme işlemiyle sınırlıdır. Ancak uygulamada, kapsayıcı adımlarına ek olarak uygulamaya özel talimatlar ve testler de eklemeniz gerekir.

Aşağıdaki komutu kullanarak dosyayı oluşturun.

cat > ./cloudbuild.yaml << EOF
steps:

# build
- id: "build"
  name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image', '.']
  waitFor: ['-']

#Run a vulnerability scan at _SECURITY level
- id: scan
  name: 'gcr.io/cloud-builders/gcloud'
  entrypoint: 'bash'
  args:
  - '-c'
  - |
    (gcloud artifacts docker images scan \
    us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image \
    --location us \
    --format="value(response.scan)") > /workspace/scan_id.txt

#Analyze the result of the scan
- id: severity check
  name: 'gcr.io/cloud-builders/gcloud'
  entrypoint: 'bash'
  args:
  - '-c'
  - |
      gcloud artifacts docker images list-vulnerabilities \$(cat /workspace/scan_id.txt) \
      --format="value(vulnerability.effectiveSeverity)" | if grep -Fxq CRITICAL; \
      then echo "Failed vulnerability check for CRITICAL level" && exit 1; else echo "No CRITICAL vulnerability found, congrats !" && exit 0; fi

#Retag
- id: "retag"
  name: 'gcr.io/cloud-builders/docker'
  args: ['tag',  'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good']


#pushing to artifact registry
- id: "push"
  name: 'gcr.io/cloud-builders/docker'
  args: ['push',  'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good']

images:
  - us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image
EOF

CI ardışık düzenini çalıştırma

CRITICAL (Kritik) önem derecesinde bir güvenlik açığı bulunduğunda derlemenin bozulduğunu doğrulamak için derlemeyi işlenmek üzere gönderin.

gcloud builds submit

Derleme hatasını inceleme

Yeni gönderdiğiniz derleme, resimde KRİTİK güvenlik açıkları olduğundan başarısız olacak.

Cloud Build Geçmişi sayfasında derleme hatasını inceleyin.

Güvenlik Açığını Düzeltme

Dockerfile'ı, CRITICAL güvenlik açıkları içermeyen bir temel resim kullanacak şekilde güncelleyin.

Aşağıdaki komutla Dockerfile'ı Debian 10 görüntüsünü kullanacak şekilde üzerine yazın.

cat > ./Dockerfile << EOF
from python:3.8-slim  

# App
WORKDIR /app
COPY . ./

RUN pip3 install Flask==2.1.0
RUN pip3 install gunicorn==20.1.0

CMD exec gunicorn --bind :\$PORT --workers 1 --threads 8 main:app

EOF

CI sürecini iyi görüntüyle çalıştırın

CRITICAL (Kritik) önem derecesinde güvenlik açığı bulunmadığında derlemenin başarılı olacağını doğrulamak için derlemeyi işlenmek üzere gönderin.

gcloud builds submit

Build'in başarısını inceleme

Güncellenen resimde KRİTİK güvenlik açığı bulunmadığından, az önce gönderdiğiniz derleme başarılı olacak.

Cloud Build Geçmişi sayfasında derleme başarısını inceleyin.

Tarama sonuçlarını inceleme

Artifact Registry'deki iyi görüntüyü inceleyin.

  1. Cloud Console'da Artifact Registry'yi açın.
  2. İçerikleri görüntülemek için artifact-scanning-repo'yu tıklayın.
  3. Görsel ayrıntılarını tıklayın.
  4. Resminizin en son özetini tıklayın.
  5. Resmin güvenlik açıkları sekmesini tıklayın.

6. Görselleri İmzalama

Onaylayan Notu Oluşturma

Onaylayıcı Notu, uygulanan imza türü için etiket görevi gören küçük bir veri parçasıdır. Örneğin, bir not güvenlik açığı taramasını belirtirken diğeri kalite güvencesi onayı için kullanılabilir. Not, imzalama sürecinde referans olarak kullanılır.

Not oluşturma

cat > ./vulnz_note.json << EOM
{
  "attestation": {
    "hint": {
      "human_readable_name": "Container Vulnerabilities attestation authority"
    }
  }
}
EOM

Notu saklama

NOTE_ID=vulnz_note

curl -vvv -X POST \
    -H "Content-Type: application/json"  \
    -H "Authorization: Bearer $(gcloud auth print-access-token)"  \
    --data-binary @./vulnz_note.json  \
    "https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/?noteId=${NOTE_ID}"

Notu doğrulama

curl -vvv  \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    "https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/${NOTE_ID}"

Onaylayan oluşturma

Onaylayıcılar, gerçek görüntü imzalama sürecini gerçekleştirmek için kullanılır ve daha sonra doğrulamak üzere notun bir örneğini görüntüye ekler. Daha sonra kullanmak üzere onaylayıcıyı oluşturun.

Onaylayan Oluştur

ATTESTOR_ID=vulnz-attestor

gcloud container binauthz attestors create $ATTESTOR_ID \
    --attestation-authority-note=$NOTE_ID \
    --attestation-authority-note-project=${PROJECT_ID}

Onaylayanı doğrulama

gcloud container binauthz attestors list

Son satırda NUM_PUBLIC_KEYS: 0 anahtarları daha sonraki bir adımda sağlayacağınız belirtilir.

Ayrıca, Cloud Build'ün, görüntü oluşturan bir derleme çalıştırdığınızda projenizde built-by-cloud-build onaylayıcısını otomatik olarak oluşturduğunu da unutmayın. Bu nedenle, yukarıdaki komut vulnz-attestor ve built-by-cloud-build olmak üzere iki onaylayıcı döndürür. Görüntüler başarıyla oluşturulduktan sonra Cloud Build bunları otomatik olarak imzalar ve onaylar oluşturur.

IAM rolü ekleme

İkili Program Yetkilendirmesi hizmet hesabının, onay notlarını görüntüleme haklarına sahip olması gerekir. Aşağıdaki API çağrısıyla erişim sağlayın

PROJECT_NUMBER=$(gcloud projects describe "${PROJECT_ID}"  --format="value(projectNumber)")

BINAUTHZ_SA_EMAIL="service-${PROJECT_NUMBER}@gcp-sa-binaryauthorization.iam.gserviceaccount.com"


cat > ./iam_request.json << EOM
{
  'resource': 'projects/${PROJECT_ID}/notes/${NOTE_ID}',
  'policy': {
    'bindings': [
      {
        'role': 'roles/containeranalysis.notes.occurrences.viewer',
        'members': [
          'serviceAccount:${BINAUTHZ_SA_EMAIL}'
        ]
      }
    ]
  }
}
EOM

IAM politikası oluşturmak için dosyayı kullanın.

curl -X POST  \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    --data-binary @./iam_request.json \
    "https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/${NOTE_ID}:setIamPolicy"

KMS anahtarı ekleme

Notu eklemek ve doğrulanabilir imzalar sağlamak için onaylayanın kriptografik anahtarlara ihtiyacı vardır. Bu adımda, Cloud Build'in daha sonra erişebilmesi için KMS'de anahtarlar oluşturup saklayacaksınız.

Öncelikle yeni anahtarı açıklayan bazı ortam değişkenleri ekleyin.

KEY_LOCATION=global
KEYRING=binauthz-keys
KEY_NAME=codelab-key
KEY_VERSION=1

Bir dizi anahtarı tutmak için anahtarlık oluşturma

gcloud kms keyrings create "${KEYRING}" --location="${KEY_LOCATION}"

Onaylayıcı için yeni bir asimetrik imzalama anahtarı çifti oluşturun.

gcloud kms keys create "${KEY_NAME}" \
    --keyring="${KEYRING}" --location="${KEY_LOCATION}" \
    --purpose asymmetric-signing   \
    --default-algorithm="ec-sign-p256-sha256"

Anahtarınızın Google Cloud Console'un KMS sayfasında görünmesi gerekir.

Şimdi gcloud binauthz komutuyla anahtarı onaylayıcınızla ilişkilendirin:

gcloud beta container binauthz attestors public-keys add  \
    --attestor="${ATTESTOR_ID}"  \
    --keyversion-project="${PROJECT_ID}"  \
    --keyversion-location="${KEY_LOCATION}" \
    --keyversion-keyring="${KEYRING}" \
    --keyversion-key="${KEY_NAME}" \
    --keyversion="${KEY_VERSION}"

Yetkililer listesini tekrar yazdırırsanız artık kayıtlı bir anahtar görmeniz gerekir:

gcloud container binauthz attestors list

İmzalı onay oluşturma

Bu noktada, resimleri imzalamanızı sağlayan özellikler yapılandırılmış olur. Daha önce oluşturduğunuz onaylayıcıyı kullanarak üzerinde çalıştığınız kapsayıcı görüntüsünü imzalayın.

CONTAINER_PATH=us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image

DIGEST=$(gcloud container images describe ${CONTAINER_PATH}:latest \
    --format='get(image_summary.digest)')

Artık gcloud'u kullanarak onayınızı oluşturabilirsiniz. Komut, yalnızca imzalama için kullanmak istediğiniz anahtarın ayrıntılarını ve onaylamak istediğiniz belirli kapsayıcı görüntüsünü alır.

gcloud beta container binauthz attestations sign-and-create  \
    --artifact-url="${CONTAINER_PATH}@${DIGEST}" \
    --attestor="${ATTESTOR_ID}" \
    --attestor-project="${PROJECT_ID}" \
    --keyversion-project="${PROJECT_ID}" \
    --keyversion-location="${KEY_LOCATION}" \
    --keyversion-keyring="${KEYRING}" \
    --keyversion-key="${KEY_NAME}" \
    --keyversion="${KEY_VERSION}"

Kapsayıcı Analizi terimleriyle ifade edersek bu işlem, yeni bir oluşum oluşturur ve bunu onaylayıcınızın notuna ekler. Her şeyin beklendiği gibi çalıştığından emin olmak için onaylarınızı listeleyebilirsiniz.

gcloud container binauthz attestations list \
   --attestor=$ATTESTOR_ID --attestor-project=${PROJECT_ID}

7. Cloud Build ile imzalama

Resim imzalamayı etkinleştirdiniz ve örnek resminizi imzalamak için Onaylayan'ı manuel olarak kullandınız. Uygulamada, CI/CD ardışık düzenleri gibi otomatik işlemler sırasında onayları uygulamak isteyeceksiniz.

Bu bölümde, görüntüleri otomatik olarak onaylamak için Cloud Build'i yapılandıracaksınız.

Roller

Cloud Build hizmet hesabına İkili Program Yetkilendirmesi Onaylayanı Görüntüleyici rolünü ekleyin:

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
  --member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
  --role roles/binaryauthorization.attestorsViewer

Cloud Build hizmet hesabına Cloud KMS CryptoKey İmzalayıcı/Doğrulayıcı rolünü ekleyin (KMS tabanlı imzalama):

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
  --member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
  --role roles/cloudkms.signerVerifier

Cloud Build hizmet hesabına Container Analysis Notes Attacher rolünü ekleyin:

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
  --member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
  --role roles/containeranalysis.notes.attacher

Özel Derleme Cloud Build Adımını Hazırlama

Onay sürecini basitleştirmek için Cloud Build'de özel derleme adımı kullanacaksınız. Google, süreci kolaylaştırmak için yardımcı işlevler içeren bu Özel Derleme adımını sağlar. Kullanımdan önce özel derleme adımının kodu bir container'a derlenmeli ve Cloud Build'e aktarılmalıdır. Bunu yapmak için aşağıdaki komutları çalıştırın:

git clone https://github.com/GoogleCloudPlatform/cloud-builders-community.git
cd cloud-builders-community/binauthz-attestation
gcloud builds submit . --config cloudbuild.yaml
cd ../..
rm -rf cloud-builders-community

cloudbuild.yaml dosyanıza imzalama adımı ekleme

Bu adımda, daha önce oluşturduğunuz Cloud Build ardışık düzeninize onay adımını ekleyeceksiniz.

  1. Ekleyeceğiniz yeni adımı inceleyin.

Yalnızca inceleme Kopyalamayın

#Sign the image only if the previous severity check passes
- id: 'create-attestation'
  name: 'gcr.io/${PROJECT_ID}/binauthz-attestation:latest'
  args:
    - '--artifact-url'
    - 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image'
    - '--attestor'
    - 'projects/${PROJECT_ID}/attestors/$ATTESTOR_ID'
    - '--keyversion'
    - 'projects/${PROJECT_ID}/locations/$KEY_LOCATION/keyRings/$KEYRING/cryptoKeys/$KEY_NAME/cryptoKeyVersions/$KEY_VERSION'
  1. cloudbuild.yaml dosyanızın üzerine güncellenmiş tam ardışık düzeni yazın.
cat > ./cloudbuild.yaml << EOF
steps:

# build
- id: "build"
  name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image', '.']
  waitFor: ['-']

#Run a vulnerability scan at _SECURITY level
- id: scan
  name: 'gcr.io/cloud-builders/gcloud'
  entrypoint: 'bash'
  args:
  - '-c'
  - |
    (gcloud artifacts docker images scan \
    us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image \
    --location us \
    --format="value(response.scan)") > /workspace/scan_id.txt

#Analyze the result of the scan
- id: severity check
  name: 'gcr.io/cloud-builders/gcloud'
  entrypoint: 'bash'
  args:
  - '-c'
  - |
      gcloud artifacts docker images list-vulnerabilities \$(cat /workspace/scan_id.txt) \
      --format="value(vulnerability.effectiveSeverity)" | if grep -Fxq CRITICAL; \
      then echo "Failed vulnerability check for CRITICAL level" && exit 1; else echo "No CRITICAL vulnerability found, congrats !" && exit 0; fi

#Retag
- id: "retag"
  name: 'gcr.io/cloud-builders/docker'
  args: ['tag',  'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good']


#pushing to artifact registry
- id: "push"
  name: 'gcr.io/cloud-builders/docker'
  args: ['push',  'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good']


#Sign the image only if the previous severity check passes
- id: 'create-attestation'
  name: 'gcr.io/${PROJECT_ID}/binauthz-attestation:latest'
  args:
    - '--artifact-url'
    - 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good'
    - '--attestor'
    - 'projects/${PROJECT_ID}/attestors/$ATTESTOR_ID'
    - '--keyversion'
    - 'projects/${PROJECT_ID}/locations/$KEY_LOCATION/keyRings/$KEYRING/cryptoKeys/$KEY_NAME/cryptoKeyVersions/$KEY_VERSION'



images:
  - us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good
EOF

Derlemeyi çalıştırma

gcloud builds submit

Cloud Build Geçmişi'nde derlemeyi inceleme

Cloud Console'u açarak Cloud Build Geçmişi sayfasını görüntüleyin ve en son derlemeyi ve derleme adımlarının başarılı şekilde yürütülmesini inceleyin.

8. Kabul Denetimi Politikaları

İkili Program Yetkilendirmesi, GKE ve Cloud Run'da bulunan ve bir container görüntüsünün çalışmasına izin verilmeden önce kuralların doğrulanmasını sağlayan bir özelliktir. Doğrulama, güvenilir bir CI/CD ardışık düzeninden veya bir kullanıcının manuel olarak dağıtmaya çalıştığı bir resimden gelen resim çalıştırma isteği üzerine gerçekleştirilir. Bu özellik, çalışma zamanı ortamlarınızı yalnızca CI/CD ardışık düzen kontrollerine kıyasla daha etkili bir şekilde güvenceye almanıza olanak tanır.

Bu özelliği anlamak için varsayılan GKE politikasını değiştirerek katı bir yetkilendirme kuralı uygulayacaksınız.

GKE kümesini oluşturma

GKE kümesini oluşturun:

gcloud beta container clusters create binauthz \
    --zone us-central1-a  \
    --binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE

Cloud Build'in bu kümeye dağıtım yapmasına izin verin:

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
        --member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
        --role="roles/container.developer"

Tümüne İzin Ver Politikası

Öncelikle varsayılan politika durumunu ve herhangi bir resmi dağıtma olanağınızı doğrulayın.

  1. Mevcut politikayı inceleme
gcloud container binauthz policy export
  1. Yaptırım politikasının ALWAYS_ALLOW olarak ayarlandığını unutmayın.

evaluationMode: ALWAYS_ALLOW

  1. Her şeyi dağıtabildiğinizi doğrulamak için örneği dağıtın.
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
  1. Dağıtımın çalıştığını doğrulama
kubectl get pods

Aşağıdaki çıkışı görürsünüz.

161db370d99ffb13.png

  1. Dağıtımı silin
kubectl delete pod hello-server

Tümünü Reddetme Politikası

Şimdi politikayı tüm resimlere izin vermeyecek şekilde güncelleyin.

  1. Mevcut politikayı düzenlenebilir bir dosyaya aktarma
gcloud container binauthz policy export  > policy.yaml
  1. Politikayı değiştir

Bir metin düzenleyicide evaluationMode'u ALWAYS_ALLOW'dan ALWAYS_DENY olarak değiştirin.

edit policy.yaml

Politika YAML dosyası şu şekilde görünmelidir:

globalPolicyEvaluationMode: ENABLE
defaultAdmissionRule:
  evaluationMode: ALWAYS_DENY
  enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
name: projects/PROJECT_ID/policy
  1. Terminal'i açıp yeni politikayı uygulayın ve değişikliğin yayılması için birkaç saniye bekleyin.
gcloud container binauthz policy import policy.yaml
  1. Örnek iş yükü dağıtımı deneme
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
  1. Dağıtım, aşağıdaki mesajla başarısız oluyor
Error from server (VIOLATES_POLICY): admission webhook "imagepolicywebhook.image-policy.k8s.io" denied the request: Image gcr.io/google-samples/hello-app:1.0 denied by Binary Authorization default admission rule. Denied by always_deny admission rule

Politikayı tümüne izin verecek şekilde geri döndürme

Bir sonraki bölüme geçmeden önce politika değişikliklerini geri aldığınızdan emin olun.

  1. Politikayı değiştir

Bir metin düzenleyicide evaluationMode'u ALWAYS_DENY'dan ALWAYS_ALLOW olarak değiştirin.

edit policy.yaml

Politika YAML dosyası şu şekilde görünmelidir:

globalPolicyEvaluationMode: ENABLE
defaultAdmissionRule:
  evaluationMode: ALWAYS_ALLOW
  enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
name: projects/PROJECT_ID/policy
  1. Geri döndürülen politikayı uygulama
gcloud container binauthz policy import policy.yaml

9. GKE'deki Güvenlik Açıklarını Engelleme

Bu bölümde, görüntüleri tarayan, ardından imzalamadan ve dağıtmaya çalışmadan önce güvenlik açığı olup olmadığını kontrol eden bir CI/CD ardışık düzenini Cloud Build ile uygulayarak şimdiye kadar öğrendiklerinizi birleştireceksiniz. GKE, görüntünün çalışmasına izin vermeden önce güvenlik açığı taramasından gelen bir imza içerdiğini doğrulamak için İkili Program Yetkilendirmesi'ni kullanır.

d5c41bb89e22fd61.png

GKE politikasını, onay gerektirecek şekilde güncelleme

GKE BinAuth politikanıza clusterAdmissionRules ekleyerek, resimlerin Onaylayanınız tarafından imzalanmasını zorunlu kılın.

Aşağıdaki komutu kullanarak politikayı güncellenmiş yapılandırmayla üzerine yazın.

COMPUTE_ZONE=us-central1-a

cat > binauth_policy.yaml << EOM
defaultAdmissionRule:
  enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
  evaluationMode: ALWAYS_DENY
globalPolicyEvaluationMode: ENABLE
clusterAdmissionRules:
  ${COMPUTE_ZONE}.binauthz:
    evaluationMode: REQUIRE_ATTESTATION
    enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
    requireAttestationsBy:
    - projects/${PROJECT_ID}/attestors/vulnz-attestor
EOM

Politikayı uygulama

gcloud beta container binauthz policy import binauth_policy.yaml

İmzalanmamış görüntüyü dağıtmaya çalışmak

Aşağıdaki komutu kullanarak daha önce oluşturduğunuz uygulama için bir dağıtım tanımlayıcısı oluşturun. Burada kullanılan görüntü, daha önce oluşturduğunuz ve kritik güvenlik açıkları içeren, imzalı onay içermeyen görüntüdür.

GKE kabul denetleyicilerinin, imzayı tutarlı bir şekilde doğrulamak için dağıtılacak görüntüyü tam olarak bilmesi gerekir. Bunu yapmak için basit bir etiket yerine resim özetini kullanmanız gerekir.

Kötü resmin özetini alma

CONTAINER_PATH=us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image


DIGEST=$(gcloud container images describe ${CONTAINER_PATH}:bad \
    --format='get(image_summary.digest)')

Kubernetes yapılandırmasında özet kullanma

cat > deploy.yaml << EOM
apiVersion: v1
kind: Service
metadata:
  name: deb-httpd
spec:
  selector:
    app: deb-httpd
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deb-httpd
spec:
  replicas: 1
  selector:
    matchLabels:
      app: deb-httpd
  template:
    metadata:
      labels:
        app: deb-httpd
    spec:
      containers:
      - name: deb-httpd
        image: ${CONTAINER_PATH}@${DIGEST}
        ports:
        - containerPort: 8080
        env:
          - name: PORT
            value: "8080"

EOM

Uygulamayı GKE'ye dağıtmaya çalışın.

kubectl apply -f deploy.yaml

Konsoldaki iş yükünü inceleyin ve dağıtımın reddedildiğini belirten hatayı not edin:

No attestations found that were valid and signed by a key trusted by the attestor

İmzalı bir görüntüyü dağıtma

Kötü resmin özetini alma

CONTAINER_PATH=us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image


DIGEST=$(gcloud container images describe ${CONTAINER_PATH}:good \
    --format='get(image_summary.digest)')

Kubernetes yapılandırmasında özet kullanma

cat > deploy.yaml << EOM
apiVersion: v1
kind: Service
metadata:
  name: deb-httpd
spec:
  selector:
    app: deb-httpd
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deb-httpd
spec:
  replicas: 1
  selector:
    matchLabels:
      app: deb-httpd
  template:
    metadata:
      labels:
        app: deb-httpd
    spec:
      containers:
      - name: deb-httpd
        image: ${CONTAINER_PATH}@${DIGEST}
        ports:
        - containerPort: 8080
        env:
          - name: PORT
            value: "8080"

EOM

Uygulamayı GKE'ye dağıtma

kubectl apply -f deploy.yaml

Konsoldaki iş yükünü inceleyin ve görüntünün başarılı bir şekilde dağıtıldığını not edin.

10. Tebrikler!

Tebrikler, codelab'i tamamladınız.

İşlediğimiz konular:

  • Otomatik tarama nasıl etkinleştirilir?
  • İsteğe bağlı tarama nasıl yapılır?
  • Tarama işlevini derleme işlem hattına entegre etme
  • Onaylanan resimleri imzalama
  • GKE kabul denetleyicilerini kullanarak görüntüleri engelleme
  • GKE'yi yalnızca imzalı onaylı görüntülere izin verecek şekilde yapılandırma

Sıradaki adım:

Temizleme

Bu eğitimde kullanılan kaynaklar için Google Cloud hesabınızın ücretlendirilmesini önlemek amacıyla kaynakları içeren projeyi silin veya projeyi koruyup tek tek kaynakları silin.

Projeyi silme

Faturalandırılmanın önüne geçmenin en kolay yolu, eğitim için oluşturduğunuz projeyi silmektir.