Autentisera åtkomst till Event Hubs-resurser med hjälp av signaturer för delad åtkomst (SAS)

Signatur för delad åtkomst (SAS) ger dig detaljerad kontroll över vilken typ av åtkomst du beviljar klienterna. Här är några av de kontroller som du kan ange i en SAS:

  • Det intervall som SAS är giltigt, vilket inkluderar starttid och förfallotid.
  • De behörigheter som beviljas av SAS. Till exempel kan en SAS för ett Event Hubs-namnområde bevilja lyssningsbehörigheten, men inte sändningsbehörigheten.
  • Endast klienter som har giltiga autentiseringsuppgifter kan skicka data till en händelsehubb.
  • En klient kan inte personifiera en annan klient.
  • En falsk klient kan blockeras från att skicka data till en händelsehubb.

Den här artikeln beskriver hur du autentiserar åtkomsten till Event Hubs-resurser med hjälp av SAS. Mer information om hur du auktoriserar åtkomst till Event Hubs-resurser med hjälp av SAS finns i den här artikeln.

Kommentar

Microsoft rekommenderar att du använder Microsoft Entra-autentiseringsuppgifter när det är möjligt som bästa praxis för säkerhet, i stället för att använda signaturer för delad åtkomst, vilket kan vara enklare att kompromettera. Även om du kan fortsätta att använda signaturer för delad åtkomst (SAS) för att ge detaljerad åtkomst till dina Event Hubs-resurser, erbjuder Microsoft Entra ID liknande funktioner utan att behöva hantera SAS-token eller oroa dig för att återkalla en komprometterad SAS.

Mer information om Microsoft Entra-integrering i Azure Event Hubs finns i Auktorisera åtkomst till Event Hubs med hjälp av Microsoft Entra-ID.

Konfigurera för SAS-autentisering

Du kan konfigurera en SAS-regel på ett Event Hubs-namnområde eller en entitet (händelsehubbinstans eller Kafka-ämne i en händelsehubb). Det går för närvarande inte att konfigurera en SAS-regel för en konsumentgrupp, men du kan använda regler som konfigurerats på ett namnområde eller entitet för att skydda åtkomsten till konsumentgruppen.

Följande bild visar hur auktoriseringsreglerna tillämpas på exempelentiteter.

Konfigurera auktoriseringsregel

I det här exemplet har Event Hubs-exempelnamnområdet (ExampleNamespace) två entiteter: eh1 och Kafka topic1. Auktoriseringsreglerna definieras både på entitetsnivå och på namnområdesnivå.

Auktoriseringsreglerna manageRuleNS, sendRuleNS och listenRuleNS gäller för både eh1 och t1. Auktoriseringsreglerna listenRule-eh och sendRule-eh gäller endast för eh1 och sendRuleT-auktoriseringsregeln gäller endast för topic1.

När du använder sendRuleNS-auktoriseringsregeln kan klientprogram skicka till både eh1 och topic1. När sendRuleT-auktoriseringsregeln används framtvingar den endast detaljerad åtkomst till ämne1 och därför kan klientprogram som använder den här regeln för åtkomst nu inte skicka till eh1, utan bara till ämne1.

Generera en signaturtoken för delad åtkomst

Alla klienter som har åtkomst till namnet på ett auktoriseringsregelnamn och en av dess signeringsnycklar kan generera en SAS-token. Token genereras genom att skapa en sträng i följande format:

  • se – Token upphör att gälla omedelbart. Heltal som reflekterar sekunder sedan epoken 00:00:00 UTC den 1 januari 1970 (UNIX-epok) när token upphör att gälla
  • skn – Namnet på auktoriseringsregeln, som är SAS-nyckelnamnet.
  • sr – URI för resursen som används.
  • sig –Signatur.

Signatursträngen är SHA-256-hashen som beräknas över resurs-URI:n (omfång enligt beskrivningen i föregående avsnitt) och strängrepresentationen av tokens förfallodatum omedelbart, avgränsat med CRLF. Hash-beräkningen liknar följande pseudokod och returnerar ett hashvärde på 256 bitar/32 byte.

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

Token innehåller de icke-hashade värdena så att mottagaren kan omkomplera hashen med samma parametrar och verifiera att utfärdaren har en giltig signeringsnyckel.

Resurs-URI:n är den fullständiga URI:n för Service Bus-resursen som åtkomsten begärs till. Till exempel, http://<namespace>.servicebus.windows.net/<entityPath> eller sb://<namespace>.servicebus.windows.net/<entityPath> det vill säga http://contoso.servicebus.windows.net/eh1.

URI:n måste vara procentkodad.

SAS-regeln som används för signering måste konfigureras för den entitet som anges av den här URI:n eller av någon av dess hierarkiska överordnade. Till exempel, http://contoso.servicebus.windows.net/eh1 eller http://contoso.servicebus.windows.net i föregående exempel.

En SAS-token är giltig för alla resurser som är prefix med den <resourceURI> som används i signatursträngen.

Kommentar

Du genererar en åtkomsttoken för Event Hubs med hjälp av principen för delad åtkomst. Mer information finns i Auktoriseringsprincip för delad åtkomst.

Generera en signatur(token) från en princip

Följande avsnitt visar hur du genererar en SAS-token med hjälp av principer för signatur för delad åtkomst,

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

Om du vill använda ett principnamn och ett nyckelvärde för att ansluta till en händelsehubb använder EventHubProducerClient du konstruktorn som tar parametern AzureNamedKeyCredential .

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

Du måste lägga till en referens till AzureNamedKeyCredential.

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

Om du vill använda en SAS-token som du genererade med hjälp av koden använder EventHubProducerClient du konstruktorn som tar parametern AzureSASCredential .

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

Du måste lägga till en referens till 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"
}

Autentisera Event Hubs-utgivare med SAS

En händelseutgivare definierar en virtuell slutpunkt för en händelsehubb. Utgivaren kan bara användas för att skicka meddelanden till en händelsehubb och inte ta emot meddelanden.

Vanligtvis använder en händelsehubb en utgivare per klient. Alla meddelanden som skickas till någon av utgivaren av en händelsehubb lagras i händelsehubben. Utgivare aktiverar detaljerad åtkomstkontroll.

Varje Event Hubs-klient tilldelas en unik token som laddas upp till klienten. Token skapas så att varje unik token ger åtkomst till olika unika utgivare. En klient som innehåller en token kan bara skicka till en utgivare och ingen annan utgivare. Om flera klienter delar samma token delar var och en av dem utgivaren.

Alla token tilldelas med SAS-nycklar. Vanligtvis signeras alla token med samma nyckel. Klienter känner inte till nyckeln, vilket hindrar klienter från att tillverka token. Klienterna arbetar på samma token tills de upphör att gälla.

Om du till exempel vill definiera auktoriseringsregler som begränsas till att endast skicka/publicera till Event Hubs måste du definiera en regel för att skicka auktorisering. Det kan göras på namnområdesnivå eller ge ett mer detaljerat omfång till en viss entitet (händelsehubbinstans eller ett ämne). En klient eller ett program som är begränsat med sådan detaljerad åtkomst kallas Event Hubs-utgivare. Följ stegen nedan:

  1. Skapa en SAS-nyckel för den entitet som du vill publicera för att tilldela sändningsomfånget för den. Mer information finns i Auktoriseringsprinciper för delad åtkomst.

  2. Generera en SAS-token med en förfallotid för en specifik utgivare med hjälp av nyckeln som genererades i steg1. Exempelkoden finns i Generera en signatur(token) från en princip.

  3. Ange token till utgivarklienten, som bara kan skicka till entiteten och utgivaren som token ger åtkomst till.

    När token upphör att gälla förlorar klienten sin åtkomst till att skicka/publicera till entiteten.

Kommentar

Även om det inte rekommenderas är det möjligt att utrusta enheter med token som ger åtkomst till en händelsehubb eller ett namnområde. Alla enheter som innehåller den här token kan skicka meddelanden direkt till händelsehubben. Dessutom kan enheten inte blockeras från att skicka till händelsehubben.

Vi rekommenderar alltid att du ger specifika och detaljerade omfång.

Viktigt!

När token har skapats etableras varje klient med en egen unik token.

När klienten skickar data till en händelsehubb taggar den sin begäran med token. För att förhindra att en angripare tjuvlyssnar och stjäl token måste kommunikationen mellan klienten och händelsehubben ske via en krypterad kanal.

Om en token blir stulen av en angripare kan angriparen personifiera klienten vars token har blivit stulen. Blockera en utgivare, gör klienten oanvändbar tills den tar emot en ny token som använder en annan utgivare.

Autentisera Event Hubs-konsumenter med SAS

För att autentisera backend-program som förbrukar från data som genereras av Event Hubs-producenter kräver Event Hubs-tokenautentisering att dess klienter antingen har hanteringsrättigheter eller lyssningsbehörigheter som tilldelats dess Event Hubs-namnområde eller händelsehubbinstans eller ämne. Data förbrukas från Event Hubs med hjälp av konsumentgrupper. Sas-principen ger dig ett detaljerat omfång, men det här omfånget definieras endast på entitetsnivå och inte på konsumentnivå. Det innebär att de behörigheter som definierats på namnområdesnivå eller händelsehubbens instans- eller ämnesnivå tillämpas på konsumentgrupperna för den entiteten.

Inaktivera autentisering med lokal/SAS-nyckel

För vissa organisationssäkerhetskrav vill du inaktivera autentisering av lokal/SAS-nyckel helt och förlita dig på Microsoft Entra ID-baserad autentisering, vilket är det rekommenderade sättet att ansluta till Azure Event Hubs. Du kan inaktivera lokal/SAS-nyckelautentisering på eventhubs-namnområdesnivå med hjälp av Azure-portalen eller Azure Resource Manager-mallen.

Inaktivera lokal/SAS-nyckelautentisering via portalen

Du kan inaktivera lokal/SAS-nyckelautentisering för ett visst Event Hubs-namnområde med hjälp av Azure-portalen.

Som du ser i följande bild väljer du Lokal autentisering i avsnittet namnområdesöversikt.

Översikt över namnområde för att inaktivera lokal autentisering

Välj sedan Alternativet Inaktiverad och välj Ok enligt följande bild. Inaktivera lokal autentisering

Inaktivera lokal/SAS-nyckelautentisering med hjälp av en mall

Du kan inaktivera lokal autentisering för ett visst Event Hubs-namnområde genom att ange disableLocalAuth egenskapen till true enligt följande Azure Resource Manager-mall (ARM-mall).

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

        }
      ]
    }
  ]

Exempel

  • Se .NET-exempel nr 6 på den här GitHub-platsen för att lära dig hur du publicerar händelser till en händelsehubb med hjälp av autentiseringsuppgifter för delad åtkomst eller standardidentiteten för Azure-autentiseringsuppgifter.
  • Se .NET-exempel nr 5 på den här GitHub-platsen för att lära dig hur du använder eller bearbetar händelser med autentiseringsuppgifter för delad åtkomst eller standardidentiteten för Azure-autentiseringsuppgifter.

Nästa steg

Mer information finns i följande artiklar:

Se följande relaterade artiklar: