Secure Build & Mit Cloud Build, Artifact Registry und GKE bereitstellen

Sichere Erstellung und Mit Cloud Build, Artifact Registry und GKE bereitstellen

Informationen zu diesem Codelab

subjectZuletzt aktualisiert: März 4, 2023
account_circleVerfasst von Christopher Grant

1. Einführung

Container Analysis bietet das Scannen auf Sicherheitslücken und das Speichern von Metadaten für Container. Der Scandienst führt Scans auf Sicherheitslücken für Images in Artifact Registry und Container Registry durch, speichert die resultierenden Metadaten und stellt sie über eine API zur Verfügung. Im Metadatenspeicher können Sie Informationen aus verschiedenen Quellen speichern, z. B. das Scannen auf Sicherheitslücken, Google Cloud-Dienste und Drittanbieter.

Das Scannen auf Sicherheitslücken kann automatisch oder on demand erfolgen:

  • Wenn automatisches Scannen aktiviert ist, wird der Scan jedes Mal automatisch ausgelöst, wenn Sie ein neues Image per Push an Artifact Registry oder Container Registry übertragen. Informationen zu Sicherheitslücken werden kontinuierlich aktualisiert, wenn neue Sicherheitslücken entdeckt werden.
  • Wenn On-Demand-Scans aktiviert ist, müssen Sie einen Befehl ausführen, um ein lokales Image oder ein Image in Artifact Registry oder Container Registry zu scannen. Mit dem On-Demand-Scanning können Sie flexibel entscheiden, wann Sie Container scannen. Sie können beispielsweise ein lokal erstelltes Image scannen und Sicherheitslücken beheben, bevor Sie es in einer Registry speichern. Die Scanergebnisse sind nach Abschluss des Scans bis zu 48 Stunden verfügbar. Informationen zu Sicherheitslücken werden nach dem Scan nicht aktualisiert.

Da Container Analysis in Ihre CI/CD-Pipeline eingebunden ist, können Sie Entscheidungen anhand dieser Metadaten treffen. Mit der Binärautorisierung können Sie beispielsweise Bereitstellungsrichtlinien erstellen, die nur Bereitstellungen für konforme Images aus vertrauenswürdigen Registrys zulassen.

Aufgaben in diesem Lab

  • Automatisches Scannen aktivieren
  • On-Demand-Scans durchführen
  • Scannen in eine Build-Pipeline einbinden
  • Genehmigte Bilder signieren
  • GKE-Admission-Controller zum Blockieren von Images verwenden
  • GKE so konfigurieren, dass nur signierte genehmigte Images zugelassen werden

2. Einrichtung und Anforderungen

Umgebung zum selbstbestimmten Lernen einrichten

  1. Melden Sie sich in der Google Cloud Console an und erstellen Sie ein neues Projekt oder verwenden Sie ein vorhandenes Projekt. Wenn Sie noch kein Gmail- oder Google Workspace-Konto haben, müssen Sie eines erstellen.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Der Projektname ist der Anzeigename für die Projektteilnehmer. Es handelt sich um eine Zeichenfolge, die von Google APIs nicht verwendet wird. Sie können sie jederzeit aktualisieren.
  • Die Projekt-ID ist für alle Google Cloud-Projekte eindeutig und unveränderlich. Sie kann nach dem Festlegen nicht mehr geändert werden. Die Cloud Console generiert automatisch einen eindeutigen String. ist Ihnen meist egal, was es ist. In den meisten Codelabs musst du auf die Projekt-ID verweisen, die üblicherweise als PROJECT_ID gekennzeichnet ist. Wenn Ihnen die generierte ID nicht gefällt, können Sie eine weitere zufällige ID erstellen. Alternativ können Sie einen eigenen verwenden und nachsehen, ob er verfügbar ist. Sie kann nach diesem Schritt nicht mehr geändert werden und bleibt für die Dauer des Projekts bestehen.
  • Zur Information gibt es noch einen dritten Wert, die Projektnummer, die von manchen APIs verwendet wird. Weitere Informationen zu allen drei Werten finden Sie in der Dokumentation.
  1. Als Nächstes müssen Sie in der Cloud Console die Abrechnung aktivieren, um Cloud-Ressourcen/APIs verwenden zu können. Dieses Codelab sollte möglichst wenig kosten. Wenn Sie Ressourcen herunterfahren möchten, um über diese Anleitung hinaus keine Kosten zu verursachen, können Sie die von Ihnen erstellten Ressourcen oder das gesamte Projekt löschen. Neue Google Cloud-Nutzer haben Anspruch auf eine kostenlose Testversion mit 300$Guthaben.

Cloud Shell-Editor starten

Dieses Lab wurde für die Verwendung mit dem Google Cloud Shell-Editor entwickelt und getestet. So greifen Sie auf den Editor zu:

  1. Rufen Sie Ihr Google-Projekt unter https://console.cloud.google.com auf.
  2. Klicken Sie rechts oben auf das Symbol für den Cloud Shell-Editor

8560cc8d45e8c112.png

  1. Unten im Fenster wird ein neuer Bereich geöffnet.

Umgebung einrichten

Legen Sie in Cloud Shell Ihre Projekt-ID und die Projektnummer für Ihr Projekt fest. Speichern Sie sie als Variablen des Typs PROJECT_ID und PROJECT_ID.

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

Dienste aktivieren

Aktivieren Sie alle erforderlichen Dienste:

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-Repository erstellen

In diesem Lab verwenden Sie Artifact Registry zum Speichern und Scannen Ihrer Images. Erstellen Sie das Repository mit dem folgenden Befehl.

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

Konfigurieren Sie Docker so, dass Ihre gcloud-Anmeldedaten für den Zugriff auf Artifact Registry verwendet werden.

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

3. Automatisches Scannen

Das Scannen von Artefakten wird automatisch ausgelöst, wenn Sie ein neues Image per Push an Artifact Registry oder Container Registry übertragen. Informationen zu Sicherheitslücken werden kontinuierlich aktualisiert, wenn neue Sicherheitslücken entdeckt werden. In diesem Abschnitt laden Sie ein Image per Push an Artifact Registry hoch und sehen sich die Ergebnisse an.

Arbeitsverzeichnis erstellen und dorthin wechseln

mkdir vuln-scan && cd vuln-scan

Beispielbild definieren

Erstellen Sie eine Datei namens Dockerfile mit folgendem Inhalt.

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

Erstellen Sie eine Datei namens "main.py" mit folgendem Inhalt:

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

Image erstellen und in AR übertragen

Mit Cloud Build können Sie einen Container erstellen und automatisch per Push in Artifact Registry übertragen. Beachten Sie das Tag bad auf dem Bild. So können Sie ihn für spätere Schritte besser identifizieren.

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

Bilddetails prüfen

Sobald der Build-Prozess abgeschlossen ist, prüfen Sie das Image und die Sicherheitslückenergebnisse im Artifact Registry-Dashboard.

  1. Öffnen Sie Artifact Registry in der Cloud Console
  2. Klicken Sie auf das Repository „Artefaktscans“, um den Inhalt anzusehen
  3. Klicken Sie auf die Bilddetails.
  4. Klicke auf den neuesten Digest deines Images
  5. Klicken Sie nach Abschluss des Scans auf den Tab „Sicherheitslücken“ für das Image.

Auf dem Tab „Sicherheitslücken“ werden die Ergebnisse des automatischen Scans für das soeben erstellte Image angezeigt.

361be7b3bf293fca.png

Das automatische Scannen ist standardmäßig aktiviert. In den Artifact Registry-Einstellungen erfahren Sie, wie Sie das automatische Scannen aktivieren/deaktivieren.

4. On-Demand-Scanning

Es gibt verschiedene Szenarien, in denen Sie möglicherweise einen Scan ausführen müssen, bevor Sie das Image per Push an ein Repository übertragen. Beispielsweise kann ein Containerentwickler ein Image scannen und die Probleme beheben, bevor er Code an die Versionsverwaltung sendet. Im folgenden Beispiel erstellen und analysieren Sie das Image lokal, bevor Sie auf die Ergebnisse reagieren.

Image erstellen

In diesem Schritt erstellen Sie das Image mit lokalem Docker im lokalen Cache.

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

Bild scannen

Fordern Sie nach dem Erstellen des Images einen Scan des Images an. Die Ergebnisse des Scans werden auf einem Metadatenserver gespeichert. Der Job wird mit dem Speicherort der Ergebnisse im Metadatenserver abgeschlossen.

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

Ausgabedatei prüfen

Nehmen Sie sich einen Moment Zeit, um sich die Ausgabe des vorherigen Schritts anzusehen, die in der Datei scan_id.txt gespeichert war. Beachten Sie den Speicherort der Scanergebnisse im Metadatenserver.

cat scan_id.txt

Detaillierte Scanergebnisse ansehen

Wenn Sie sich die tatsächlichen Ergebnisse des Scans ansehen möchten, verwenden Sie den Befehl list-vulnerabilities für den in der Ausgabedatei angegebenen Speicherort des Berichts.

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

Die Ausgabe enthält eine erhebliche Menge an Daten zu allen Sicherheitslücken im Image.

Kritische Probleme melden

Die im Bericht gespeicherten Daten werden nur selten direkt von Menschen verwendet. Normalerweise werden die Ergebnisse von einem automatisierten Prozess verwendet. Verwende die folgenden Befehle, um die Berichtsdetails zu lesen und zu protokollieren, ob KRITISCHE Sicherheitslücken gefunden wurden

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

Die Ausgabe dieses Befehls ist

Failed vulnerability check for CRITICAL level

5. Pipeline-Scan erstellen

In diesem Abschnitt erstellen Sie eine automatisierte Build-Pipeline, die Ihr Container-Image erstellt, es scannt und anschließend die Ergebnisse auswertet. Wenn keine KRITISCHEN Sicherheitslücken gefunden werden, wird das Image in das Repository verschoben. Wenn KRITISCHE Sicherheitslücken gefunden werden, schlägt der Build fehl und wird beendet.

Zugriff für Cloud Build-Dienstkonto gewähren

Cloud Build benötigt Rechte für den Zugriff auf die On-Demand-Scan-API. Gewähren Sie den Zugriff mit den folgenden Befehlen.

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-Pipeline erstellen

Mit dem folgenden Befehl wird in Ihrem Verzeichnis die Datei cloudbuild.yaml erstellt, die für den automatisierten Prozess verwendet wird. In diesem Beispiel sind die Schritte auf den Container-Build-Prozess beschränkt. In der Praxis würden Sie jedoch zusätzlich zu den Containerschritten anwendungsspezifische Anweisungen und Tests einbeziehen.

Erstellen Sie die Datei mit dem folgenden Befehl.

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-Pipeline ausführen

Reichen Sie den Build zur Verarbeitung ein, um zu prüfen, ob der Build nicht funktioniert, wenn eine Sicherheitslücke mit dem Schweregrad KRITISCH gefunden wird.

gcloud builds submit

Build-Fehler überprüfen

Der gerade eingereichte Build schlägt fehl, da das Image KRITISCHE Sicherheitslücken enthält.

Prüfen Sie den Build-Fehler auf der Seite Cloud Build-Verlauf

Sicherheitslücke beheben

Aktualisieren Sie das Dockerfile, um ein Basis-Image zu verwenden, das keine KRITISCHEN Sicherheitslücken enthält.

Überschreiben Sie das Dockerfile mit dem folgenden Befehl, um das Debian 10-Image zu verwenden

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-Prozess mit dem guten Image ausführen

Reichen Sie den Build zur Verarbeitung ein, um zu prüfen, ob der Build erfolgreich ist, wenn keine Sicherheitslücken mit dem Schweregrad KRITISCH gefunden werden.

gcloud builds submit

Build-Erfolg überprüfen

Der soeben eingereichte Build wird erfolgreich sein, da das aktualisierte Image keine KRITISCHEN Sicherheitslücken enthält.

Build-Erfolg auf der Seite Cloud Build-Verlauf prüfen

Scanergebnisse prüfen

Gutes Image in Artifact Registry prüfen

  1. Öffnen Sie Artifact Registry in der Cloud Console
  2. Klicken Sie auf das Repository „Artefaktscans“, um den Inhalt anzusehen
  3. Klicken Sie auf die Bilddetails.
  4. Klicke auf den neuesten Digest deines Images
  5. Klicken Sie für das Image auf den Tab „Sicherheitslücken“.

6. Bilder signieren

Attestierernotiz erstellen

Eine Attestierernotiz ist einfach ein kleines Datenelement, das als Beschriftung für den anzuwendenden Signaturtyp dient. Eine Notiz kann beispielsweise auf das Scannen auf Sicherheitslücken hinweisen, während eine andere für die QA-Genehmigung verwendet wird. Der Hinweis wird während des Signaturvorgangs referenziert.

Notiz erstellen

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

Notiz speichern

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}"

Notiz bestätigen

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

Attestierer erstellen

Attestierer werden für den eigentlichen Image-Signierungsprozess verwendet und hängen ein Vorkommen des Hinweises zur späteren Überprüfung an das Image an. Erstellen Sie den Attestierer zur späteren Verwendung.

Attestierer erstellen

ATTESTOR_ID=vulnz-attestor

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

Attestierer verifizieren

gcloud container binauthz attestors list

In der letzten Zeile steht, NUM_PUBLIC_KEYS: 0. Sie geben die Schlüssel in einem späteren Schritt an.

Cloud Build erstellt außerdem automatisch den Attestierer built-by-cloud-build in Ihrem Projekt, wenn Sie einen Build ausführen, der Images generiert. Der obige Befehl gibt also die beiden Attestierer vulnz-attestor und built-by-cloud-build zurück. Nachdem die Images erfolgreich erstellt wurden, signiert Cloud Build sie automatisch und erstellt Attestierungen für sie.

IAM-Rolle wird hinzugefügt

Das Dienstkonto Binärautorisierung benötigt Rechte zum Ansehen der Attestierungshinweise. Zugriff mit dem folgenden API-Aufruf bereitstellen

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

Datei zum Erstellen der IAM-Richtlinie verwenden

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-Schlüssel hinzufügen

Der Attestierer benötigt kryptografische Schlüssel, um den Hinweis anzuhängen und überprüfbare Signaturen bereitzustellen. In diesem Schritt erstellen und speichern Sie Schlüssel in KMS, damit Cloud Build später darauf zugreifen kann.

Fügen Sie zuerst einige Umgebungsvariablen hinzu, um den neuen Schlüssel zu beschreiben

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

Schlüsselbund für eine Reihe von Schlüsseln erstellen

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

Neues asymmetrisches Signaturschlüsselpaar für den Attestierer erstellen

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

Ihr Schlüssel sollte in der Google Cloud Console auf der KMS-Seite angezeigt werden.

Verknüpfen Sie nun den Schlüssel über den Befehl „gcloud binauthz“ mit Ihrem Attestierer:

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}"

Wenn Sie die Liste der Behörden noch einmal ausdrucken, sollte jetzt ein Schlüssel registriert sein:

gcloud container binauthz attestors list

Signierte Attestierung erstellen

Jetzt haben Sie die Funktionen konfiguriert, mit denen Sie Bilder signieren können. Mit dem zuvor erstellten Attestierer das Container-Image signieren, mit dem Sie gearbeitet haben

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)')

Jetzt können Sie die Attestierung mit gcloud erstellen. Der Befehl gibt einfach die Details des Schlüssels an, den Sie zum Signieren verwenden möchten, und das spezifische Container-Image, das Sie genehmigen möchten

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}"

In Container Analysis wird damit ein neues Vorkommen erstellt und an den Hinweis des Attestierers angehängt. Sie können Ihre Attestierungen auflisten, um sicherzustellen, dass alles wie erwartet funktioniert hat

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

7. Mit Cloud Build signieren

Sie haben die Image-Signatur aktiviert und manuell den Attestierer verwendet, um Ihr Beispiel-Image zu signieren. In der Praxis sollten Sie Attestierungen während automatisierter Prozesse wie CI/CD-Pipelines anwenden.

In diesem Abschnitt konfigurieren Sie Cloud Build so, dass Images automatisch attestiert werden.

Rollen

Fügen Sie dem Cloud Build-Dienstkonto die Rolle "Betrachter der Attestierer von Binärautorisierungen" hinzu:

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

Fügen Sie dem Cloud Build-Dienstkonto (KMS-basierte Signatur) die Rolle "Cloud KMS CryptoKey-Signer/Prüffunktion" hinzu:

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

Fügen Sie dem Cloud Build-Dienstkonto die Rolle "Hinzufüger von Container Analysis-Hinweisen" hinzu:

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

Benutzerdefinierten Cloud Build-Schritt vorbereiten

Sie verwenden einen benutzerdefinierten Build-Schritt in Cloud Build, um den Attestierungsprozess zu vereinfachen. Google bietet diesen benutzerdefinierten Build-Schritt mit Hilfsfunktionen zur Rationalisierung des Prozesses. Vor der Verwendung muss der Code für den benutzerdefinierten Build-Schritt in einen Container eingebunden und an Cloud Build übertragen werden. Führen Sie dazu die folgenden Befehle aus:

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

Signierschritt zu cloudbuild.yaml hinzufügen

In diesem Schritt fügen Sie der zuvor erstellten Cloud Build-Pipeline den Attestierungsschritt hinzu.

  1. Sehen Sie sich den neuen Schritt an, den Sie hinzufügen werden.

Nur Rezension. Nicht kopieren

#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. Überschreiben Sie Ihre cloudbuild.yaml-Datei mit der aktualisierten vollständigen Pipeline.
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

Build ausführen

gcloud builds submit

Build im Cloud Build-Verlauf überprüfen

Öffnen Sie in der Cloud Console die Seite Cloud Build-Verlauf und prüfen Sie den neuesten Build und die erfolgreiche Ausführung der Build-Schritte.

8. Zugangskontrollrichtlinien

Die Binärautorisierung ist ein Feature in GKE und Cloud Run, mit dem Regeln validiert werden können, bevor ein Container-Image ausgeführt werden darf. Die Validierung wird bei jeder Anfrage ausgeführt, um ein Image auszuführen, sei es von einer vertrauenswürdigen CI/CD-Pipeline oder von einem Nutzer, der manuell versucht, ein Image bereitzustellen. Mit dieser Funktion können Sie Ihre Laufzeitumgebungen effektiver schützen als mit CI/CD-Pipelineprüfungen allein.

Damit Sie diese Funktion besser verstehen können, ändern Sie die GKE-Standardrichtlinie, um eine strenge Autorisierungsregel zu erzwingen.

GKE-Cluster erstellen

Erstellen Sie den GKE-Cluster:

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

Erlauben Sie Cloud Build die Bereitstellung in diesem Cluster:

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

Alle Richtlinien zulassen

Prüfen Sie zuerst den Standardstatus der Richtlinie und Ihre Fähigkeit, ein beliebiges Image bereitzustellen

  1. Vorhandene Richtlinie überprüfen
gcloud container binauthz policy export
  1. Beachten Sie, dass die Erzwingungsrichtlinie auf „ALWAYS_ALLOW“ festgelegt ist

evaluationMode: ALWAYS_ALLOW

  1. Beispiel bereitstellen, um zu prüfen, ob alles bereitgestellt werden kann
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
  1. Prüfen, ob die Bereitstellung funktioniert hat
kubectl get pods

Sie sehen die folgende Ausgabe

161db370d99ffb13.png

  1. Deployment löschen
kubectl delete pod hello-server

Alle Richtlinien ablehnen

Aktualisieren Sie jetzt die Richtlinie, um alle Bilder nicht mehr zuzulassen.

  1. Aktuelle Richtlinie in eine bearbeitbare Datei exportieren
gcloud container binauthz policy export  > policy.yaml
  1. Richtlinie ändern

Ändern Sie in einem Texteditor den Auswertungsmodus von ALWAYS_ALLOW in ALWAYS_DENY.

edit policy.yaml

Die YAML-Richtliniendatei sollte so aussehen:

globalPolicyEvaluationMode: ENABLE
defaultAdmissionRule:
  evaluationMode: ALWAYS_DENY
  enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
name: projects/PROJECT_ID/policy
  1. Öffnen Sie das Terminal, wenden Sie die neue Richtlinie an. Warten Sie dann einige Sekunden, bis die Änderung wirksam wird.
gcloud container binauthz policy import policy.yaml
  1. Beispiel für die Arbeitslastbereitstellung versuchen
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
  1. Die Bereitstellung schlägt mit der folgenden Meldung fehl
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

Setzen Sie die Richtlinie zurück, um alle zuzulassen

Machen Sie die Richtlinienänderungen rückgängig, bevor Sie mit dem nächsten Abschnitt fortfahren.

  1. Richtlinie ändern

Ändern Sie in einem Texteditor den Auswertungsmodus von ALWAYS_DENY in ALWAYS_ALLOW.

edit policy.yaml

Die YAML-Richtliniendatei sollte so aussehen:

globalPolicyEvaluationMode: ENABLE
defaultAdmissionRule:
  evaluationMode: ALWAYS_ALLOW
  enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
name: projects/PROJECT_ID/policy
  1. Wiederhergestellte Richtlinie anwenden
gcloud container binauthz policy import policy.yaml

9. Sicherheitslücken in GKE blockieren

In diesem Abschnitt kombinieren Sie das bisher Gelernte, indem Sie eine CI/CD-Pipeline mit Cloud Build implementieren. Diese scannt die Images und prüft diese auf Sicherheitslücken, bevor Sie das Image signieren und bereitstellen. GKE prüft mithilfe der Binärautorisierung, ob das Image eine Signatur aus dem Scannen auf Sicherheitslücken hat, bevor das Image ausgeführt werden kann.

d5c41bb89e22fd61.png

GKE-Richtlinie so aktualisieren, dass eine Bestätigung erforderlich ist

Erforderliche Images müssen von Ihrem Attestierer signiert sein. Dazu fügen Sie Ihrer GKE-BinAuth-Richtlinie clusterAdmissionRules hinzu.

Überschreiben Sie die Richtlinie mit der aktualisierten Konfiguration mithilfe des folgenden Befehls.

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

Richtlinie anwenden

gcloud beta container binauthz policy import binauth_policy.yaml

Versuchen, das unsignierte Image bereitzustellen

Erstellen Sie mit dem folgenden Befehl einen Bereitstellungsdeskriptor für die zuvor erstellte Anwendung. Das hier verwendete Image ist das Image, das Sie zuvor erstellt haben. Es enthält kritische Sicherheitslücken und NICHT die signierte Attestierung.

GKE-Admission-Controller müssen das genaue Image kennen, das bereitgestellt werden soll, um die Signatur einheitlich validieren zu können. Um dies zu erreichen, müssen Sie den Image-Digest und ein einfaches Tag verwenden.

Image-Digest für schlechtes Image abrufen

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)')

Digest in der Kubernetes-Konfiguration verwenden

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

Versuchen, die Anwendung in GKE bereitzustellen

kubectl apply -f deploy.yaml

Überprüfen Sie die Arbeitslast in der Console und sehen Sie sich den Fehler an, der besagt, dass die Bereitstellung abgelehnt wurde:

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

Signiertes Image bereitstellen

Image-Digest für schlechtes Image abrufen

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)')

Digest in der Kubernetes-Konfiguration verwenden

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

Anwendung in GKE bereitstellen

kubectl apply -f deploy.yaml

Überprüfen Sie die Arbeitslast in der Console und notieren Sie die erfolgreiche Bereitstellung des Images.

10. Glückwunsch!

Glückwunsch, du hast das Codelab abgeschlossen.

Behandelte Themen:

  • Automatisches Scannen aktivieren
  • On-Demand-Scans durchführen
  • Scannen in eine Build-Pipeline einbinden
  • Genehmigte Bilder signieren
  • GKE-Admission-Controller zum Blockieren von Images verwenden
  • GKE so konfigurieren, dass nur signierte genehmigte Images zugelassen werden

Nächste Schritte:

Bereinigen

Damit Ihrem Google Cloud-Konto die in dieser Anleitung verwendeten Ressourcen nicht in Rechnung gestellt werden, können Sie entweder das Projekt löschen, das die Ressourcen enthält, oder das Projekt beibehalten und die einzelnen Ressourcen löschen.

Projekt löschen

Am einfachsten vermeiden Sie weitere Kosten durch Löschen des für die Anleitung erstellten Projekts.