Blog
Bewährte Praktiken für die Verwendung privater GitHub-Läufer

In diesem Beitrag möchte ich mich mit privaten Runnern für Ihre GitHub Workflows befassen und Ihnen einige bewährte Verfahren dafür zeigen. GitHub Workflows können entweder auf einem GitHub Hosted Runner oder auf Ihrem eigenen privaten Runner laufen. Den privaten Runner können Sie auf einem Rechner Ihrer Wahl installieren und Sie verwalten alles auf diesem Rechner: die Tools, die Sie vorinstallieren, den Netzwerkstack, auf den der Runner Zugriff hat, und jeden Speicher, den er während seiner Läufe verwendet.
Dieser Beitrag ist Teil einer Serie über bewährte Methoden zur sicheren Verwendung von GitHub Actions. Die anderen Beiträge finden Sie hier:
Foto von Sherise VD auf Unsplash
Warum einen privaten Läufer benutzen?
Einige Unternehmen haben die Richtlinie, dass ihre Builds (oder Deployments) immer in ihrem eigenen (gehosteten) Rechenzentrum ausgeführt werden müssen. Ein anderer Grund könnte sein, dass Sie eine lizenzierte Software verwenden müssen, die Sie nur in Ihrer eigenen Umgebung ausführen können. Oder vielleicht benötigen Sie in Ihrem Arbeitsablauf eine GPU-Einrichtung (diese sind meines Wissens nicht bei GitHub Hosted Runners verfügbar).
Der Läufer selbst ist offene Quelle damit Sie sich die Funktionsweise ansehen und Aktualisierungen dazu beitragen können. Die Installation ist sehr einfach: Sie können zu Ihrem Repository oder Ihrer Organisation oder Ihrem Unternehmen gehen. Gehen Sie zu Einstellungen -> Aktionen und am unteren Rand finden Sie eine Schaltfläche zum Hinzufügen eines neuen Läufers.
Wenn Sie den Runner auf Organisationsebene hinzufügen, ist er für alle Repositories in dieser Organisation verfügbar. Wenn Sie den Runner auf Unternehmensebene hinzufügen, ist er für alle Repositorys in allen Organisationen des Unternehmens verfügbar.
Die Installation besteht aus der Ausführung dieser Schritte:
- Laden Sie die neueste gezippte Version des Runners herunter unter Releases - actions/runner
- Entpacken Sie es
- Führen Sie das Skript config.cmd mit der URL der Ebene aus, zu der der Runner hinzugefügt werden soll, und einem bestimmten Token (beachten Sie, dass Sie dieses Token auch über die GitHub-API erhalten können). Das Token ist 1 Stunde lang gültig.
- Starten Sie den Läufer
Der Runner wird mit den Rechten ausgeführt, die Sie bei der Installation angegeben haben, und startet eine lange abfragende ausgehende Verbindung über HTTPS zu GitHub. Diese ausgehende Verbindung wird aus Sicherheitsgründen (z.B. Firmen-Firewalls) über HTTPS hergestellt, um sie so sicher wie möglich zu machen. Der Runner fragt GitHub in regelmäßigen Abständen (ich glaube jede Minute), ob es etwas zu tun gibt, und wenn nicht, zieht er sich für eine weitere Minute zurück.
Bewährte Praktiken in diesem Beitrag:
- Beschränken Sie den Zugriff auf Ihren privaten Läufer
- Verwenden Sie einen Runner nicht für mehr als ein Repository (auf einem persistenten Runner)
- Verwenden Sie niemals einen privaten Runner für Ihre öffentlichen Repositories
Wenn Sie mehr über die Härtung Ihrer Runner-Umgebungen erfahren möchten, können Sie die GitHub-Dokumentation hier lesen.
Beschränken Sie den Zugriff auf Ihren privaten Läufer
Beschränken Sie den Zugriff des privaten Runners auf ein absolutes Minimum. Denken Sie an all die Dinge, auf die die Prozesse, die der Runner selbst oder die Aktionen, die er für Sie ausführt, Zugriff haben. Niemals Installieren Sie es mit Netzwerkadministrator- oder Root-Rechten. Geben Sie dem Programm gerade genug Rechte, um nur das zu tun, wofür es gedacht ist.
Muss der Runner wirklich Zugriff auf Ihren Datenbank-Cluster haben? Wenn nicht, schränken Sie den Netzwerkzugriff für ihn ein (z.B. durch Segmentierung des Netzwerks).
Braucht der Runner wirklich Zugriff auf Ihre Dateifreigabe? Was könnte er mit all diesen Dateien tun? Was ist, wenn eine Aktion die Freigabe scannt und die interessanten Teile an einen externen Server sendet? Was ist, wenn die Aktion Ihren Code ausführt, eine Drittanbieterabhängigkeit herunterlädt, die kompromittiert wurde und anfängt, etwas in Ihrer Umgebung zu tun?
Was passiert, wenn die Aktion die Sandbox des Läufers durchbricht? Könnte er sich in ein privilegierteres Konto verwandeln?
Beste Praxis: Geben Sie dem Runner so wenig Zugriff wie möglich auf den Rechner, auf dem er läuft.
Verwenden Sie einen persistenten Runner nicht für mehr als ein Repository
Diese bewährte Praxis stammt aus der gleichen Praxis wie zuvor und stammt meist aus den Methoden, die bei Angriffen auf die Lieferkette verwendet werden, wie z.B. bei dem jüngsten Solorigate Angriff. Sowohl die ausgeführte Aktion als auch die von ihr verwendeten Abhängigkeiten von Drittanbietern (NPM- oder NuGet-Pakete oder alle Schichten im verwendeten Docker-Image) können Dinge auf dem Rechner des Läufers speichern. Sogar der Runner selbst könnte diese Dinge speichern, auch wenn eine Kompromittierung des Runners weniger wahrscheinlich ist, könnte sie dennoch passieren (wir sind schließlich alle Menschen). Hier kommt es auf den Kontext an: Dies ist nicht so relevant für das, was wir einen ephemeren Runner nennen: einen Runner, der nur für die Dauer eines Auftrags (nicht eines Workflows!) existiert. Es ist nicht möglich, Daten auf einem ephemeren Runner zu speichern, da der Runner danach gelöscht wird.
Dieses Thema ist natürlich besonders wichtig für persistente Läufer: Stellen Sie sich eine virtuelle Maschine vor, die ständig läuft.
Was ist, wenn ein erster Lauf ein kompromittiertes Paket herunterlädt und es in Ihrem lokalen Paket-Cache speichert? Ein zweiter Durchlauf, der dieses Paket benötigt, findet es im Paket-Cache und verwendet diese Version, anstatt die korrekte Version abzurufen? Wie in der Solorigate Angriff wurde nur 1 Assembly als Ausgangspunkt des Kompromisses überschrieben.
Dieses Problem könnte sogar noch vergrößert werden, wenn derselbe Runner für mehrere Repositories verwendet wird: Die Vergiftung des Paket-Caches in einem Repository könnte anschließend von allen anderen Workflows genutzt werden, die mit demselben Runner ausgeführt werden.
Noch schlimmer ist es, mehrere Runner auf demselben Rechner zu installieren, um die verfügbaren Ressourcen des Rechners effizienter zu nutzen: Was, wenn alle denselben Paket-Cache verwenden? NuGet verwendet zum Beispiel einen zentral gespeicherten Cache auf Rechnerebene...
Wenn Sie also wirklich einen Runner benötigen, sollten Sie zumindest einen neuen Runner auf einem neuen Rechner für jedes Repo erstellen und ihm die Mindestrechte geben, die er für seine Arbeit benötigt.
Eine noch bessere Möglichkeit ist es, für jeden Lauf einen neuen Läufer zu erstellen. Verwenden Sie zum Beispiel einen Aktion die einen neuen Läufer nur für diesen speziellen Lauf erstellt, oder hosten Sie Ihren Läufer auf AWS Fargate oder sogar eine automatische Skalierung einrichten Sie selbst.
Hinweis: Die oben genannten Optionen verwenden alle AWS für das Hosting. Ich habe noch keine Beispiele für diese Einrichtung auf Azure gesehen. Wenn Sie ein Azure-Beispiel haben, lassen Sie es mich wissen: Ich werde es der obigen Liste hinzufügen.
Verwenden Sie niemals einen privaten Runner für Ihre öffentlichen Repositories
Auch erwähnt in der Anleitung von GitHub ist, dass Sie keine privaten Runner für öffentliche Repositories verwenden sollten. Abhängig von Ihrer Einrichtung werden Ihre Workflows durch neue Commits, die in das Repository gepusht werden, oder durch eine eingehende Pull-Anfrage ausgelöst.
Was ist, wenn jemand mit böser Absicht Ihr Repository forkt, Code oder eine Abhängigkeit hinzufügt, die Ihr Setup (oder sogar den Workflow selbst) gefährdet, und einen neuen Pull Request für Ihr Repository erstellt? Der Workflow wird ausgelöst (hey, sie können sogar den Auslöser für Sie!) und die bösartige Installation wird auf Ihrem Rechner mit allen Zugriffsmöglichkeiten des Läufers ausgeführt. Dies wird aus offensichtlichen Gründen als sehr gefährlich angesehen.
Verfasst von
Rob Bos
Rob has a strong focus on ALM and DevOps, automating manual tasks and helping teams deliver value to the end-user faster, using DevOps techniques. This is applied on anything Rob comes across, whether it’s an application, infrastructure, serverless or training environments. Additionally, Rob focuses on the management of production environments, including dashboarding, usage statistics for product owners and stakeholders, but also as part of the feedback loop to the developers. A lot of focus goes to GitHub and GitHub Actions, improving the security of applications and DevOps pipelines. Rob is a Trainer (Azure + GitHub), a Microsoft MVP and a LinkedIn Learning Instructor.
Unsere Ideen
Weitere Blogs
Contact



