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

1. Giriş

Container Analizi, 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 elde edilen meta verileri depolar ve bir API aracılığıyla kullanıma sunar. Meta veri depolama alanı, güvenlik açığı taraması, Google Cloud hizmetleri ve üçüncü taraf sağlayıcılar dahil olmak üzere farklı kaynaklardan gelen bilgileri depolamanızı sağlar.

Güvenlik açığı taraması otomatik olarak veya isteğe bağlı olarak yapılabilir:

  • Otomatik tarama etkinleştirildiğinde, Artifact Registry veya Container Registry'ye her yeni görüntü aktardığınızda tarama otomatik olarak tetiklenir. Yeni güvenlik açıkları keşfedildiğinde güvenlik açığı bilgileri sürekli olarak güncellenir.
  • İstediğiniz Zaman 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 bir kayıt deposunda depolamadan önce güvenlik açıklarını giderebilirsiniz. Tarama sonuçları, tarama tamamlandıktan sonra 48 saat boyunca kullanılabilir. Güvenlik açığı bilgileri tarama sonrasında güncellenmez.

CI/CD ardışık düzeninize entegre edilmiş Container Analysis ile bu meta verilere dayalı kararlar alabilirsiniz. Örneğin, yalnızca güvenilir kayıt defterilerdeki 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 taramayı etkinleştirme
  • İsteğe bağlı tarama nasıl yapılır?
  • Taramayı derleme ardışık düzenine entegre etme
  • Onaylanmış resimleri imzalama
  • GKE giriş denetleyicilerini kullanarak resimleri engelleme
  • GKE'yi yalnızca imzalanmış onaylanmış görüntülere izin verecek şekilde yapılandırma

2. Kurulum ve Gereksinimler

Kendi hızınızda 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ının görünen adıdı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 değiştirilemez (ayarlandıktan sonra değiştirilemez). Cloud Console, benzersiz bir dize otomatik olarak oluşturur. Bu dizenin ne olduğu genellikle önemli değildir. Çoğu kod laboratuvarında proje kimliğine (genellikle PROJECT_ID olarak tanımlanır) referans vermeniz gerekir. Oluşturulan kimliği beğenmezseniz rastgele başka bir kimlik oluşturabilirsiniz. Alternatif olarak, kendi anahtarınızı deneyerek kullanılabilir olup olmadığını görebilirsiniz. Bu adımdan sonra değiştirilemez ve proje boyunca geçerli kalır.
  • Bazı API'lerin kullandığı üçüncü bir değer (Proje Numarası) olduğunu belirtmek isteriz. Bu üç değer hakkında daha fazla bilgiyi dokümanlar bölümünde bulabilirsiniz.
  1. Ardından, Cloud kaynaklarını/API'lerini kullanmak için Cloud Console'da faturalandırmayı etkinleştirmeniz gerekir. Bu codelab'i çalıştırmak çok pahalı olmayacaktır. Bu eğitimden sonra faturalandırılmamak 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ğerindeki ücretsiz deneme programına uygundur.

Cloudshell 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 bulut kabuğu 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 komutu kullanarak deposu oluşturun.

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

Docker'ı, Artifact Registry'ye erişirken gcloud kimlik bilgilerinizi kullanacak şekilde yapılandırın.

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

3. Otomatik Tarama

Artifact taraması, Artifact Registry veya Container Registry'ye her yeni görüntü gönderdiğinizde otomatik olarak tetiklenir. Yeni güvenlik açıkları keşfedildiğinde güvenlik açığı bilgileri sürekli olarak güncellenir. Bu bölümde, Artifact Registry'ye bir görüntü aktaracak ve sonuçları keşfedeceksiniz.

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

mkdir vuln-scan && cd vuln-scan

Örnek resim tanımlama

Aşağıdaki içeriğe 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çeriğe 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şturup AR'ye aktarma

Container'ınızı oluşturmak ve Artifact Registry'ye otomatik olarak aktarmak için Cloud Build'i kullanın. Resimde bad etiketini görebilirsiniz. Bu, sonraki adımlarda bu ağı tanımlamanıza 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üyü ve güvenlik açığı sonuçlarını inceleyin.

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

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

361be7b3bf293fca.png

Taramayı otomatikleştirme özelliği varsayılan olarak etkindir. Otomatik taramayı nasıl kapatıp açabileceğinizi görmek için Artifact Registry ayarlarını keşfedin.

4. İsteğe Bağlı Tarama

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

Resim oluşturma

Bu adımda, yerel önbelleğinize görüntü 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. Taramanın 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ı inceleme

Bir önceki adımın scan_id.txt dosyasında saklanan çıktısını inceleyin. Meta veri sunucusunda 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 çıkış 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çerir.

Kritik sorunları işaretleme

İnsanlar, raporda depolanan 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 ÖNEMLİ düzeyde 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ışı

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 sonuçları değerlendirecek otomatik bir derleme ardışık düzeni oluşturacaksınız. Kritik güvenlik açığı bulunmazsa görüntü depoya gönderilir. ÖNEMLİ düzeyde güvenlik açığı bulunursa derleme başarısız olur ve sonlandırılır.

Cloud Build hizmet hesabı için erişim sağlama

Cloud Build'in, isteğe bağlı tarama API'sine erişmek için haklarına sahip olması gerekir. Aşağıdaki komutlarla erişim izni verin.

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ı oluşturma süreciyle 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

ÖNEMLİ önem derecesine sahip bir güvenlik açığı bulunduğunda derlemenin kesintiye uğradığını doğrulamak için derlemeyi işleme gönderin.

gcloud builds submit

İnceleme Derleme Hatası

Gönderdiğiniz derleme, resimde ÖNEMLİ güvenlik açıkları bulunduğu için başarısız oldu.

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

Güvenlik açığını düzeltme

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

Aşağıdaki komutu kullanarak Debian 10 görüntüsünü kullanmak için Dockerfile'in ü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

İyi resimle CI işlemini çalıştırın

ÖNEMLİ önem derecesine sahip güvenlik açığı bulunmadığında derlemenin başarılı olacağını doğrulamak için derlemeyi işleme gönderin.

gcloud builds submit

Derleme Başarısını İnceleme

Güncellenen resimde ÖNEMLİ güvenlik açığı bulunmadığından, az önce gönderdiğiniz derleme başarılı olacaktır.

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

Tarama sonuçlarını inceleme

Artifact Registry'de iyi resmi inceleyin

  1. Cloud Console'da Artifact Registry'yi açın
  2. İçeriği görüntülemek için artifact-scanning-repo'yu tıklayın.
  3. Resim 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. Resimleri imzalama

Onaylayan Notu Oluşturma

Onaylayan 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ı belirtebilirken başka bir not QA onayı için kullanılabilir. İmzalama işlemi sırasında notlara başvurulur.

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 resim imzalama işlemini gerçekleştirmek için kullanılır ve daha sonra doğrulanması için notun bir örneğini resme ekler. Daha sonra kullanmak üzere doğrulayı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: 0anahtarları daha sonraki bir adımda sağlayacağınız belirtilir.

Ayrıca, Cloud Build'in, resim oluşturan bir derleme çalıştırdığınızda projenizde otomatik olarak built-by-cloud-build doğrulayıcıyı oluşturduğunu 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, görüntüleri otomatik olarak imzalar ve bunlar için doğrulamalar oluşturur.

IAM rolü ekleme

İkili Program Yetkilendirmesi hizmet hesabının, tasdik notlarını görüntüleme haklarına sahip olması gerekir. Aşağıdaki API çağrısıyla erişimi 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ını 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

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

Öncelikle yeni anahtarı tanımlamak için bazı ortam değişkenleri ekleyin

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

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, Google Cloud Console'un KMS sayfasında görünür.

Ardından, gcloud binauthz komutunu kullanarak anahtarı doğrulayı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}"

Yetkililerin listesini tekrar yazdırırsanız artık kayıtlı bir anahtar görürsünüz:

gcloud container binauthz attestors list

İmzalı Onay Oluşturma

Bu noktada, resimleri imzalamanızı sağlayan özellikleri yapılandırdınız. Daha önce oluşturduğunuz Attestor'u 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 doğrulama belgenizi oluşturabilirsiniz. Komut, 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 bu işlem, yeni bir gerçekleşme oluşturur ve bunu onaylayan kişinin 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 Attestor'u manuel olarak kullandınız. Uygulamada, CI/CD ardışık düzenleri gibi otomatik süreçler sırasında Attestations'ı uygulamak isteyeceksiniz.

Bu bölümde, Cloud Build'i görüntüleri otomatik olarak doğrulayacak şekilde 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 KMS CryptoKey İmzalayıcı/Doğrulayıcı rolünü Cloud Build Hizmet Hesabı'na 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

Onaylama 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. Özel derleme adımı kodu, kullanılmadan önce bir kapsayıcıya derlenip Cloud Build'e aktarılmalıdır. Bunun 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 doğrulama adımını ekleyeceksiniz.

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

Yalnızca inceleme. Kopyalama

#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çıp Cloud Build Geçmişi sayfasına gidin 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 bir container görüntüsünün çalıştırılmasına izin verilmeden önce kuralları doğrulama olanağı sunan bir özelliktir. Doğrulama, güvenilir bir CI/CD ardışık düzeninden veya bir kullanıcının manuel olarak görüntü dağıtmaya çalıştığı her görüntü çalıştırma isteğinde gerçekleştirilir. Bu özellik, çalışma ortamılarınızın güvenliğini yalnızca CI/CD ardışık düzeni kontrollerinden daha etkili bir şekilde sağlamanıza olanak tanır.

Bu özelliği anlamak için varsayılan GKE politikasını katı bir yetkilendirme kuralı uygulayacak şekilde değiştireceksiniz.

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ğıtması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 resim dağıtıp dağıtamayacağınızı doğrulayın

  1. Mevcut politikayı inceleyin
gcloud container binauthz policy export
  1. Yaptırım politikasının ALWAYS_ALLOW olarak ayarlandığını fark edin.

evaluationMode: ALWAYS_ALLOW

  1. Herhangi bir öğeyi dağıtabileceğinizi doğrulamak için örnek dağıtma
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ü Reddet Politikası

Ardından, tüm resimlere izin vermeyecek şekilde politikayı 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 değerini ALWAYS_ALLOW yerine ALWAYS_DENY olarak değiştirin.

edit policy.yaml

Politika YAML dosyası aşağıdaki gibi 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 uygulanması için birkaç saniye bekleyin.
gcloud container binauthz policy import policy.yaml
  1. Örnek iş yükü dağıtımını deneme
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
  1. Dağıtım, aşağıdaki mesajla birlikte 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

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 değerini ALWAYS_DENY yerine ALWAYS_ALLOW olarak değiştirin.

edit policy.yaml

Politika YAML dosyası aşağıdaki gibi 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'de güvenlik açıklarını engelleme

Bu bölümde, Cloud Build ile görüntüleri tarayan ve ardından görüntüyü imzalayıp dağıtmaya çalışmadan önce güvenlik açıklarını kontrol eden bir CI/CD ardışık düzeni uygulayarak şimdiye kadar öğrendiklerinizi birleştireceksiniz. GKE, görüntünün çalışmasına izin vermeden önce görüntünün güvenlik açığı taramasından alınmış bir imzaya sahip olduğunu doğrulamak için İkili Program Yetkilendirmesi'ni kullanır.

d5c41bb89e22fd61.png

GKE Politikası'nı, Onaylama'yı Zorunlu Kılacak Şekilde Güncelleme

GKE BinAuth Politikanıza clusterAdmissionRules ekleyerek resimlerin Attestor'unuz tarafından imzalanmasını zorunlu kılın

Aşağıdaki komutu kullanarak politikanın üzerine güncel yapılandırmayla 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

İmzasız resmi dağıtmaya çalışma

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 ancak imzalı doğrulama içermeyen görüntüdür.

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

Kötü resmin resim ö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 özeti 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

Console'daki 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 resim dağıtma

Kötü resmin resim ö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 özeti 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, kod laboratuvarını tamamladınız.

Ele aldığımız konular:

  • Otomatik taramayı etkinleştirme
  • İsteğe bağlı tarama nasıl yapılır?
  • Taramayı derleme ardışık düzenine entegre etme
  • Onaylanmış resimleri imzalama
  • GKE giriş denetleyicilerini kullanarak resimleri engelleme
  • GKE'yi yalnızca imzalanmış onaylanmış görüntülere izin verecek şekilde yapılandırma

Sıradaki adım:

Temizleme

Bu eğiticide kullanılan kaynaklar için Google Cloud hesabınızın ücretlendirilmesini istemiyorsanız kaynakları içeren projeyi silin veya projeyi saklayıp kaynakları tek tek silin.

Projeyi silme

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