Authentifizieren des Zugriffs auf Event Hubs-Ressourcen mit Shared Access Signatures (SAS)

Shared Access Signature (SAS) ermöglicht Ihnen die präzise Steuerung des Zugriffstyps, den Sie den Clients gewähren. Folgende Kontrollen können Sie beispielsweise in einer SAS festlegen:

  • Das Intervall, in dem die SAS gültig ist, einschließlich der Startzeit und der Ablaufzeit.
  • Berechtigungen, die von der SAS gewährt werden. Beispielsweise kann eine SAS für einen Event Hubs-Namespace die Berechtigung „Lauschen“, jedoch nicht die Berechtigung „Senden“ gewähren.
  • Nur Clients, die gültige Anmeldeinformationen bereitstellen, können Daten an einen Event Hub senden.
  • Ein Client kann nicht die Identität eines anderen Clients annehmen.
  • Ein nicht autorisierter Client kann daran gehindert werden, Daten an einen Event Hub zu senden.

In diesem Artikel wird die Authentifizierung des Zugriffs auf Event Hubs-Ressourcen mit SAS behandelt. Informationen zum Autorisieren des Zugriffs auf Event Hubs-Ressourcen mit SAS finden Sie in diesem Artikel.

Hinweis

Microsoft empfiehlt als bewährte Methode, nach Möglichkeit Microsoft Entra Anmeldeinformationen anstelle der Shared Access Signatures zu verwenden, da diese leichter kompromittiert werden können. Sie können weiterhin Shared Access Signatures (SAS) verwenden, um differenzierte Zugriffsrechte für Ihre Event Hubs-Ressourcen zu gewähren. Microsoft Entra ID bietet jedoch ähnliche Funktionen ohne die Notwendigkeit, SAS-Token verwalten oder sich um das Widerrufen einer kompromittierten SAS kümmern zu müssen.

Weitere Informationen zur Microsoft Entra Integration in Azure Event Hubs finden Sie unter Autorisieren des Zugriffs auf Event Hubs-Ressourcen mit Microsoft Entra ID.

Konfigurieren der SAS-Authentifizierung

Sie können eine SAS-Regel für einen Event Hubs-Namespace oder eine Entität (Event Hub-Instanz oder Kafka-Thema in einer Event Hub-Instanz) konfigurieren. Das Konfigurieren einer SAS-Regel für eine Consumergruppe wird zurzeit nicht unterstützt, Sie können den Zugriff auf Consumergruppen jedoch mit den für einen Namespace oder eine Entität konfigurierten Regeln sichern.

Die folgende Abbildung zeigt, wie die Autorisierungsregeln auf Beispielentitäten angewendet werden.

Konfigurieren einer Autorisierungsregel

In diesem Beispiel enthält der Event Hubs-Beispielnamespace (ExampleNamespace) zwei Entitäten: „eh1“ und „topic1“ von Kafka. Die Autorisierungsregeln werden sowohl auf Entitätsebene als auch auf Namespaceebene definiert.

Die Autorisierungsregeln „manageRuleNS“, „sendRuleNS“ und „listenRuleNS“ gelten sowohl für „eh1“ als auch „t1“. Die Autorisierungsregeln „listenRule-eh“ und „sendRule-eh“ gelten nur für „eh1“, und die Autorisierungsregel „sendRuleT“ gilt nur für das „topic1“.

Wenn Sie die Autorisierungsregel „sendRuleNS“ verwenden, können Clientanwendungen sowohl an „eh1“ als auch an „topic1“ Daten senden. Bei Verwendung der Autorisierungsregel „sendRuleT“ wird nur der differenzierte Zugriff auf „topic1“ erzwungen. Daher können Clientanwendungen, die diese Regel für den Zugriff verwenden, keine Daten an „eh1“ senden, sondern nur an „topic1“.

Generieren eines SAS-Tokens

Jeder Client mit Zugriff auf den Namen einer Autorisierungsregel und einen von deren Signaturschlüsseln kann ein SAS-Token generieren. Zur Tokengenerierung wird eine Zeichenfolge im folgenden Format erstellt:

  • se: Tokenablaufwert. Eine ganze Zahl, die die Anzahl von Sekunden seit der Epoche 00:00:00 Uhr UTC am 1. Januar 1970 (UNIX-Epoche) beim Ablauf des Tokens darstellt.
  • skn: Name der Autorisierungsregel, d. h. der Name des SAS-Schlüssels.
  • sr: URI der Ressource, auf die zugegriffen wird.
  • sig: Signatur.

Die Signaturzeichenfolge ist der SHA-256-Hash, der über den Ressourcen-URI berechnet wird (der im vorherigen Abschnitt beschriebene Bereich), und eine Zeichenfolgendarstellung des Tokenablaufwerts, getrennt durch CR-LF. Die Berechnung des Hashs ähnelt dem folgenden Pseudocode und gibt einen 256-Bit-/32-Byte-Hashwert zurück.

SHA-256('https://<yournamespace>.servicebus.windows.net/'+'\n'+ 1438205742)

Das Token enthält die Werte ohne Hash, sodass der Empfänger den Hash mit den gleichen Parametern neu berechnen und überprüfen kann, ob der Aussteller im Besitz eines gültigen Signaturschlüssels ist.

Der Ressourcen-URI ist der vollständige URI der Service Bus-Ressource, auf die der Zugriff beansprucht wird. Beispiel: http://<namespace>.servicebus.windows.net/<entityPath> oder sb://<namespace>.servicebus.windows.net/<entityPath>, also http://contoso.servicebus.windows.net/eh1.

Der URI muss als Prozentwert codiert sein.

Die zum Signieren verwendete SAS-Regel muss für die durch diesen URI angegebene Entität oder eines seiner hierarchisch übergeordneten Elemente konfiguriert werden. Beispiel: http://contoso.servicebus.windows.net/eh1 oder http://contoso.servicebus.windows.net im vorherigen Beispiel.

Ein SAS-Token ist für alle Ressourcen mit dem Präfix <resourceURI> in der Signaturzeichenfolge gültig.

Hinweis

Sie generieren mithilfe der SAS-Richtlinie ein Zugriffstoken für Event Hubs. Weitere Informationen finden Sie unter Shared access authorization policies (SAS-Autorisierungsrichtlinien).

Generieren einer Signatur (eines Tokens) anhand einer Richtlinie

Im folgenden Abschnitt wird gezeigt, wie Sie ein SAS-Token mithilfe von SAS-Richtlinien erstellen:

NodeJS

function createSharedAccessToken(uri, saName, saKey) { 
  if (!uri || !saName || !saKey) { 
          throw "Missing required parameter"; 
      } 
  var encoded = encodeURIComponent(uri); 
  var now = new Date(); 
  var week = 60*60*24*7;
  var ttl = Math.round(now.getTime() / 1000) + week;
  var signature = encoded + '\n' + ttl; 
  var hash = crypto.createHmac('sha256', saKey).update(signature, 'utf8').digest('base64'); 
  return 'SharedAccessSignature sr=' + encoded + '&sig=' +  
      encodeURIComponent(hash) + '&se=' + ttl + '&skn=' + saName; 
}

Um einen Richtliniennamen und einen Schlüsselwert zum Herstellen einer Verbindung mit einem Event Hub zu verwenden, nutzen Sie den Konstruktor EventHubProducerClient, der den Parameter AzureNamedKeyCredential verwendet.

const producer = new EventHubProducerClient("NAMESPACE NAME.servicebus.windows.net", eventHubName, new AzureNamedKeyCredential("POLICYNAME", "KEYVALUE"));

Sie müssen einen Verweis auf AzureNamedKeyCredentialhinzufügen.

const { AzureNamedKeyCredential } = require("@azure/core-auth");

Um ein SAS-Token zu nutzen, das Sie mit dem Code generiert haben, verwenden Sie den Konstruktor EventHubProducerClient, der den Parameter AzureSASCredential verwendet.

var token = createSharedAccessToken("https://NAMESPACENAME.servicebus.windows.net", "POLICYNAME", "KEYVALUE");
const producer = new EventHubProducerClient("NAMESPACENAME.servicebus.windows.net", eventHubName, new AzureSASCredential(token));

Sie müssen einen Verweis auf AzureSASCredentialhinzufügen.

const { AzureSASCredential } = require("@azure/core-auth");

Java

private static String GetSASToken(String resourceUri, String keyName, String key)
  {
      long epoch = System.currentTimeMillis()/1000L;
      int week = 60*60*24*7;
      String expiry = Long.toString(epoch + week);

      String sasToken = null;
      try {
          String stringToSign = URLEncoder.encode(resourceUri, "UTF-8") + "\n" + expiry;
          String signature = getHMAC256(key, stringToSign);
          sasToken = "SharedAccessSignature sr=" + URLEncoder.encode(resourceUri, "UTF-8") +"&sig=" +
                  URLEncoder.encode(signature, "UTF-8") + "&se=" + expiry + "&skn=" + keyName;
      } catch (UnsupportedEncodingException e) {

          e.printStackTrace();
      }

      return sasToken;
  }


public static String getHMAC256(String key, String input) {
    Mac sha256_HMAC = null;
    String hash = null;
    try {
        sha256_HMAC = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(), "HmacSHA256");
        sha256_HMAC.init(secret_key);
        Encoder encoder = Base64.getEncoder();

        hash = new String(encoder.encode(sha256_HMAC.doFinal(input.getBytes("UTF-8"))));

    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
   } catch (IllegalStateException e) {
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }

    return hash;
}

PHP

function generateSasToken($uri, $sasKeyName, $sasKeyValue) 
{ 
    $targetUri = strtolower(rawurlencode(strtolower($uri))); 
    $expires = time(); 	
    $expiresInMins = 60; 
    $week = 60*60*24*7;
    $expires = $expires + $week; 
    $toSign = $targetUri . "\n" . $expires; 
    $signature = rawurlencode(base64_encode(hash_hmac('sha256', 			
     $toSign, $sasKeyValue, TRUE))); 
    
    $token = "SharedAccessSignature sr=" . $targetUri . "&sig=" . $signature . "&se=" . $expires . 		"&skn=" . $sasKeyName; 
    return $token; 
}

C#

private static string createToken(string resourceUri, string keyName, string key)
{
    TimeSpan sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
    var week = 60 * 60 * 24 * 7;
    var expiry = Convert.ToString((int)sinceEpoch.TotalSeconds + week);
    string stringToSign = HttpUtility.UrlEncode(resourceUri) + "\n" + expiry;
    using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key)))
    {
        var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
        var sasToken = String.Format(CultureInfo.InvariantCulture, "SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}", HttpUtility.UrlEncode(resourceUri), HttpUtility.UrlEncode(signature), expiry, keyName);
        return sasToken;
    }
}

PowerShell

[Reflection.Assembly]::LoadWithPartialName("System.Web")| out-null
$URI="myNamespace.servicebus.windows.net/myEventHub/"
$Access_Policy_Name="RootManageSharedAccessKey"
$Access_Policy_Key="myPrimaryKey"
#Token expires now+300
$Expires=([DateTimeOffset]::Now.ToUnixTimeSeconds())+300
$SignatureString=[System.Web.HttpUtility]::UrlEncode($URI)+ "`n" + [string]$Expires
$HMAC = New-Object System.Security.Cryptography.HMACSHA256
$HMAC.key = [Text.Encoding]::ASCII.GetBytes($Access_Policy_Key)
$Signature = $HMAC.ComputeHash([Text.Encoding]::ASCII.GetBytes($SignatureString))
$Signature = [Convert]::ToBase64String($Signature)
$SASToken = "SharedAccessSignature sr=" + [System.Web.HttpUtility]::UrlEncode($URI) + "&sig=" + [System.Web.HttpUtility]::UrlEncode($Signature) + "&se=" + $Expires + "&skn=" + $Access_Policy_Name
$SASToken

BASH

get_sas_token() {
    local EVENTHUB_URI='EVENTHUBURI'
    local SHARED_ACCESS_KEY_NAME='SHAREDACCESSKEYNAME'
    local SHARED_ACCESS_KEY='SHAREDACCESSKEYVALUE'
    local EXPIRY=${EXPIRY:=$((60 * 60 * 24))} # Default token expiry is 1 day

    local ENCODED_URI=$(echo -n $EVENTHUB_URI | jq -s -R -r @uri)
    local TTL=$(($(date +%s) + $EXPIRY))
    local UTF8_SIGNATURE=$(printf "%s\n%s" $ENCODED_URI $TTL | iconv -t utf8)

    local HASH=$(echo -n "$UTF8_SIGNATURE" | openssl sha256 -hmac $SHARED_ACCESS_KEY -binary | base64)
    local ENCODED_HASH=$(echo -n $HASH | jq -s -R -r @uri)

    echo -n "SharedAccessSignature sr=$ENCODED_URI&sig=$ENCODED_HASH&se=$TTL&skn=$SHARED_ACCESS_KEY_NAME"
}

Authentifizieren von Event Hubs-Herausgebern mit SAS

Ein Ereignisherausgeber definiert einen virtuellen Endpunkt für einen Event Hub. Der Herausgeber kann nur zum Senden von Nachrichten an einen Event Hub verwendet werden, nicht zum Empfangen von Nachrichten.

In der Regel setzt ein Event Hub einen Herausgeber pro Client ein. Alle Nachrichten, die an einen der Herausgeber eines Event Hubs gesendet werden, werden in die Warteschlange innerhalb dieses Event Hubs eingereiht. Herausgeber ermöglichen eine präzise Zugriffssteuerung.

Jedem Event Hubs-Client wird ein eindeutiges Token zugewiesen, das auf den Client hochgeladen wird. Token werden so erzeugt, dass jedes eindeutige Token Zugriff auf einen anderen eindeutigen Herausgeber gewährt. Ein Client, der über ein Token verfügt, kann nur an einen Herausgeber Daten senden und an keinen anderen. Wenn mehrere Clients dasselbe Token gemeinsam nutzen, verwendet jeder von ihnen denselben Herausgeber.

Alle Token werden mit SAS-Schlüsseln zugewiesen. Alle Token werden in der Regel mit demselben Schlüssel signiert. Clients kennen den Schlüssel nicht. Clients können daher keine Token generieren. Clients verwenden die gleichen Token, bis diese ablaufen.

Zum Definieren von Autorisierungsregeln, die nur für das Senden/Veröffentlichen von Daten an bzw. in Event Hubs gelten, müssen Sie beispielsweise eine Autorisierungsregel für das Senden definieren. Sie können die Regel auf der Namespaceebene definieren oder einen differenzierteren Bereich für eine bestimmte Entität festlegen (Event Hubs-Instanz oder ein Thema). Ein Client oder eine Anwendung, für den bzw. die ein solch präziser Zugriff festgelegt ist, wird als Event Hubs-Herausgeber bezeichnet. Gehen Sie dazu folgendermaßen vor:

  1. Erstellen Sie einen SAS-Schlüssel für die Entität, die Sie veröffentlichen möchten, um ihr den Bereich Senden zuzuweisen. Weitere Informationen finden Sie unter Shared access authorization policies (SAS-Autorisierungsrichtlinien).

  2. Generieren Sie mit dem in Schritt 1 generierten Schlüssel ein SAS-Token mit einer Ablaufzeit für einen bestimmten Herausgeber. Den Beispielcode finden Sie unter Generieren einer Signatur(eines Tokens) aus einer Richtlinie.

  3. Stellen Sie das Token für den Herausgeberclient bereit, der nur an die Entität und den Herausgeber Daten senden kann, auf die das Token Zugriff gewährt.

    Nach dem Ablauf des Tokens verliert der Client seinen Sende-/Veröffentlichungszugriff auf die Entität.

Hinweis

Obwohl dies nicht empfohlen wird, ist es möglich, Geräte mit Token auszustatten, die Zugriff auf einen Event Hub oder Namespace gewähren. Alle Geräte mit diesem Token können Nachrichten direkt an den Event Hub senden. Darüber hinaus kann das Gerät nicht davon gesperrt werden, an den betreffenden Event Hub zu senden.

Es empfiehlt sich immer, spezifische und präzise Bereiche festzulegen.

Wichtig

Sobald die Token erstellt wurden, wird jedem Client sein eigenes eindeutiges Token bereitgestellt.

Wenn der Client Daten an einen Event Hub sendet, taggt er seine Anforderung mit dem Token. Um Lauschangriffe und Diebstahl von Token von einem Angreifer zu verhindern, muss die Kommunikation zwischen dem Client und dem Event Hub über einen verschlüsselten Kanal erfolgen.

Wenn ein Token von einem Angreifer gestohlen wurde, kann der Angreifer den Client imitieren, dessen Token gestohlen wurde. Wird ein Herausgeber in eine Blockliste eingetragen, wird dieser Client als nicht verwendbar gekennzeichnet, bis er ein neues Token mit einem anderen Herausgeber erhält.

Authentifizieren von Event Hubs-Consumern mit SAS

Zum Authentifizieren von Back-End-Anwendungen, die von Event Hubs-Producern generierte Daten nutzen, erfordert die Event Hubs-Tokenauthentifizierung, dass den Clients entweder Rechte zum Verwalten oder die Berechtigung Lauschen für den Event Hubs-Namespace, die Event Hub-Instanz oder das Thema zugewiesen sind. Daten werden von Event Hubs mithilfe von Consumergruppen genutzt. Mit einer SAS-Richtlinie können Sie zwar einen präzisen Bereich festlegen, dieser Bereich wird aber nur auf der Entitätsebene definiert und nicht auf der Consumerebene. Die auf der Ebene des Namespaces, der Event Hub-Instanz oder des Themas definierten Berechtigungen werden folglich auf die Consumergruppen dieser Entität angewendet.

Deaktivieren der Authentifizierung mit lokalem/SAS-Schlüssel

Für bestimmte Sicherheitsanforderungen der Organisation müssen Sie die Authentifizierung mit lokalem Schlüssel bzw. SAS-Schlüssel vollständig deaktivieren und sich auf die Microsoft Entra ID-basierte Authentifizierung verlassen. Dies ist die empfohlene Methode zum Herstellen einer Verbindung mit Azure Event Hubs. Sie können die Authentifizierung mit lokalem/SAS-Schlüssel auf der Event Hubs-Namespaceebene deaktivieren, indem Sie das Azure-Portal oder eine Azure Resource Manager-Vorlage verwenden.

Deaktivieren der Authentifizierung mit lokalem/SAS-Schlüssel über das Portal

Sie können die Authentifizierung mit lokalem/SAS-Schlüssel für einen bestimmten Event Hubs-Namespace mithilfe von Azure-Portal deaktivieren.

Wählen Sie wie im folgenden Bild dargestellt im Abschnitt „Namespace overview“ (Übersicht über Namespaces) die Option Lokale Authentifizierung aus.

Übersicht über Namespaces zum Deaktivieren der lokalen Authentifizierung

Wählen Sie dann die Option Deaktiviert aus, und klicken Sie wie auf der folgenden Abbildung gezeigt auf OK. Deaktivieren der lokalen Authentifizierung

Deaktivieren der Authentifizierung mit lokalem/SAS-Schlüssel mithilfe einer Vorlage

Sie können die lokale Authentifizierung für einen bestimmten Event Hubs-Namespace deaktivieren, indem Sie die Eigenschaft disableLocalAuth wie in der folgenden Azure Resource Manager-Vorlage (ARM-Vorlage) gezeigt auf true festlegen.

"resources":[
      {
         "apiVersion":"[variables('ehVersion')]",
         "name":"[parameters('eventHubNamespaceName')]",
         "type":"Microsoft.EventHub/Namespaces",
         "location":"[variables('location')]",
         "sku":{
            "name":"Standard",
            "tier":"Standard"
         },
         "resources": [
    {
      "apiVersion": "2017-04-01",
      "name": "[parameters('eventHubNamespaceName')]",
      "type": "Microsoft.EventHub/Namespaces",
      "location": "[resourceGroup().location]",
      "sku": {
        "name": "Standard"
      },
      "properties": {
        "isAutoInflateEnabled": "true",
        "maximumThroughputUnits": "7", 
        "disableLocalAuth": false
      },
      "resources": [
        {
          "apiVersion": "2017-04-01",
          "name": "[parameters('eventHubName')]",
          "type": "EventHubs",
          "dependsOn": [
            "[concat('Microsoft.EventHub/namespaces/', parameters('eventHubNamespaceName'))]"
          ],
          "properties": {
            "messageRetentionInDays": "[parameters('messageRetentionInDays')]",
            "partitionCount": "[parameters('partitionCount')]"
          }

        }
      ]
    }
  ]

Beispiele

  • Im .NET-Beispiel #6 an diesem GitHub-Speicherort erfahren Sie, wie Sie Ereignisse mithilfe von Anmeldeinformationen für den gemeinsamen Zugriff oder der Standardidentität von Azure-Anmeldeinformationen in einem Event Hub veröffentlichen.
  • Im .NET-Beispiel #5 an diesem GitHub-Speicherort erfahren Sie, wie Sie Ereignisse mithilfe von Anmeldeinformationen für den gemeinsamen Zugriff oder der Standardidentität von Azure-Anmeldeinformationen nutzen oder verarbeiten.

Nächste Schritte

Weitere Informationen finden Sie in folgenden Artikeln:

Weitere Informationen finden Sie in den folgenden verwandten Artikeln: