1. Einführung
Container Analysis bietet Scannen auf Sicherheitslücken und Metadatenspeicher 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 dem Metadatenspeicher 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 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.
Aufgaben in diesem Lab
- Automatisches Scannen aktivieren
- On-Demand-Scanning 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
Einrichten der Umgebung im eigenen Tempo
- 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 ein Konto erstellen.
- Der Projektname ist der Anzeigename für die Teilnehmer dieses Projekts. Es ist ein Zeichenstring, der von Google APIs nicht verwendet wird. Sie können ihn jederzeit aktualisieren.
- Die Projekt-ID ist für alle Google Cloud-Projekte eindeutig und kann nach der Festlegung nicht mehr geändert werden. In der Cloud Console wird automatisch ein eindeutiger String generiert. Normalerweise spielt es keine Rolle, wie er lautet. In den meisten Codelabs müssen Sie auf die Projekt-ID verweisen (normalerweise als
PROJECT_ID
gekennzeichnet). Wenn Ihnen die generierte ID nicht gefällt, können Sie eine andere zufällige generieren. Alternativ können Sie Ihr eigenes Gerät testen, um zu 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 finden Sie in der Dokumentation.
- Als Nächstes müssen Sie die Abrechnung in der Cloud Console aktivieren, um Cloud-Ressourcen/-APIs verwenden zu können. Die Ausführung dieses Codelabs sollte nur wenige Kosten verursachen, wenn überhaupt. Wenn Sie die Ressourcen deaktivieren möchten, damit keine Kosten über diese Anleitung hinaus anfallen, können Sie die von Ihnen erstellten Ressourcen oder das gesamte Projekt löschen. Neuen Nutzern der Google Cloud Platform steht das kostenlose Testprogramm mit einem Guthaben von 300$ zur Verfügung.
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:
- Rufen Sie Ihr Google-Projekt unter https://console.cloud.google.com auf.
- Klicken Sie oben rechts auf das Cloud Shell-Editorsymbol.
- Unten im Fenster wird ein neuer Bereich geöffnet.
Umgebung einrichten
Legen Sie in Cloud Shell eine Projekt-ID und Projektnummer für Ihr Projekt fest. Speichern Sie sie als Variablen vom Typ 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 Bilder. 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 beim Zugriff auf Artifact Registry Ihre gcloud-Anmeldedaten verwendet werden.
gcloud auth configure-docker us-central1-docker.pkg.dev
3. Automatische Suche
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 in die Artifact Registry und sehen sich die Ergebnisse an.
Arbeitsverzeichnis erstellen und in dieses wechseln
mkdir vuln-scan && cd vuln-scan
Beispielbild definieren
Erstellen Sie eine Datei mit dem Namen Dockerfile und 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 mit dem Namen „main.py“ und 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 per Push in AR übertragen
Mit Cloud Build können Sie Ihren Container erstellen und automatisch in die Artifact Registry übertragen. Beachten Sie das Tag bad
im Bild. So können Sie ihn bei den nächsten Schritten leichter wiederfinden.
gcloud builds submit . -t us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:bad
Bilddetails ansehen
Prüfen Sie nach Abschluss des Build-Prozesses das Image und die Ergebnisse der Sicherheitslücken im Artifact Registry-Dashboard.
- Öffnen Sie Artifact Registry in der Cloud Console.
- Klicken Sie auf das Repository „artifact-scanning“, um den Inhalt aufzurufen.
- Klicken Sie auf die Bilddetails.
- Klicken Sie auf den neuesten Digest Ihres Bildes.
- Klicken Sie nach Abschluss des Scans auf den Tab „Sicherheitslücken“ für das Bild.
Auf dem Tab „Sicherheitslücken“ sehen Sie die Ergebnisse des automatischen Scans für das gerade erstellte Image.
Die automatische Suche 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 möglicherweise einen Scan ausführen müssen, bevor Sie das Image in ein Repository pushen. Ein Containerentwickler kann beispielsweise ein Image scannen und die Probleme beheben, bevor er Code in die Versionskontrolle pusht. Im folgenden Beispiel erstellen und analysieren Sie das Bild lokal, bevor Sie die Ergebnisse verwenden.
Image erstellen
In diesem Schritt erstellen Sie das Image mit lokalem Docker in Ihrem lokalen Cache.
docker build -t us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image .
Bild scannen
Sobald das Bild erstellt wurde, können Sie einen Scan des Bildes anfordern. Die Ergebnisse der Suche werden auf einem Metadatenserver gespeichert. Der Job wird mit einem 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 überprüfen
Sehen Sie sich die Ausgabe des vorherigen Schritts an, die in der Datei „scan_id.txt“ gespeichert wurde. Notieren Sie sich den Speicherort der Scanergebnisse im Metadatenserver.
cat scan_id.txt
Detaillierte Scanergebnisse prüfen
Wenn Sie die tatsächlichen Ergebnisse des Scans sehen möchten, verwenden Sie den Befehl list-vulnerabilities
an dem 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 selten direkt von Menschen verwendet. In der Regel werden die Ergebnisse von einem automatisierten Prozess verwendet. Mit den folgenden Befehlen können Sie die Berichtsdetails lesen und 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 sieht so aus:
Failed vulnerability check for CRITICAL level
5. Build-Pipeline-Scan
In diesem Abschnitt erstellen Sie eine automatisierte Build-Pipeline, mit der Ihr Container-Image erstellt, gescannt und die Ergebnisse ausgewertet werden. Wenn keine KRITISCHEN Sicherheitslücken gefunden werden, wird das Image in das Repository gepusht. 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 mit den folgenden Befehlen Zugriff.
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 im Verzeichnis eine cloudbuild.yaml-Datei 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 angeben.
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 abgebrochen wird, wenn eine Sicherheitslücke mit dem Schweregrad „KRITISCH“ gefunden wird.
gcloud builds submit
Build-Fehler prüfen
Der Build, den Sie gerade eingereicht haben, schlägt fehl, da das Image KRITISCH wichtige Sicherheitslücken enthält.
Prüfen Sie den Buildfehler auf der Seite Cloud Build-Verlauf.
Sicherheitslücke schließen
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 korrekten Bild ausführen
Reichen Sie den Build zur Verarbeitung ein, um zu prüfen, ob der Build erfolgreich ist, wenn keine Sicherheitslücken der KRITISCHEN Schwere gefunden werden.
gcloud builds submit
Erfolgreichen Build prüfen
Der Build, den Sie gerade eingereicht haben, wird erfolgreich sein, da das aktualisierte Image keine KRITISCHEN Sicherheitslücken enthält.
Erfolg des Builds auf der Seite Cloud Build-Verlauf prüfen
Scanergebnisse prüfen
Korrekte Bilddatei in Artifact Registry prüfen
- Öffnen Sie Artifact Registry in der Cloud Console.
- Klicken Sie auf das Repository „artifact-scanning“, um den Inhalt aufzurufen.
- Klicken Sie auf die Bilddetails.
- Klicken Sie auf den neuesten Digest Ihres Bildes.
- Klicken Sie für das Image auf den Tab „Sicherheitslücken“.
6. Bilder signieren
Attestierernotiz erstellen
Ein Attestator-Hinweis ist einfach ein kleines Datenelement, das als Label für die Art der angewendeten Unterschrift dient. Eine Notiz kann beispielsweise auf einen Sicherheitslückenscan hinweisen, während eine andere für die QA-Abnahme verwendet wird. Auf die Notiz wird während des Signaturvorgangs verwiesen.
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}"
Hinweis 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 die eigentliche Bildsignatur verwendet und hängen dem Bild zur späteren Überprüfung ein Vorkommen der Notiz an. Erstellen Sie den Attestierer für die spätere 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 bestätigen
gcloud container binauthz attestors list
In der letzten Zeile wird NUM_PUBLIC_KEYS: 0
angegeben, dass Sie die Schlüssel in einem späteren Schritt angeben.
Beachten Sie auch, 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 Attester 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 für die Binary Authorization benötigt Berechtigungen zum Ansehen der Attestationsnotizen. 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
IAM-Richtlinie mit der Datei 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 Attestator 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, 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 Aufbewahren mehrerer Schlüssel erstellen
gcloud kms keyrings create "${KEYRING}" --location="${KEY_LOCATION}"
Neues asymmetrisches Schlüsselpaar für den Attestator 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 jetzt auf der KMS-Seite der Google Cloud Console angezeigt werden.
Verknüpfen Sie den Schlüssel nun über den Befehl „gcloud binauthz“ mit Ihrem Attestator:
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 registrierter Schlüssel angezeigt werden:
gcloud container binauthz attestors list
Signierte Attestierung erstellen
Sie haben jetzt die Funktionen konfiguriert, mit denen Sie Bilder 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)')
Sie können jetzt mit gcloud eine Attestierung erstellen. Der Befehl nimmt einfach die Details des Schlüssels auf, 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 dadurch ein neues Vorkommen erstellt und an den Hinweis des Attestators angehängt. Sie können Ihre Attestationen auflisten, um sicherzustellen, dass alles wie erwartet funktioniert.
gcloud container binauthz attestations list \
--attestor=$ATTESTOR_ID --attestor-project=${PROJECT_ID}
7. Mit Cloud Build signieren
Sie haben die Bildsignatur aktiviert und Ihr Beispielbild manuell mit dem Attestor signiert. In der Praxis sollten Sie Attestationen 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 stellt diesen Schritt „Benutzerdefiniertes Build“ bereit, der Hilfsfunktionen zur Optimierung des Prozesses enthält. 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
Signaturschritt zur Datei „cloudbuild.yaml“ hinzufügen
In diesem Schritt fügen Sie den Attestierungsschritt Ihrer zuvor erstellten Cloud Build-Pipeline hinzu.
- Sehen Sie sich den neuen Schritt an, den Sie hinzufügen möchten.
Nur Rezensionen. 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 die 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
Build im Cloud Build-Verlauf prüfen
Ö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 Zulassungskontrolle
Die Binärautorisierung ist eine Funktion in GKE und Cloud Run, mit der 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, sei es von einer vertrauenswürdigen CI/CD-Pipeline oder von einem Nutzer, der versucht, ein Image manuell bereitzustellen. So können Sie Ihre Laufzeitumgebungen effektiver schützen als nur mit CI/CD-Pipeline-Prüfungen.
Um diese Funktion zu verstehen, ändern Sie die Standard-GKE-Richtlinie, um eine strenge Autorisierungsregel durchzusetzen.
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"
Richtlinie „Alle zulassen“
Prüfen Sie zuerst den Status der Standardrichtlinie und ob Sie ein Image bereitstellen können.
- Vorhandene Richtlinie prüfen
gcloud container binauthz policy export
- Die Durchsetzungsrichtlinie ist auf
ALWAYS_ALLOW
festgelegt.
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
Die folgende Ausgabe wird angezeigt:
- Deployment löschen
kubectl delete pod hello-server
Richtlinie „Alle ablehnen“
Aktualisieren Sie nun die Richtlinie, um alle Images zu verbieten.
- Aktuelle Richtlinie in eine bearbeitbare Datei exportieren
gcloud container binauthz policy export > policy.yaml
- Richtlinie ändern
Ändern Sie in einem Texteditor den Wert „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 übernommen wurde.
gcloud container binauthz policy import policy.yaml
- Beispielbereitstellung einer Arbeitslast versuchen
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 zurücksetzen, um alle zuzulassen
Bevor Sie mit dem nächsten Abschnitt fortfahren, müssen Sie die Richtlinienänderungen rückgängig machen.
- Richtlinie ändern
Ändern Sie in einem Texteditor den Wert für „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, was Sie bisher gelernt haben, indem Sie eine CI/CD-Pipeline mit Cloud Build implementieren, die die Images scannt und dann auf Sicherheitslücken prüft, bevor das Image signiert und bereitgestellt wird. GKE prüft mit der Binärautorisierung, ob das Image eine Signatur aus dem Scannen auf Sicherheitslücken hat, bevor es ausgeführt wird.
GKE-Richtlinie so aktualisieren, dass eine Attestierung erforderlich ist
Erforderlichen Sie, dass Images von Ihrem Attestor signiert werden, indem Sie Ihrer GKE-BinAuth-Richtlinie clusterAdmissionRules hinzufügen.
Überschreiben Sie die Richtlinie mit der aktualisierten Konfiguration mit dem folgenden Befehl.
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
Versuch, das nicht signierte Image bereitzustellen
Erstellen Sie mit dem folgenden Befehl einen Bereitstellungs-Descriptor für die zuvor erstellte Anwendung. Das hier verwendete Image ist das Image, das Sie zuvor erstellt haben und das kritische Sicherheitslücken enthält, aber KEINE signierte Attestierung.
GKE-Zulassungscontroller müssen das genaue Image kennen, das bereitgestellt werden soll, um die Signatur einheitlich zu validieren. Dazu müssen Sie den Bild-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, die App 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
Anwendung in GKE bereitstellen
kubectl apply -f deploy.yaml
Sehen Sie sich die Arbeitslast in der Console an und prüfen Sie, ob das Image erfolgreich bereitgestellt wurde.
10. Glückwunsch!
Herzlichen Glückwunsch, Sie haben das Codelab abgeschlossen.
Behandelte Themen:
- Automatisches Scannen aktivieren
- On-Demand-Scanning 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 sichern | 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.