Autenticare l'accesso alle risorse di Hub eventi usando firme di accesso condiviso

La firma di accesso condiviso offre un controllo granulare sul tipo di accesso concesso ai client. Ecco alcuni dei controlli che è possibile impostare in una firma di accesso condiviso:

  • 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, una firma di accesso condiviso per uno spazio dei nomi di Hub eventi potrebbe concedere l'autorizzazione di ascolto, ma non l'autorizzazione di invio.
  • Solo i client che presentano le credenziali valide possono inviare dati a un hub eventi.
  • Un client non può rappresentare un altro client.
  • A un client non autorizzato può essere impedito l'invio di dati a un hub eventi.

Questo articolo illustra l'autenticazione dell'accesso alle risorse di Hub eventi usando la firma di accesso condiviso. Per informazioni sull'autorizzazionedell'accesso alle risorse di Hub eventi tramite firma di accesso condiviso, vedere questo articolo.

Nota

Microsoft consiglia di usare le credenziali di Microsoft Entra quando possibile come procedura consigliata per la sicurezza, anziché usare le firme di accesso condiviso, che possono essere compromesse più facilmente. 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 tramite Microsoft Entra ID.

Configurazione per l'autenticazione con firma di accesso condiviso

È possibile configurare una regola di firma di accesso condiviso in uno spazio dei nomi di Hub eventi o un'entità (istanza dell'hub eventi o argomento Kafka in un hub eventi). La configurazione di una regola di firma di accesso condiviso in un gruppo di consumer non è attualmente supportata, ma è possibile usare regole configurate in uno spazio dei nomi o un'entità per proteggere l'accesso al gruppo di consumer.

L'immagine seguente mostra come le regole di autorizzazione si applicano alle entità di esempio.

Configurare la regola di autorizzazione

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 t1. 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 ora inviare a eh1, ma solo a topic1.

Generare un token della firma di accesso condiviso

Qualsiasi client che abbia accesso al nome di una regola di autorizzazione e a una delle relative chiavi di firma può generare un token di firma di accesso condiviso. Il token viene generato creando una stringa nel formato seguente:

  • se : istante di scadenza del token. Numero intero che riflette i secondi dal periodo 00:00:00 UTC del 1° gennaio 1970 (periodo UNIX) alla 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 accede.
  • sig –Firma.

La stringa di firma è l'hash SHA-256 calcolato sull'URI della risorsa (ambito come descritto nella sezione precedente) e la rappresentazione di stringa dell'istante di scadenza del token, separati da CRLF. Il calcolo del codice hash è simile allo pseudo codice seguente e restituisce un valore hash a 256 bit o 32 byte.

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

Il token contiene i valori non hash in modo che il destinatario possa ricalcolare il codice hash con gli stessi parametri, verificando che l'autorità di certificazione sia in possesso di 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> è , http://contoso.servicebus.windows.net/eh1.

L'URI deve essere codificato in percentuale.

La regola di firma di accesso condiviso usata per la firma deve essere configurata nell'entità specificata da questo URI o da uno dei relativi elementi padre 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 precedute dall'oggetto <resourceURI> usato nella stringa di firma.

Nota

Si genera un token di accesso per Hub eventi usando i criteri di accesso condiviso. Per altre informazioni, vedere Criteri di autorizzazione di accesso condiviso.

Generazione di una firma (token) da un criterio

La sezione seguente illustra la generazione di un token di firma di accesso condiviso con i criteri di firma di accesso condiviso.

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

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

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

È necessario aggiungere un riferimento a AzureNamedKeyCredential.

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

Per usare un token di firma di accesso condiviso generato usando il codice, usare il EventHubProducerClient costruttore che accetta 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));

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

Autenticazione degli editori di Hub eventi con firma di accesso condiviso

Un publisher di eventi definisce un endpoint virtuale per un hub eventi. Il publisher può essere usato solo per inviare messaggi a un hub eventi e non per ricevere messaggi.

In genere, un hub eventi usa un solo publisher per ogni client. Tutti i messaggi inviati a uno dei publisher di un hub eventi vengono accodati all'interno di tale hub eventi. Publishers consentono il controllo di accesso con granularità fine.

A ogni client di Hub eventi viene assegnato un token univoco, che viene caricato nel client. I token vengono generati in modo che ogni token univoco conceda l'accesso a server di pubblicazione univoci diversi. Un client in possesso di un token può inviare a un solo publisher e a nessun altro. Se più client condividono lo stesso token, ognuno condivide il publisher.

Tutti i token vengono assegnati con chiavi di firma di accesso condiviso. Tutti i token vengono in genere firmati con la stessa chiave. I client non conoscono la chiave, quindi non possono creare token. I client operano sugli stessi token fino alla scadenza.

Ad esempio, per definire regole di autorizzazione con ambito limitato all'invio/pubblicazione a Hub eventi, è necessario definire una regola di autorizzazione di invio. Può essere eseguita a livello di spazio dei nomi o assegnare un ambito più granulare a una determinata entità (istanza di Hub eventi o un argomento). Un client o un'applicazione con ambito con tale accesso granulare viene chiamato Server di pubblicazione di Hub eventi. A tale scopo, effettuare i passaggi seguenti:

  1. Creare una chiave di firma di accesso condiviso nell'entità da pubblicare per assegnare l'ambito di invio . Per altre informazioni, vedere Criteri di autorizzazione di accesso condiviso.

  2. Generare un token di firma di accesso condiviso con una scadenza per un server di pubblicazione specifico usando la chiave generata nel passaggio 1. Per il codice di esempio, vedere Generazione di una firma(token) da un criterio.

  3. Fornire il token al client di pubblicazione, che può inviare solo all'entità e al server di pubblicazione a cui il token concede l'accesso.

    Una volta scaduto il token, il client perde l'accesso all'entità di invio/pubblicazione.

Nota

Anche se non è consigliabile, è possibile equipaggiare i dispositivi con token che concedono l'accesso a un hub eventi o a uno spazio dei nomi. Qualsiasi dispositivo che contiene questo token può inviare messaggi direttamente all'hub eventi. Inoltre, il dispositivo non può essere bloccato dall'invio a tale hub eventi.

È sempre consigliabile assegnare ambiti specifici e granulari.

Importante

Dopo avere creato i token, viene eseguito il provisioning di ogni client con il proprio token univoco.

Quando il client invia dati a un hub eventi, contrassegna la 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.

In caso di furto di un token da parte di un utente malintenzionato, l'autore dell'attacco può rappresentare il client il cui token è stato rubato. Bloccando un server di pubblicazione, viene eseguito il rendering di tale client inutilizzabile fino a quando non riceve un nuovo token che usa un server di pubblicazione diverso.

Autenticazione dei consumer di Hub eventi con firma di accesso condiviso

Per autenticare le applicazioni back-end che utilizzano i dati generati dai producer di Hub eventi, l'autenticazione dei token di Hub eventi richiede ai client di avere diritti di gestione o privilegi di ascolto assegnati al relativo spazio dei nomi di Hub eventi oppure all'istanza o all'argomento dell'hub eventi. 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. Questo significa che i privilegi definiti a livello di spazio dei nomi oppure a livello di istanza o argomento dell'hub eventi verranno applicati ai gruppi di consumer di tale entità.

Disabilitazione dell'autenticazione con chiave locale/firma di accesso condiviso

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

Disabilitazione dell'autenticazione della chiave locale/firma di accesso condiviso tramite il portale

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

Come illustrato nell'immagine seguente, nella sezione panoramica dello spazio dei nomi selezionare Autenticazione locale.

Panoramica dello spazio dei nomi per la disabilitazione dell'autenticazione locale

Selezionare quindi l'opzione Disabilitata e selezionare OK come illustrato nell'immagine seguente. Disabilitazione dell'autenticazione locale

Disabilitazione dell'autenticazione con chiave locale/firma di accesso condiviso con un modello

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

"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')]"
          }

        }
      ]
    }
  ]

Esempi

  • 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 usare o elaborare eventi usando le credenziali di accesso condiviso o l'identità predefinita delle credenziali di Azure.

Passaggi successivi

Fai riferimento ai seguenti articoli:

Vedere gli articoli correlati seguenti: