I have code that generates tokens for distributed clients for Azure Service Bus (and event hubs). This worked well with the old Nuget package Microsoft.Azure.ServiceBus and Microsoft.Azure.EventHubs, these package would appear to have been deprecated.
I've upgraded the rest of my code to use Azure.Messaging.ServiceBus and Azure.Messaging.EventHubs but I haven't be able to find a replacement for API to generate tokens to be used on remote apps CreateSharedAccessSignatureTokenProvider
.
I assume the answer will be the same, but I need to do the same thing after replacing EventHubs.
Is there a replacement for Azure EventHubs and Azure ServiceBus where I can generate tokens to grant remote services access to ServiceHub and EventHub resources?
No; the client library does not generate SAS tokens nor connection strings. As a general rule, the current generation of Azure SDKs are intended to support keys and connection strings only in the form returned by the Azure portal or from the Azure CLI.
For programmatic generation, the recommended approach for generating them is documented here for Service Bus and here for Event Hubs, though the format is actually common between them.
Here's an example C# implementation:
public static string BuildSignature(
string fullyQualifiedNamespace,
string entityName,
string sharedAccessKeyName,
string sharedAccessKey,
DateTimeOffset expirationTime)
{
if (string.IsNullOrEmpty(fullyQualifiedNamespace))
{
throw new ArgumentException($" { nameof(fullyQualifiedNamespace) } cannot be null or empty.", nameof(fullyQualifiedNamespace));
}
if (string.IsNullOrEmpty(entityName))
{
throw new ArgumentException($" { nameof(entityName) } cannot be null or empty.", nameof(entityName));
}
if (string.IsNullOrEmpty(fullyQualifiedNamespace))
{
throw new ArgumentException($" { nameof(sharedAccessKeyName) } cannot be null or empty.", nameof(sharedAccessKeyName));
}
if (string.IsNullOrEmpty(fullyQualifiedNamespace))
{
throw new ArgumentException($" { nameof(sharedAccessKey) } cannot be null or empty.", nameof(sharedAccessKey));
}
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(sharedAccessKey));
var encodedAudience = WebUtility.UrlEncode(BuildAudience(fullyQualifiedNamespace, entityName));
var expiration = Convert.ToString(ConvertToUnixTime(expirationTime), CultureInfo.InvariantCulture);
var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes($"{ encodedAudience }\n{ expiration }")));
return string.Format(CultureInfo.InvariantCulture, "{0} {1}={2}&{3}={4}&{5}={6}&{7}={8}",
"SharedAccessSignature",
"sr",
encodedAudience,
"sig",
WebUtility.UrlEncode(signature),
"se",
WebUtility.UrlEncode(expiration),
"skn",
WebUtility.UrlEncode(sharedAccessKeyName));
}
private static string BuildAudience(
string fullyQualifiedNamespace,
string entityName)
{
var builder = new UriBuilder(fullyQualifiedNamespace)
{
Scheme = "amqps",
Path = entityName,
Port = -1,
Fragment = string.Empty,
Password = string.Empty,
UserName = string.Empty,
};
builder.Path = builder.Path.TrimEnd('/');
return builder.Uri.AbsoluteUri.ToLowerInvariant();
}
private static long ConvertToUnixTime(DateTimeOffset dateTimeOffset) =>
Convert.ToInt64((dateTimeOffset - Epoch).TotalSeconds);
private static readonly DateTimeOffset Epoch = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
In the case of Service Bus and Event Hubs, I think a case could be made for supporting SAS generation, since there is no support in the Azure portal nor CLI. However, it's not a feature that we've received many requests for and isn't something that we're currently tracking for consideration.
If you'd like, please feel free to open a feature request in the Azure SDK repository and encourage upvotes. This will help us to prioritize for consideration.