Mengautentikasi akses ke sumber daya Azure Event Hubs menggunakan tanda tangan akses bersama (SAS)

Tanda tangan akses bersama (SAS) memberi Anda kontrol terperinci atas jenis akses yang Anda berikan kepada klien. Berikut adalah beberapa kontrol yang dapat Anda tetapkan di SAS:

  • Interval di mana SAS valid, yang mencakup waktu mulai dan waktu kedaluwarsa.
  • Izin yang diberikan oleh SAS. Misalnya, SAS untuk namespace layanan Azure Event Hubs mungkin memberikan izin mendengarkan, tetapi bukan izin kirim.
  • Hanya klien yang menunjukkan info masuk yang valid yang dapat mengirim data ke hub peristiwa.
  • Klien tidak dapat meniru klien lain.
  • Klien nakal dapat diblokir dari pengiriman data ke hub peristiwa.

Artikel ini membahas tentang mengautentikasi akses ke sumber daya Azure Event Hubs menggunakan SAS. Untuk mempelajari tentang mengotorisasi akses ke sumber daya Azure Event Hubs menggunakan SAS, lihat artikel ini.

Catatan

Microsoft menyarankan agar Anda menggunakan kredensial Microsoft Entra jika memungkinkan sebagai praktik terbaik keamanan, daripada menggunakan tanda tangan akses bersama, yang dapat lebih mudah disusupi. Meskipun Anda dapat terus menggunakan tanda tangan akses bersama (SAS) untuk memberikan akses detail ke sumber daya Event Hubs Anda, MICROSOFT Entra ID menawarkan kemampuan serupa tanpa perlu mengelola token SAS atau khawatir mencabut SAS yang disusupi.

Untuk informasi selengkapnya tentang integrasi Microsoft Entra di Azure Event Hubs, lihat Mengotorisasi akses ke Azure Event Hubs menggunakan ID Microsoft Entra.

Mengonfigurasikan untuk autentikasi SAS

Anda dapat mengonfigurasi aturan SAS pada namespace Layanan Pusat Aktivitas, atau entitas (instans hub peristiwa atau Topik Kafka di hub peristiwa). Mengonfigurasi aturan SAS pada grup konsumen saat ini tidak didukung, tetapi Anda dapat menggunakan aturan yang dikonfigurasi pada namespace atau entitas untuk mengamankan akses ke grup konsumen.

Gambar berikut menunjukkan bagaimana aturan otorisasi berlaku pada entitas sampel.

Mengonfigurasikan aturan otorisasi

Dalam contoh ini, contoh namespace Layanan Azure Event Hubs (ExampleNamespace) memiliki dua entitas: eh1 dan topik Kafka1. Aturan otorisasi didefinisikan baik di tingkat entitas dan juga pada tingkat namespace layanan.

Aturan otorisasi manageRuleNS, sendRuleNS, dan listenRuleNS berlaku untuk eh1 dan t1. Aturan otorisasi listenRule-eh dan sendRule-eh hanya berlaku untuk eh1 dan aturan otorisasi sendRuleT hanya berlaku untuk topik1.

Saat Anda menggunakan aturan otorisasi sendRuleNS, aplikasi klien dapat mengirim ke eh1 dan topik1. Ketika aturan otorisasi sendRuleT digunakan, aturan ini memberlakukan akses terperinci ke topik1 saja dan karenanya aplikasi klien yang menggunakan aturan ini untuk akses sekarang tidak dapat mengirim ke eh1, tetapi hanya ke topik1.

Menghasilkan token Shared Access Signature

Setiap klien yang memiliki akses ke nama aturan otorisasi dan salah satu kunci penandatanganannya dapat menghasilkan token SAS. Token dihasilkan dengan membuat string dalam format berikut:

  • se – Token kedaluwarsa secara instan. Bilangan bulat mencerminkan detik sejak zaman 00:00:00 UTC pada 1 Januari 1970 (zaman UNIX) ketika token kedaluwarsa
  • skn – Nama aturan otorisasi, yang merupakan nama kunci SAS.
  • sr - URI berkode sumber daya yang diakses.
  • sig – Tanda Tangan.

