Eine Kundenumgebung onboarden¶
Dieses Runbook richtet sich an das Plattform-Team. Es beschreibt, wie eine neue Umgebung des Portals zur gemeinsamen Code-Basis hinzugefügt und deployt wird. Es ist generisch: Werte stehen als Platzhalter (<customer>, <env>, <tenant-id>), und das Vorgehen beschreibt das Referenzdesign. Dein Deployment kann abweichen. „Kunde“ ist die Organisation, der die Azure subscriptions gehören. Sind Plattform-Team und Kunde dieselbe Organisation (Eigenbetrieb), lies die Schritte entsprechend (Betriebsmodelle).
Code und pipelines bleiben beim Anbieter
Im Liefermodell der Quelle erhält der Kunde ein deploytes Produkt und die Azure-Ressourcen in seiner subscription. Der Kunde erhält weder den Code noch die pipelines. Wie ein Team im Eigenbetrieb das Portal ohne sie betreibt, beschreibt die Quelle nicht. Stimme das daher zuerst mit dem Anbieter ab.
Phasen¶
| Phase | Ergebnis | Verantwortlich |
|---|---|---|
| Plan | Kick-off durchgeführt (60 Minuten): was das Portal ist, Kernbotschaften, was der Kunde bereitstellt, Zeitplan. Danach werden Fragebogen und Voraussetzungen verschickt. | Delivery Manager |
| Prepare | Fragebogen ausgefüllt und Voraussetzungen erfüllt | Engineer verfolgt, Kunde erfüllt |
| Deploy | Umgebung im Repository definiert und über die pipeline deployt. Im Tenant des Kunden wird nichts von Hand konfiguriert, außer den Genehmigungen und Berechtigungen unten. | Engineer |
| Validate | Ein zweiter Engineer prüft die Validierungsliste | Zweiter Engineer |
| Closure | Technisches Übergabegespräch (60 bis 90 Minuten) mit den technischen und Security-Ansprechpartnern des Kunden: Demo mit den eigenen Daten des Kunden, Self-Service, Agents, MCP in der Entwicklungsumgebung. Abnahme. | Delivery Manager, Engineer führt die Demo vor |
Kernbotschaften zum Wiederholen
Die Azure-Kosten landen auf der Rechnung des Kunden. Der Anbieter behält das Eigentum am Code. Die Daten bleiben in der Umgebung des Kunden. Nenne die Betriebsgarantie so, wie sie im Vertrag vereinbart ist: Sie ist in den technischen Quellen nicht beschrieben.
Kundenspezifische Code-Änderungen werden nicht vorgenommen. Eine Anfrage, die nicht zur gemeinsamen Code-Basis passt, wird zu separater Feature-Arbeit. Siehe ADR-0007 in Entscheidungen.
Vorgehen¶
Verwende für die Schritte 1 bis 6 einen branch und einen Pull Request.
1. GitHub Environments anlegen¶
Lege pro Azure-Umgebung ein GitHub Environment an, benannt <customer>_<env> (zum Beispiel <customer>_acc und <customer>_prod). Verlange Reviewer in Produktion. Acceptance hat keine Reviewer. Das Environment enthält das Genehmigungs-Gate für das Anwenden eines Terraform-Plans (Deployment und Umgebungen).
2. Federated credentials hinzufügen¶
Füge auf der Deployment-App-Registration Entra federated credentials hinzu, eine für jedes der folgenden Subjects, mit Audience api://AzureADTokenExchange:
| Subject | Verwendet von |
|---|---|
pull_request |
Plan bei Pull Requests |
ref:refs/heads/main |
Plan und Build auf main |
environment:<customer>_<env> |
Apply, eines pro Umgebung |
Der Issuer ist der OIDC-Issuer des GitHub-Enterprise-Tenants. Die Subjects verwenden die unveränderlichen Owner- und Repository-IDs statt Namen. Lässt sich keine federated credential anlegen, weiche auf ein Client Secret (AZURE_CLIENT_SECRET_<OWNER>_<ENV>) aus und frage erneut nach der federated credential. Siehe Authentifizierung gegenüber Azure.
3. Zeilen in der Environments-Datei hinzufügen¶
Füge der Environments-Datei (infra/customer-environments.json) pro Umgebung eine Zeile hinzu. Die Zeile enthält Owner, Umgebung, ring, Terraform-Backend, Deployment-Identität sowie die Namen von Web App und Registry. Siehe Die Environments-Datei.
Setze die erste Umgebung (Acceptance oder Test) in denselben ring wie die ersten Umgebungen anderer Kunden und Produktion in den nächsten ring. Eine strikte Reihenfolge relativ zu einem bestimmten anderen Kunden braucht eine neue ring-Nummer, was die Reihenfolge für jeden Kunden ändert. Bespreche das, bevor du es tust.
4. Secrets setzen¶
Lege das Repository Secret an, auf das die Zeile für das Terraform Client Secret verweist: BACKSTAGE_CLIENT_SECRET_<OWNER>_<ENV>. Es ist das einzige echte Secret im Setup. Der Pull Request enthält nur seinen Namen. Andere App-Secrets (zum Beispiel GitHub-App-Werte) werden in der Zeile benannt und erscheinen als Key-Vault-Referenzen.
5. Infrastruktur hinzufügen¶
Jede Kundenumgebung hat ihr eigenes Terraform root module:
infra/
<customer>/
acc/main.tf
prod/main.tf
Das root setzt die gemeinsamen modules zusammen: spoke canvas (bestehendes Netzwerk lesen), naming, Resource Group, App Service Plan, Key Vault, Container Registry, Azure Monitor, Tenant-Konfiguration, das module backstage und bei Bedarf foundry_platform, cost_insights und pagerduty. Siehe Deployment und Umgebungen und ADR-0009 in Entscheidungen.
Setze die App-Einstellung APP_CONFIG_organization_name im module backstage. Sie wählt die Konfigurationsdatei app-config.<customer>.yaml, daher müssen der Wert im module und der Dateiname exakt übereinstimmen, auch in der Groß- und Kleinschreibung.
6. Konfigurationsdatei hinzufügen¶
Erstelle app-config.<customer>.yaml mit der Microsoft-Anmeldung und dem Repository-Provider. Beispiel (Platzhalter):
auth:
providers:
microsoft:
production:
clientId: ${BACKSTAGE_CLIENT_ID}
clientSecret: ${BACKSTAGE_CLIENT_SECRET}
tenantId: ${BACKSTAGE_TENANT_ID}
signIn:
resolvers:
- resolver: emailMatchingUserEntityAnnotation
catalog:
providers:
azureDevOps:
<organisation>:
host: dev.azure.com
organization: <organisation>
project: '*'
repository: '*'
path: 'catalog-info.yaml'
schedule:
frequency: { minutes: 30 }
timeout: { minutes: 3 }
Optional kannst du für den Kunden einen Feature Loader in packages/backend/src/features/<customer>.ts hinzufügen, um backend plugins ein- oder auszuschalten. Tu das nur, wenn ein Konfigurations-Flag es nicht kann. Siehe Konfiguration.
Optional kannst du Alerting hinzufügen. Das module pagerduty erstellt einen Service, eine Abhängigkeit zu einem Business Service und eine Azure-Monitor-Action-Group. Die gemeinsame Escalation Policy, auf die es verweist, muss bereits existieren (Betrieb).
Private Konnektivität¶
Mehrere Durchläufe nötig
Deployt der Anbieter aus seinem eigenen Netzwerk, braucht er private endpoints, um Ressourcen zu erreichen, die er selbst erstellt. Der Anbieter braucht eine Verbindung zum Deployen, und das Deployment erstellt die nächsten Ressourcen, die er erreichen muss. Rechne damit, dass der erste Lauf fehlschlägt.
- Füge das Terraform-State-Storage-Account zur Liste der privaten Verbindungen im Plattform-root des Anbieters hinzu (Resource-ID und Subresource
blob). - Merge. Die Plattform-pipeline plant bei Pull Requests und wendet beim Merge auf main an.
- Der Kunde genehmigt die ausstehenden private-endpoint-Verbindungen auf den Zielressourcen. Die Anfrage enthält eine Nachricht, die erklärt, dass sie für das Deployment nötig ist. Der Kunde kann eine Verbindung später widerrufen.
- Verbinde die neuen private endpoints mit den privaten DNS zones der Plattform. Dieser Schritt ist für endpoints, die eine Genehmigung brauchen, manuell, weil die Policy, die ihn automatisch erledigt, auf sie nicht greift.
-
Starte den Dispatch-Workflow mit eingeschalteter Infrastruktur und ausgeschaltetem Portal-Build:
gh workflow run cicd-dispatch.yml --ref <your-branch> \ -f "deploy_to=ring 3" -f deploy_infra=true -f build_and_deploy_backstage=falseDer erste Lauf schlägt fehl, wenn Terraform Key Vault oder die Registry über die Data Plane erreicht, weil deren private endpoints noch nicht existieren. Das ist erwartet. 6. Füge die privaten Verbindungen für das Key Vault (
vault), die Container Registry (registry) und die weiteren nun existierenden Ressourcen hinzu (SQL server, Web App und staging slot, blob). Wiederhole die Schritte 2 bis 5, bis der Lauf erfolgreich ist.
Das Genehmigen von Verbindungen lässt sich skripten. Der Kernbefehl lautet:
az network private-endpoint-connection approve --id <connection-id> \
--description "Required for the deployment of the portal"
7. Das Portal deployen¶
Starte den Dispatch-Workflow mit eingeschalteter Infrastruktur und eingeschaltetem Portal:
gh workflow run cicd-dispatch.yml --ref <your-branch> \
-f "deploy_to=ring 3" -f deploy_infra=true -f build_and_deploy_backstage=true
Wiederhole danach die Schritte 5 und 6 für die nächste Umgebung und deploye sie.
8. Der Managed Identity Zugriff gewähren¶
Die Managed Identity des Portals existiert erst nach dem ersten Deployment. Danach:
- Ein Entra-Administrator erteilt die Graph-Anwendungsberechtigungen
User.Read.AllundGroupMember.Read.Allmit Admin Consent (Voraussetzungen). - Der Administrator der Cloud-Plattform vergibt die Azure-Rollen (Voraussetzungen).
Bis beides erledigt ist, fehlen Benutzer und Gruppen, und die Insights sind leer.
9. Optionale Features aktivieren¶
| Feature | Seite |
|---|---|
| Cost Insights | Cost-Insights-Setup |
| AI Agents | AI-Setup |
| Custom Domain und WAF | WAF und Custom Domain |
| GitHub-Integration, Theme, Module Registry | Konfiguration |
Validierung¶
Ein zweiter Engineer führt die Prüfungen durch und hält für jede die verwendete Entity oder den verwendeten Wert fest, nicht nur ein Häkchen.
| Prüfung | Vorgehen |
|---|---|
| Anmeldung | Ein Benutzer der konfigurierten Gruppe meldet sich an und landet in einem gefüllten Katalog |
| Azure-Ingestion | Ein bekannter workload erscheint im Katalog, mit Insights (Kosten, Compliance, Security) |
| Timing der Kosten | Exports laufen normalerweise innerhalb von 24 Stunden und die Ingestion über Nacht, daher können Kostendaten ein bis zwei Tage brauchen. Stoße sie bei Bedarf manuell an. Eine bekannte subscription zeigt den letzten vollständigen Monat. |
| Repository-Ingestion | Die catalog-info.yaml eines bekannten Repositorys erscheint |
| Benutzer und Gruppen | Ein bekannter Benutzer und eine bekannte Gruppe existieren |
| Agents | Der Spoke-Agent beantwortet einen Test-Prompt wie „List all spoke files“, und die Tool-Liste des MCP-Servers ist nicht leer |
| Zugriffskontrolle | Ein Benutzer außerhalb des besitzenden Teams sieht die Details blockierter Firewall-Requests eines workloads, der ihm nicht gehört, nicht |
| Private endpoints | Key Vault, Registry und SQL server werden nur über private endpoints erreicht |
| Datenresidenz | Keine Daten verlassen die subscriptions des Kunden |
| Security-Baseline | Defender-Empfehlungen triagiert, kein öffentlicher Netzwerkzugriff auf Datendienste, überall Managed Identities verwendet |