Zum Inhalt springen

Secrets vor Git verbergen in SwiftPM

Eine Schritt-für-Schritt-Anleitung, wie du verhinderst, dass deine Secrets für Drittanbieter-Dienste in Git landen, wenn du Apps verwendest, die mit SwiftPM modularisiert sind.

Secrets vor Git verbergen in SwiftPM

Du kennst vielleicht einige traditionelle Methoden, um Secrets wie einen API-Key oder ein Token für Drittanbieter-Dienste zu verstecken, das du für deine App brauchst. Aber heutzutage werden Ansätze zur Modularisierung deiner App mit SwiftPM immer beliebter.

Point-Free hat zum Beispiel eine großartige kostenlose Episode zu diesem Thema, und Majid Jabrayilov hat kürzlich eine 4-teilige Serie über “Microapps Architecture” geschrieben (Teile 1, 2, 3, 4), die ich beide als Einstieg empfehlen kann.

Außerdem möchtest du vielleicht Secrets auch in öffentlichen Open-Source-Bibliotheken verstecken, z.B. in den Unit-Tests einer Drittanbieter-Service-Integration, wo Nutzer der Bibliothek ihr eigenes Token bereitstellen, du aber möchtest, dass deine Tests mit deinem eigenen laufen.

Was all diese Situationen gemeinsam haben: Sie basieren auf einer manuell gepflegten Package.swift-Datei – nicht der, die Xcode für dich verwaltet, wenn du einfach eine Abhängigkeit zu einem App-Projekt hinzufügst. Die App oder das Projekt ist in viele kleine Module aufgeteilt, ohne eine zugehörige .xcodeproj-Datei – Xcode öffnet einfach direkt die Package.swift-Datei, ganz ohne ein Projekt.

Das bedeutet auch, dass es für die einzelnen Module keine Möglichkeit gibt, Build-Einstellungen oder Build-Skripte innerhalb von Xcode festzulegen – alles muss direkt in der Package.swift-Manifestdatei gemacht werden.

Obwohl immer mehr solcher Features zu SwiftPM hinzugefügt werden (wie SE-303, SE-325, SE-332) in zukünftigen Releases, gibt es keine Anzeichen dafür, dass sie Xcode-spezifische Features wie .xcconfig-Dateien unterstützen werden.

Wie können wir also Secrets heute davon abhalten, in Git zu landen, damit sie nicht an unseren Git-Provider oder jemanden mit Zugriff auf unser Repository gelangen?

SwiftPM-Ressourcen & JSONDecoder

Ich bin sicher, es gibt nicht die eine “beste” Antwort darauf und andere haben vielleicht cleverere Ideen als ich. Aber ich halte die Dinge gerne einfach und verwende gerne grundlegende Features, weil ich sie gut kenne und erwarte, dass andere Entwickler sie bei Bedarf schnell verstehen. Außerdem kann ich mir sicher sein, dass sie zukunftssicher sind.

Der Ansatz, den ich verwenden möchte, ist der klassische .env-Datei-Ansatz, der in der Webentwicklung verbreitet ist. Aber statt einer speziell formatierten .env-Datei möchte ich einfach eine .json-Datei mit meinen Secrets verwenden, weil JSON-Dateien vielen iOS-Entwicklern vertraut sind und wir dank JSONDecoder in Swift bereits eingebaute Unterstützung fürs Parsen haben. Das Laden von Dateien oder allgemeiner “Ressourcen” wird ebenfalls seit Swift 5.3 von SwiftPM unterstützt (SE-271).

Hier ist die Grundidee, wie ich Secrets vor Git verbergen möchte:

  1. Eine secrets.json.sample-Datei mit den Keys, aber ohne Werte, in Git einchecken

  2. Entwickler duplizieren sie, entfernen die .sample-Endung und tragen die Werte ein

  3. Die secrets.json-Datei über .gitignore ignorieren, damit sie nie eingecheckt wird

  4. Ein einfaches struct bereitstellen, das Decodable implementiert, um die Secrets auszulesen

Der Rest dieses Artikels ist eine Schritt-für-Schritt-Anleitung, wie du diesen Ansatz anwendest. Ich werde als Beispiel die Unit-Tests meines Open-Source-Übersetzungstools BartyCrouch verwenden, das zwei Drittanbieter-Übersetzungsdienste integriert.

⚠️ Beachte bitte, dass du bei der Anwendung dieses Ansatzes auf ein App-Target, das du an Nutzer ausliefern willst, wahrscheinlich auf dasselbe Problem stößt, das beim .xcconfig-Ansatz in diesem NSHipster-Artikel beschrieben wird. Meine Methode hilft nur beim Verbergen der Secrets vor Git – du brauchst zusätzliche Verschleierung, wenn du sie an Nutzer ausliefern willst.

Die secrets.json-Ressourcendatei hinzufügen

Zuerst fügen wir die secrets.json-Datei zu unserem Projekt hinzu. Da es eine zugehörige secrets.json.sample und eine Secrets.swift-Datei geben wird, erstelle ich zunächst einen Ordner Secrets, dann eine leere Datei namens secrets.json, und füge eine einfache JSON-Dictionary-Struktur mit zwei Keys hinzu:

Die <code>secrets.json</code>-Datei mit zwei echten Secrets, dem Projekt hinzugefügt.

Und so ist auch meine CI eingerichtet, um sicher auf meine Secrets zuzugreifen, ohne sie preiszugeben.

Hat dir dieser Beitrag gefallen? Folge mir auf Bluesky und Mastodon für mehr Swift-Tipps und Indie-Dev-Updates.