Container-Builds sichern

1. Einführung

ead1609267034bf7.png

Sicherheitslücken in Software sind Schwachstellen, die zu einem unbeabsichtigten Systemausfall führen oder böswilligen Akteuren die Möglichkeit geben können, Ihre Software zu manipulieren. Die Containeranalyse bietet zwei Arten von Betriebssystemscans, um Sicherheitslücken in Containern zu finden:

  • Mit der On-Demand Scanning API können Sie Container-Images manuell auf Betriebssystem-Sicherheitslücken scannen – entweder lokal auf Ihrem Computer oder remote in Container Registry oder Artifact Registry.
  • Mit der Container Scanning API können Sie die Erkennung von Sicherheitslücken im Betriebssystem automatisieren und jedes Mal einen Scan ausführen, wenn Sie ein Image in Container Registry oder Artifact Registry hochladen. Wenn Sie diese API aktivieren, werden auch Sprachpakete auf Go- und Java-Sicherheitslücken gescannt.

Mit der On-Demand Scanning API können Sie Images scannen, die lokal auf Ihrem Computer oder remote in Container Registry oder Artifact Registry gespeichert sind. So lässt sich genau steuern, welche Container auf Sicherheitslücken gescannt werden sollen. Mit On-Demand-Scans können Sie Images in Ihrer CI/CD-Pipeline scannen, bevor Sie entscheiden, ob Sie sie in einer Registry speichern möchten.

Lerninhalte

Aufgaben in diesem Lab:

  • Images mit Cloud Build erstellen
  • Artifact Registry für Container verwenden
  • Automatisches Scannen auf Sicherheitslücken verwenden
  • On-Demand-Scans konfigurieren
  • Image-Scans in CI/CD in Cloud Build hinzufügen

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. 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 Teilnehmer dieses Projekts. Er ist ein String, 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 unveränderlich. Sie kann also nicht geändert werden, nachdem sie festgelegt wurde. Die Cloud Console generiert automatisch einen eindeutigen String. In den meisten Codelabs müssen Sie auf die Projekt-ID verweisen (sie wird in der Regel als PROJECT_ID angegeben). Wenn Ihnen die generierte ID nicht gefällt, können Sie eine andere zufällige ID generieren. Alternativ können Sie eine eigene ID verwenden und prüfen, ob sie verfügbar ist. Sie kann nach diesem Schritt nicht mehr geändert werden und bleibt für die Dauer des Projekts bestehen.
  • Es gibt noch einen dritten Wert, die Projektnummer, die von einigen APIs verwendet wird. Weitere Informationen zu diesen drei Werten finden Sie in der Dokumentation.
  1. 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 nicht viel kosten, wenn überhaupt. Wenn Sie Ressourcen herunterfahren möchten, damit Ihnen nach dieser Anleitung keine Kosten in Rechnung gestellt werden, können Sie die erstellten Ressourcen oder das gesamte Projekt löschen. Neue Google Cloud-Nutzer können am kostenlosen Testprogramm im Wert von 300$ teilnehmen.

Umgebung einrichten

Legen Sie in Cloud Shell Ihre Projekt-ID und die Projektnummer für Ihr Projekt fest. Speichern Sie sie als Variablen PROJECT_ID und `PROJECT_NUMBER`.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 

3. Images mit Cloud Build erstellen

In diesem Abschnitt erstellen Sie eine automatisierte Build-Pipeline, mit der Ihr Container-Image erstellt, gescannt und die Ergebnisse ausgewertet werden. 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"

Arbeitsverzeichnis erstellen und wechseln

mkdir vuln-scan && cd vuln-scan

Beispiel-Image 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

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: ['-']


EOF

CI-Pipeline ausführen

Build zur Verarbeitung senden

gcloud builds submit

Build-Details prüfen

Nachdem der Build-Prozess gestartet wurde, können Sie den Fortschritt im Cloud Build-Dashboard prüfen.

  1. Öffnen Sie Cloud Build in der Cloud Console.
  2. Klicken Sie auf den Build, um den Inhalt aufzurufen.

4. Artifact Registry für Container

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

Cloud Build-Pipeline aktualisieren

Ändern Sie Ihre Build-Pipeline so, dass das resultierende Image per Push zu Artifact Registry übertragen wird.

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: ['-']

# push 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']

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

CI-Pipeline ausführen

Build zur Verarbeitung senden

gcloud builds submit

5. Automatisches Scannen auf Sicherheitslücken

Das Artefaktscannen wird jedes Mal automatisch ausgelöst, wenn Sie ein neues Image per Push zu Artifact Registry oder Container Registry übertragen. Die Informationen zu Sicherheitslücken werden kontinuierlich aktualisiert, wenn neue Sicherheitslücken entdeckt werden. In diesem Abschnitt sehen Sie sich das Image an, das Sie gerade erstellt und in die Artifact Registry übertragen haben, und untersuchen die Ergebnisse zu den Sicherheitslücken.

Image-Details prüfen

Nach Abschluss des vorherigen Build-Prozesses können Sie sich das Image und die Ergebnisse zu den Sicherheitslücken im Artifact Registry-Dashboard ansehen.

  1. Öffnen Sie Artifact Registry in der Cloud Console.
  2. Klicken Sie auf „artifact-scanning-repo“, um den Inhalt aufzurufen.
  3. Klicken Sie auf die Image-Details.
  4. Klicken Sie auf den neuesten Digest Ihres Images.
  5. 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.

361be7b3bf293fca.png

Das automatische Scannen ist standardmäßig aktiviert. In den Artifact Registry-Einstellungen können Sie das automatische Scannen deaktivieren oder aktivieren.

6. On-Demand-Scans

Es gibt verschiedene Szenarien, in denen Sie einen Scan durchführen müssen, bevor Sie das Image in ein Repository übertragen. Ein Containerentwickler kann beispielsweise ein Image scannen und die Probleme beheben, bevor er Code in die Quellcodeverwaltung überträgt. 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 .

Image 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 prüfen

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.

Kritische 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

7. Scannen in CI/CD mit Cloud Build

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 aktualisieren

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 gerade gesendete Build schlägt fehl, weil das Image CRITICAL-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 funktionierenden Image 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

Build-Erfolg prüfen

Der gerade gesendete Build ist erfolgreich, weil das aktualisierte Image keine CRITICAL-Sicherheitslücken enthält.

Sehen Sie sich den Build-Erfolg auf der Seite „Cloud Build-Verlauf“ an.

Scanergebnisse prüfen

Prüfen Sie das funktionierende Image in Artifact Registry.

  1. Öffnen Sie Artifact Registry in der Cloud Console.
  2. Klicken Sie auf „artifact-scanning-repo“, um den Inhalt aufzurufen.
  3. Klicken Sie auf die Image-Details.
  4. Klicken Sie auf den neuesten Digest Ihres Images.
  5. Klicken Sie für das Image auf den Tab „Sicherheitslücken“.

8. Glückwunsch!

Sie haben das Codelab abgeschlossen.

Behandelte Themen:

  • Images mit Cloud Build erstellen
  • Artifact Registry für Container
  • Automatisches Scannen auf Sicherheitslücken
  • On-Demand-Scans
  • Scannen in CI/CD mit Cloud Build

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.

Letzte Aktualisierung: 21.03.2023