Авторизация доступа к ресурсам концентраторов событий с помощью подписанных URL-адресов
Подписанный URL-адрес (SAS) обеспечивает детальный контроль над типом доступа, предоставляемым клиентам. Вот некоторые элементы управления, которые можно настроить в SAS.
- Интервал, в течение которого sas действителен, который включает время начала и истечение срока действия.
- Разрешения, предоставляемые с помощью SAS. Например, SAS для пространства имен концентраторов событий может предоставлять разрешение на прослушивание, но не на отправку.
- Только клиенты, предоставляющие действительные учетные данные, могут передать данные в концентратор событий.
- Клиент не может действовать от имени другого клиента.
- Постороннему клиенту можно запретить отправку данных в концентратор событий.
В этой статье рассматривается проверка подлинности доступа к ресурсам концентраторов событий с помощью SAS. Дополнительные сведения о предоставлении доступа к ресурсам концентраторов событий с помощью SAS см. в этой статье.
Примечание.
Мы рекомендуем использовать учетные данные Microsoft Entra, если это возможно, как рекомендации по обеспечению безопасности, а не использовать подписанные URL-адреса, что может быть проще скомпрометировано. Хотя вы можете продолжать использовать подписанные URL-адреса (SAS) для предоставления детального доступа к ресурсам Центров событий, идентификатор Microsoft Entra ID предлагает аналогичные возможности без необходимости управлять маркерами SAS или беспокоиться о отмене скомпрометированного SAS.
Дополнительные сведения об интеграции Microsoft Entra в Центры событий Azure см. в разделе "Авторизация доступа к центрам событий" с помощью идентификатора Microsoft Entra.
Настройка проверки подлинности SAS
Правило SAS можно настроить в пространстве имен Центров событий или сущности (концентратор событий или раздел Kafka). Настройка правила SAS в группе потребителей в настоящее время не поддерживается, но вы можете использовать правила, настроенные в пространстве имен или сущности для защиты доступа к группе потребителей. На следующем рисунке показано, как правила авторизации применяются к примерам сущностей.
В этом примере в примере пространства имен Центров событий (ExampleNamespace) есть две сущности: eh1 и Kafka topic1. Правила авторизации определяются как на уровне сущности, так и на уровне пространства имен.
Правила авторизации manageRuleNS, sendRuleNS и listenRuleNS применяются как к eh1, так и к разделу1. Правила авторизации listenRule-eh и sendRule-eh применяются только к правилу авторизации eh1, а правило авторизации sendRuleT применяется только к разделу1.
При использовании правила авторизации sendRuleNS клиентские приложения могут отправляться как в eh1, так и в раздел1. При использовании правила авторизации sendRuleT применяется детальный доступ только к разделу1, поэтому клиентские приложения, использующие это правило для доступа, теперь не могут отправляться в eh1, а только в раздел1.
Создание маркера подписанного URL-адреса
Каждый клиент, который имеет доступ к имени правила авторизации и одному из его ключей подписи, может создать маркер SAS. Маркер создается путем составления строки в следующем формате:
se
— срок действия маркера. Количество секунд с начала эпохи UNIX (00:00:00 UTC 1 января 1970 г.) до истечения срока действия маркера.skn
— имя правила авторизации, которое является именем ключа SAS.sr
— URI ресурса, к которому осуществляется доступ.sig
— подпись.
Строка сигнатуры — это хэш SHA-256, вычисляемый по URI ресурса (область, как описано в предыдущем разделе) и строковое представление мгновенного истечения срока действия маркера, разделенное возвратом каретки и каналом строк (CRLF). Вычисление хэша напоминает следующий псевдокод и возвращает 256-битное (32-байтное) значение хэша.
SHA-256('https://<yournamespace>.servicebus.windows.net/'+'\n'+ 1438205742)
Маркер содержит нехэшируемые значения, что позволяет получателю повторно вычислить хэш с теми же параметрами и проверить, что издатель использует допустимый ключ подписи.
URI ресурса — это полный URI ресурса служебной шины, к которому запрашивается доступ. Например, http://<namespace>.servicebus.windows.net/<entityPath>
или sb://<namespace>.servicebus.windows.net/<entityPath>
. Вся строка будет выглядеть так: http://contoso.servicebus.windows.net/eh1
.
URI должен быть закодирован с помощью знака процента.
Правило SAS, используемое для подписывания, должно быть настроено для сущности, указанной этим универсальным кодом ресурса (URI) или одним из его иерархических родителей. Например, в предыдущем примере это — http://contoso.servicebus.windows.net/eh1
или http://contoso.servicebus.windows.net
.
Маркер SAS действителен для всех ресурсов с префиксом <resourceURI>
, используемым в строке подписи.
Примечание
Маркер доступа создается для концентраторов событий с помощью политики общего доступа. Дополнительные сведения см. в разделе Политика авторизации общего доступа.
Создание (маркера) подписи на основе политики
В следующем разделе показано, как создать маркер SAS с помощью политик подписанного URL-доступа.
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;
}
Чтобы использовать имя политики и значение ключа для подключения к концентратору событий, используйте конструктор EventHubProducerClient
, принимающий параметр AzureNamedKeyCredential
.
const producer = new EventHubProducerClient("NAMESPACE NAME.servicebus.windows.net", eventHubName, new AzureNamedKeyCredential("POLICYNAME", "KEYVALUE"));
Необходимо добавить ссылку на AzureNamedKeyCredential
.
const { AzureNamedKeyCredential } = require("@azure/core-auth");
Чтобы использовать маркер SAS, созданный с помощью кода, используйте EventHubProducerClient
конструктор, принимающий AzureSASCredential
параметр.
var token = createSharedAccessToken("https://NAMESPACENAME.servicebus.windows.net", "POLICYNAME", "KEYVALUE");
const producer = new EventHubProducerClient("NAMESPACENAME.servicebus.windows.net", eventHubName, new AzureSASCredential(token));
Необходимо добавить ссылку на 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"
}
Проверка подлинности издателей концентраторов событий с помощью SAS
Издатель событий определяет виртуальную конечную точку для концентратора событий. Издатель можно использовать только для отправки сообщений в концентратор событий, но не для их получения.
Как правило, концентратор событий использует один издатель на клиент. Все сообщения, отправленные любому из издателей концентратора событий, добавляются в очередь этого концентратора событий. Издатели обеспечивают точно детализированный контроль доступа.
Каждому клиенту Центров событий назначается уникальный маркер, который передается в клиент. Маркеры созданы таким образом, что каждый уникальный маркер предоставляет доступ к одному уникальному издателю. Клиент, имеющий маркер, может отправлять данные только одному издателю и никаким больше. Если несколько клиентов совместно используют один маркер, они также совместно используют издатель.
Всем маркерам назначаются ключи SAS. Как правило, все маркеры должны быть подписаны тем же ключом. Клиенты не знают о ключе, что не дает клиентам создавать маркеры. Клиенты используют одни и те же маркеры до истечения срока их действия.
Например, чтобы определить правила авторизации, разрешающие только отправку данных в концентраторы событий и публикацию данных в концентраторах, необходимо определить правило авторизации отправки. Его можно сделать на уровне пространства имен или предоставить более детализированную область определенной сущности (экземпляр концентраторов событий или раздел). Клиент или приложение, область действия которого имеет такой детализированный доступ, называется издателем концентраторов событий. Для этого выполните следующие действия.
Создайте ключ SAS для сущности, которую необходимо опубликовать, чтобы назначить ей область отправки. Дополнительные сведения см. в разделе Политики авторизации общего доступа.
Создайте маркер SAS с временем окончания срока действия для определенного издателя с помощью ключа, созданного в шаге 1. Пример кода см. в разделе Создание (маркера) подписи на основе политики.
Предоставьте маркер клиенту издателя, который может отправлять данные только сущности и издателю, к которым маркер предоставляет доступ.
После истечения срока действия маркера клиент теряет доступ к отправке данных в сущность или их публикации в сущности.
Примечание.
Несмотря на то, что мы не рекомендуем использовать их, можно предоставить устройствам маркеры, предоставляющие доступ к концентратору событий или пространству имен. Любое устройство с этим маркером может отправлять сообщения непосредственно в концентратор событий. Кроме того, устройство нельзя внести в список блокировок, чтобы запретить отправку данных в концентратор событий.
Рекомендуется предоставить конкретные и детализированные области.
Важно!
После создания маркеров каждому клиенту присваивается собственный уникальный маркер.
Когда клиент отправляет данные в концентратор событий, к запросу прикрепляется специальный маркер. Во избежание перехвата и кражи маркера злоумышленником связь между клиентом и концентратором событий должна выполняться по зашифрованному каналу.
Если маркер украден злоумышленником, злоумышленник может действовать от имени клиента, маркер которого был украден. Добавление издателя в список блокировок означает, что этот клиент не сможет работать, пока не получит новый маркер, использующий другой издатель.
Проверка подлинности потребителей концентраторов событий с помощью SAS
Для проверки подлинности серверных приложений, которые используют данные, формируемые производителями концентраторов событий, проверка подлинности маркеров концентраторов событий требует, чтобы клиенты имели права управления или прослушивания, назначенные пространству имен концентраторов событий либо экземпляру или разделу концентратора событий. Данные поступают из концентраторов событий с помощью групп потребителей. Хотя политика SAS обеспечивает детальную область, эта область определяется только на уровне сущности, а не потребителя. Это означает, что привилегии, определенные на уровне пространства имен, или концентратор событий или уровень раздела применяются к группам потребителей этой сущности.
Отключение проверки подлинности локального или SAS-ключа
Для определенных требований к безопасности организации необходимо полностью отключить проверку подлинности локального или SAS-ключа и использовать проверку подлинности на основе идентификатора Microsoft Entra, которая является рекомендуемым способом подключения к Центры событий Azure. Вы можете отключить проверку подлинности локального ключа/ключа SAS на уровне пространства имен Центров событий с помощью портала Azure или шаблона Azure Resource Manager.
Отключение проверки подлинности локального или SAS-ключа с помощью портала
На портале Azure можно отключить проверку подлинности локального ключа/ключа SAS для данного пространства имен Центров событий.
Перейдите к пространству имен Центров событий на портале Azure.
На странице обзора выберите "Включена локальная проверка подлинности", как показано на следующем рисунке.
Во всплывающем запустите локальную проверку подлинности , нажмите кнопку "Отключено" и нажмите кнопку "ОК".
Отключение проверки подлинности локального или SAS-ключа с помощью шаблона
Вы можете отключить локальную проверку подлинности для заданного пространства имен Центров событий, установив disableLocalAuth
свойство, true
как показано в следующем шаблоне Azure Resource Manager (шаблон 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": true
},
"resources": [
{
"apiVersion": "2017-04-01",
"name": "[parameters('eventHubName')]",
"type": "EventHubs",
"dependsOn": [
"[concat('Microsoft.EventHub/namespaces/', parameters('eventHubNamespaceName'))]"
],
"properties": {
"messageRetentionInDays": "[parameters('messageRetentionInDays')]",
"partitionCount": "[parameters('partitionCount')]"
}
}
]
}
]
Примеры
- См. пример .NET #6 в этом расположении GitHub, чтобы узнать, как публиковать события в концентраторе событий с использованием учетных данных общего доступа или удостоверения учетных данных Azure по умолчанию.
- См. пример .NET #5 в этом расположении GitHub, чтобы узнать, как использовать или обрабатывать события с использованием учетных данных общего доступа или удостоверения учетных данных Azure по умолчанию.
Дальнейшие действия
См. следующие статьи:
- Авторизация с помощью SAS
- Авторизация с помощью управления доступом на основе ролей Azure (RBAC)
- Дополнительные сведения о концентраторах событий
См. следующие статьи по этой теме:
- Проверка подлинности запросов на Центры событий Azure из приложения с помощью идентификатора Microsoft Entra
- Проверка подлинности управляемого удостоверения с помощью идентификатора Microsoft Entra для доступа к ресурсам Центров событий
- Авторизация доступа к ресурсам Центров событий с помощью Microsoft Entra ID
- Авторизация доступа к ресурсам Центров событий с помощью подписанных URL-адресов