Gating von Deployments mit Binary Auth

1. Einführung

Mit der Binärautorisierung wird die Sicherheit beim Deployment überprüft. So werden nur vertrauenswürdige Container-Images in der Google Kubernetes Engine (GKE) oder Cloud Run bereitgestellt. 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 in einer Einrichtung mit Binärautorisierung/Cloud Build:

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

In dieser Pipeline gilt:

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

In diesem Lab geht es um die Tools und Techniken, mit denen Sie bereitgestellte Artefakte schützen können. In diesem Lab geht es um Artefakte (Container), nachdem sie erstellt, aber noch nicht in einer bestimmten Umgebung bereitgestellt wurden.

Lerninhalte

  • Image signieren
  • Richtlinien für die Zugangssteuerung
  • Gescannte Images signieren
  • Signierte Images autorisieren
  • Blockierte unsignierte Images

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. 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_ID angegeben). 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
  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 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.

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

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

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

3. Image signieren

Was ist ein Attestierer?

Attestierer

  • Diese Person oder dieser Prozess ist für ein Glied in der Vertrauenskette des Systems verantwortlich.
  • Während des Genehmigungsprozesses wird ein Image mit einem kryptografischen Schlüssel signiert.
  • Während der Ersteller die Richtlinie auf einer abstrakten Ebene festlegt, ist der Attestor für die konkrete Durchsetzung eines Aspekts der Richtlinie verantwortlich.
  • Das kann eine echte Person wie ein QA-Tester oder ein Manager oder ein Bot in einem CI-System sein.
  • Die Sicherheit des Systems hängt von ihrer Vertrauenswürdigkeit ab. Daher ist es wichtig, dass ihre privaten Schlüssel sicher aufbewahrt werden.

Jede dieser Rollen kann eine einzelne Person oder ein Team in Ihrer Organisation darstellen. In einer Produktionsumgebung werden diese Rollen wahrscheinlich von separaten Google Cloud Platform-Projekten (GCP) verwaltet und der Zugriff auf Ressourcen wird mithilfe von Cloud IAM jeweils nur eingeschränkt freigegeben.

a37eb2ed54b9c2eb.png

Attestoren in Binärautorisierung werden zusätzlich zur Cloud Container Analysis API implementiert. Daher ist es wichtig, die Funktionsweise zu beschreiben, bevor Sie fortfahren. Die Container Analysis API wurde entwickelt, damit Sie Metadaten bestimmten Container-Images zuordnen können.

Beispielsweise könnte eine Notiz erstellt werden, um die Heartbleed-Sicherheitslücke zu verfolgen. Sicherheitsanbieter erstellen dann Scanner, um Container-Images auf die Sicherheitslücke zu testen, und erstellen für jeden kompromittierten Container einen Hinweis.

208aa5ebc53ff2b3.png

Container Analysis wurde nicht nur für das Erfassen von Sicherheitslücken, sondern auch als generische Metadata API entwickelt. Die Binärautorisierung verwendet Container Analysis, um Signaturen den Container-Images zuzuordnen, die sie prüfen**.** Eine Container Analysis-Notiz wird verwendet, um einen einzelnen Attestierer darzustellen. Hinweise werden erstellt und jedem Container zugeordnet, den der Attestierer genehmigt hat.

In der Binary Authorization API werden die Konzepte „Attestierer“ und „Attestierungen“ verwendet. Diese werden jedoch mithilfe der entsprechenden Notizen und Hinweise in der Container Analysis API implementiert.

63a701bd0057ea17.png

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.

919f997db0ffb881.png

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

Ihr Hinweis wird jetzt in der Container Analysis API gespeichert.

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. Damit Sie Ihren 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}

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

1e3af7c177f7a311.png

Bevor Sie diesen Attestierer verwenden können, muss Ihre Zertifizierungsstelle 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 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.

858d7e6feeb6f159.png

Eine Attestierung muss eine kryptografische Signatur enthalten, um anzugeben, dass der Attestierer ein bestimmtes Container-Image überprüft hat und es sicher ist, es in Ihrem Cluster auszuführen. Wenn Sie angeben möchten, welches Container-Image bestätigt werden soll, müssen Sie den 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 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}

4. 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 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 zulassen“-Richtlinie

Prüfen Sie zuerst den Standardrichtlinienstatus und ob Sie ein beliebiges Image bereitstellen können.

  1. Vorhandene Richtlinie prüfen
gcloud container binauthz policy export
  1. Die Richtlinie zur Durchsetzung ist auf ALWAYS_ALLOW festgelegt.

evaluationMode: ALWAYS_ALLOW

  1. 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
  1. Prüfen, ob die Bereitstellung funktioniert hat
kubectl get pods

Es wird die folgende Ausgabe angezeigt:

161db370d99ffb13.png

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

„Alle ablehnen“-Richtlinie

Aktualisieren Sie nun die Richtlinie, um keine Images zuzulassen.

  1. Aktuelle Richtlinie in eine bearbeitbare Datei exportieren
gcloud container binauthz policy export  > policy.yaml
  1. 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

Diese Richtlinie ist relativ einfach. Die Zeile globalPolicyEvaluationMode 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 wird in der Richtlinie eine defaultAdmissionRule deklariert, 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, nicht im Cluster ausgeführt werden dürfen.

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 und warten Sie einige Sekunden, bis die Änderung wirksam wird.
gcloud container binauthz policy import policy.yaml
  1. Beispielarbeitslast bereitstellen
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

Richtlinie auf „Alle zulassen“ zurücksetzen

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

  1. 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
  1. Zurückgesetzte Richtlinie anwenden
gcloud container binauthz policy import policy.yaml

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

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"

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

  1. Sehen Sie sich den Signierungsschritt unten an.

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

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

6. Signierte Images autorisieren

In diesem Abschnitt aktualisieren Sie GKE, um mit der Binärautorisierung zu prüfen, ob das Image eine Signatur vom Scannen auf Sicherheitslücken hat, bevor das Image ausgeführt werden darf.

d5c41bb89e22fd61.png

GKE-Richtlinie auf „require“-Attestierung aktualisieren

„require“-Images werden von Ihrem Attestor signiert, indem Sie Ihrer GKE BinAuth-Richtlinie „clusterAdmissionRules“ hinzufügen.

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

Sie sollten jetzt die neue Datei „updated_policy.yaml“ auf dem Laufwerk haben. Anstatt alle Images standardmäßig abzulehnen, wird jetzt zuerst Ihr Attestierer auf Bestätigungen geprüft.

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

7. Blockierte unsignierte Images

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

Nicht signiertes Image per Push in das Repository übertragen

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

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

8. Glückwunsch!

Herzlichen Glückwunsch! Sie haben das Codelab abgeschlossen.

Behandelte Themen:

  • Image signieren
  • Richtlinien für die Zugangssteuerung
  • Gescannte Images signieren
  • Signierte Images autorisieren
  • Blockierte unsignierte Images

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