Builds absichern

In diesem Dokument werden Best Practices zum Schutz Ihrer Builds beschrieben. Der Baucode kann sich auf verschiedene Arten von Vorgängen beziehen, z. B.:

  • Code optimieren oder verschleiern: Das Open-Source-Tool Closure Compiler von Google parst und analysiert beispielsweise JavaScript, entfernt toten Code, schreibt um und minimiert den verbleibenden Code. Außerdem wird der Code auf häufige JavaScript-Fehler geprüft.
  • Code in Zwischencode kompilieren: Sie können beispielsweise Java-Code in eine Java-Klassendatei (.class) oder C++-Code in eine Objektdatei (.obj) kompilieren.
  • Code kompilieren und verknüpfen, Bibliothek oder ausführbare Datei erstellen: Beispiel: Kompilieren von C++-Code in eine gemeinsam genutzte Bibliothek (.so) oder eine ausführbare Windows-Datei (.exe).
  • Code in einem verteilbaren oder bereitstellbaren Format packen: Beispiele hierfür sind das Erstellen von Java WAR-Dateien (.war) aus Java-Klassendateien, das Erstellen eines Docker-Images oder das Erstellen einer in Python erstellten Distribution (.whl).

Abhängig von der verwendeten Programmiersprache und der Umgebung, in der Sie die Bereitstellung durchführen, kann Ihr Build unterschiedliche Kombinationen dieser Vorgänge enthalten. Beispielsweise kann ein Build Python-Code in eine integrierte Distribution verpacken und in einen Artefaktspeicher wie Artifact Registry oder PyPI hochladen, sodass Sie ihn als Abhängigkeit in Cloud Functions verwenden können. Sie können auch den Python-Code in einen Container verlagern und das Container-Image in Cloud Run oder der Google Kubernetes Engine bereitstellen.

Bei den Praktiken in diesem Dokument geht es vorrangig um das Erstellen von Code für das Packen oder Bereitstellen in Laufzeitumgebungen, nicht um das Kompilieren von Code.

Automatisierte Builds verwenden

Ein automatisierter Build oder skriptbasierter Build definiert alle Build-Schritte im Build-Skript oder in der Build-Konfiguration, einschließlich der Schritte zum Abrufen des Quellcodes und der Schritte zum Erstellen des Codes. Der einzige manuelle Befehl, falls vorhanden, ist der Befehl zum Ausführen des Builds.

Ein Build-Skript kann beispielsweise so aussehen:

  • Eine Cloud Build-cloudbuild.yaml.
  • Ein Makefile, das Sie mit dem make-Tool ausführen.
  • Eine GitHub Actions-Workflowdatei im YAML-Format, die in Ihrem Verzeichnis .github/workflows/ gespeichert ist.

Automatisierte Builds sorgen für Konsistenz in den Build-Schritten. Es ist jedoch auch wichtig, Builds in einer konsistenten, vertrauenswürdigen Umgebung auszuführen.

Obwohl lokale Builds für das Debugging nützlich sein können, kann die Veröffentlichung von Software aus lokalen Builds viele Sicherheitsbedenken, Inkonsistenzen und Ineffizienzen in den Build-Prozess mit sich bringen.

  • Wenn Sie lokale Builds zulassen, können Angreifer mit böswilligen Absichten den Build-Prozess ändern.
  • Inkonsistenzen in der lokalen Entwicklungsumgebung und Entwicklerpraktiken erschweren es, Builds zu reproduzieren und Build-Probleme zu diagnostizieren.

Manuelle Builds machen den Prozess ineffizient, da mehr Infrastrukturressourcen wie Rechen-, Speicher- und Netzwerkressourcen genutzt werden. In den Anforderungen des SLSA-Frameworks sind automatisierte Builds eine Voraussetzung für SLSA-Level 1. Für SLSA-Level 2 ist die Verwendung eines Build-Dienstes anstelle von Entwicklerumgebungen für Builds eine Voraussetzung.

Cloud Build ist der verwaltete Build-Dienst in Google Cloud. Es verwendet eine Build-Konfigurationsdatei, um Build-Schritte für Cloud Build bereitzustellen. Sie können Builds konfigurieren, um Abhängigkeiten abzurufen, Einheitentests, statische Analysen und Integrationstests auszuführen und Artefakte mit Build-Tools wie Docker, Gradle, Maven, Go und Python zu erstellen. Cloud Build ist vollständig in andere CI/CD-Dienste in Google Cloud wie Artifact Registry und Cloud Deploy sowie in Laufzeitumgebungen wie GKE und Cloud Run eingebunden. Außerdem ist eine Einbindung in wichtige Quellcode-Verwaltungssysteme wie GitHub und Bitbucket möglich.

Build-Herkunft generieren

Die Build-Herkunft ist eine Sammlung von überprüfbaren Daten zu einem Build.

Herkunftsmetadaten umfassen Details wie die Digests der erstellten Images, die Speicherorte der Eingabequellen, die Build-Toolchain und die Build-Dauer.

Das Generieren der Build-Herkunft hilft Ihnen:

  • Prüfen, ob ein erstelltes Artefakt von einem vertrauenswürdigen Quellspeicherort und von einem vertrauenswürdigen Build-System erstellt wurde
  • Identifizieren Sie Code, der aus einem nicht vertrauenswürdigen Quellspeicherort oder Build-System eingeschleust wurde.

Sie können Benachrichtigungs- und Richtlinienmechanismen verwenden, um Build-Herkunftsdaten proaktiv zu verwenden. Sie können beispielsweise Richtlinien erstellen, die nur die Bereitstellung von Code zulassen, der aus verifizierten Quellen erstellt wurde.

Für SLSA-Level 1 muss die Build-Herkunft für die Nutzer der erstellten Artefakte verfügbar sein. Für SLSA-Level 2 müssen die Build-Herkunftsdaten außerdem:

  • Diese werden vom Build-Dienst generiert oder können direkt aus dem Build-Dienst gelesen werden.
  • Durch einen Verbraucher überprüfbar auf Authentizität und Integrität. Dies sollte mit einer digitalen Signatur geschehen, die von dem Dienst generiert wird, der die Build-Herkunftsdaten erstellt.

Für SLSA-Level 3 muss der Herkunftsinhalt außerdem Folgendes enthalten:

  • Der Einstiegspunkt der Build-Definition.
  • Alle Build-Parameter, die vom Nutzer gesteuert werden.

Cloud Build kann die Build-Herkunft für Container-Images generieren, die SLSA-Level 3-Build-Sicherheit bieten. Weitere Informationen finden Sie unter Build-Herkunft ansehen.

Sitzungsspezifische Build-Umgebung verwenden

Sitzungsspezifische Umgebungen sind temporäre Umgebungen, die für einen einzelnen Build-Aufruf beibehalten werden sollen. Nach dem Build wird die Umgebung geleert oder gelöscht. Sitzungsspezifische Builds sorgen dafür, dass der Build-Dienst und die Build-Schritte in einer sitzungsspezifischen Umgebung wie einem Container oder einer VM ausgeführt werden. Anstatt eine vorhandene Build-Umgebung wiederzuverwenden, stellt der Build-Dienst für jeden Build eine neue Umgebung bereit und löscht sie nach Abschluss des Build-Prozesses.

Sitzungsspezifische Umgebungen sorgen für saubere Builds, da keine Restdateien oder Umgebungseinstellungen aus früheren Builds vorhanden sind, die den Build-Prozess beeinträchtigen könnten. Eine nicht sitzungsspezifische Umgebung bietet Angreifern die Möglichkeit, schädliche Dateien und Inhalte einzuschleusen. Eine sitzungsspezifische Umgebung reduziert auch den Wartungsaufwand und reduziert Inkonsistenzen in der Build-Umgebung.

Mit Cloud Build wird für jeden Build eine neue VM-Umgebung eingerichtet und nach dem Build gelöscht.

Zugriff auf den Build-Dienst einschränken

Folgen Sie dem Sicherheitsprinzip der geringsten Berechtigung und gewähren Sie dem Build-Dienst und den Build-Ressourcen die minimal erforderlichen Berechtigungen. Sie sollten außerdem eine nicht-menschliche Identität verwenden, um Builds auszuführen und mit anderen Diensten im Namen des Builds zu interagieren.

Wenn Sie Cloud Build verwenden:

  • Gewähren Sie Mitgliedern Ihrer Organisation die erforderlichen Mindestberechtigungen.
  • Passen Sie die Berechtigungen für das Dienstkonto, das im Auftrag von Cloud Build agiert, so an, dass es nur die für Ihre Nutzung erforderlichen Berechtigungen hat. Bearbeiten Sie die Berechtigungen des standardmäßigen Cloud Build-Dienstkontos oder verwenden Sie stattdessen ein benutzerdefiniertes Dienstkonto.
  • Verwenden Sie die Organisationsrichtlinie Zulässige Integrationen von Cloud Build, um die externen Dienste zu steuern, die Build-Trigger aufrufen dürfen.
  • Platzieren Sie Cloud Build mithilfe von VPC Service Controls in einem Dienstperimeter. Der Perimeter ermöglicht die kostenlose Kommunikation zwischen Google Cloud-Diensten innerhalb des Perimeters, schränkt jedoch die Kommunikation innerhalb des Perimeters auf der Grundlage von Regeln ein, die Sie angeben. Außerdem verringert der Perimeter das Risiko der Daten-Exfiltration.

    Cloud Build unterstützt VPC Service Controls nur für Builds, die in einem privaten Pool ausgeführt werden.

Anmeldedaten schützen

Builds enthalten oft Verbindungen zu anderen Systemen wie Versionsverwaltung, Artefaktspeichern und Bereitstellungsumgebungen. Der Schutz von Anmeldedaten, die Sie in Ihren Builds verwenden, trägt dazu bei, unbefugten Zugriff auf Systeme in Ihrer Softwarelieferkette und Daten-Exfiltration zu verhindern.

Speichern Sie hartcodierte Anmeldedaten nicht direkt in der Versionsverwaltung oder in der Build-Konfiguration. Speichern Sie Anmeldedaten stattdessen in einem sicheren Schlüsselspeicher.

Secret Manager speichert API-Schlüssel, Passwörter und andere sensible Daten in Google Cloud sicher. Sie können Cloud Build für die Verwendung von in Secret Manager gespeicherten Secrets konfigurieren.

Abhängigkeiten verwalten

Die Integrität Ihrer Anwendungen hängt sowohl von der Integrität des von Ihnen entwickelten Codes als auch von den verwendeten Abhängigkeiten ab. Außerdem müssen Sie berücksichtigen, wo Sie die Abhängigkeiten veröffentlichen, wer Lese- und Schreibzugriff auf Ihre Artefakt-Repositories hat und welche Richtlinien für vertrauenswürdige Quellen von Build-Artefakten gelten, die Sie in Ihren Laufzeitumgebungen bereitstellen.

Weitere Informationen zum Abhängigkeitsmanagement finden Sie unter Abhängigkeiten verwalten.

In Cloud Build verwenden Sie Cloud-Builder, um Befehle auszuführen. Builder sind Container-Images, in denen häufig genutzte Sprachen und Tools installiert sind. Sie können öffentliche Container-Images aus öffentlichen Registries wie Docker Hub, von Cloud Build bereitgestellten Buildern, von der Community beigetragenen Buildern und benutzerdefinierten Buildern verwenden, die Sie erstellen. Sie können auch Buildpacks als Builder verwenden, einschließlich Buildpacks von Google Cloud.

Sehen Sie sich die Builder an, die Sie in Ihren Cloud Build-Builds verwenden, finden Sie heraus, von wem sie bereitgestellt werden, und entscheiden Sie, ob Sie ihnen in Ihrer Softwarelieferkette vertrauen. Wenn Sie mehr Kontrolle über den Code in einem Builder haben möchten, können Sie benutzerdefinierte Builder erstellen, anstatt Builder aus einer öffentlichen Quelle zu verwenden.

Änderungen am Build reduzieren

Es gibt eine Reihe anderer Faktoren, die einen Build beeinflussen können, darunter:

  • Builds, die gleichzeitig ausgeführt werden und sich gegenseitig beeinflussen können, oder Builds, die bestehen bleiben und sich auf einen nachfolgenden Build auswirken.
  • Builds, die andere Nutzerparameter als den Build-Einstiegspunkt und den Quellspeicherort der obersten Ebene akzeptieren.
  • Builds, die Abhängigkeiten mit Bereichen oder Abhängigkeiten angeben, die änderbar sind (z. B. Verwendung eines Images mit dem Tag latest). Diese Ansätze bergen das Risiko, dass Builds ungültige oder unerwünschte Versionen von Abhängigkeiten verwenden.

Die folgenden Praktiken helfen, diese Risiken zu mindern:

  • Führen Sie jeden Build in einer sitzungsspezifischen Umgebung aus.
  • Vermeiden Sie die Ausführung von Builds mit zusätzlichen Parametern, damit Nutzer die in den Build-Skripts definierten Variablen nicht beeinflussen können.
  • Beschränken Sie den Zugriff auf den Build-Dienst und die Build-Ressourcen.
  • Verweisen Sie auf unveränderliche Versionen von Abhängigkeiten statt auf Kennungen wie Tags, die in Zukunft auf eine andere Version des Artefakts verweisen können. Weitere Informationen zu Abhängigkeiten finden Sie unter Abhängigkeitsverwaltung.

Best Practices für Containererstellung

Unter Best Practices für das Erstellen von Containern erfahren Sie mehr über Möglichkeiten zum Erstellen von Container-Images, die zuverlässiger und weniger anfällig für Angriffe sind. Dazu gehören:

  • Paket für einzelne Anwendungen erstellen
  • Umgang mit Prozessen
  • Docker-Build-Cache optimieren
  • Unnötige Tools entfernen und Bilder so klein wie möglich halten
  • Scannen auf Sicherheitslücken mit der Artefaktanalyse. Sie können in Artifact Registry gespeicherte Images scannen oder sie vor dem Speichern lokal scannen.
  • Best Practices für das Tagging
  • Sicherheitsaspekte bei der Verwendung öffentlicher Images

Software Delivery Shield

Software Delivery Shield ist eine vollständig verwaltete End-to-End-Lösung für die Sicherheit der Softwarelieferkette. Es bietet einen umfassenden und modularen Satz von Funktionen und Tools für Google Cloud-Dienste, mit denen Entwickler, DevOps- und Sicherheitsteams den Sicherheitsstatus der Softwarelieferkette verbessern können. Sicherheitsinformationen für erstellte Anwendungen werden in der Cloud Build-UI in der Google Cloud Console angezeigt. Dazu zählen:

  • Die SLSA-Ebene, die die Reifestufe Ihrer Softwarelieferkette angibt.
  • Sicherheitslücken, Softwareliste (SBOM) und VEX-Anweisungen (Vulnerability Exploitability eXchange) für Build-Artefakte.
  • Build-Herkunft, eine Sammlung überprüfbarer Metadaten zu einem Build. Sie enthält Details wie die Digests der erstellten Images, die Speicherorte der Eingabequellen, die Build-Toolchain, Build-Schritte und die Build-Dauer.

Eine Anleitung zum Aufrufen von Sicherheitsstatistiken für erstellte Anwendungen finden Sie unter Anwendung erstellen und Sicherheitsinformationen ansehen.

Nächste Schritte