Codefresh + Snyk = schnell und sicher ausliefern
Antoine Arlaud
11. Dezember 2018
0 Min. LesezeitBei moderner Softwareentwicklung geht es ums Programmieren. Nicht ums Erstellen, nicht ums Ausliefern, sondern ums Entwickeln – wir programmieren, führen Änderungen zusammen, der Build läuft, die Software wird ausgeliefert. Wichtig ist, auf beiden Seiten der Repository-Grenze zu testen – zwischen dem Code und den automatisierten Abläufen. Ziel ist es, vor dem Zusammenführen zu testen, damit die Änderungen reibungslos durch die Pipeline laufen.
Pipelines sind nicht dafür gedacht, dass wir Entwickler unsere Änderungen zum ersten Mal testen. Sie sollen verhindern, dass unser Code ausgeliefert wird, wenn er die Kriterien für das neue Release nicht erfüllt. Das ist wie eine abschließende Checkliste, während die Rakete noch auf der Startrampe steht. In einer idealen Welt wäre es sogar schon etwas zu spät, wenn wir während einer Pipeline noch Fehler beheben müssen. Das würden wir lieber während der Entwicklung und/oder beim Zusammenführen erledigen. Da die Welt jedoch nicht immer ideal ist, sollten wir grundsätzlich versuchen, Änderungen in der Entwicklungsphase zu halten.
Dafür sollten Sie früher testen und möglichst früh Feedback einholen, zum Beispiel auf Ihrem Rechner oder in Ihrem Code-Repository. Natürlich müssen Sie zunächst auch diese Pipeline aufbauen und die erforderlichen Tests integrieren. Hier kommt Codefresh ins Spiel. Damit können Sie automatisierte Pipelines erstellen, um Ihre Apps in Containern und Kubernetes-Deployments auszuliefern.
Diese Tests MÜSSEN Sicherheit einschließen. Das ist schlicht ein Muss. Wenn Sie noch nicht überzeugt sind, hören Sie auf, diesen Beitrag zu lesen, und sprechen Sie mit Ihrem Security-Team, einer Kollegin oder einem Kollegen, anderen Fachleuten, einer Meetup-Gruppe oder auch mit uns. Wir erklären Ihnen gern, warum das wichtig ist ... und genau hier kommt Snyk ins Spiel.
Wir nehmen uns 5–10 Minuten Zeit und erstellen diese Pipeline in Codefresh, wobei wir Sicherheitstests mit Snyk integrieren. Die Tests bleiben kurz und unkompliziert, damit wir schnell wieder programmieren und letztlich neue Funktionen ausliefern können. Sowohl Codefresh als auch Snyk bieten kostenlose Tarife, sodass Sie ohne Kosten mitmachen können. Zusammen mit dem Codefresh-Team habe ich außerdem ein Webinar gehalten. Wenn Sie lieber das Video ansehen möchten, finden Sie es hier.
Wir erstellen eine Beispiel-App mit Node und liefern sie in einem Docker-Container aus, den wir anschließend auf Docker Hub hochladen. Danach startet eine weitere Pipeline und stellt das Ergebnis als Kubernetes-Anwendung bereit. Codefresh erkennt Änderungen, die in unser Repository übernommen wurden, erstellt die Docker-Images und führt anschließend die Snyk-Tests aus, um festzustellen, ob das resultierende Ergebnis sicher ausgeliefert werden kann.
Zunächst ein kurzer Überblick über Anwendungen und Container. Die folgende Abbildung veranschaulicht den Aufbau einer typischen Anwendung, die auf einer Container-Infrastruktur läuft.
Die Pipeline ruft den Quellcode meiner Anwendung aus meinem GitHub-Repository ab, erstellt daraus einen Docker-Container und prüft dann sowohl die Anwendungsabhängigkeiten als auch die Betriebssystemabhängigkeiten auf Sicherheitsprobleme, bevor sie das Image auf Docker Hub hochlädt. Solange keine Schwachstellen gefunden werden, läuft sie ohne Unterbrechung durch.

Erstellen wir diese Pipeline nun tatsächlich!
1. Registrieren Sie sich für neue Codefresh- und Snyk.io-Konten.
2. Fügen Sie ein Repository in Codefresh hinzu.

Für diese Demo verwenden wir das Repository https://github.com/snyk-playground/codefresh-pipeline-snyk-app-docker-scan.

3. Wählen Sie als Nächstes Start from template als Build-Methode aus.

Hier verwenden wir eine NodeJS-Anwendung. Wählen Sie diese aus und klicken Sie auf „Weiter“.

Wir verwenden zunächst die Standardvorlage. Sie können sie nach Bedarf anpassen.

Alles klar, unser neues Repository wurde hinzugefügt. Jetzt können wir die Pipeline definieren.

4. Erstellen Sie jetzt den Build für das Repository, indem Sie auf Create pipeline klicken.
Definieren wir zunächst einige erforderliche Umgebungsvariablen. Geheimnisse werden dabei verschlüsselt. Fügen Sie eine neue Variable mit dem Namen „SNYK_TOKEN“ hinzu.

Den Wert finden Sie unter https://app.snyk.io/account.

Fügen Sie dort auch eine weitere Variable namens SNYK_ORG hinzu. Als Wert verwenden Sie den letzten Teil Ihrer URL https://app.snyk.io/org/. In meinem Fall lautet er aarlaud-snyk-demo.

Das war's für Snyk.
Jetzt brauchen wir noch einige Umgebungsvariablen, um das Image aus der Codefresh-Registry abzurufen und das fertige Image auf Docker Hub hochzuladen.
Damit Codefresh auf unsere private Image-Registry zugreifen kann, fügen Sie die folgenden Variablen hinzu (weitere Informationen finden Sie hier: https://codefresh.io/docs/docs/docker-registries/codefresh-registry/#generate-cfcr-login-token):
CF_USER_NAME– mein Codefresh-Benutzername (bei mir z. B. aarlaud)CFCR_ACCOUNT– bei mir derselbe Wert wie mein Benutzername: aarlaudCFCR_LOGIN_TOKEN– erstellen Sie ein Token unter https://g.codefresh.io/user/settings und verschlüsseln Sie es!
Für die Docker-Hub-Integration speichern wir unter der folgenden Variable den Namen, unter dem wir unser fertiges Docker-Image auf Docker Hub hochladen möchten:
IMAGE_NAME – in meinem Fall zum Beispiel aarlaudsnyk/trainingapp
Ihre Variablen sollten in etwa so aussehen:

Zum Schluss müssen Sie im Bereich „Integrations“ von Codefresh die Docker-Konfiguration einrichten:

Dafür benötigen Sie ein Docker-Hub-Konto (https://hub.docker.com/). Erstellen Sie eines, falls Sie noch keines haben, und richten Sie dann die Docker-Registry-Integration ein:

Alles klar, jetzt können wir weitermachen! Wenn Sie sich Ihre Trigger ansehen, werden Sie feststellen, dass jeder Commit einen Build auslöst. Da wir diese Pipeline auf Grundlage des Master-Branches erstellt haben, lösen nur Commits auf master den Build aus. Das reicht zunächst aus und lässt sich für andere Branches und Umgebungen einfach ändern oder duplizieren.

Im Workflow erkennen wir die Docker-Vorlage wieder, die wir vorhin gesehen haben. Irgendwann könnte es sinnvoll sein, diese in eine Dockerfile zu verschieben.

Versuchen wir nun, den Build auszuführen, um zu prüfen, ob alles wie erwartet funktioniert, bevor wir weitermachen.

Der Build startet:

Und jetzt wurde meine App erstellt.

Codefresh legt dieses Image automatisch in Ihrer privaten Docker-Registry in Ihrem Codefresh-Konto ab. Im Bereich „Images“ sehe ich mein gerade erstelltes Docker-Image:

Bevor ich dieses Image einfach auf Docker Hub hochlade, möchte ich außerdem sicherstellen, dass es keine Sicherheitslücken enthält.
5. Kehren wir zur Pipeline zurück und fügen den Befehl snyk test hinzu, um die Abhängigkeiten auf Sicherheitslücken zu prüfen.
Zuerst installieren wir Snyk und führen es anschließend mit einfachen Befehlen aus, die den Build bei schwerwiegenden Problemen abbrechen. Bei Problemen mit niedrigem oder mittlerem Schweregrad möchte ich den Build vorerst nicht abbrechen, bis ich meinen Workflow besser im Griff habe.

Klicken Sie auf „Speichern“ und führen Sie den Build erneut aus. In der Pipeline sehen Sie einen Schritt zum Ausführen von Unit-Tests. Wahrscheinlich schlägt er wegen einiger Probleme fehl. Diese beheben wir später. Scannen wir nun das Docker-Image selbst auf Probleme mit den Betriebssystemkomponenten meiner App.
Wenn Codefresh die App erstellt, lädt es das Image in unsere private Registry hoch. Anschließend ruft es das Image ab, um die Unit-Tests auszuführen. Diesen Vorgang wiederholen wir für einen zweiten Snyk-Test, der gezielt das Docker-Image prüft.
Dazu verwenden wir eine Codefresh Composition. Weitere Details finden Sie in der Dokumentation. Wir wechseln jedoch zu YAML, um mehr Möglichkeiten zu haben.

Fügen wir im YAML-Modus zunächst direkt nach „version: ‘1.0’“ die folgenden drei Zeilen hinzu: stages:
Diese Änderung ist rein kosmetisch – sie erstellt in der Benutzeroberfläche einen Abschnitt, ähnlich einem Bucket. Passen wir nun den vorhandenen Abschnitt RunningUnitTests etwas an und verwenden dafür den Abschnitt SnykAppScan. Neben den Titeländerungen haben wir einen Stage-Abschnitt hinzugefügt, um den Schritt im richtigen UI-Bucket anzuzeigen. Außerdem übergeben wir die Umgebungsvariablen direkt und räumen ein paar Dinge auf.
Fügen wir nun den Abschnitt SnykScanImage für das Scannen unseres Docker-Images hinzu. Auch hier ist der Stage scan, sodass der Schritt im selben Bucket wie das Scannen der Anwendungsabhängigkeiten erscheint. In der Composition-Dokumentation wird beschrieben, wie Sie mehrere Services für Ihre Tests ausführen können.
In unserem Fall ist BuildingDockerImage das Image-Ergebnis des Build-Stage. Wir möchten dieses Image von außen testen. Deshalb erstellen wir eine Composition mit einem Scan-Service, der ein weiteres, zuvor von mir erstelltes Image ausführt: aarlaudsnyk/snyk-container-scan-docker. Dieses Image bündelt einfach die erforderlichen Komponenten, damit Snyk ein Docker-Image testen kann. Den Quellcode finden Sie hier:
Der relevante Abschnitt aus der obigen YAML-Datei lautet:
Wir verwenden dieses Image, um anschließend den Python-Befehl auszuführen, der im Wesentlichen zwei Dinge erledigt:
Ruft das zu testende Image ab und lädt es lokal herunter
Führt „snyk test --docker “ aus
Dieses Image wurde so erstellt, dass es das Image aus der Codefresh-Registry abruft, wenn die folgenden Umgebungsvariablen definiert sind:
CFCR_ACCOUNT
CF_USER_NAME
CFCR_LOGIN_TOKEN
So können wir das gerade erstellte Image testen. Andernfalls wird standardmäßig versucht, ein Image von Docker Hub abzurufen.
Zum Schluss fügen wir am Ende den Docker-Hub-Registry-Push hinzu, damit dieses Image tatsächlich hochgeladen wird, sofern unsere Tests erfolgreich sind:
Hier ist nichts Besonderes nötig. Codefresh macht das Hochladen auf Docker Hub ganz einfach, sobald die Integration eingerichtet ist (siehe oben). Beachten Sie, dass der Stage „promote“ heißt, damit er sich von den Scan-Tests unterscheidet.
Insgesamt sollte das Ganze in etwa so aussehen:
6. Versuchen wir jetzt, den Build auszuführen, um einen Ausgangswert zu erhalten. Unsere Organisation scheint gut aufgestellt zu sein:

Nach einem Moment erhalten wir Folgendes:

Oh nein, offenbar gibt es Probleme in unserer App – die Pipeline wurde sicher angehalten, bevor etwas mit Sicherheitsproblemen ausgeliefert wurde. Beheben wir das, indem wir den im Ergebnis angezeigten Schritten zur Behebung folgen. Es reicht aus, das qs-Paket in der package.json auf Version 6.0.4 zu aktualisieren.
Führen wir den Build erneut aus.

Die qs-Schwachstelle ist behoben, juchhu! Doch jetzt gibt es offenbar ein Problem mit den Betriebssystemabhängigkeiten in unserem Docker-Image.

Als Abhilfe wird vorgeschlagen, das Image zu aktualisieren (weitere Informationen finden Sie im Docker-Abschnitt unter snyk.io/docs). Aktualisieren wir also auf node:10-alpine und versuchen es erneut.

Speichern => Build ausführen => Während des Builds Liegestütze machen!

Super! Jetzt haben wir einen sauberen Ausgangswert und eine voll funktionsfähige Pipeline, die unsere App und den Container auf Docker Hub ausliefert.
Jetzt können wir wieder programmieren. Achten Sie darauf, für Ihre Änderungen snyk test auszuführen, bevor Sie sie zusammenführen, und/oder testen Sie Ihre Änderungen mit der GitHub-PR-Integration von Snyk. Anschließend werden die Änderungen automatisch ausgeliefert. Und als Extra-Bonus: die neueste Ergänzung!
Verwenden Sie snyk monitor, um Ihre Abhängigkeiten langfristig im Blick zu behalten. Niemand möchte Projekte ständig überwachen müssen. Wenn Sie snyk monitor ausführen, benachrichtigt Snyk Sie automatisch, falls eine neue Schwachstelle in einer Abhängigkeit des Projekts oder Docker-Images bekannt wird. Fügen Sie einfach snyk monitor nach dem Abschnitt „snyk test“ hinzu.

Die URL des Snapshots für die Überwachung wird dann in der Ausgabe angezeigt:

Der Docker-Schritt wird automatisch ausgeführt, wenn snyk test erfolgreich ist (also keine bekannten Probleme vorliegen). Links zu den Überwachungs-Snapshots werden ebenfalls bereitgestellt.

Die überwachten Projekte finden Sie auch in der Snyk-Benutzeroberfläche in Ihrer Snyk-Organisation:

Rufen Sie die Codefresh-Pipeline auf, indem Sie auf das Badge im Repository klicken (https://github.com/snyk-playground/codefresh-pipeline-snyk-app-docker-scan).
Das war's, Leute! Bleiben Sie sicher!
Starten Sie mit Capture the Flag
Erfahren Sie in unserem virtuellen On-Demand-Workshop für Einsteiger, wie Sie Capture-the-Flag-Herausforderungen lösen.