Signature-string adalah hash SHA-256 yang dikomputasi atas URI sumber daya (cakupan seperti yang dijelaskan di bagian sebelumnya) dan representasi string dari instan kedaluwarsa token, dipisahkan oleh CRLF. Komputasi hash terlihat mirip dengan kode pseudo berikut dan mengembalikan 256-bit/32-byte nilai hash.

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

Token berisi nilai yang tidak di-hash sehingga penerima dapat mengalah ulang hash dengan parameter yang sama, memverifikasi bahwa penerbit memiliki kunci penandatanganan yang valid.

Sumber daya URI adalah URI penuh dari sumber daya Azure Service Bus yang aksesnya diklaim. Misalnya, http://<namespace>.servicebus.windows.net/<entityPath> atau sb://<namespace>.servicebus.windows.net/<entityPath> yang merupakan, http://contoso.servicebus.windows.net/eh1.

URI harus dikodekan dengan persen.

Aturan SAS yang digunakan untuk penandatanganan harus dikonfigurasi pada entitas yang ditentukan oleh URI ini, atau oleh salah satu orang tua hierarkisnya. Misalnya, http://contoso.servicebus.windows.net/eh1 atau http://contoso.servicebus.windows.net di contoh sebelumnya.

Token SAS berlaku untuk semua sumber daya yang diawali dengan <resourceURI> yang digunakan dalam string tanda tangan.

Catatan

Anda membuat token akses untuk Azure Event Hubs menggunakan kebijakan akses bersama. Untuk informasi selengkapnya, lihat Kebijakan otorisasi akses bersama.

Menghasilkan tanda tangan(token) dari kebijakan

Bagian berikut menunjukkan bagaimana menghasilkan token SAS menggunakan kebijakan tanda tangan akses bersama,

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

Untuk menggunakan nama kebijakan dan nilai kunci untuk menyambungkan ke hub peristiwa, gunakan konstruktor EventHubProducerClient yang mengambil parameter AzureNamedKeyCredential.

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

Anda perlu menambahkan referensi ke AzureNamedKeyCredential.

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

Untuk menggunakan token SAS yang Anda buat menggunakan kode, gunakan EventHubProducerClient konstruktor yang mengambil AzureSASCredential parameter .

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

Anda perlu menambahkan referensi ke 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"
}

Mengautentikasi penerbit Azure Event Hubs dengan SAS

Penerbit peristiwa menentukan titik akhir virtual untuk hub peristiwa. Penerbit hanya dapat digunakan untuk mengirim pesan ke hub peristiwa dan tidak menerima pesan.

Biasanya, hub peristiwa menggunakan satu penerbit per klien. Semua pesan yang dikirim ke salah satu penerbit hub peristiwa diantrekan dalam hub peristiwa tersebut. Penerbit mengaktifkan kontrol akses mendetail.

Setiap klien Azure Event Hubs diberi token unik, yang diunggah ke klien. Token diproduksi sedemikian rupa sehingga setiap token unik memberikan akses ke penerbit khusus yang berbeda. Klien yang memegang token hanya dapat mengirim ke satu penerbit, dan tidak ada penerbit lain. Jika beberapa klien berbagi token yang sama, maka masing-masing dari mereka berbagi penerbit.

Semua token ditetapkan dengan kunci SAS. Biasanya, semua token ditandatangani dengan kunci yang sama. Klien tidak mengetahui kuncinya, yang mencegah klien dari pembuatan token. Klien beroperasi pada token yang sama sampai kedaluwarsa.

Misalnya, untuk menentukan aturan otorisasi yang mencakup hanya mengirim/menerbitkan ke Azure Event Hubs, Anda perlu menentukan aturan otorisasi pengiriman. Ini dapat dilakukan pada tingkat namespace layanan atau memberikan cakupan yang lebih terperinci ke entitas tertentu (instans hub peristiwa atau topik). Klien atau aplikasi yang tercakup dalam akses terperinci tersebut disebut penerbit Azure Event Hubs. Untuk melakukannya, ikuti langkah-langkah berikut:

  1. Buat kunci SAS pada entitas yang ingin Anda terbitkan untuk menetapkan cakupan kirim di atasnya. Untuk informasi selengkapnya, lihat Kebijakan otorisasi akses bersama.

  2. Hasilkan token SAS dengan waktu kedaluwarsa untuk penerbit tertentu dengan menggunakan kunci yang dihasilkan pada langkah1. Untuk kode sampel, lihat Membuat tanda tangan(token) dari kebijakan.

  3. Berikan token kepada klien penerbit, yang hanya dapat mengirim ke entitas dan penerbit yang diberikan akses oleh token.

    Setelah token kedaluwarsa, klien kehilangan aksesnya untuk mengirim/menerbitkan ke entitas.

Catatan

Meskipun tidak disarankan, dimungkinkan untuk melengkapi perangkat dengan token yang memberikan akses ke hub peristiwa atau namespace layanan. Perangkat apa pun yang memegang token ini dapat mengirim pesan langsung ke hub peristiwa tersebut. Selain itu, perangkat tidak dapat diblokir dari pengiriman ke hub peristiwa tersebut.

Selalu disarankan untuk memberikan cakupan spesifik dan terperinci.

Penting

Setelah token dibuat, setiap klien disediakan token uniknya sendiri.

Saat klien mengirim data ke hub peristiwa, klien menandai permintaannya dengan token. Untuk mencegah penyerang menguping dan mencuri token, komunikasi antara klien dan hub peristiwa harus terjadi melalui saluran terenkripsi.

Jika token dicuri oleh penyerang, penyerang dapat meniru klien yang tokennya telah dicuri. Memblokir penerbit, membuat klien tersebut tidak dapat digunakan hingga menerima token baru yang menggunakan penerbit lain.

Mengautentikasi konsumen Azure Event Hubs dengan SAS

Untuk mengautentikasi aplikasi back-end yang mengkonsumsi dari data yang dihasilkan oleh produsen Azure Event Hubs, autentikasi token Azure Event Hubs mengharuskan kliennya untuk memiliki hak kelola atau hak mendengarkan yang ditetapkan ke namespace layanan Azure Event Hubs atau instans atau topik hub peristiwa. Data dikonsumsi dari Azure Event Hubs menggunakan grup konsumen. Meskipun kebijakan SAS memberi Anda cakupan terperinci, cakupan ini hanya didefinisikan pada tingkat entitas dan bukan di tingkat konsumen. Ini berarti bahwa hak istimewa yang ditentukan pada tingkat namespace atau instans hub peristiwa atau tingkat topik akan diterapkan ke grup konsumen entitas tersebut.

Menonaktifkan autentikasi Kunci Lokal/SAS

Untuk persyaratan keamanan organisasi tertentu, Anda ingin menonaktifkan autentikasi kunci lokal/SAS sepenuhnya dan mengandalkan autentikasi berbasis ID Microsoft Entra, yang merupakan cara yang disarankan untuk terhubung dengan Azure Event Hubs. Anda dapat menonaktifkan autentikasi kunci lokal/SAS di tingkat namespace layanan Pusat Aktivitas menggunakan portal Microsoft Azure atau templat Azure Resource Manager.

Menonaktifkan autentikasi Kunci Lokal/SAS melalui portal

Anda dapat menonaktifkan autentikasi kunci lokal/SAS untuk namespace layanan Pusat Aktivitas tertentu menggunakan portal Microsoft Azure.

Seperti yang ditunjukkan pada gambar berikut, di bagian gambaran umum namespace, pilih Autentikasi Lokal.

Gambaran umum kumpulan nama XML untuk menonaktifkan auth lokal

Lalu pilih opsi Dinonaktifkan dan pilih Ok seperti yang ditunjukkan pada gambar berikut. Menonaktifkan auth lokal

Menonaktifkan autentikasi Kunci Lokal/SAS menggunakan templat

Anda dapat menonaktifkan autentikasi lokal untuk namespace layanan Pusat Aktivitas tertentu dengan mengatur disableLocalAuthpropertitrue seperti yang ditunjukkan pada templat Azure Resource Manager berikut (Templat 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')]"
          }

        }
      ]
    }
  ]

Sampel

  • Lihat sampel .NET #6 di lokasi GitHub ini untuk mempelajari cara menerbitkan peristiwa ke pusat aktivitas menggunakan kredensial akses bersama atau identitas kredensial Azure default.
  • Lihat sampel .NET #5 di lokasi GitHub ini untuk mempelajari cara menggunakan atau memproses peristiwa menggunakan kredensial akses bersama atau identitas kredensial Azure default.

Langkah berikutnya

Lihat artikel berikut:

Lihat artikel terkait berikut ini: