Abhängigkeitsmanagement

Dieses Dokument beschreibt Anwendungsabhängigkeiten und Best Practices für deren Verwaltung, einschließlich Monitoring der Sicherheitslücken, Artefaktüberprüfung und Schritten zur Reduzierung der Abhängigkeitsbilanz und zur Unterstützung reproduzierbarer Builds.

Anwendungsabhängigkeiten sind für die Erstellung oder Ausführung einer Anwendung erforderliche Technologien. Beispiele für Softwareabhängigkeiten sind Betriebssysteme, Softwarebibliotheken, Plug-ins, Datenbanken oder Plattformen.

Abhängigkeiten können sowohl von Ihnen erstellte Komponenten als auch von Drittanbieter-Software enthalten. Der Ansatz, mit dem Sie Abhängigkeiten verwalten, kann die Sicherheit und Zuverlässigkeit Ihrer Anwendungen beeinträchtigen.

Die Details zur Implementierung von Best Practices können je nach Artefaktformat und verwendeten Tools variieren. Die allgemeinen Grundsätze gelten jedoch weiterhin.

Ansätze zum Einbinden von Abhängigkeiten

Es gibt mehrere gängige Methoden zum Einbinden von Abhängigkeiten in Ihre Anwendung:

Direkt aus öffentlichen Quellen installieren
Installieren Sie Open-Source-Abhängigkeiten direkt aus öffentlichen Repositories, wie z. B. Docker Hub, npm, PyPI oder Maven Central. Dieser Ansatz ist praktisch, da Sie Ihre externen Abhängigkeiten nicht verwalten müssen. Da Sie diese externen Abhängigkeiten jedoch nicht steuern, ist Ihre Softwarelieferkette anfälliger für Open-Source-Lieferkettenangriffe.
Kopien von Abhängigkeiten im Quell-Repository speichern
Dieser Ansatz wird auch als Anbieter bezeichnet. Anstatt während Ihrer Builds eine externe Abhängigkeit aus einem öffentlichen Repository zu installieren, laden Sie sie herunter und kopieren Sie sie in die Quellstruktur des Projekts. Sie haben mehr Kontrolle über die von Ihnen verwendeten anbieterabhängigen Abhängigkeiten, es gibt jedoch einige Nachteile:
  • Diese Abhängigkeiten erhöhen die Größe Ihres Quell-Repositorys und erhöhen die Abwanderung.
  • Sie müssen für jede separate Anwendung dieselben Abhängigkeiten einrichten. Wenn Ihr Quell-Repository oder Build-Prozess keine wiederverwendbaren Quellmodule unterstützt, müssen Sie möglicherweise mehrere Kopien Ihrer Abhängigkeiten verwalten.
  • Das Upgrade anbieterabhängiger Abhängigkeiten kann schwieriger sein.
Abhängigkeiten in einer privaten Registry speichern
Mit Artifact Registry können Sie bequem aus einem öffentlichen Repository installieren und Ihre Abhängigkeiten steuern.
  • Sie können Ihre Docker- und Sprachpaketclients so konfigurieren, dass sie in Artifact Registry mit privaten Repositories interagieren, wie bei öffentlichen Repositories.
  • Sie steuern die Abhängigkeiten in Ihren privaten Repositories und können den Zugriff auf jedes Repository einschränken.
  • Ihre Abhängigkeiten sind für alle Ihre Anwendungen zentralisiert.
  • Ihre Repositories sind eng in Cloud Build- und Google Cloud-Laufzeiten wie Google Kubernetes Engine und Cloud Run eingebunden.
  • Sie können die Vorteile von Metadatenverwaltung, Scannen auf Sicherheitslücken und Genehmigung von Workflows für die Bereitstellung mit Container Analysis und Binärautorisierung nutzen.

Verwenden Sie nach Möglichkeit eine private Registry für Ihre Abhängigkeiten. Wenn Sie keine private Registry verwenden können, sollten Sie die Abhängigkeiten bereitstellen. Damit können Sie die Inhalte in Ihrer Softwarelieferkette steuern.

Angepinnte Version

Das Zurückstellen von Versionen bedeutet, dass eine Anwendungsabhängigkeit auf eine bestimmte Version oder einen bestimmten Versionsbereich beschränkt wird. Im Idealfall pinnen Sie eine einzelne Version einer Abhängigkeit an.

Durch das Anpinnen der Version einer Abhängigkeit wird sichergestellt, dass Ihre Anwendungs-Builds reproduzierbar sind. Dies bedeutet jedoch auch, dass Ihre Builds keine Aktualisierungen der Abhängigkeit enthalten, einschließlich Sicherheits- oder Fehlerkorrekturen oder Verbesserungen.

Dieses Problem können Sie mit automatischen Tools zum Abhängigkeitsmanagement umgehen, die Abhängigkeiten in Ihren Quell-Repositories auf neue Releases überwachen. Mit diesen Tools werden Ihre Anforderungsdateien aktualisiert, um bei Bedarf Abhängigkeiten zu aktualisieren. Sie enthalten häufig Änderungsprotokollinformationen oder zusätzliche Details.

Das Zurückstellen von Versionen gilt nur für direkte Abhängigkeiten, nicht für transitive Abhängigkeiten. Wenn Sie beispielsweise die Version des Pakets my-library anpinnen, schränkt die Markierung die Version von my-library ein, jedoch nicht die Softwareversionen, für die my-library eine Abhängigkeit hat. Sie können die Abhängigkeitsstruktur für ein Paket in einigen Sprachen mithilfe einer Sperrdatei einschränken.

Signatur- und Hash-Bestätigung

Es gibt eine Reihe von Methoden, mit denen Sie die Authentizität eines Artefakts überprüfen können, das Sie als Abhängigkeit verwenden.

Hash-Bestätigung

Ein Hash ist ein generierter Wert für eine Datei, die als eindeutige Kennung dient. Sie können den Hash eines Artefakts mit dem vom Anbieter des Artefakts berechneten Hash-Wert vergleichen, um die Integrität der Datei zu bestätigen. Mit der Hash-Überprüfung können Sie Änderungen, Manipulationen oder Beschädigungen von Abhängigkeiten durch einen Man-in-the-Middle-Angriff oder eine Manipulation des Artefakt-Repositorys ermitteln.

Bei der Verwendung der Hash-Prüfung muss sichergestellt werden, dass der Hash, den Sie zum Zeitpunkt der Überprüfung (oder zum ersten Abruf) vom Artefakt-Repository erhalten, nicht manipuliert wurde.

Signaturbestätigung

Die Signaturprüfung bietet zusätzlichen Schutz für die Prüfung. Das Artefakt-Repository, die Administratoren der Software oder beides können Artefakte signieren. Dienste wie sigstore bieten Administratoren die Möglichkeit, Softwareartefakte zu signieren und für Nutzer zum Prüfen dieser Signaturen.

Dateien und kompilierte Abhängigkeiten sperren

Sperren sind vollständig aufgelöste Anforderungsdateien, in denen genau angegeben ist, welche Version der einzelnen Abhängigkeiten für eine Anwendung installiert werden soll. In der Regel werden Sperrdateien in der Regel automatisch von Installationstools erstellt. Versionsfixierung und Signatur- oder Hash-Überprüfung werden mit einer vollständigen Abhängigkeitsstruktur für die Anwendung kombiniert.

Installationstools erstellen Abhängigkeitsstrukturen, indem alle nachgelagerten transitiven Abhängigkeiten Ihrer Abhängigkeiten der obersten Ebene vollständig aufgelöst und dann die Abhängigkeitsstruktur in Ihre Sperrdatei aufgenommen werden. Daher können nur diese Abhängigkeiten installiert werden, wodurch Builds reproduzierbar und konsistent sind.

Private und öffentliche Abhängigkeiten kombinieren

Moderne cloudnative Anwendungen hängen oft sowohl von Open-Source-Code, Drittanbietercode als auch von internen Open-Source-Bibliotheken ab. Mit Artifact Registry können Sie Ihre Geschäftslogik für mehrere Anwendungen freigeben und dieselben Tools wiederverwenden, um sowohl externe als auch interne Bibliotheken zu installieren.

Wenn Sie jedoch private und öffentliche Abhängigkeiten kombinieren, ist Ihre Softwarelieferkette anfällig für Angriffe auf die Abhängigkeitsabhängigkeit. Wenn sie Projekte mit demselben Namen wie Ihr internes Projekt in Open-Source-Repositories veröffentlichen, können Angreifer möglicherweise falsch installierte Installationsprogramme nutzen, um ihren schädlichen Code anstelle Ihrer internen Abhängigkeit zu installieren.

Zur Vermeidung von Angriffen zur Abhängigkeit von Abhängigkeiten haben Sie folgende Möglichkeiten:

  • Prüfen Sie die Signatur oder Hashes Ihrer Abhängigkeiten, indem Sie sie in eine Sperrdatei einfügen
  • Installation von Abhängigkeiten von Drittanbietern und internen Abhängigkeiten in zwei separate Schritte aufteilen
  • Spiegeln Sie die Drittanbieter-Abhängigkeiten explizit in Ihrem privaten Repository, entweder manuell oder über einen Pull-Proxy
  • Verwenden Sie für die containerbasierte Entwicklung vertrauenswürdige Quellen für Ihre Basis-Images. Google bietet verwaltete Basis-Images, die Sie direkt verwenden können, und eine sichere Image-Pipeline zum Generieren Ihrer eigenen Basis-Images.

Nicht verwendete Abhängigkeiten entfernen

Wenn sich Ihre Anforderungen ändern und Ihre Anwendung sich weiterentwickelt, können Sie einige Abhängigkeiten ändern oder diese nicht mehr verwenden. Wenn Sie nicht verwendete Abhängigkeiten mit Ihrer Anwendung installieren, erhöht sich die Abhängigkeitsbilanz und das Risiko, dass Sie von einer Sicherheitslücke in den Abhängigkeiten betroffen sind.

Wenn die Anwendung lokal ausgeführt wird, wird normalerweise jede Abhängigkeit kopiert, die Sie während des Entwicklungsprozesses installiert haben, in die Anforderungensdatei für Ihre Anwendung. Anschließend stellen Sie die Anwendung mit all diesen Abhängigkeiten bereit. Dieser Ansatz gewährleistet, dass die bereitgestellte Anwendung funktioniert, gibt jedoch wahrscheinlich auch Abhängigkeiten ein, die Sie in der Produktion nicht benötigen.

Seien Sie vorsichtig, wenn Sie Ihrer Anwendung neue Abhängigkeiten hinzufügen. Jeder Code hat das Potenzial, zusätzlichen Code einzuführen, den Sie nicht vollständig kontrollieren können. Binden Sie im Rahmen Ihrer regulären Linting- und Testpipeline Tools ein, die Ihre Anforderungsdateien prüfen, um festzustellen, ob Sie die Abhängigkeiten tatsächlich verwenden oder importieren.

Scannen auf Sicherheitslücken

Durch eine schnelle Reaktion auf Sicherheitslücken in Ihren Abhängigkeiten können Sie Ihre Softwarelieferkette schützen.

Mithilfe des Scannens auf Sicherheitslücken können Sie automatisch und konsistent beurteilen, ob Ihre Abhängigkeiten Sicherheitslücken in Ihrer Anwendung verursachen. Tools zum Scannen auf Sicherheitslücken nutzen Sperrdateien, um genau zu ermitteln, von welchen Artefakten Sie abhängig sind. Sie werden benachrichtigt, wenn neue Sicherheitslücken auftreten, manchmal auch bei vorgeschlagenen Upgradepfaden.

Tools wie Container Analysis bieten eine Vielzahl von Sicherheitslückenscans für Container-Images sowie Sprachartefakte wie Java-Paketscans. Wenn es aktiviert ist, werden Sicherheitslücken in Ihren Container-Images erkannt. Images werden gescannt, wenn sie in Artifact Registry hochgeladen werden, und die Daten werden bis zu 30 Tage nach dem Hochladen des Images kontinuierlich auf neue Sicherheitslücken überprüft.

Sie können auch das On-Demand-Scanning verwenden, um Container-Images lokal zu scannen. So können Sie Sicherheitslücken frühzeitig identifizieren und beheben, bevor Sie sie in Artifact Registry speichern.