adesso Blog

Wenn sich eine Person gegenüber einem Programm authentifiziert, gibt sie dafür ein Passwort ein. Aber was macht ein Programm, wenn es sich gegenüber einer anderen Ressource authentifizieren muss? Microsoft bietet mit Azure Identity eine Lösung für die meisten Szenarien. In einem aktuellen Projekt standen wir jedoch vor dem Problem, dass sich unser Programm am Steuerungsserver einer Maschine anmelden musste. Dieser unterstützt Azure nicht, der Hersteller hat uns nur einen Benutzernamen und ein Passwort zur Verfügung gestellt.

Der intuitive Ansatz wäre, die Zugangsdaten auf der Maschine zu hinterlegen. Damit kein Benutzer sie lesen kann, müssten sie verschlüsselt werden. Der Schlüssel müsste wiederum irgendwo hinterlegt werden, und so dreht sich die Idee im Kreis. Aber auch dafür hat Microsoft eine Lösung: Azure KeyVault.

KeyVault

Azure Key Vault ist ein Cloud-Dienst zur sicheren Speicherung von API-Tokens, Passwörtern, Zertifikaten oder kryptografischen Schlüsseln. Der Zugriff darauf kann sehr genau kontrolliert werden.

Zunächst empfiehlt es sich, für jede Anwendung einen eigenen Vault anzulegen. Der Zugriff darauf kann dann auf eine Reihe von IP-Adressen beschränkt werden, um nur Benutzer aus dem eigenen VPN zuzulassen. Um genau zu wissen, wer wann die Geheimnisse gelesen oder geändert hat, kann optional eine detaillierte Protokollierung eingeschaltet werden.

Welche Benutzer die Geheimnisse im Tresor lesen, schreiben oder löschen dürfen, wird über Rollen festgelegt. Das Konzept Role-Base Access Control (RBAC) zieht sich durch ganz Azure. Um es zu verstehen, müssen zunächst drei grundlegende Begriffe geklärt werden:

  • Sicherheitsprinzipal: Dieser Oberbegriff umfasst Benutzerinnen und Benutzer, Gruppen, verwaltete Identitäten und Dienstprinzipale. Letztere sind auch als registrierte Anwendungen bekannt und repräsentieren die Rechte eines Programms, das außerhalb der Cloud ausgeführt wird.
  • Scope: Dieser Begriff lässt sich am besten mit „Umfang“ übersetzen. Es handelt sich um eine begrenzte Menge von Ressourcen. Im Idealfall ist dies ein einzelner Azure Service, es können aber auch Berechtigungen für eine ganze Gruppe von Ressourcen vergeben werden
  • Rollen: Eine Rollendefinition enthält Listen von Erlaubnissen und Verboten.

Damit ein Programm auf seine Geheimnisse zugreifen kann, benötigt es einen Sicherheitsprinzipal, der eine Rolle besitzt, die dies erlaubt. Ein Dienstprinzipal ist eine Identität, die in Azure verwaltet wird. Wie das Programm mit seiner Identität verknüpft wird und damit seine Rolle erhält, hängt davon ab, wo es sich befindet.

Registrierte Anwendungen

Angenommen, alle beteiligten Dienste laufen in einem beliebigen Rechenzentrum. Der betreffende Webservice, nennen wir ihn Maschinen-Client, hat Zugriff auf Azure im Internet und auf den Maschinen-Server im lokalen Netzwerk. Alle notwendigen Zugangsdaten befinden sich gut geschützt im KeyVault.

Im einfachsten Fall liefe der Maschinenclient in einem Docker-Container. Dann würde man ihn über eine Pipeline in Azure DevOps starten und ihm alle nötigen Geheimnisse aus dem KeyVault als Umgebungsvariablen mitgeben. Nur die Pipeline würde Zugriff auf den KeyVault benötigen. Leider war dies nicht der Fall. Stattdessen sollte der Client auf einer lokalen Maschine in der Nähe der Maschine laufen. Er musste also selbst mit Azure kommunizieren.

Bevor der Maschinenclient aus KeyVault lesen darf, muss er als Anwendung in Azure registriert werden. Anschließend wird ein selbstsigniertes Zertifikat direkt auf dem Zielrechner erzeugt. Es besteht aus öffentlichem und privatem Schlüssel. Der Öffentliche wird nun in eine Datei exportiert und im Azure-Portal unter „Zertifikate und Geheimnisse“ hochgeladen.

Mit dem lokal installierten Zertifikat kann sich die registrierte Anwendung bei Azure anmelden, hat aber noch keinen Zugriff auf KeyVault. Dazu muss der Anwendung noch die vordefinierte Rolle „Key Vault Reader“ zugewiesen werden. Anschließend ist sie bereit, sich das Passwort für den Maschinenserver aus KeyVault abzuholen.

Die Abbildung zeigt den Datenfluss. Die Client-Anwendung auf einem beliebigen Rechner wählt zunächst das installierte Zertifikat aus, mit dem sie sich bei Azure anmeldet. Azure wählt dann Zugriff auf KeyVault. Von dort liest die Anwendung nun das Passwort und meldet sich damit auf der Maschine an.

In .NET ist dieser Prozess transparenter als die Abbildung auf den ersten Blick vermuten lässt. Der KeyVault wird beim Start einfach als zusätzliche Konfigurationsquelle registriert. Danach können alle Geheimnisse so verwendet werden, als wären sie offen in den Einstellungen.

	
	builder.Configuration.AddAzureKeyVault(kvUri, clientCertificateCredential);
		var app = builder.Build();
		var myPassword = app.Configuration["my-app-password"];
	

Anmeldung an KeyVault

Microsoft Entra

Für den Fall, dass alle beteiligten Dienste in der Azure Cloud laufen, sollte Managed Identity eingesetzt werden. Keine Anwendung benötigt dann noch ein Zertifikat oder andere Geheimnisse. Azure verwaltet die Identitäten intern und weist allen Services automatisch die vorgesehenen Berechtigungen zu.

Verwaltete Identitäten können entweder nutzerseitig oder systemseitig vergeben werden. Benutzerseitige Identitäten decken den Sonderfall ab, dass sich mehrere Ressourcen eine Identität teilen müssen. Eine systemseitige Identität wird von Azure für genau eine Ressource generiert. Im Beispiel wäre unser Maschinenclient eine Azure-Ressource und hätte somit ohne weiteres Zutun eine Identität innerhalb von Azure, der Rollen zugewiesen werden können.

Im Intranet

In diesem Projekt scheiterte das Azure-Konzept am übergeordneten Sicherheitskonzept. Dem Steuerungsserver der Maschine wurde kein Internetzugang erlaubt. Auch eine VPN-Route zu Azure war nicht erlaubt. Ebenso blieb der Rechner, auf dem unser Client laufen sollte, auf das sicherheitskritische Firmennetzwerk beschränkt. Das ist sehr umsichtig und in diesem Fall absolut sinnvoll. Es kollidierte jedoch mit der Vorgabe, Geheimnisse ausschließlich in KeyVault abzulegen.

Erschwerend kam hinzu, dass der Client seine Einstellungen von einem Konfigurationsserver im selben Netz beziehen sollte. Die Zugangsdaten wären dort offen einsehbar. Sie mussten also verschlüsselt werden. Wieder drehte sich das Problem im Kreis, irgendwo musste der Schlüssel für die Konfiguration ja liegen.

Schließlich installierten wir ein selbstsigniertes Zertifikat auf dem Rechner. Ein Zertifikat ist ein Schlüsselpaar für asymmetrische Kryptographie. Es enthält einen privaten Schlüssel, der zum Entschlüsseln des Geheimnisses dient und fest auf dem Rechner verbleibt, und einen öffentlichen Schlüssel, der ausschließlich zum Verschlüsseln dient und im Konfigurationstool hinterlegt werden kann. So wurden die von den Maschinenherstellern erhaltenen Passwörter für die Steuerungsserver vor dem Hochladen auf den Konfigurationsserver sicher asymmetrisch verschlüsselt und erst bei Bedarf, unmittelbar vor dem Login, vom Clientprogramm entschlüsselt.

Ausblick

So praktisch Cloud-Lösungen auch sein mögen, es wird immer Grenzfälle geben, in denen sie nicht einsetzbar sind. Dann ist es gut, ein paar Standardlösungen zur Hand zu haben, die nicht von einem Cloud-Anbieter abhängig sind.

Wenn aber Azure zur Verfügung steht, dann ist es wünschenswert, möglichst alle Programme, die Azure-Ressourcen nutzen sollen, direkt in Azure zu hosten. Denn dann können alle Berechtigungen über Managed Identity verwaltet werden und die Schlüsselproblematik entfällt komplett.

In den meisten Projekten dürfte heute ein Mischbetrieb aus eigenen Ressourcen und Cloud-Diensten üblich sein. Hier sind Sicherheitsprinzipien mit Client-Zertifikaten die beste Brücke.

Ihr möchtet gern mehr über spannende Themen aus der adesso-Welt erfahren? Dann werft auch einen Blick in unsere bisher erschienenen Blog-Beiträge.

Bild Corinna John

Autorin Corinna John

Corinna John ist Senior Software Engineer bei adesso in Hannover. Ihr Schwerpunkt liegt in der C#-Entwicklung.

Diese Seite speichern. Diese Seite entfernen.