1. Einführung
Container Analysis bietet Scans auf Sicherheitslücken und Metadatenspeicherung für Container. Der Scandienst führt Scans auf Sicherheitslücken in Images in Artifact Registry und Container Registry durch, speichert die resultierenden Metadaten und stellt sie über eine API zur Verfügung. Mit der Speicherung von Metadaten können Sie Informationen aus verschiedenen Quellen speichern, einschließlich Scans auf Sicherheitslücken, Google Cloud-Diensten und Drittanbietern.
Das Scannen auf Sicherheitslücken kann automatisch oder on demand erfolgen:
- Wenn automatisches Scannen aktiviert ist, wird jedes Mal automatisch gescannt, wenn Sie ein neues Image in Artifact Registry oder Container Registry hochladen. Die Informationen zu Sicherheitslücken werden kontinuierlich aktualisiert, wenn neue Sicherheitslücken entdeckt werden.
- Wenn On-Demand-Scanning aktiviert ist, müssen Sie einen Befehl ausführen, um ein lokales Image oder ein Image in Artifact Registry oder Container Registry zu scannen. On-Demand-Scanning bietet mehr Flexibilität beim Scannen von Containern. Sie können beispielsweise ein lokal erstelltes Image scannen und Sicherheitslücken beheben, bevor Sie es in einer Registry speichern. Scanergebnisse sind bis zu 48 Stunden nach Abschluss des Scans verfügbar und Informationen zu Sicherheitslücken werden nach dem Scan nicht aktualisiert.
Durch das Einbinden von Container Analysis in Ihre CI-/CD-Pipeline können Sie auf der Grundlage dieser Metadaten Entscheidungen treffen. Sie können beispielsweise mit der Binärautorisierung Deployment-Richtlinien erstellen, die nur Deployments für konforme Images aus vertrauenswürdigen Registries zulassen.
Lerninhalte
- Automatisches Scannen aktivieren
- On-Demand-Scans durchführen
- Scannen in eine Build-Pipeline einbinden
- Genehmigte Bilder signieren
- GKE-Zugangs-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
- Melden Sie sich in der Google Cloud Console an und erstellen Sie ein neues Projekt oder verwenden Sie ein vorhandenes. Wenn Sie noch kein Gmail- oder Google Workspace-Konto haben, müssen Sie eines erstellen.



- Der Projektname ist der Anzeigename für die Teilnehmer dieses Projekts. Es handelt sich um einen String, der nicht von Google APIs verwendet wird. Sie können ihn jederzeit aktualisieren.
- Die Projekt-ID ist für alle Google Cloud-Projekte eindeutig und unveränderlich (kann nach dem Festlegen nicht mehr geändert werden). In der Cloud Console wird automatisch ein eindeutiger String generiert. Normalerweise ist es nicht wichtig, wie dieser String aussieht. In den meisten Codelabs müssen Sie auf die Projekt-ID verweisen (sie wird in der Regel als
PROJECT_IDangegeben). Wenn Ihnen die generierte ID nicht gefällt, können Sie eine andere zufällige ID generieren. Alternativ können Sie es mit einem eigenen versuchen und sehen, ob es verfügbar ist. Sie kann nach diesem Schritt nicht mehr geändert werden und bleibt für die Dauer des Projekts bestehen. - Zur Information: Es gibt einen dritten Wert, die Projektnummer, die von einigen APIs verwendet wird. Weitere Informationen zu diesen drei Werten
- Als Nächstes müssen Sie die Abrechnung in der Cloud Console aktivieren, um Cloud-Ressourcen/-APIs zu verwenden. Die Durchführung dieses Codelabs sollte keine oder nur geringe Kosten verursachen. Wenn Sie Ressourcen herunterfahren möchten, damit Ihnen nach Abschluss dieser Anleitung keine Kosten mehr in Rechnung gestellt werden, können Sie die von Ihnen erstellten Ressourcen oder das gesamte Projekt löschen. Neue Nutzer von Google Cloud kommen für das Programm für kostenlose Testversionen mit einem Guthaben von 300$ infrage.
Cloud Shell-Editor starten
Dieses Lab wurde für die Verwendung mit Google Cloud Shell Editor entwickelt und getestet. So greifen Sie auf den Editor zu:
- Rufen Sie Ihr Google-Projekt unter https://console.cloud.google.com auf.
- Klicken Sie oben rechts auf das Cloud Shell Editor-Symbol.

