Secrets Not Included: Pipeline Security
Pipeline Security klingt trocken. Ist es aber nicht. Denn genau hier entscheidet sich, ob deine CI/CD nur schnell ist — oder auch wirklich sicher. In der neuen Folge von Secrets Not Included sprechen Daniel und Ole über die Sicherheitsprobleme, die in Pipelines ständig unterschätzt werden: langlebige Secrets, zu große Rechte, unsaubere Tests, fehlende Signaturen, SBOMs und Deployments, bei denen niemand mehr genau sagen kann, was eigentlich wirklich in Produktion gelandet ist. Es geht um eine klare Frage: Wie baust du Pipelines so, dass sie liefern — ohne dabei selbst zum Risiko zu werden? Wir sprechen darüber, warum Secrets nicht in Pipelines gehören, warum kurzlebige Tokens der bessere Weg sind, warum Tests gegen echte Umgebungen anders gedacht werden müssen und warum SBOM, Signierung und Runtime statt Bauchgefühl heute kein Luxus mehr sind. Keine Buzzwords. Keine Sicherheitsfolklore. Sondern die unbequemen Punkte, die in echten Setups relevant werden. Neue Folge von Secrets Not Included — mit Daniel und Ole. --- Ole ist Gründer der Moselwal Digitalagentur und Beschäftigt sich mit Hyperautomatisierurng (auch mit KI), Sicherheit und CMS. Daniel ist Geschäftsführer der xebro GmbH und sein Schwerpunkt liegt auf PHP, Symfony, E Commerce, DevOps und AWS.
Transkript anzeigenTranskript verbergen
Willkommen zu einer neuen Folge der neunten Folge Secrets Not Included in dieser Woche wieder mit Daniel und Ole und wir möchten uns heute mal über Pipeline Security austauschen, was so in CI-CD abgeht und was man dort eigentlich beachten sollte, damit diese Pipelines auch mal sicher sind. Daniel, magst du loslegen?
Ich glaube, das ist eher deine Stärke, das Thema. Aber wir können anfangen mit dem allseits nervigen Thema Security, also Secrets in Pipelines. Das, was eigentlich so den Entwicklern meistens auf den Füßen liegt, ist, wenn man eine Pipeline gebaut hat oder deployen möchte, möchte man Tests ausführen. Oft gibt es auch Testsysteme, die Secrets brauchen oder es gibt andere Services, die getestet werden, wogegen getestet wird.
Mhm.
Und damit das funktioniert, braucht man dafür Secrets in der Pipeline. Und wie diese da reinkommen und wie diese genutzt werden und welche Rechte auch in der Pipeline da vorherrschen, damit man Systeme und Tests ausführen kann. Das ist, glaube ich, ein sehr nerviges Thema. Also, weil die Entwicklung und Ops da immer... konträr gegeneinander überstehen. Die einen wollen natürlich möglichst alles testen und brauchen alle Credentials und Zugriff auf alle Systeme. Und OBS versucht natürlich so den Blast Radius so möglichst klein zu halten, damit möglichst wenig Zugriffe irgendwie oder Credentials auch in der Pipeline irgendwo rumfliegen. Weil meistens ist das ja auch dann
Ähm, ehrlicherweise bin ich ja der radikalen Meinung, ähm, die Credentials für Test, Port, whatever, brauchst du nicht wissen. Also, weder du als Entwickler, noch als Ops, noch als Pipeline oder CI-System.
Mhm.
Ähm, Warum behaupte ich das? Es ist vielleicht die spannendste Frage. Also erstmal langlebige Secrets irgendwo rumfliegen lassen ist immer eine total beschissene Idee. Und ich bin auch der Meinung und der Überzeugung, wenn die Pipeline sich irgendwo anmelden muss, muss sie das mit einem eigenen Job spezifischen Token machen. GitLab CI hat das zum Beispiel gelöst. Da bekommst du ein Token- der für diesen Job gerade gültig ist und danach nicht mehr gültig ist. Damit kannst du dich an allen wichtigen Dingen anmelden. Bei Registry, also sowohl für die Images als auch bei den Package Registries. Sprich, du kannst Images ziehen, bauen, pushen. Du kannst Pakete ziehen, bauen, pushen. Und damit ist ja eigentlich alles geschafft, was du möchtest, was du ja eigentlich in einer CI-CD-Pipeline haben möchtest, ist, wenn wir mal am Anfang anfangen, du pushst das Zeugs dahin was du gebaut hast oder nein, du pushst nicht in die Pipeline, du pushst in das Repository und die Pipeline wird dadurch getriggert, dass dort hoffentlich auf einem neuen Feature-Branch im Übrigen Neuer Code angekommen ist. Dann läuft die Pipeline los und fängt mit den Tests an oder der Prüfung, die am schnellsten läuft, ja, Syntaxfehler und so weiter und so fort.
Vielen Dank.
Dafür brauchst du keine Credentials, dafür musst du eigentlich gar nichts wissen, also was sicherheitsrelevant ist. dann läufst du ja immer weiter zu den länger laufenden Tests und irgendwann kommst du, glaube ich, an die Testart an, die du meinst, nämlich so etwas wie Functional Tests oder End-to-End Tests, die in irgendeiner Art und Weise mehr benötigen als den statischen Code.
oder Smoketests nach dem Deployment, um zu verifizieren, dass das System noch, also grundlegendst läuft.
Und ja, genau.
Und da brauchst du dann oft reale Credentials, leider.
Ja, das kommt jetzt auf die Infrastruktur an, sage ich. Wenn du möchtest, dass keine dieser Credentials irgendwie in der Pipeline liegen, ich meine, wir haben das früher auch gemacht, wir haben zum Beispiel.endfights mal irgendwann da reingeschrieben oder auch PHP-Dateien da in der CI-Pipeline aus dem, naja, irgendwo hergeholt, vielleicht aus Variablen, als es das alles noch nicht so gab und so verbrettet war, aus Variablen halt dann in der PHP-Datei geschrieben, später in der Enddatei, dann waren aus dem 1Password-Zili haben wir, glaube ich, auch mal die Credentials holt und dann so da reingeschrieben. Das ist aber alles keine gute Idee, wenn man das sich überlegt. Ja, weil dann hast du zumindest mal irgendwo langlebige Credentials liegen, um an die Credentials zu kommen und das ist alles irgendwie nicht cool. Weil Credentials selbst für Datenbankzugriff und so gehören in die Runtime, nicht in irgendein Image reingebaut oder so.
Mhm.
Deswegen ist der Prozess, den ich bevorzuge, um die Pipeline sicher zu haben, ist möglich, Wir laufen alles durch, dass wir wissen an statischen Analysen, okay, der Code würde vermutlich laufen. Also nach statischen Gesichtspunkten sieht das gut aus. Dann bauen wir ein Image. Das taggen wir definitiv als Testing. Also nicht Produktionsgreif, sondern man sieht, das ist einfach Alphabeta-whatever. pushen das in die Image-Registry und ziehen uns das auf ein Testsystem dann runter.
Mhm.
Und dann, wenn das da deployed ist, dann läuft letztendlich eine weitere Pipeline oder die gleiche, wartet, whatever, was auch immer, wie man das jetzt ausmalt, ob man dann aktiv aufs Testsystem pusht quasi oder ob man darauf wartet, dass irgendwie ein Watchtower oder so das zieht. Jetzt eine Million Varianten gefühlt. Ähm... also egal ob jetzt Push oder Pull, dann läuft die Pipeline weiter und führt dann diese Smoke-Tests etc. durch oder auch Chaos-Tests. Einfach mal Services wegschießen in so einem Cluster und schauen, was passiert.
Oh ja.
Aber alle Tests, die laufen sollten, laufen dann gegen ein Testsystem, das alles hat, das aber auch im Idealfall zum Beispiel einen gewissen Datenbankstand deployed bekommen hat, wenn ich da Abhängigkeiten drin habe. Ich sage jetzt mal, in CMS-Systemen gibt es ja immer wieder den Mix aus der Herausforderung. Eigentlich wollen wir möglichst aktuell gegen Produktivdaten testen, aber auf der anderen Seite müssen wir auch Funktionen testen. Heißt, wir testen
Gerade neue Funktionen zum Beispiel, die noch gar nicht auf dem Produktivsystem sind, kannst du so gar nicht testen meistens. Hm.
Genau, das heißt wir, oder halt auch alte Funktionen, die jetzt nicht mehr auf dem Produktivsystem zum Beispiel sichtbar sind, irgendeine Slider-Funktion, die mal mega wichtig war natürlich zu bauen und ganz dringend benötigt war. Aber jetzt, dann war die zwei Wochen online, da hat man fast gesagt, brauchen wir doch gar nicht. Aber sie muss ja weiter funktionieren. Also testest du sie ja in den Testfällen weiter. Außer es gibt die Entscheidung, wir bauen es dann auch wieder aus. Die fällt ja nicht so häufig. Also sprich, das ist ja die Herausforderung bei der Art von Tests.
Vielen Dank.
Und heißt, du fährst dann ja letztendlich eine gewisse Datenbank mit gewissen Fictures hoch, gegen die testest du. Und das ist aus meiner Sicht auf einem Testsystem, das hochgefahren wird für genau diesen Zweck, mit genau diesem Branch und dann halt läuft. Und das ist nämlich genau der Punkt. Dann habe ich nämlich in dem Testsystem wieder meinen ganz normalen Mechanismus, wie komme ich an diese Credentials. und habe in der Pipeline letztendlich nichts damit zu tun, außer dass ich vielleicht der Pipeline mitgebe, hey, da muss jetzt dieser Datenbank-Dump im weitesten Sinne, diese Datenbank-Daten sollen in die Datenbank geschrieben werden.
Also das setzt aber voraus, dass du das Produktivsystem von der Infrastruktur wirklich eins zu eins kopieren kannst. Also dass du eine Testdatenbank, also im Idealfall sogar vielleicht eine Kopie machen kannst von einer Produktivdatenbank, irgendwie Daten anonymisieren. Einfach mal so am Rande erwähnt, macht man natürlich eine Nicht einfach Nutzerdaten von A nach B schieben, so mit Kreditkarteninfos und sowas, aber du hast eine anonymisierte Produktivdatenbank, du kannst andere Systeme kopieren, dann funktioniert sowas super.
Ja, definitiv.
Es gibt aber immer wieder Ausnahmen, die du nicht kopieren kannst. Also gerade so im E-Commerce-Bereich Payment. Du kannst, also so reich kannst du nicht sein, dass du automatisiert mit deiner eigenen Kreditkarte oder Tests durchlaufen lässt.
Ja, genau.
Deswegen
Genau, es gibt da Gänzen. Ich sage nicht, das ist die ideale Welt, damit kannst du alle Testfälle abdecken.
Nein, nein.
Ja.
Also worauf ich hinaus wollte, ist, man kann unterscheiden zwischen lesenden und schreibenden Tests. Also gerade bei Smoke-Tests sage ich immer, es gibt lesende Tests, die sich einfach durch die Applikation durchklicken und so wie ein Benutzer so ein bisschen streunen, sage ich mal, und einfach so ein paar Klickstrecken nachgehen und erwarten, dass keine Fehlermeldungen da sind oder Überschriften irgendwo auftauchen, Titel und sowas. Und es gibt schreibende Tests, die sind spezieller, Also in deinem Setup, so wie du es beschrieben hast, wenn du das kopieren kannst oder einen Großteil kopieren kannst, ist das super, weil dann kannst du auch schreibende Tests machen. Dann kannst du Nutzer anlegen, du kannst Nutzer löschen, also auch solche Tests machen.
Genau, bis halt auf das, was gegen Drittanbieter Zeugs läuft.
Ja.
Und mit Drittanbieter meine ich manchmal auch das Team, was nebenan am TÜV sitzt. Also du kannst halt in dieser Art von Testumgebung, die halt aus Security-Sicht für die Pipeline bedeutet, die Pipeline kennt keine Credentials und braucht keine Credentials außer den eigenen Job-Token,
Mhm. Mhm.
kannst du dann natürlich für deinen Teil der Applikation oder für die Applikation, die du betreust, beliebige Dinge machen. Wenn du jetzt mit anderen Services reden musst, die anderen Menschen gehören, anderen Teams gehören, dann bist du natürlich in der Situation drin, da ist halt die Grenze, aber da ist ja auch so eine Verantwortungsgrenze. Also es ist jetzt ja nicht so, dass sich jeden Tag die vereinbarten Schnittstellen verändern. Zum Glück nicht.
Nicht täglich, aber das reicht einmal.
Hoffentlich nicht.
Aber...
Genau. Aber das ist ja auch das, wo... Ja. Ja.
Also das beschriebene Problem löst man ja auch anders. Also jetzt zum Beispiel das mit dem Payment-Anbieter kannst du anders lösen. Es gibt extra Monitoring und da baust du zum Beispiel was ein, was das wenn nach einem Deployment, weiß ich nicht, 30 Minuten lang, also je nachdem, wie viel auf dem Shop los ist, zum Beispiel eine Stunde lang keine Bestellung eingeht, dann würde ich sofort einen Alarm auslösen, weil da ist was kaputt. Das ist so Backup-mäßig, Also reicht auch oder ist kompensiert aber, dass ich keine schreibenden Tests gegen externe Systeme machen kann. Also, ja, sorry.
Ja, wir überspringen jetzt auch Punkte in der Pipeline, ehrlicherweise.
Ja.
Du springst jetzt vom Testsystem aufs Produktivsystem. Wobei, lass uns mal bei unserem Testsystem gerade bleiben und gleich aufs Produktivsystem springen, wenn wir dann doch was Kaputtes deployed haben. Und Also was ich wichtig finde, ist halt, wenn, das deckt halt das tägliche Arbeiten ab in diesem Testszenario, ne?
Mhm.
Wenn du, ähm, wenn du natürlich jetzt an Punkte kommst, die einmal vorkommen oder alle x Monate oder alle x Jahre vorkommen können, naja, API-Version und solche Dinge, ja, das passiert ja nicht unangekündigt über Nacht, ähm, dann musst du halt anders testen, manuell nachtesten oder halt Vorwegstrategien haben. Ich finde aber, das ist etwas, was man nicht in der Arbeit oder in der Pipeline für jeden Tag haben muss oder abdecken muss.
Also genau, die Tests, also die Grundlage der Tests sind ja eigentlich nur, ich habe als Entwickler keinen Bock von Hand die Sachen durchzuklicken.
Ich finde so...
Also normalerweise oder vor 30 Jahren war es ja gefühlt so, du hast geschrieben, hast durch den Browser geklickt, ja, kein Fehler, passt.
Nicht nur als Entwickler, auch als Gester und Product Owner. Ja.
Und dann hat man halt immer die wichtigen Sachen vergessen und dann mit den Tests angefangen, die Sachen zu automatisieren und das dann auch viel besser, also jetzt End-to-End-Tests. Und das Ganze dadurch dann einfach viel besser zu machen, weil das wiederholbar ist und vorhersehbar ist und man kann nichts vergessen. Das ist ja eigentlich die Grundlage davon, ne?
Genau, und heute kannst du ja noch viel weitergehen. Also wir hatten ja schon irgendwie gesagt, okay, diese langlebenden Secrets sind ziemlich unpassend heute. Würde ich also nicht machen. Selbst wenn man die rotiert, das löst halt einfach nicht das Problem. Sowas wie OpenID Connect funktioniert halt auch ohne Probleme in der Pipeline mit Token.
Hmm. Hmm.
Das sollte man sich immer überlegen, dass... Im Prinzip eine Pipeline, wenn man den Credentials gibt, muss man die behandeln wie ein Produktivsystem. In dem Moment, wo die Pipeline Zugriff auf Secrets bekommt, aus welchen Gründen auch immer, musst du damit hantieren, als wäre das ein Produktivsystem. Das heißt auch, du musst dann zum Beispiel in den Logs, die ja geschrieben werden und ausgegeben werden, dafür sorgen, dass da deine Secrets schon gar nicht mehr auftauchen. Das ist halt sonst ein Megaproblem, wenn du jetzt sagst, ja, hier mein API-Key, den brauche ich aber, den schreibe ich mir jetzt irgendwo rein und dann steht er in jedem Log drin. So.
Also kleine Anekdote wieder zu dem Thema. Wenn du Entwickler bist oder wie es nicht sein sollte, du bist Entwickler, bist gerade was am Debuggen und brauchst Infos zu Umgebungsvariablen, machst natürlich einen Dump da drauf, weil du denkst, das ist eine ganz normale Config, du willst wissen, ob die Applikation gerade im Testmodus läuft und dieser Dump wird dann ausgegeben und da sind dann Credentials drin, weil auch die Container dann die Credentials in Umgebungsvariablen haben, ist das ganz schlecht. Mhm.
Ja, das ist nämlich auch genau der nächste Punkt. Wenn du die Credentials so in den Container reinpackst, reinpackst, also reinpackst und da fixierst drin, dann sind sie halt letztendlich über die Registry immer abrufbar. Dann kannst du halt sagen, na ja, komm, wurde ja netterweise mit reingeschrieben, so dann sind sie halt nicht mehr geheim.
Hack mir ist doch verboten. Ja.
Ja, jetzt kann man natürlich sagen, ja, das ist alles unser internes Netz, das ist alles sicher und alles toll bis zu dem Zeitpunkt, bis dann halt mal irgendjemand Zugriff drauf hatte, den man jetzt nicht mehr mag. Oder, oder, oder. Es gibt ja immer wieder den Fall, wo man sich überlegt, jetzt sollten wir doch nochmal die ganzen Secrets rotieren aus Gründen. Das sind ja völlig unterschiedliche Gründe. Aber wenn du halt die Secrets gar nicht in den Züge von einem bestimmten Personenkreis hast, dann kannst du halt die Notwendigkeit krass minimieren. Ähm... Und das ist ja so, ich habe das auch häufig genug gesehen und wir haben das früher ja genauso gemacht in den Pipelines. Das ist ja einfach der Erfahrungswert. Das ist jetzt ja gar nicht so ein, ja, ihr dürft aber nicht. Und ich mache das alles besser. Ich habe nie solche Dinge gemacht, sondern das ist ja wirklich eine Entwicklung. Das ist auch genauso, wie wir heute halt zum Beispiel noch hingehen und mit eigenen Policies prüfen, ob zum Beispiel gewisse Standards eingehalten sind, ja, ob bestimmte Benahmungen, ähm, da sind in.end-Files, ja, auch wir nutzen an bestimmten Stellen.end-Files, die enthalten nur keine Credentials, ja, die enthalten halt so etwas wie, hey, die App läuft nicht in Debug, sondern sie ist auf produktiv gestellt, ja.
Ganz normale Config, genau.
Genau, so.
Also keine Secrets, sondern Konfiguration der Applikation, ja.
oder dass ein bestimmtes Feature jetzt eingeschaltet ist und solche Dinge. Das schreiben wir ja auch in.env-Files und die prüfen wir oder wir prüfen auch unsere Compose-Templates. Wir haben ja keine Compose-Dateien mehr in den Repositories drin, sondern wir haben ein Template und unser Makefile sorgt dafür, dass wir die richtigen Templates einbinden und nutzen anhand der Services, die wir brauchen, anhand der PHP-Pakete, die wir eingebunden haben. Da prüfen wir halt auch mit Policies, ob das alles so stimmt, ja, ob zum Beispiel niemand irgendwie versucht, ein MySQL-Passwort so da reinzusneaken, sondern dass die immer über die Runtime kommen.
Also nicht versehentlich mal Sachen mit committed werden oder so, ja.
Und
Hm.
Ja, genau. Manchmal bist du ja in diesem Debuggen drin, änderst Sachen, um einfach mal voranzukommen. Und umgehst bewusst die Mechanismen, die eigentlich da sind. Und damit das aber nicht weiter wandert. Also dann ist es schon committed, dann ist es schon im Repository gelandet. Das ist doof.
Den kann man noch wegschießen, ja.
Aber dann ist es immerhin nur auf einem Feature-Branch. Den kann man wegschießen und dann sind es ja auch nur Dev-Credentials. Dev-Credentials sind auch etwas, die kennen wir nicht, die generieren wir bei den Starts immer wieder neu. Also so nach dem Motto, I don't care, welche, wie das Passwort für den Wall-Key ist oder für die Datenbank auch, also im im lokalen System, ja, beim Starten wird die E gebaut und reingekopiert die Daten, leg halt einen User an mit dem Passwort, was jetzt gerade für diese Umgebung richtig ist.
Mhm.
Funktioniert übrigens hervorragend. Ja, so, ist jetzt auch kein echtes Problem, so DevCredentials, aber dann ist es halt auch egal, ob sie da sind oder nicht da sind, wir brauchen sie nicht im Repo, sie werden automatisch generiert und irgendwie ist es echt angenehm, ja, du musst nicht dran denken, irgendwas anlegen zu müssen, dass deine Entwicklungsumgebung läuft. Wir waren aber in der Pipeline irgendwo und ich bin gedanklich falsch abgeboken.
im entferntesten Sinn ist das ja noch Pipeline. Also aus dem Depp-System heraus
Ja, das ist der Schritt vor der Pipeline, genau. Ah, genau, ich war bei den Policies. Policies habe ich auch letztendlich im letzten Jahr erst so richtig angefangen zu benutzen. Und mittlerweile liebe ich es, weil wir einfach diese Prüfschritte drin haben. Entspricht das alles auch unserem Standard? Haben wir nicht...
Mit welchen Tools definierst du diese Policies denn? Also gibt es sowas wie, sagen wir mal, PHP-Stan oder CS-Fixer oder sowas, dass man sagen kann, ich konfiguriere mir solche Policies mit irgendeinem Tool zusammen und das lasse ich durch das Projekt durchlaufen oder?
Ja, also natürlich nicht mit CS-Fixer, sondern es gibt eigene losgelöste Tools.
Nein, aber...
Lass mich die auch gerne kurz in unserem Setup nachschauen. Ja, Namen sind ja Schall und Rauch für mich. Und du fragst mich direkt nach Tool-Namen, Dani. Das ist hervorragend. Warte mal, ich muss mal mein geliebtes PHP-Storm an dieser Stelle kurz aufmachen. meine große Schwäche sind ja Namen.
Gerade weil man es niederschreibt, muss man sich das eh nicht merken.
Ja, genau, das ist so dieses reingeschrieben, das steht ja auch in unseren Tools.
Ich sage immer, mein Kontext.
Und die Dateiendung ist Rego.
Riko.
Das ist gut. Warte mal. Ja.
Ja, also können wir eine andere Folge mal drüber machen, wo wir wirklich spezifischer drauf eingehen, weil das würde mich echt interessieren, wie man das definiert und was man da genau machen kann.
Ja, vielleicht
Aber generell finde ich es gut zu sagen, es gibt Sachen, die zum Beispiel nach Secrets oder nach Credentials suchen, nach Variablen, die einfach darauf hindeuten, dass Secrets im Code sind, denke ich mal.
Genau, nach klassischen Patterns, so was, wenn irgendwo bestimmte Worte dran stehen, dann finden wir es doof.
Ja, genau. Ja.
So was wie API oder Key. So, das ist so das erste Ding, was dann gefleckt wird, wenn du das in der.env-Datei oder in einer.env-Datei findest, dann mach mal erst mal hier dicht und sag, nee, sorry. so. Tool. Wäre ja was.
Ich finde eine extra Folge dafür gut.
Ja. So, was uns aber auch dazu führt... ich muss jetzt aufpassen, dass ich persönlich gedanklich nicht so sehr springe heute, dass man heute halt auch hingehen kann, wunderbarerweise, und CI, CD-Components, wie sie GitLab hat, jetzt bin ich natürlich wieder sehr tool-lastig und sage, okay, in GitLab ist das so, aber das Prinzip funktioniert, glaube ich, überall, dass man diese einzelnen Jobs, die man hat, mit Tests versieht und schaut, dass die auch getestet sind und eine eigene Release-Pipeline haben. Also unsere Jobs bauen sich zum Beispiel, Pipelines bauen sich aus festen Komponenten, auf und bevor wir eine neue Version releasen, davon durchlaufen die auch Tests und werden dann automatisch released.
Also die Pipeline selber.
Also, ja, die Pipelines selber. Auf die dann wieder die gleichen Sicherheitsregeln im Übrigen gelten. Ja, auch da schauen wir, gibt es Secrets da drin? Verlieren wir irgendwas? Ist da was Auffälligges? Und die Hauptfrage, funktionieren die? Stell dir vor, wir pushen jetzt eine neue Version für das Bauen von Images. Und uns geht dabei die S-Bomb-Generation verloren.
Mhm.
Das wäre halt für uns irgendwie dumm. oder ungünstig, sagen wir mal, weil dann natürlich weitere Schritte irgendwie nicht funktionieren und durchlaufen. Oder die Signierung von Images geht kaputt oder von Paketen. Das können wir halt dadurch, dass wir vorher die Pipeline prüfen, vor dem Release, also den Job prüfen mit Tests und dann erst releasen, können wir das halt sicherstellen, dass die einzelnen Jobs immer funktional bleiben, immer so funktionell wie wir es definiert haben. Und bei uns ist es halt auch noch so, sobald wir eine neue Version von so einer CI-CD-Component erstellt haben, geht halt Renovate hin und updatet alle Abhängigkeiten in den anderen Repositories. Renovate ist ein Tool, womit du Dependency-Updates automatisieren kannst.
Oh.
Sprich, er prüft regelmäßig nicht nur interne, sondern auch externe Abhängigkeiten, gibt es hier eine neue Version. Und in unserem Fall ist es so konfiguriert in bestimmten Grenzen natürlich. Wenn es eine neue Version gibt, geh hin, CD macht zum Beispiel das Composer Update. machen Merch-Requests dafür auf, also ein neuer Feature-Brand oder eine neue Branche, Merch-Requests aufmachen, dann läuft die Pipeline durch und wenn die Pipeline erfolgreich ist, dann mercht der auch selbstständig und lässt das zum Teil bis aufs Produktivsystem durchbauen.
Hm, geil.
So, bedeutet aber auch an der Stelle wieder, wir haben automatische Tests, die halt vollautomatisch durchlaufen können. Und ich habe ja eben schon sowas anklingen lassen wie S-Bomb und Signierung. Das sind auch aus meiner Sicht heute zwei enorm wichtige Baustellen in so einer Pipeline drin und in dem Ganzen, was wir eigentlich mit der Pipeline auch an Sicherheit erreichen wollen. Wir möchten am Tagesende dass das Ergebnis, was wir rausbringen, dem entspricht, was wir getestet haben und wir aber auch jederzeit wissen, was es enthalten, wurde das tatsächlich von uns rausgegeben und ist das auch heute noch sicher.
Mhm. Mhm.
Also, stellen wir mal vor, uns fällt Renovate aus und das macht keine automatischen Updates. Kann ja passieren. Ähm... Oder irgendwo der Prozess hängt oder whatever. Die S-Bomb, die generiert werden kann, das ist ja so eine lange JSON-Datei, die kann ja kein Mensch lesen.
Was ist das genau?
Die enthält aber und wurde hoffentlich zur Build-Zeit gebaut. Also nicht erst irgendwann später mal noch nachgezogen oder so, sondern in dem Moment, wo man alles zusammenbaut, erstellt man diese S-Bomb. und enthält alle eingesetzten Pakete, Software, whatever, die halt in so einem Image und in deiner Applikation enthalten sind. Und das mit der jeweilig verwendeten Version. Sprich, wir wissen eigentlich zu dem Zeitpunkt dann, welche Pakete sind enthalten und welche sind nicht mehr sicher.
Mhm.
Und dieses... Das ist ja in dem Moment, wo ich das baue, nur eine Momentaufnahme. Was ich dann machen muss mit dieser Information, ist aber auch, einen Pipeline-Job zu haben oder ein Tool oder whatever. Irgendein Prozess, der dafür sorgt, dass dieses Bild-Artefakt, was es ja ist, die S-Bomb, mit der Version verbunden ist und dann immer wieder periodisch geprüft wird, sind für die eingesetzten Versionen neue Sicherheitslücken bekannt geworden. Dass ich zu jedem Zeitpunkt weiß, welche Lücken habe ich denn und muss ich jetzt handeln?
Sind neue dazugekommen, ja.
Ist da etwas Kritisches drin, wo ich jetzt sofort was machen muss? Also ich meine, in unserem Prozess würde hoffentlich Renovate, wie gesagt, schon dafür gesorgt haben, dass die neue Version eingespielt ist und alles cool ist. Aber wie gesagt, es kann halt auch immer sein, dass Renovate so eine neue Version nicht bekommt, dass dann Breaking Change ist, dass irgendwas kaputt gegangen ist, wir etwas umkonfigurieren müssen und die Pipeline nicht automatisch durchläuft. Also sprich, du brauchst eine Form von Monitoring und Alerting auf die eingesetzten Pakete, damit du mitbekommst, oh, ich muss jetzt aber handeln. Und das macht dann nicht deine Pipeline sicherer an der Stelle, sondern deine Applikation, aber gehört ja auch irgendwie in diesen Pipeline-Prozess rein. Jetzt waren wir schon auf dem Testsystem, wir haben irgendwie adressiert, okay, wir wissen, was ist da drin, was wir dann noch machen, was das Ergebnis sicherer macht, gar nicht die Pipeline, ist mit Cosign hingehen und uns.
Vielen Dank.
Überprüfbar und im Prinzip sichtbar, was auch bedeutet, wenn wir uns ein Image ziehen, dann prüfen wir auch die Signatur. Wenn die Signatur ungültig ist, dann sehen wir die nicht mehr.
Ja, also das mit den Images und den Signaturen kenne ich.
Hm?
Also ich kenne zum Beispiel den Ansatz ein bisschen anders, dass der Gedanke ist, man baut die Applikation fertig in einem Container. Also es bezieht sich auch wirklich nur auf Docker, also entweder ECS oder hier Kubernetes oder so.
Ja, ist ja...
baust deine Applikation im Container fertig, signierst das Ganze und das ist sozusagen dein Bildartefakt und das Ding kannst du dann durchdeployen und hast sozusagen die Unveränderlichkeit. Also ich glaube, das ist ähnlich wie mit dem S-Bomb so ein bisschen.
Ja, genau.
Also diese Unveränderlichkeit zumindest festgestellt, dass in Prod die gleiche Konstellation von Abhängigkeiten genutzt wird wie im Testsystem. Aber was
Also die S-Bomb beschreibt ja, was du drin hast und das Signieren sorgt ja nur dafür, was heißt sorgt nur dafür, sagt halt, okay, hier, die haben es rausgebracht und wenn du halt statt einer Versionsnummer zumindest bei Container-Images hingehst und die Digits nimmst oder wie auch immer man das ausspricht, also den Char-Wert, dann sorgst du ja dafür, dass du wirklich die Version nimmst, die du haben möchtest.
Ja.
Das ist zum Beispiel auch etwas, was wir machen. Wir nutzen diesen unfassbar langen String, den Hashwert, zum Identifizieren, welche Version wollen wir dann ausspielen. Oder welche Version wird da genutzt? Da steht zwar vor, dann unsere semantische Versionssummer, aber letztendlich beziehen wir uns immer darauf, welcher Hash es ist.
Ja, macht es dann auch. Also der Hash ist dann der Comet-Hash oder aus dem signierten Container? Sorry.
Boah, du stellst hier eine Frage.
Also ich frage deswegen, weil, also ich nutze gerne den Comet-Hash, weil in der Pipeline dann recht einfach auch Rollbacks machbar sind, dass du sagen kannst, guck mal, ich triggere, also produktiv hat nicht funktioniert, ist irgendwas gefailt, ich kann die Pipeline davor nochmal triggern und dann wird der Container
Das ist...
Also wenn der Container Hash gleich dem Comet Hash ist, dann hast du ja eine recht einfache Versionierung drin und kannst sagen, das ist das Artefakt.
Du nimmst quasi den Commit-Hash als Versionsnummer. Ja, wir nehmen da semantische Versionsnummern. Also, sprich...
Sieht schöner aus, aber dann musst du da hin und her rechnen und dafür war ich zu faul.
Ja, wir setzen aber halt an jedes Paket, das wir bauen, also auch an die Gesamt-CMS-Applikationen, also an das Gesamt-CMS-Paket mit allen Extensions und so weiter, setzen wir die semantische Versionsnummer.
Mhm.
Da legen wir die fest und übergeben die an die Container-Pipeline, die den Container baut. Und der Commit-Hash ist auch so ein Ding. Also im Prinzip ist es ein Git-Tag, den wir da weitergeben, der die Versionsnummer macht, aber die Digits, also dieser Hash, der das in Absolut für Docker oder oder Kubernetes oder, oder, oder identifiziert, das ist nochmal ein Ding, was halt bei dem Bild von dem Image entsteht.
sehr mathematisch gleich.
der leitet sich jetzt nicht irgendwie ab aus der Versionsnummer oder aus irgendetwas, was du selber dranhängst, sondern das ist nochmal ein anderer Heft, der, ich weiß leider nicht, wie der berechnet wird, aber der halt ganz eindeutig jetzt dieses eine Image identifiziert und der auch nicht veränderlich ist. Weil du könntest ja zum Beispiel einfach ein Container-Image löschen, und den gleichen Tag nochmal vergeben. Also egal, ob das ein Commit ist oder eine semantische Versionsnummer, du könntest halt sagen, okay, bau mir halt Latest nochmal neu. Und Latest ist ja so ein Ding, was zum Beispiel ja total häufig ver... Ja, genau.
Niemand benutzt Latest.
Aber was ja einfach gar keinen Bezug zur Realität hat, das ändert sich ja, was Latest ist.
Ja, also du kannst in dem Repository einstellen, dass Tags, also in dem Container Repository, dass Tags nicht wiederverwendbar sind.
Ja, musst du halt machen.
Also das habe ich jetzt natürlich nicht gesagt, aber davon gehe ich aus, weil ansonsten hast du ganz viele Probleme, wenn Tags nicht wieder, wenn Tags wiederverwendet werden oder wiederverwendbar sind.
Ja. Ja.
Also hier die üblichen Pod, Dev und Staging Tags, wo die Container immer neu gepusht werden. Aber da hast du andere Probleme dann. Richtig.
Habe ich nicht, weil haben wir ja gesetzt. Ja. Aber sowas wie Latest ist halt so ein Standardding. Jeder schreibt irgendwie Latest und jeder schreibt irgendwie Def. Und da entstehen natürlich, wenn du das so machst, hast du natürlich irgendwann Probleme. Es ist auch total toll, immer Latest zu ziehen. Das gibt Sicherheit, dass man weiß, was drin ist.
Ja, es ist natürlich einfacher, ein Skript zu schreiben, also in meinem Kontext jetzt mit AWS oder so, ist es einfacher ein Skript zu schreiben, was einfach sagt, ne, baue oder deploy diesen Task nochmal neu und die Version soll latest sein. Easy festgeschrieben, weil ansonsten musst du ja bei jedem Deployment rausfinden, was die Version ist, die deployed wurde und auch den AWS-Task anpassen. Also du musst so ein bisschen mehr machen und ich kann nicht schon verstehen, dass dann es einfacher ist oder dass man dann geneigt ist zu sagen, ich möchte prod, dev oder stage deployen.
Genau. Kann man so machen.
Das ist ein fester Wert und den muss ich nicht irgendwo herbekommen. Hm.
kommt halt darauf an, was man an einem weiteren Setup haben möchte. Ich sage jetzt mal, das ist ja auch so ein gewisser Reifegrad, der sich entwickelt. Niemand startet damit und sagt jetzt, ich baue jetzt die perfekte Pipeline oder den perfekten Cluster, sondern das ist ja ein Aufbauen und eine Evolution und es verändert sich ja auch mit den Dingen, die
Ja, ja.
man erfüllen will oder erfüllen muss oder der Erfahrung auch haben. Wenn dir fünfmal oder vielleicht auch zwei-, dreimal nur das System kaputt gegangen ist, dann schreibst du ja hoffentlich irgendwann einen Test dafür, dass das nicht mehr passiert. So. Und genauso funktioniert das ja mit Pipelines und diesen ganzen Prozessen. Es ist ja nicht so, dass auch die Pipelines und die Steps, die wir jetzt gerade hier machen, dass das über Nacht entstanden ist. Also ich habe irgendwann mit CI-CD angefangen, als Jenkins noch Hudson hieß.
Oh ja, mhm.
So, und irgendwann saß ich dann auch mal in einer Runde, wo jemand seine Probleme mit der CI-CD-Pipeline berichtet hat und erzählt hat, naja, wir spielen das dann auf den Testserver aus und dann machen wir Composer Update. Und dann spielen wir das auf den Produktiv-Server auf und da machen wir Composer Update. Und dann halt so dieses Problem beschrieben hat, was auch ganz logisch ist, wenn man halt weiß, wie das funktioniert, aber ganz logisch war an der Stelle. dass dann halt die Versionen und gar nicht stimmt und da geht immer so viel kaputt und irgendwie ist dieses automatische Deployment ja überhaupt gar nicht sinnvoll und diese Pipelines, das hilft ja alles nichts. Früher war alles besser mit FTP so ungefähr, aber das ist halt so ein, man muss sich halt daran gewöhnen, im ersten Schritt dieser Pipeline wird meinetwegen das Composer Update gemacht,
SFTP.
wenn man das automatisch macht, weil man mit Paketen arbeitet, die dann das triggern. Und danach ist das aber festgelegt und wenn man jetzt nicht diese Bildartefakte mitschleppt, dann macht man immer ein Composer. Ja, eigentlich ist halt
Ja.
macht man in einer Pipeline, außer man hat so eine automatisierte Update-Pipeline-Geschichte da, idealerweise mit Renovate oder einem anderen Tool, das es macht, Depender-Bot oder so, hast du halt ja nie das Bedürfnis oder solltest du nie das Bedürfnis haben, einfach Updates zu machen, ja, zu sagen, hier Composer Update und vor allem nicht, wenn du auf dem Server direkt drauf deployst, gar nicht mit Containern arbeitest und da sagst, das ist ein anderer Pipeline-Cheap irgendwie, ne, da brauchst du dir ja den Image-Bild, aber dann, dann
Hmm.
hast du idealerweise ja auch in der Pipeline das PHP-Artefakt quasi zusammengebaut, das du dann rüberkopierst mit AirSync, ohne Git, ohne Tests, ohne, hast du nicht gesehen, ja, dass man auch diese Dinge rauslässt, Testfälle zum Beispiel gehören gar nicht auf ein Produktivsystem am Tagesende. Also diese PHP-Unit-Testsachen, die ließen bei uns gar nicht mit in das Produktive oder in das Image dann rein. Selbst in das Test-Image sind sie nicht drin, nachher reingebaut.
Sollten sie auch nicht.
Das sind alles Sachen, die vorher ausgeführt werden und dann wird gefiltert.
Ich meine, das wird sich halt zurückgehen. Hm.
Und genauso, wenn man halt auf Bare Metal oder V-House oder so rübergeht, ist es ja nicht so, dass auch Composer da leben sollte. Also Composer sollte da auch als Executive gar nicht existieren. Aus meiner Sicht, ja, du möchtest da gar kein Composer-Install machen. Du möchtest eigentlich dein festes Set an PHP-Dateien nehmen und dort rüberbringen und dann hoffentlich bitte nicht den SSH-Key in der Variable im GitLab haben als protected, sondern sondern bitte über OIDC oder meinetwegen über ein Secret, das man aus einem Vault oder so gezogen hat, sich anmelden kann.
Ja.
weil wenn du auch, also egal wo, in allen, in der Statistik, OWAPS Top 10 ist es so, dass in den nicht-menschlichen Interaktionen langlebende Secrets auf Platz 3 im Moment platziert wurde in den Top 10. Und ich glaube, dem sollte man bisschen mehr Aufmerksamkeit schenken und sagen, okay, lasst uns schauen, dass wir die Secrets möglichst rausbekommen und nur mit kurzlebigen Dingen arbeiten zum Identifizieren und auch so Sachen nutzen wie MTLS etc.,
Mhm.
dass wir unsere Prozesse sauber haben, ohne Secrets, ohne Credentials auskommen. Und dann quasi wie hier unser Podcast unterwegs ist mit Secrets not included, dass man das so ein bisschen zum Motto der Pipelines und Container und Bildartefakte macht, dass die Geheimnisse tatsächlich einfach nur in der Runtime existieren.
Was ich als Fazit aber noch ganz gut fand, das hast du gerade eben kurz angeschnitten, niemand kommt in ein Projekt und baut eine fertige Pipeline bis zum Ende und in alle Richtungen ausgeprägt, sondern das ist Immer nach Bedarf, je nach Teamgröße, gesetzliche Vorschriften, was auch immer, gibt es ganz viele unterschiedliche Anforderungen. Und dieses, ich würde jetzt auch von vornher nicht hingehen und direkt alles einbauen, sondern erst mal bauen, automatisieren, dann sagen, was sind die nächsten großen Schmerzen. Und die können je nach Projekt unterschiedlich sein. Also es gibt nicht one size fits all. Und das ist die Pipeline, die macht alles richtig und ihr alle anderen macht alles falsch. Das gibt es nicht.
Also das Einzige, wo ich dir widerspreche, S-Bone. Das musst du aus Compliance-Gründen halt haben, genauso wie das Monitoring darauf. Das sind halt gesetzliche Anforderungen und ansonsten Pain-Driven Development.
Ja. Ja.
Oder man hat halt, man sagt halt, okay, wir nehmen ein Set, das macht schon sehr, sehr viel von diesen Dingen, die wir haben wollen und das funktioniert und zieht sich öffentlich aus die ICD-Components für die Sachen rein und baut sich halt das quasi wie mit Lego zusammen. Ja, mit Klemmbaustein, man darf ja Lego gar nicht sagen. mit Klemmbausteinen zusammen und ist dann damit schneller. Man muss das Rad nicht neu erfinden, auch bei Pipelines heute nicht mehr. Ja, Ja, so.
Das ja stimmt.
Ich glaube, das ist ein gutes Fazit. Kleinstarten, groß werden, wiederverwenden, S-Bomb erfüllen, weil man das erfüllen muss und gut ist. Der Rest ist geschenkt. Und Und vielleicht noch zum Schluss, also man kann ja auch immer erfahrene Leute Fragen anschreiben. Und es gibt, glaube ich, wenig Menschen, die jetzt sagen, wir finden da keine Lösung, wie man euch da weiterbringt.
Fragen kosten nichts. Zumindest als Beratung. Dann ciao.
Ja, die erste Frage kostet nichts ungefähr. Wunderbar. Dann, glaube ich, sind wir am Ende unserer wunderbaren Folge diese Woche und sehen uns nächste Woche wieder. Bis dahin. Macht's gut. Tschö.



