Gating von Deployments mit Binary Auth

1. Einführung

Mit der Binärautorisierung wird die Sicherheit beim Deployment überprüft. So können Sie dafür sorgen, dass nur vertrauenswürdige Container-Images in der Google Kubernetes Engine (GKE) oder Cloud Run bereitgestellt werden. Sie können dabei festlegen, dass die Images während des Entwicklungsprozesses von vertrauenswürdigen Stellen signiert werden, und dann beim Deployment die Signaturprüfung erzwingen. Damit haben Sie eine stärkere Kontrolle über die Containerumgebung und sorgen dafür, dass nur verifizierte Images in den Build- und Release-Prozess eingebunden werden.

Das folgende Diagramm zeigt die Komponenten einer Binärautorisierung/Cloud Build-Einrichtung:

Binärautorisierungs/Cloud Build-Attestierungspipeline**Abbildung 1.**Cloud Build-Pipeline, die eine Attestierung für die Binärautorisierung erstellt.

In dieser Pipeline gilt:

  1. Code zum Erstellen des Container-Images wird an ein Quell-Repository wie Cloud Source Repositories übertragen.
  2. Cloud Build ist ein Tool für Continuous Integration (CI), erstellt und testet den Container.
  3. Der Build überträgt das Container-Image per Push in Container Registry oder eine andere Registry, in der die erstellten Images gespeichert sind.
  4. Der Cloud Key Management Service bietet eine Schlüsselverwaltung für das kryptografische Schlüsselpaar und signiert das Container-Image. Die resultierende Signatur wird dann in einer neu erstellten Attestierung gespeichert.
  5. Zum Zeitpunkt der Bereitstellung überprüft der Attestierer die Attestierung mithilfe des öffentlichen Schlüssels aus dem Schlüsselpaar. Die Binärautorisierung erzwingt die Richtlinie, indem zum Bereitstellen des Container-Images signierte Attestierungen erforderlich sind.

In diesem Lab konzentrieren Sie sich auf die Tools und Techniken zum Schutz bereitgestellter Artefakte. In diesem Lab geht es um Artefakte (Container), die erstellt, aber nicht in einer bestimmten Umgebung bereitgestellt wurden.

Aufgaben in diesem Lab

  • Bildsignatur
  • Zugangskontrollrichtlinien
  • Gescannte Bilder signieren
  • Signierte Bilder autorisieren
  • Blockierte Images ohne Signatur

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.

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

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

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.

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

3. Bildsignatur

Was ist ein Attestierer?

Attestierer

  • Diese Person bzw. dieser Prozess ist für ein Glied in der Vertrauenskette des Systems verantwortlich.
  • Sie haben einen kryptografischen Schlüssel und signieren ein Bild, wenn es den Genehmigungsprozess besteht.
  • Der Policy Creator legt die Richtlinien auf übergeordneter und abstrakter Weise fest. Der Attestierer ist jedoch dafür verantwortlich, einen Aspekt der Richtlinie konkret durchzusetzen.
  • Dabei kann es sich um eine echte Person wie ein QA-Tester oder einen Manager oder um einen Bot in einem CI-System handeln.
  • Die Sicherheit des Systems hängt von seiner Vertrauenswürdigkeit ab. Daher ist es wichtig, dass die privaten Schlüssel sicher aufbewahrt werden.

Jede dieser Rollen kann eine einzelne Person oder ein Team von Personen in Ihrer Organisation repräsentieren. In einer Produktionsumgebung werden diese Rollen wahrscheinlich von separaten Google Cloud Platform-Projekten (GCP) verwaltet und der Zugriff auf Ressourcen wird eingeschränkt über Cloud IAM zwischen ihnen geteilt.

a37eb2ed54b9c2eb.png

Attestierer in der Binärautorisierung werden zusätzlich zur Cloud Container Analysis API implementiert. Daher ist es wichtig zu beschreiben, wie das funktioniert, bevor Sie fortfahren. Mit der Container Analysis API können Sie Metadaten bestimmten Container-Images zuordnen.

Beispielsweise kann eine Notiz erstellt werden, um die Sicherheitslücke Herzblutend zu verfolgen. Sicherheitsanbieter erstellten dann Scanner, um Container-Images auf die Sicherheitslücke zu testen, und erstellten ein Vorkommen, das jedem manipulierten Container zugeordnet ist.

208aa5ebc53ff2b3.png

Container Analysis wurde zusammen mit dem Tracking von Sicherheitslücken als generische Metadaten-API entwickelt. Bei der Binärautorisierung werden mithilfe von Container Analysis Signaturen den zu überprüfenden Container-Images zugeordnet.** Ein Container Analysis-Hinweis wird für einen einzelnen Attestierer verwendet. Vorkommen werden erstellt und mit jedem Container verknüpft, der vom Attestierer genehmigt wurde.

Die Binary Authorization API verwendet das Konzept der „Attestierer“ und "Attestierungen". Diese werden jedoch mit entsprechenden Hinweisen und Vorkommen in der Container Analysis API implementiert.

63a701bd0057ea17.png

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.

919f997db0ffb881.png

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

Ihre Notiz wird jetzt in der Container Analysis API gespeichert.

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. Damit Sie den Attestierer verwenden können, müssen Sie den Hinweis auch bei der Binärautorisierung registrieren:

ed05d438c79b654d.png

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

1e3af7c177f7a311.png

Bevor Sie diesen Attestierer verwenden können, muss Ihre Behörde ein kryptografisches Schlüsselpaar erstellen, mit dem Container-Images signiert werden können. Dies kann über den Google Cloud Key Management Service (KMS) erfolgen.

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. Verwenden Sie den zuvor erstellten Attestierer, um das Container-Image zu signieren, mit dem Sie gearbeitet haben.

858d7e6feeb6f159.png

Eine Attestierung muss eine kryptografische Signatur enthalten, die angibt, dass der Attestierer ein bestimmtes Container-Image verifiziert hat und sicher auf Ihrem Cluster ausgeführt werden kann. Um anzugeben, welches Container-Image attestiert werden soll, müssen Sie den zugehörigen Digest ermitteln.

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}

4. 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 mit aktivierter Binärautorisierung:

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

Diese Richtlinie ist relativ einfach. In der Zeile globalPolicyEvaluationMode wird deklariert, dass diese Richtlinie die von Google definierte globale Richtlinie erweitert. Dadurch können alle offiziellen GKE-Container standardmäßig ausgeführt werden. Außerdem deklariert die Richtlinie eine defaultAdmissionRule, die angibt, dass alle anderen Pods abgelehnt werden. Die Zulassungsregel enthält die Zeile enforcementMode, die angibt, dass alle Pods, die nicht dieser Regel entsprechen, für den Cluster blockiert werden sollen.

Eine Anleitung zum Erstellen komplexerer Richtlinien finden Sie in der Dokumentation zur Binärautorisierung.

657752497e59378c.png

  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

5. Gescannte Bilder 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

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"

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 Cloud Build-Pipeline den Attestierungsschritt hinzu.

  1. Lies dir den folgenden Schritt zur Signatur durch.

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. Schreiben Sie eine cloudbuild.yaml-Datei mit der vollständigen Pipeline unten.
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.

6. Signierte Bilder autorisieren

In diesem Abschnitt aktualisieren Sie die GKE so, dass mit der Binärautorisierung geprüft wird, 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.

Derzeit wird in Ihrem Cluster eine Richtlinie mit einer Regel ausgeführt: Container aus offiziellen Repositories zulassen und alle anderen ablehnen.

Ü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

Auf dem Laufwerk sollte jetzt eine neue Datei mit dem Namen " updated_policy.yaml" vorhanden sein. Anstatt jetzt alle Images abzulehnen, prüft die Standardregel zuerst Ihren Attestierer auf Überprüfungen.

822240fc0b02408e.png

Laden Sie die neue Richtlinie in die Binärautorisierung hoch:

gcloud beta container binauthz policy import binauth_policy.yaml

Signiertes Image bereitstellen

Image-Digest für das gute 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.

7. Blockierte Images ohne Signatur

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:bad .

Unsigniertes Image in das Repository übertragen

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

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

8. Glückwunsch!

Glückwunsch, du hast das Codelab abgeschlossen.

Behandelte Themen:

  • Bildsignatur
  • Zugangskontrollrichtlinien
  • Gescannte Bilder signieren
  • Signierte Bilder autorisieren
  • Blockierte Images ohne Signatur

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