- 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 die Variablen 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 jedes Mal automatisch ausgelöst, wenn Sie ein neues Image in Artifact Registry oder Container Registry hochladen. Die Informationen zu Sicherheitslücken werden kontinuierlich aktualisiert, wenn neue Sicherheitslücken entdeckt werden. In diesem Abschnitt übertragen Sie ein Image per Push in die Artifact Registry und sehen sich die Ergebnisse an.
Arbeitsverzeichnis erstellen und in dieses Verzeichnis wechseln
mkdir vuln-scan && cd vuln-scan
Beispielbild definieren
Erstellen Sie eine Datei mit dem Namen „Dockerfile“ und dem folgenden 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 mit dem Namen „main.py“ und dem folgenden 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 per Push in AR übertragen
Mit Cloud Build können Sie Ihren Container erstellen und automatisch per Push in Artifact Registry übertragen. Beachten Sie das Tag bad auf dem Bild. So können Sie ihn in späteren Schritten leichter identifizieren.
gcloud builds submit . -t us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:bad
Image-Details prüfen
Nach Abschluss des Build-Prozesses können Sie sich das Image und die Ergebnisse zu den Sicherheitslücken im Artifact Registry-Dashboard ansehen.
- Öffnen Sie Artifact Registry in der Cloud Console.
- Klicken Sie auf „artifact-scanning-repo“, um den Inhalt aufzurufen.
- Klicken Sie auf die Bilddetails.
- Klicken Sie auf den neuesten Digest Ihres Images.
- Klicken Sie nach Abschluss des Scans auf den Tab „Sicherheitslücken“ für das Image.
Auf dem Tab „Sicherheitslücken“ sehen Sie die Ergebnisse des automatischen Scans für das Image, das Sie gerade erstellt haben.

Das automatisierte Scannen ist standardmäßig aktiviert. In den Artifact Registry-Einstellungen können Sie das automatische Scannen deaktivieren oder aktivieren.
4. On-Demand-Scanning
Es gibt verschiedene Szenarien, in denen Sie einen Scan durchführen müssen, bevor Sie das Image in ein Repository übertragen. Bei der Containerentwicklung können Sie z. B. ein Image scannen und die gefundenen Probleme beheben, bevor Sie den Code in die Quellcodeverwaltung übertragen. Im folgenden Beispiel erstellen und analysieren Sie das Image lokal, bevor Sie auf die Ergebnisse reagieren.
Image erstellen
In diesem Schritt verwenden Sie das lokale Docker, um das Image in Ihrem lokalen Cache zu erstellen.
docker build -t us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image .
Bild scannen
Wenn das Image erstellt wurde, fordern Sie einen Scan des Images an. Die Ergebnisse des Scans werden auf einem Metadatenserver gespeichert. Der Job wird mit dem Speicherort der Ergebnisse auf dem 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
Sehen Sie sich die Ausgabe des vorherigen Schritts an, die in der Datei „scan_id.txt“ gespeichert wurde. Beachten Sie den Speicherort des Berichts mit den Scanergebnissen auf dem Metadatenserver.
cat scan_id.txt
Detaillierte Scanergebnisse ansehen
Verwenden Sie den Befehl list-vulnerabilities für den in der Ausgabedatei angegebenen Speicherort des Berichts, um die tatsächlichen Ergebnisse des Scans aufzurufen.
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.
Schwerwiegende Probleme melden
Die im Bericht gespeicherten Daten werden selten von Menschen direkt verwendet. Die Ergebnisse werden normalerweise von einem automatisierten Prozess genutzt. Mit den folgenden Befehlen können Sie die Berichtsdetails lesen und protokollieren, ob CRITICAL-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
Dies ist die Ausgabe dieses Befehls:
Failed vulnerability check for CRITICAL level
5. Build-Pipeline-Scanning
In diesem Abschnitt erstellen Sie eine automatisierte Build-Pipeline, um Ihr Container-Image zu erstellen, zu scannen und die Ergebnisse auszuwerten. Wenn keine Sicherheitslücken mit dem Schweregrad CRITICAL gefunden werden, wird das Image in das Repository übertragen. Wenn CRITICAL-Sicherheitslücken gefunden werden, schlägt der Build fehl und wird beendet.
Zugriff für Cloud Build-Dienstkonto bereitstellen
Cloud Build benötigt Berechtigungen für den Zugriff auf die On-Demand Scanning API. Gewähren Sie 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 eine cloudbuild.yaml-Datei erstellt, die für den automatisierten Prozess verwendet wird. In diesem Beispiel beschränken sich die Schritte auf den Container-Build-Prozess. In der Praxis würden Sie jedoch zusätzlich zu den Container-Schritten anwendungsspezifische Anweisungen und Tests einfügen.
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
Senden Sie den Build zur Verarbeitung, um zu prüfen, ob er fehlschlägt, wenn eine Sicherheitslücke mit dem Schweregrad CRITICAL gefunden wird.
gcloud builds submit
Build-Fehler prüfen
Der Build, den Sie gerade eingereicht haben, schlägt fehl, weil das Image KRITISCHE Sicherheitslücken enthält.
Sehen Sie sich den Build-Fehler auf der Seite Cloud Build-Verlauf an.
Sicherheitslücke beheben
Aktualisieren Sie das Dockerfile, damit ein Basis-Image verwendet wird, das keine Sicherheitslücken mit dem Schweregrad CRITICAL 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 Bild ausführen
Senden Sie den Build zur Verarbeitung, um zu prüfen, ob er erfolgreich ist, wenn keine Sicherheitslücken mit dem Schweregrad CRITICAL gefunden werden.
gcloud builds submit
Erfolg von Builds prüfen
Der Build, den Sie gerade eingereicht haben, wird erfolgreich sein, da das aktualisierte Image keine Sicherheitslücken mit dem Schweregrad CRITICAL enthält.
Prüfen Sie den Build-Erfolg auf der Seite Cloud Build-Verlauf.
Scanergebnisse prüfen
Funktionierendes Image in Artifact Registry prüfen
- Öffnen Sie Artifact Registry in der Cloud Console.
- Klicken Sie auf „artifact-scanning-repo“, um den Inhalt aufzurufen.
- Klicken Sie auf die Bilddetails.
- Klicken Sie auf den neuesten Digest Ihres Images.
- Klicken Sie für das Image auf den Tab „Sicherheitslücken“.
6. Images signieren
Attestier-Hinweis erstellen
Ein Attestier-Hinweis ist einfach ein kleiner Datenteil, der als Label für die Art der angewendeten Signatur dient. Ein Hinweis kann sich beispielsweise auf einen Scan auf Sicherheitslücken beziehen während ein anderer für die QA-Freigabe verwendet werden kann. Während des Signierungsprozesses wird auf den Hinweis Bezug genommen.
Notiz erstellen
cat > ./vulnz_note.json << EOM
{
"attestation": {
"hint": {
"human_readable_name": "Container Vulnerabilities attestation authority"
}
}
}
EOM
Speichern Sie den Hinweis:
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}"
Bestätigen Sie den Hinweis:
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 verwendet, um den eigentlichen Signierungsprozess für das Image durchzuführen. Sie fügen dem Image eine Version des Hinweises zur späteren Überprüfung hinzu. 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}
Bestätigen Sie den Attestierer:
gcloud container binauthz attestors list
In der letzten Zeile wird NUM_PUBLIC_KEYS: 0 angezeigt. Sie geben die Schlüssel in einem späteren Schritt an.
Beachten Sie außerdem, dass Cloud Build automatisch den Attestierer built-by-cloud-build in Ihrem Projekt erstellt, wenn Sie einen Build ausführen, der Images generiert. Der obige Befehl gibt also zwei Attestierer zurück: vulnz-attestor und built-by-cloud-build. Nachdem die Images erfolgreich erstellt wurden, signiert Cloud Build automatisch Attestierungen für die Images.
IAM-Rolle hinzufügen
Das Dienstkonto der Binärautorisierung benötigt Berechtigungen zum Aufrufen der Attestierung-Hinweise. Gewähren Sie den Zugriff mit dem folgenden API-Aufruf:
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
Verwenden Sie die Datei, um die IAM-Richtlinie zu erstellen.
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 die Anmerkung anzuhängen und überprüfbare Signaturen bereitzustellen. In diesem Schritt erstellen und speichern Sie Schlüssel in KMS, auf die Cloud Build später 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 zum Speichern von Schlüsseln erstellen
gcloud kms keyrings create "${KEYRING}" --location="${KEY_LOCATION}"
Erstellen Sie ein neues asymmetrisches Schlüsselpaar für die Signierung für den Attestierer:
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 den Schlüssel nun mit Ihrem Attestierer über den gcloud-Befehl „binauthz“:
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 Zertifizierungsstellen noch einmal ausdrucken, sollte jetzt ein registrierter Schlüssel angezeigt werden:
gcloud container binauthz attestors list
Signierte Attestierung erstellen
An diesem Punkt haben Sie die Features konfiguriert, mit denen Sie Images signieren können. Verwenden Sie den zuvor erstellten Attestierer, um das Container-Image zu 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 mit gcloud Ihre Attestierung erstellen. Der Befehl verwendet einfach die Details des Schlüssels, 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 Bezug auf Container Analysis wird dadurch ein neuer Hinweis erstellt und an die Notiz des Attestierers angehängt. Sie können Ihre Attestierungen auflisten, um zu prüfen, ob 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-Signierung aktiviert und den Attestierer manuell 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 bestätigt 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. Dieser Schritt wird von Google bereitgestellt und umfasst Hilfsfunktionen zur Optimierung des Prozesses. Bevor Sie den Schritt verwenden, muss sein Code in einen Container eingebunden und per Push 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
Fügen Sie Ihrer Datei „cloudbuild.yaml“ einen Signierungsschritt hinzu.
In diesem Schritt fügen Sie Ihrer zuvor erstellten Cloud Build-Pipeline den Attestierungsschritt hinzu.
- Prüfen Sie den neuen Schritt, den Sie hinzufügen möchten.
Nur überprüfen. 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'
- Überschreiben Sie Ihre Datei „cloudbuild.yaml“ 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
Überprüfen Sie den Build im Cloud Build-Verlauf:
Öffnen Sie in der Cloud Console die Seite Cloud Build-Verlauf und prüfen Sie den letzten Build und die erfolgreiche Ausführung der Build-Schritte.
8. Richtlinien für die Zugangssteuerung
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 zum Ausführen eines Images ausgeführt, unabhängig davon, ob die Anfrage von einer vertrauenswürdigen CI/CD-Pipeline oder von jemandem stammt, der versucht, ein Image manuell bereitzustellen. So können Sie Ihre Laufzeitumgebungen effektiver schützen als mit CI/CD-Pipeline-Prüfungen allein.
Sie ändern hierfür die Standardrichtlinie für GKE, 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 zulassen“-Richtlinie
Prüfen Sie zuerst den Standardrichtlinienstatus und ob Sie ein beliebiges Image bereitstellen können.
- Vorhandene Richtlinie prüfen
gcloud container binauthz policy export
- Die Richtlinie zur Durchsetzung ist auf
ALWAYS_ALLOWfestgelegt.
evaluationMode: ALWAYS_ALLOW
- Beispiel bereitstellen, um zu prüfen, ob Sie etwas bereitstellen können
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
- Prüfen, ob die Bereitstellung funktioniert hat
kubectl get pods
Es wird die folgende Ausgabe angezeigt:

- Deployment löschen
kubectl delete pod hello-server
„Alle ablehnen“-Richtlinie
Aktualisieren Sie nun die Richtlinie, um keine Images zuzulassen.
- Aktuelle Richtlinie in eine bearbeitbare Datei exportieren
gcloud container binauthz policy export > policy.yaml
- Richtlinie ändern
Ändern Sie in einem Texteditor „evaluationMode“ 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
- Öffnen Sie das Terminal, wenden Sie die neue Richtlinie an und warten Sie einige Sekunden, bis die Änderung wirksam wird.
gcloud container binauthz policy import policy.yaml
- Beispielarbeitslast bereitstellen
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
- 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
Richtlinie auf „Alle zulassen“ zurücksetzen
Machen Sie die Richtlinienänderungen rückgängig, bevor Sie mit dem nächsten Abschnitt fortfahren.
- Richtlinie ändern
Ändern Sie in einem Texteditor „evaluationMode“ 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
- Zurückgesetzte 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, die die Images scannt und dann vor dem Signieren des Images und dem Bereitstellungsversuch auf Sicherheitslücken prüft. GKE verwendet die Binärautorisierung, um zu prüfen, ob das Image eine Signatur vom Scannen auf Sicherheitslücken hat, bevor das Image ausgeführt werden darf.

GKE-Richtlinie auf „require“-Attestierung aktualisieren
„require“-Images werden von Ihrem Attestor signiert, indem Sie Ihrer GKE BinAuth-Richtlinie „clusterAdmissionRules“ hinzufügen.
Überschreiben Sie die Richtlinie mit der aktualisierten Konfiguration, indem Sie den folgenden Befehl ausführen.
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 Sie, das nicht signierte Image bereitzustellen.
Erstellen Sie mit dem folgenden Befehl einen Bereitstellungsdeskriptor für die Anwendung, die Sie zuvor erstellt haben. Das hier verwendete Image ist das Image, das Sie zuvor erstellt haben und das kritische Sicherheitslücken enthält und KEINE signierte Attestierung.
GKE-Zulassungscontroller müssen das genaue Image kennen, das bereitgestellt werden soll, um die Signatur konsistent zu validieren. Dazu müssen Sie den Image-Digest anstelle eines einfachen Tags verwenden.
Image-Digest für das fehlerhafte Bild 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 Sie, die Anwendung in GKE bereitzustellen:
kubectl apply -f deploy.yaml
Sehen Sie sich die Arbeitslast in der Console an und notieren Sie sich den Fehler, der angibt, 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 das fehlerhafte Bild 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
Stellen Sie die Anwendung in GKE bereit:
kubectl apply -f deploy.yaml
Sehen Sie sich die Arbeitslast in der Console an und notieren Sie sich die erfolgreiche Bereitstellung des Images.
10. Glückwunsch!
Herzlichen Glückwunsch! Sie haben das Codelab abgeschlossen.
Behandelte Themen:
- Automatisches Scannen aktivieren
- On-Demand-Scans durchführen
- Scannen in eine Build-Pipeline einbinden
- Genehmigte Bilder signieren
- GKE-Zugangs-Controller zum Blockieren von Images verwenden
- GKE so konfigurieren, dass nur signierte, genehmigte Images zugelassen werden
Nächste Schritte:
- Bereitstellung von Images in Cloud Run und Google Kubernetes Engine schützen | Cloud Build-Dokumentation
- Kurzanleitung: Richtlinie zur Binärautorisierung mit GKE konfigurieren | Google Cloud
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.