Ověření přístupu k Event Hubs pomocí sdílených přístupových podpisů (SAS)

Sdílený přístupový podpis (SAS) poskytuje podrobnou kontrolu nad typem přístupu, který udělíte klientům, kteří mají sdílený přístupový podpis. Tady je několik ovládacích prvků, které můžete nastavit v SAS:

  • Interval, během kterého je SAS platný, včetně času spuštění a doby vypršení platnosti.
  • Oprávnění udělená SAS. Například SAS pro obor názvů Event Hubs může udělit oprávnění k naslouchání, ale ne oprávnění k odesílání.
  • Data do centra událostí mohou odesílat pouze klienti, kteří prezentovat platné přihlašovací údaje.
  • Klient nemůže zosobnit jiného klienta.
  • Podvodný klient může mít zablokovaný odesílání dat do centra událostí.

Tento článek popisuje ověřování přístupu k prostředkům Event Hubs pomocí SAS. Další informace o povolení přístupu k prostředkům Event Hubs pomocí SAS najdete v tomto článku.

Poznámka

Microsoft doporučuje používat přihlašovací údaje Azure AD, pokud je to možné, jako osvědčený postup zabezpečení místo používání sdílených přístupových podpisů, které je možné snadněji ohrozit. I když můžete dál používat sdílené přístupové podpisy (SAS) k udělení jemně odpracovaného přístupu k prostředkům služby Event Hubs, Azure AD nabízí podobné funkce bez nutnosti spravovat tokeny SAS nebo si dělat starosti s odvoláním ohroženého sdíleného přístupového podpisu.

Další informace o integraci Azure AD v Azure Event Hubs najdete v tématu Autorizace přístupu k Event Hubs pomocí Azure AD.

Konfigurace ověřování SAS

Autorizační pravidlo sdíleného přístupu služby EventHubs můžete nakonfigurovat v oboru názvů služby Event Hubs nebo entitě (instance centra událostí nebo téma Kafka v centru událostí). Konfigurace pravidla autorizace sdíleného přístupu pro skupinu uživatelů se v současné době nepodporuje, ale k zabezpečení přístupu ke skupině uživatelů můžete použít pravidla nakonfigurovaná pro obor názvů nebo entitu.

Následující obrázek ukazuje, jak se autorizační pravidla vztahují na ukázkové entity.

Konfigurace autorizačního pravidla

V tomto příkladu má ukázkový obor názvů Event Hubs (ExampleNamespace) dvě entity: eh1 a topic1. Autorizační pravidla jsou definována na úrovni entity i na úrovni oboru názvů.

Autorizační pravidla manageRuleNS, sendRuleNS a listenRuleNS platí pro instanci centra událostí eh1 i téma t1. Autorizační pravidla listenRule-eh a sendRule-eh platí jenom pro instanci centra událostí eh1 a autorizační pravidlo sendRuleT se vztahuje jenom na téma topic1.

Při použití autorizačního pravidla sendRuleNS mohou klientské aplikace odesílat do eh1 i topic1. Při použití autorizačního pravidla sendRuleT se vynucuje pouze podrobný přístup k tématu topic1, a proto klientské aplikace, které toto pravidlo používají pro přístup, teď nemohou odesílat do eh1, ale pouze do tématu topic1.

Vygenerování tokenu sdíleného přístupového podpisu

Token SAS může vygenerovat každý klient, který má přístup k názvu autorizačního pravidla a jednomu z jeho podpisových klíčů. Token se vygeneruje vytvořením řetězce v následujícím formátu:

  • se – Okamžitě vyprší platnost tokenu. Integer reflecting seconds since epoch 00:00:00 UTC on 1 January 1970 (systém UNIX epoch) when the token expires
  • skn – Název autorizačního pravidla, to je název klíče SAS.
  • sr – Identifikátor URI prostředku, ke které se přistupuje.
  • sig – Podpis.

Řetězec podpisu je hodnota hash SHA-256 vypočítaná pomocí identifikátoru URI prostředku (rozsah, jak je popsáno v předchozí části) a řetězcové vyjádření okamžitého vypršení platnosti tokenu oddělené znakem CRLF.

Výpočet hodnoty hash vypadá podobně jako následující pseudokód a vrací 256bitovou/32bitovou hodnotu hash.

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

Token obsahuje hodnoty bez hodnoty hash, aby příjemce mohl hodnotu hash přepočítat se stejnými parametry a ověřit tak, že vystavitel vlastní platný podpisový klíč.

Identifikátor URI prostředku je úplný identifikátor URI prostředku Service Bus, ke kterému je nárokován přístup. Například nebo http://<namespace>.servicebus.windows.net/<entityPath> sb://<namespace>.servicebus.windows.net/<entityPath> , to je http://contoso.servicebus.windows.net/eh1 .

Identifikátor URI musí být zakódovaný v procentech.

Autorizační pravidlo sdíleného přístupu použité k podepisování musí být nakonfigurované pro entitu určenou tímto identifikátorem URI nebo jedním z jeho hierarchických nadřízenosti. Například nebo http://contoso.servicebus.windows.net/eh1 http://contoso.servicebus.windows.net v předchozím příkladu.

Token SAS je platný pro všechny prostředky s předponou <resourceURI> použitou v řetězci podpisu.

Poznámka

K vygenerování přístupového tokenu pro Event Hubs pomocí zásad sdíleného přístupu. Další informace najdete v tématu Zásady autorizace sdíleného přístupu.

Generování podpisu (tokenu) ze zásad

Následující část ukazuje vygenerování tokenu SAS pomocí zásad sdíleného přístupového podpisu.

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 signatureUTF8 = utf8.encode(signature); 
    var hash = crypto.createHmac('sha256', saKey).update(signatureUTF8).digest('base64'); 
    return 'SharedAccessSignature sr=' + encoded + '&sig=' +  
        encodeURIComponent(hash) + '&se=' + ttl + '&skn=' + saName; 

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

Ověřování vydavatelů Event Hubs sas

Vydavatel události definuje virtuální koncový bod pro centrum událostí. Vydavatele je možné použít pouze k odesílání zpráv do centra událostí, nikoli k přijímání zpráv.

Centrum událostí obvykle využívá jednoho vydavatele na klienta. Všechny zprávy odeslané do libovolného vydavatele centra událostí se zařadí do fronty v tomto centru událostí. Vydavatelé umožňují jemně odlišené řízení přístupu.

Každému Event Hubs klientovi je přiřazen jedinečný token, který se nahraje do klienta. Tokeny jsou vytvářeny tak, aby každý jedinečný token uděloval přístup jinému jedinečnému vydavateli. Klient, který obsahuje token, může odeslat pouze jednomu vydavateli a žádnému jinému vydavateli. Pokud více klientů sdílí stejný token, pak každý z nich sdílí vydavatele.

Ke všem tokenům se přiřazuje klíč SAS. Obvykle jsou všechny tokeny podepsané stejným klíčem. Klienti si klíč neuvědomují, což klientům brání ve výrobě tokenů. Klienti pracují se stejnými tokeny, dokud jejich platnost nevyprší.

Pokud například chcete definovat autorizační pravidla vymezená jenom na odesílání a publikování do Event Hubs, musíte definovat autorizační pravidlo pro odesílání. To lze provést na úrovni oboru názvů nebo poskytnout podrobnější obor konkrétní entity (instance služby Event Hubs nebo téma). Klient nebo aplikace s oborem s takto podrobným přístupem se volá jako Event Hubs vydavatel. To můžete provést pomocí těchto kroků:

  1. Vytvořte klíč SAS pro entitu, kterou chcete publikovat, a přiřaďte k ní obor odeslání. Další informace najdete v tématu Zásady autorizace sdíleného přístupu.

  2. Vygenerování tokenu SAS s časem vypršení platnosti pro konkrétního vydavatele pomocí klíče vygenerovaného v kroku 1.

    var sasToken = SharedAccessSignatureTokenProvider.GetPublisherSharedAccessSignature(
                new Uri("Service-Bus-URI"),
                "eventub-name",
                "publisher-name",
                "sas-key-name",
                "sas-key",
                TimeSpan.FromMinutes(30));
    
  3. Zadejte token klientovi vydavatele, který může odeslat jenom entitě a vydavateli, kterému token uděluje přístup.

    Po vypršení platnosti tokenu klient ztratí přístup k odesílání a publikování do entity.

Poznámka

I když se to nedoporučuje, je možné zařízení vybavit tokeny, které udělují přístup k centru událostí nebo oboru názvů. Jakékoli zařízení, které tento token obsahuje, může odesílat zprávy přímo do tohoto centra událostí. Zařízení navíc není možné blokovat odesílání do tohoto centra událostí.

Vždy se doporučuje poskytnout konkrétní a podrobné rozsahy.

Důležité

Po vytvoření tokenů je každý klient zřízen s vlastním jedinečným tokenem.

Když klient odešle data do centra událostí, značek svůj požadavek tokenem. Aby útočník odposlouchával a odcizoval token, musí komunikace mezi klientem a centrem událostí proběhovat přes šifrovaný kanál.

Pokud útočník token odcize, může se zosobnit klienta, jehož token byl odcizen. Blokování vydavatele vykreslí tohoto klienta jako nepoužitelného, dokud neobdrží nový token, který používá jiného vydavatele.

Ověřování Event Hubs pomocí SAS

K ověřování back-endových aplikací, které využívají data generovaná producenty Event Hubs, vyžaduje ověřování pomocí tokenu Event Hubs, aby jeho klienti buď mají práva ke správě, nebo oprávnění k naslouchání přiřazená k oboru názvů Event Hubs nebo instanci nebo tématu centra událostí. Data se využívají z Event Hubs skupin uživatelů. Zásady SAS sice nabízí podrobný rozsah, ale tento obor se definuje jenom na úrovni entity, a ne na úrovni příjemce. To znamená, že oprávnění definovaná na úrovni oboru názvů nebo instance centra událostí nebo téma se použijí na skupiny uživatelů této entity.

Zakázání ověřování pomocí místního klíče nebo klíče SAS

V případě určitých požadavků na zabezpečení organizace možná budete muset úplně zakázat ověřování pomocí místního klíče nebo klíče SAS a spoléhat na ověřování založené na službě Azure Active Directory (Azure AD), což je doporučený způsob připojení k Azure Event Hubs. Ověřování pomocí místního klíče nebo klíče SAS můžete zakázat na Event Hubs oboru názvů pomocí Azure Portal nebo Azure Resource Manager šablony.

Zakázání ověřování pomocí místního klíče NEBO klíče SAS prostřednictvím portálu

Ověřování pomocí místního klíče nebo klíče SAS pro daný obor názvů Event Hubs můžete zakázat pomocí Azure Portal.

Jak je znázorněno na následujícím obrázku, v části Přehled oboru názvů klikněte na místní ověřování.

Přehled oboru názvů pro zakázání místního ověřování

Pak vyberte možnost Zakázáno a klikněte na OK, jak je znázorněno níže. Zakázání místního ověřování

Zakázání ověřování pomocí místního klíče NEBO klíče SAS pomocí šablony

Místní ověřování pro daný obor názvů Event Hubs můžete zakázat nastavením vlastnosti na , jak je znázorněno v Azure Resource Manager disableLocalAuth true šablony (šablona ARM).

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

        }
      ]
    }
  ]

Další kroky

Viz následující články:

Podívejte se na následující související články: