Autentica l'accesso alle risorse degli Event Hubs utilizzando le firme di accesso condiviso (SAS)

Utilizzando una firma di accesso condiviso (SAS), puoi controllare il tipo di accesso che concedi ai clienti. Puoi impostare i seguenti controlli in un SAS:

  • Intervallo in cui la firma di accesso condiviso è valida, che include l'ora di inizio e l'ora di scadenza.
  • Le autorizzazioni concesse dalla firma di accesso condiviso. Ad esempio, un SAS per uno spazio di nome Event Hub potrebbe concedere il permesso di ascoltare eventi, ma non il permesso di inviare eventi.

L'autenticazione SAS offre questi vantaggi:

  • Solo i client che presentano le credenziali valide possono inviare dati a un hub eventi.
  • Un client non può rappresentare un altro client.
  • Puoi bloccare un client malizioso che invia dati a un event hub.

Questo articolo tratta l'autenticazione dell'accesso alle risorse degli Event Hub utilizzando SAS. Per saperne come autorizzare l'accesso alle risorse degli Event Hub utilizzando SAS, vedi Autorizzare l'accesso alle risorse degli Event Hub utilizzando firme di accesso condivise.

Note

Come buona prassi di sicurezza, utilizza le credenziali Microsoft Entra quando possibile invece di usare le firme di accesso condivise, che possono essere più facilmente compromesse. Anche se è possibile continuare a usare firme di accesso condiviso (SAS) per concedere l'accesso granulare alle risorse di Hub eventi, Microsoft Entra ID offre funzionalità simili senza dover gestire i token di firma di accesso condiviso o preoccuparsi di revocare una firma di accesso condiviso compromessa.

Per altre informazioni sull'integrazione di Microsoft Entra in Hub eventi di Azure, vedere Autorizzare l'accesso a Hub eventi usando Microsoft Entra ID.

Configura l'autenticazione SAS

È possibile configurare una regola di firma di accesso condiviso in uno spazio dei nomi di Hub eventi o in un'entità (hub eventi o argomento Kafka). Configurare una regola SAS su un gruppo di consumatori non è supportato, ma puoi usare regole configurate su uno spazio di nomi o un'entità per garantire l'accesso a un gruppo di consumatori. L'immagine seguente mostra come le regole di autorizzazione si applicano alle entità di esempio.

Diagramma che mostra gli hub eventi con regole di ascolto, invio e gestione.

In questo esempio lo spazio dei nomi di Hub eventi di esempio (ExampleNamespace) ha due entità: eh1 e Kafka topic1. Le regole di autorizzazione vengono definite sia a livello di entità che a livello di spazio dei nomi.

Le regole di autorizzazione manageRuleNS, sendRuleNS e listenRuleNS si applicano sia a eh1 che a topic1. Le regole di autorizzazione listenRule-eh e sendRule-eh si applicano solo a eh1 e la regola di autorizzazione sendRuleT si applica solo a topic1.

Quando si usa la regola di autorizzazione sendRuleNS, le applicazioni client possono essere inviate sia a eh1 che a topic1. Quando si usa la regola di autorizzazione sendRuleT, applica solo l'accesso granulare a topic1 e quindi le applicazioni client che usano questa regola per l'accesso non possono effettuare invii a eh1, ma solo a topic1.

Generare un token della firma di accesso condiviso

Qualsiasi client che ha accesso al nome di una regola di autorizzazione e a una delle relative chiavi può generare un SAS token. Genera il token creando una stringa nel seguente formato:

  • se - Istante di scadenza del token. Numero intero che rappresenta i secondi trascorsi dalle 00:00:00 UTC del 1° gennaio 1970 (epoca UNIX) al momento della scadenza del token.
  • skn: nome della regola di autorizzazione, ovvero il nome della chiave di firma di accesso condiviso.
  • sr: URI della risorsa a cui si ha accesso.
  • sig: firma.

La stringa firma è l'hash HMAC-SHA256 calcolato sull'URI della risorsa (ambito descritto nella sezione precedente) e la rappresentazione della stringa dell'istante di scadenza del token, separati da un line feed (LF). Inserisci l'hash con una delle chiavi di firma della regola di autorizzazione. Il calcolo dell'hash restituisce un valore hash di 256 bit/32 byte.

HMAC-SHA256(signingKey, 'https://<yournamespace>.servicebus.windows.net/' + '\n' + 1438205742)

Il token contiene i valori non hash affinché il destinatario possa ricalcolare l'hash con gli stessi parametri e verificare che l'emittente abbia una chiave di firma valida.

L'URI di risorsa è l'URI completo della risorsa del bus di servizio a cui si richiede l'accesso. Ad esempio, http://<namespace>.servicebus.windows.net/<entityPath> o sb://<namespace>.servicebus.windows.net/<entityPath>, come .http://contoso.servicebus.windows.net/eh1

Codifica l'URI in percentuale.

Configurare la regola SAS utilizzata per la firma sull'entità specificata da questo URI o da uno dei suoi genitori gerarchici. Ad esempio http://contoso.servicebus.windows.net/eh1 o http://contoso.servicebus.windows.net nell'esempio precedente.

Un token di firma di accesso condiviso è valido per tutte le risorse il cui prefisso è <resourceURI> usato nella stringa della firma.

Note

Generi un token di accesso per gli Event Hub utilizzando una policy di accesso condiviso. Per altre informazioni, vedere Criteri di autorizzazione di accesso condiviso.

Genera una firma (token) a partire da un criterio

La sezione seguente mostra come generare un token SAS utilizzando politiche di firma di accesso condiviso.

Node.js

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; 
}

Per usare un nome di criterio e un valore di chiave per connettersi a un hub eventi, usare il costruttore EventHubProducerClient che accetta il parametro AzureNamedKeyCredential.

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

Aggiungere un riferimento a AzureNamedKeyCredential.

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

Per usare un token SAS che generi usando il codice, usa il EventHubProducerClient costruttore che prende il AzureSASCredential parametro.

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

Aggiungere un riferimento a AzureSASCredential.

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"
}

Autentica gli editori di Event Hubs con SAS

Un autore di eventi definisce un endpoint virtuale per un hub eventi. Il server di pubblicazione può essere usato solo per inviare messaggi a un hub eventi, ma non per riceverli.

In genere, un Hub eventi usa un autore per ogni client. Tutti i messaggi inviati a uno qualsiasi degli autori di un Hub eventi vengono accodati all'interno di tale Hub eventi. I server di pubblicazione consentono il controllo di accesso con granularità fine.

A ciascun client di Event Hubs viene assegnato un token univoco, che viene trasferito al client. I token vengono prodotti in modo tale che ogni token univoco conceda l'accesso a un diverso autore univoco. Un client in possesso di un token può effettuare invii a un solo server di pubblicazione e a nessun altro. Se più client condividono lo stesso token, allora ogni client condivide il server di pubblicazione.

A tutti i token vengono assegnate chiavi SAS. In genere, tutti i token sono firmati con la stessa chiave. I client non conoscono la chiave, quindi non possono creare token. I client usano gli stessi token fino alla scadenza.

Ad esempio, per definire regole di autorizzazione ridotte all'invio o pubblicazione solo agli Event Hub, devi definire una regola di autorizzazione di invio. Puoi creare la regola a livello di namespace o assegnare un ambito più dettagliato a una particolare entità, come un'istanza di event hub o un argomento. Un client o un'applicazione che ha questo accesso granulare è chiamato publisher Event Hubs. Per configurare questa autenticazione, segui questi passaggi:

  1. Crea una chiave SAS nell'entità in cui vuoi pubblicare e assegnale l'ambito send. Per altre informazioni, vedere Criteri di autorizzazione di accesso condiviso.

  2. Genera un token SAS con un tempo di scadenza per un editore specifico usando la chiave che hai creato nel passo 1. Per il codice di esempio, vedi Genera una firma (token) da una policy.

  3. Fornisci il token al client del publisher, che può inviare solo all'entità e al publisher a cui il token autorizza l'accesso.

    Quando il token scade, il client perde l'accesso per inviare o pubblicare all'entità.

Note

Anche se non lo consigliamo, puoi equipaggiare i dispositivi con token che concedono l'accesso a un hub eventi o a uno spazio di nomi. Qualsiasi dispositivo che contiene un token di questo tipo può inviare messaggi direttamente a tale hub eventi. Non puoi inserire il dispositivo nella lista di blocco per impedirgli di inviare dati a quell'event hub.

È consigliabile assegnare ambiti specifici e granulari.

Important

Quando crei i token, ogni client ottiene il proprio token unico.

Quando il client invia dati a un event hub, etichetta la sua richiesta con il token. Per evitare che un utente malintenzionato intercetti e rubi il token, la comunicazione tra il client e l'Hub eventi deve verificarsi su un canale crittografato.

Se un attaccante ruba un token, può impersonare il client il cui token è stato rubato. Se si nega un publisher, quel client diventa inutilizzabile finché non riceve un nuovo token che utilizza un publisher diverso.

Autentica i consumatori degli Event Hub con SAS

Per autenticare le applicazioni back-end che utilizzano i dati generati dai produttori di Event Hubs, l'autenticazione del token di Event Hubs richiede ai clienti di disporre dei diritti di gestione o dei privilegi di ascolto assegnati allo spazio dei nomi di Event Hubs o all'istanza o al topico dell'Event Hub. I dati vengono utilizzati da Hub eventi tramite gruppi di consumer. Anche se i criteri di firma di accesso condiviso offrono un ambito granulare, questo ambito viene definito solo a livello di entità e non a livello di consumer. Ciò significa che i privilegi definiti a livello di spazio dei nomi o dell'hub eventi o dell'argomento vengono applicati ai gruppi di consumer di tale entità.

Disabilita l'autenticazione locale o SAS con chiave

Per determinati requisiti di sicurezza dell'organizzazione, si vuole disabilitare completamente l'autenticazione con chiave locale/firma di accesso condiviso e ci si vuole basare sull'autenticazione con Microsoft Entra ID, che è il modo consigliato per connettersi a Hub eventi di Azure. È possibile disabilitare l'autenticazione della chiave locale/SAS a livello di spazio dei nomi di Hub eventi usando il portale di Azure o il modello di Azure Resource Manager.

Disabilita l'autenticazione locale o SAS tramite chiave utilizzando il portale

È possibile disabilitare l'autenticazione della chiave locale/SAS per uno spazio dei nomi di Hub eventi specifico usando il portale di Azure.

  1. Passare allo spazio dei nomi di Hub eventi nel portale di Azure.

  2. Nella pagina Panoramica selezionare Abilitato per Autenticazione locale, come illustrato nell'immagine seguente.

    Screenshot che mostra l'opzione Autenticazione locale selezionata.

  3. Nella finestra popup Autenticazione locale selezionare Disabilitato e selezionare OK.

    Screenshot che mostra il popup Autenticazione locale con l'opzione Disabilitata selezionata.

Disabilita l'autenticazione locale o SAS tramite chiave utilizzando un template

È possibile disabilitare l'autenticazione locale per uno spazio dei nomi di Hub eventi specifico impostando la proprietà disableLocalAuth su true, come illustrato nel modello di Azure Resource Manager seguente.

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

Samples

  • Vedere l'esempio .NET n. 6 in questa posizione di GitHub per informazioni su come pubblicare eventi in un hub eventi usando credenziali di accesso condiviso o l'identità predefinita delle credenziali di Azure.
  • Vedere l'esempio .NET n. 5 in questa posizione di GitHub per informazioni su come utilizzare o elaborare eventi usando credenziali di accesso condiviso o l'identità predefinita delle credenziali di Azure.

Ora che hai capito l'autenticazione SAS, esplora questi articoli correlati: