Cannot create a new Topic in ServiceBus with CreateTopicAsync - c#

I'm trying to create a new Topic (and then a subscription) with the method CreateTopicAsync of the library Microsoft.Azure.ServiceBus.Management.
The connection string is correct and I can send and receive messages if I create the topic trough the Azure portal.
What am I doing wrong? Any help is appreciated.
var managementClient = new ManagementClient(ServiceBusConnectionString);
bool topicExists = await managementClient.TopicExistsAsync(TopicName).ConfigureAwait(false);
if (!topicExists) {
TopicDescription td = new TopicDescription(TopicName);
td.MaxSizeInMB = 1024;
td.DefaultMessageTimeToLive = new TimeSpan(2, 0, 0, 0);
await managementClient.CreateTopicAsync(td).ConfigureAwait(false);
}

Although the Service Bus ConnectionString might be correct, for your application to be able to create a Topic it needs to have the Manage right (claim).
Taken from Service Bus access control with Shared Access Signatures:
For each authorization policy rule, you decide on three pieces of information: name, scope, and rights. The name is just that; a unique name within that scope. The scope is easy enough: it's the URI of the resource in question. For a Service Bus namespace, the scope is the fully qualified domain name (FQDN), such as https://.servicebus.windows.net/.
The rights conferred by the policy rule can be a combination of:
'Send' - Confers the right to send messages to the entity
'Listen' - Confers the right to listen (relay) or receive (queue, subscriptions) and all related message handling
'Manage' - Confers the right to manage the topology of the namespace, including creating and deleting entities
The 'Manage' right includes the 'Send' and 'Receive' rights.

Related

Error creating role assignment using Azure REST API - Principal does not exist in the directory

I'm trying to use the Azure REST api to create role assignments, but it's giving an error:
Exception: {"error":{"code":"PrincipalNotFound","message":"Principal 83ad8925d1714aa380a8555cec2d400c does not exist in the directory ####-####-####"}}
var url = $"https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Authorization/roleAssignments/{Guid.NewGuid()}?api-version=2015-07-01";
object payload = new
{
properties = new
{
roleDefinitionId = role.id,
principalId
}
};
await PutAsync<object>(url, payload);
Switching the API version to 2018-09-01-preview does not prevent the issue from occurring.
Related links
https://stackoverflow.com/a/60517687/11141271
https://learn.microsoft.com/en-us/azure/role-based-access-control/role-assignments-template#new-service-principal
https://learn.microsoft.com/en-us/azure/role-based-access-control/role-assignments-rest
https://learn.microsoft.com/en-us/graph/api/group-post-groups?view=graph-rest-1.0&tabs=csharp
Seems to be an issue caused by replication delay on Microsoft's side.
Attempting to create the role assignment right after creating the security group principal can sometimes result in this error.
I resolved this by just putting my API call in a try-catch with 20 retries with a 20 second delay between each attempt. Eventually it just succeeds.
Note that the error message provided by the API doesn't contain the hyphens/dashes in the GUID, this does NOT mean you passed a bad GUID, the error message is just misleading.

Manage a long-running operation in MS Teams Bot

I am using the following sample / article to Manage a Long-running operation in MS Teams Bot.
https://learn.microsoft.com/en-us/azure/bot-service/bot-builder-howto-long-operations-guidance?view=azure-bot-service-4.0
In step 5, a DirectLineClient is being created and an Event Activity is sent to Bot using PostActivityAsync.
var responseActivity = new Activity("event");
responseActivity.Value = originalActivity;
responseActivity.Name = "LongOperationResponse";
responseActivity.From = new ChannelAccount("GenerateReport", "AzureFunction");
var directLineSecret = Environment.GetEnvironmentVariable("DirectLineSecret");
using(DirectLineClient client = new DirectLineClient(directLineSecret))
{
var conversation = await client.Conversations.StartConversationAsync();
await client.Conversations.PostActivityAsync(conversation.ConversationId, responseActivity);
}
However, I need the above sample to work for MS Teams Bot and not the DirectLineClient.
I used Microsoft.Bot.Connector.ConnectorClient but StartconversationAsync and PostActivityAsync methods are not available.
I tried the methods available in Microsoft.Bot.Connector.ConnectorClient
connectorClient.Conversations.CreateConversationAsync(conversationparameters)
connectorClient.ConversationsCreateDirectConversationAsync(botAccount, userAccount, (Activity)newActivity);
connectorClient.Conversations.SendToConversationAsync(conversationid, (Activity)newActivity);
But all the methods failed with Bad Requestwith the error as seen in the Response:
{"error":{"code":"BadArgument","message":"Unknown activity type"}}
The newActivity is created as below:
var messagnewActivity = new Activity("event");
newActivity.Value = originalActivity;
newActivity.From = new ChannelAccount("GenerateReport", "AzureFunction");
newActivity.Type = "event";
newActivity.Conversation = new ConversationAccount { Id = originalActivity.Conversation.Id };
newActivity.ChannelId = originalActivity.ChannelId;
Can someone please suggest how do I pass the Activity (Event Activity type) to MS Teams Bot.
Thanks
Gagan
I'm not really familiar with Direct Line, but I think it's effectively an -alternative- type of bot to Teams, so if you're trying to do this inside Teams, it explains the issue. In principle, the basic idea is quite simple though:
you store state somehow (e.g. in memory or in a database) to indicate that the long running operation is in progress for the user
when the long-running process is complete, your code (which could live OUTSIDE your bot, e.g. in an Azure Function) can send the user a message AS IF IT WAS the bot - this is called Pro-Active Messaging and you can read more about it at https://learn.microsoft.com/en-us/graph/teams-proactive-messaging.
This is to inform you that I was facing the same issue sometime before then I found a tweak in the code while debugging. when it calls twice recursively then the Activity Id is the same as the previous one. you can check if the activity id is the same then return the request else go with it.

Configuring wildcard topic selectors in ActiveMQ

Based on the documentation wildcards support does exist, but I can't seem to find any other info on whether it's just supposed to work or if it's configured on the server or whether the producers or consumers need to configure it.
I'm assuming as a publisher I would just send messages to a topic named /patient/2/goal/ and when a consumer subscribed to a topic called /patient/*/goal/ it would still receive the message, however nothing shows up. What am I missing?
Please note that if I publish a message to /patient/*/goal/ and subscribe to /patient/*/goal/ then I receive the message. However, that only confirms my message bus is working, not that wildcard support is working.
Producer test:
var connectUri = new Uri("...");
var factory = new NMSConnectionFactory(connectUri);
var connection = factory.CreateConnection();
session = connection.CreateSession();
var destination = session.GetTopic("/patient/1/goal/");
producer = session.CreateProducer(destination);
...
Consumer:
var topic = _session.GetTopic("/patient/*/goal/");
var consumer = _session.CreateConsumer(topic);
...
Using / as the the path separator needs to be configured through a plugin. Switching to . made it work as expected.

AmazonAWSHealthClient.DescribeEventsRequest: No such host is known

I want to make a request for the health events on my AWS account. I use this code to do the request:
using (var client = new AmazonAWSHealthClient("accesskey", "privatekey", RegionEndpoint.EUCentral1))
{
var request = new DescribeEventsRequest();
var response = client.DescribeEventsAsync(request).Result;
}
But the response is "No such host is known". What do I need to change? Do I need to alter some settings on my AWS account?
I had to switch out the EUCentral1 in the clients constructor for USEast1 and it worked (I was then missing some permissions, but that I can fix). Not providing a region for the client also didn't help, I specifically had to provide the USEast1 region. Apparently that region is the one that AWS treats as "Global", as you see "Global" selected as a region, when you are in the Personal Health Dashboard.

Create Azure Service Bus queue Shared Access Policy programmatically

I have implemented an Azure Service Bus REST API client. At the moment I am building xUnit tests for my REST project and need to create a Queue with a name provided by the test, send messages with the REST client and then delete the Queue with that specific name.
One of my requirements are to specify a Shared Access Policy for the newly created Queue with only Send permissions programmatically but I can't find anything online that suggests that this is possible.
So far I have this
TokenProvider credentials = TokenProvider.CreateSharedAccessSignatureTokenProvider("MyBusAccessPolicy", "XXXXXXXXXXXXXXXX");
NamespaceManager namespaceManager = new NamespaceManager(ServiceBusEnvironment.CreateServiceUri("sb", _serviceNamespace, string.Empty), credentials);
QueueDescription queueDescription = await namespaceManager.CreateQueueAsync(queueName);
How would I proceed to create the Shared Access Policy specifically for that queue if even possible?
Neil,
Something like this should work:
string queuePolicyName = "SendPolicy";
string queuePrimaryKey = SharedAccessAuthorizationRule.GenerateRandomKey();
QueueDescription queueDescription = new QueueDescription(queueName);
SharedAccessAuthorizationRule queueSharedAccessPolicy = new SharedAccessAuthorizationRule(queuePolicyName, queuePrimaryKey, new[] { AccessRights.Send });
queueDescription.Authorization.Add(queueSharedAccessPolicy);
await _namespaceManager.CreateQueueAsync(queueDescription);

Categories

Resources