Bei Android beginnt die Vorbereitung einer CI/CD-Pipeline meistens mit einem Keystore. Bei iOS müssen wir deutlich früher anfangen.
Bevor GitHub Actions eine gültige .ipa-Datei für uns erzeugen kann, müssen zunächst die notwendigen Voraussetzungen für das iOS Code Signing geschaffen werden.
Dazu gehören unter anderem:
- ein passender App Identifier
- ein Apple Distribution Certificate
- der dazugehörige Private Key
- ein Provisioning Profile
- ein App Store Connect API Key
Gerade am Anfang kann dieses Zusammenspiel etwas unübersichtlich wirken, da wir dafür sowohl das Apple Developer Portal als auch App Store Connect und zusätzlich die Schlüsselbundverwaltung auf einem Mac benötigen.
Wenn wir die einzelnen Bestandteile jedoch getrennt betrachten, ist das Ganze deutlich überschaubarer.
In diesem Beitrag bereiten wir daher alle benötigten Apple-Ressourcen für einen späteren automatisierten .NET MAUI iOS Build vor.
Unser Ziel ist:
- die benötigten Signing-Komponenten verstehen
- einen App Identifier erstellen
- einen Certificate Signing Request erzeugen
- ein Apple Distribution Certificate erstellen
- das Zertifikat als
.p12exportieren - ein Provisioning Profile erstellen
- einen App Store Connect API Key für unsere CI/CD-Pipeline erzeugen
Den eigentlichen GitHub-Actions-Workflow schauen wir uns anschließend in einem separaten Beitrag an.
Warum ist die Vorbereitung des iOS Signings so wichtig?
Bei iOS kann unser automatisierter Build nur dann zuverlässig funktionieren, wenn die Signing-Konfiguration korrekt vorbereitet wurde.
Wenn beispielsweise Zertifikat, App Identifier und Provisioning Profile nicht zusammenpassen, schlägt die Pipeline nicht zufällig fehl. In den meisten Fällen liegt die Ursache dann genau in dieser Konfiguration.
Wenn wir das Signing von Anfang an sauber aufsetzen, erhalten wir einige Vorteile:
- unsere Bundle ID wird einmal definiert und anschließend konsistent verwendet
- unser Signing Certificate kann über eine
.p12-Datei in die CI-Umgebung importiert werden - unser Provisioning Profile gehört eindeutig zu unserer Anwendung
- GitHub Actions kann später das passende Provisioning Profile verwenden
- zukünftige Release-Builds hängen nicht mehr von einem speziell konfigurierten Mac ab
Das eigentliche Ziel besteht also auch hier wieder darin, den Release-Prozess reproduzierbar zu machen.
Voraussetzungen
Bevor wir beginnen, benötigen wir:
- eine aktive Mitgliedschaft im Apple Developer Program
- Zugriff auf App Store Connect
- einen Mac beziehungsweise Zugriff auf macOS
- eine geplante Bundle ID für unsere Anwendung
Für unser Beispiel verwenden wir folgende Bundle ID:
com.companyname.myawesomemauiapp
Natürlich solltet ihr hier eure eigene Domain beziehungsweise eure eigene Namensstruktur verwenden.
Die wichtigsten Bestandteile des iOS Signings
Bevor wir die einzelnen Ressourcen erstellen, sollten wir zunächst kurz klären, welche Rolle sie spielen.
Bundle ID / App ID
Die Bundle ID ist die eindeutige Kennung unserer Anwendung.
Zum Beispiel: com.companyname.myawesomemauiapp
Diese ID muss sowohl innerhalb unserer .NET MAUI Anwendung als auch im Apple Developer Portal und im Provisioning Profile identisch sein.
Certificate Signing Request
Der Certificate Signing Request, kurz CSR, wird verwendet, um bei Apple ein Signing Certificate anzufordern.
Die CSR-Datei enthält Informationen, die Apple benötigt, um uns anschließend ein Zertifikat auszustellen.
Apple Distribution Certificate
Das Apple Distribution Certificate wird zum Signieren unserer Release-Builds verwendet.
Es bestätigt, dass unsere Anwendung von einem berechtigten Apple Developer Account signiert wurde.
.p12-Datei
Eine .p12-Datei enthält unser Zertifikat zusammen mit dem dazugehörigen privaten Schlüssel.
Genau diese Kombination benötigen wir später in unserer CI/CD-Pipeline.
Provisioning Profile
Das Provisioning Profile verbindet mehrere Dinge miteinander:
- unsere App ID
- die gewünschte Distribution-Methode
- unser Signing Certificate
Nur wenn diese Komponenten zusammenpassen, kann unsere Anwendung korrekt signiert werden.
App Store Connect API Key
Über einen App Store Connect API Key kann sich unsere GitHub Action später automatisiert gegenüber Apple authentifizieren.
Dieser Key wird nicht zum Signieren der Anwendung verwendet.
Er dient beispielsweise dazu, benötigte Ressourcen aus App Store Connect abzurufen.
Der wichtigste Punkt ist also weniger, sich alle Begriffe zu merken. Entscheidend ist vielmehr, dass alle Komponenten dieselbe Anwendung beschreiben.
Schritt 1: App ID unserer .NET MAUI App prüfen
Bevor wir irgendetwas im Apple Developer Portal anlegen, sollten wir zunächst prüfen, welche Bundle ID unsere Anwendung verwenden soll.
In einer .NET MAUI Anwendung finden wir diese normalerweise in der .csproj-Datei:
<ApplicationId>com.companyname.myawesomemauiapp</ApplicationId>
Alternativ können wir diesen Wert später auch während unseres CI-Builds überschreiben.
Unabhängig davon, welchen Ansatz wir wählen, muss die verwendete Bundle ID mit dem Identifier bei Apple übereinstimmen.
Wenn wir unsere Bundle ID später ändern, müssen wir entsprechend auch den Identifier und das Provisioning Profile bei Apple anpassen.
Daher lohnt es sich, die ID frühzeitig festzulegen.
Schritt 2: Identifier im Apple Developer Portal erstellen
Als Nächstes erstellen wir die App ID für unsere Anwendung.
Dafür öffnen wir im Apple Developer Portal den Bereich: Certificates, Identifiers & Profiles
Anschließend:
- Identifiers öffnen
- Register an App ID auswählen
- als Typ App auswählen
- eine Beschreibung vergeben
- unsere Bundle ID eintragen
- benötigte Capabilities aktivieren
- Identifier speichern
Schritt 3: Certificate Signing Request erstellen
Um unser Apple Distribution Certificate erstellen zu können, benötigen wir zunächst einen Certificate Signing Request.
Diesen erstellen wir normalerweise über die Schlüsselbundverwaltung von macOS.
Auf einem Mac öffnen wir dafür Keychain Access beziehungsweise die Schlüsselbundverwaltung.
Anschließend wählen wir: Keychain Access → Certificate Assistant → Request a Certificate From a Certificate Authority
Dort geben wir unsere E-Mail-Adresse und unseren Namen an.
Anschließend wählen wir: Saved to disk
Die erzeugte Datei speichern wir beispielsweise als CertificateSigningRequest.certSigningRequest oder als .csr-Datei.
An dieser Stelle passiert außerdem etwas sehr Wichtiges.
Beim Erstellen des Certificate Signing Requests wird auf unserem Mac gleichzeitig ein privater Schlüssel erzeugt.
Dieser Private Key gehört zu unserem späteren Apple Distribution Certificate.
Genau diese Verbindung benötigen wir später noch einmal.
Schritt 4: Apple Distribution Certificate erstellen
Mit unserem Certificate Signing Request können wir nun das eigentliche Distribution Certificate erzeugen.
Dafür wechseln wir wieder in: Apple Developer → Certificates, Identifiers & Profiles
Anschließend:
- Certificates öffnen
- ein neues Zertifikat hinzufügen
- Apple Distribution auswählen
- unseren zuvor erzeugten CSR hochladen
- das erzeugte Zertifikat herunterladen
Apple stellt uns anschließend normalerweise eine .cer-Datei zur Verfügung.
Dieses Zertifikat verwenden wir für unsere späteren Release-Builds.
Die .cer-Datei alleine reicht für unsere GitHub Action allerdings noch nicht aus.
Unsere CI-Pipeline benötigt neben dem Zertifikat auch den dazugehörigen privaten Schlüssel.
Daher müssen wir das Zertifikat als .p12 exportieren.
Schritt 5: Zertifikat als .p12 exportieren
Nun öffnen wir auf unserem Mac die heruntergeladene .cer-Datei.
Durch einen Doppelklick wird sie normalerweise automatisch in die Schlüsselbundverwaltung importiert.
Unter My Certificates beziehungsweise Meine Zertifikate sollten wir nun unser Apple Distribution Certificate sehen.
Wichtig ist, dass darunter auch der zugehörige Private Key angezeigt wird.
Anschließend:
- Zertifikat inklusive Private Key auswählen
- Rechtsklick
- Export auswählen
- als
.p12exportieren - ein sicheres Passwort für den Export vergeben
Diese .p12-Datei können wir später innerhalb unserer GitHub Action in einen temporären Keychain importieren.
Falls unter unserem Zertifikat kein Private Key angezeigt wird, passt das Zertifikat nicht zum privaten Schlüssel auf diesem Mac.
Das passiert beispielsweise, wenn:
- der CSR auf einem anderen Mac erstellt wurde
- der private Schlüssel gelöscht wurde
- das Zertifikat auf Basis eines anderen CSR erzeugt wurde
Ohne den passenden Private Key können wir keine funktionierende .p12-Datei exportieren.
Das ist eine der häufigsten Fehlerquellen beim iOS Code Signing.
Daher sollten CSR und Zertifikat immer zusammen betrachtet und entsprechend sicher aufbewahrt werden.
Schritt 6: Provisioning Profile erstellen
Nachdem Identifier und Distribution Certificate vorhanden sind, können wir nun unser Provisioning Profile erzeugen.
Dafür öffnen wir erneut: Apple Developer → Certificates, Identifiers & Profiles
Anschließend:
- Profiles öffnen
- ein neues Profil hinzufügen
- den passenden Distribution-Typ auswählen
- unsere App ID auswählen
- unser Apple Distribution Certificate auswählen
- einen eindeutigen Namen vergeben
- Provisioning Profile erzeugen
Das Provisioning Profile verbindet jetzt unsere Anwendung mit dem zuvor erzeugten Distribution Certificate.
Damit haben wir einen weiteren wichtigen Bestandteil für unseren späteren CI-Build vorbereitet.
Schritt 7: App Store Connect API Key erstellen
Für unsere GitHub Action benötigen wir zusätzlich einen App Store Connect API Key.
Über diesen Key kann sich unsere Pipeline später gegenüber App Store Connect authentifizieren.
Dafür öffnen wir App Store Connect und wechseln zu: Users and Access → Integrations → App Store Connect API
Dort erstellen wir einen neuen API Key.
Wir vergeben einen passenden Namen und wählen die benötigten Berechtigungen.
Anschließend benötigen wir drei Informationen:
- die
.p8-Datei - die Key ID
- die Issuer ID
Die Key-Datei sieht beispielsweise folgendermaßen aus: AuthKey_ABC123DEF4.p8
Die .p8-Datei kann nur einmal heruntergeladen werden.
Daher sollten wir sie direkt sicher speichern.
Die Key ID und Issuer ID benötigen wir später ebenfalls innerhalb unserer GitHub Action.
Wichtig ist dabei noch einmal: Der App Store Connect API Key wird nicht zum Signieren unserer App verwendet. Das Signing erfolgt weiterhin mit unserem Apple Distribution Certificate. Der API Key wird lediglich zur Authentifizierung gegenüber Apples APIs verwendet.
Schritt 8: Alle Komponenten überprüfen
Bevor wir mit unserer eigentlichen GitHub Action beginnen, sollten wir überprüfen, ob alle Komponenten korrekt zusammenpassen. Dabei sollten wir insbesondere folgende Punkte kontrollieren:
- die Bundle ID unserer .NET MAUI App entspricht dem Apple Identifier
- das Provisioning Profile wurde für genau diesen Identifier erzeugt
- das Provisioning Profile verwendet unser Apple Distribution Certificate
- unsere
.p12-Datei enthält Zertifikat und zugehörigen Private Key - der App Store Connect API Key besitzt die benötigten Berechtigungen
- Zertifikat und Provisioning Profile sind noch gültig und nicht abgelaufen
Wenn all diese Komponenten zusammenpassen, wird unser späterer GitHub-Actions-Workflow deutlich einfacher.
Dann müssen wir im Wesentlichen nur noch die vorbereiteten Ressourcen importieren beziehungsweise abrufen und anschließend dotnet publish ausführen.
Fazit
Der schwierigste Teil eines automatisierten iOS-Builds ist meistens nicht die eigentliche GitHub Action. Die größere Herausforderung besteht darin, die verschiedenen Apple-Ressourcen korrekt vorzubereiten und miteinander zu verknüpfen.
Ab diesem Punkt wird die eigentliche Automatisierung deutlich mechanischer.
Wir bewegen uns damit von der Frage: Kann ein entsprechend konfigurierter Mac einen signierten iOS Build erzeugen? hin zu: Kann unsere CI/CD-Pipeline jederzeit denselben signierten Build reproduzierbar erstellen? Genau das ist unser Ziel.
Im nächsten Beitrag schauen wir uns daher an, wie wir diese vorbereiteten Ressourcen in GitHub Secrets hinterlegen und über GitHub Actions automatisch eine .ipa-Datei für unsere .NET MAUI Anwendung erzeugen.