Search code examples
azureazureservicebusservicebusazure-servicebus-queues

List Queues/Topics of Azure Service Bus using Rest API with SharedAccessKey


I am trying to list the Queues/Topics in an Azure Service Bus using the REST API.

When I try to connect I just get back a blank feed saying "This is the list of publicly-listed services currently available".

I am using the RootManageSharedAccessKey in the portal (for dev only, I can create a more restricted key later) so it should have all the access rights that I need, I just can't seem to get it to return anything. This documentation seems to suggest that this will work, but there's no actual working examples, just theoretical responses.

I have tried doing a GET request with the signature in the URL like this:

https://myservicebusnamespace.servicebus.windows.net/$Resources/Queues;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=MYSHAREDACCESSKEY

I have also tried doing it like this:

https://myservicebusnamespace.servicebus.windows.net/$Resources

and then setting the Authorization header to

WRAP access_token="MYSHAREDACCESSKEY="

Both times I just get this back

<feed xmlns="http://www.w3.org/2005/Atom">
    <title type="text">Publicly Listed Services</title>
    <subtitle type="text">This is the list of publicly-listed services currently available.</subtitle>
    <id>uuid:6a5d438d-1793-451b-be41-XXXXXXXXXXXX;id=XXXXXX</id>
    <updated>2020-06-28T13:03:04Z</updated>
    <generator>Service Bus 1.1</generator>
</feed>

If I change the url slightly to be:

https://myservicebusnamespace.servicebus.windows.net/$Resources/Queues/

I get a slightly different response back of:

<Error>
    <Code>401</Code>
    <Detail>claim is empty. TrackingId:c40a2bd2-490d-4b5b-adde-33bc89aa84ff_G36, SystemTracker:myservicebusnamespace.servicebus.windows.net:$Resources/Queues, Timestamp:2020-06-28T13:27:40</Detail>
</Error>

Which seems to suggest that I am not authorised, or I am missing something. If I add an acutual queue name to the end of that url, it goes back to the original response.

I believe there is another way to get this information by using subscription ids and pem keys... using the management urls (https://management.core.windows.net/{subscription ID}/services/ServiceBus/Namespaces/{Namespace}/Topics/) but this should all be possible using the format above, I just can't figure out the exact format required.

EDIT/UPDATE: If I don't include my auth claim, the result is exactly the same, suggesting that it's not seeing my auth claim or it's invalid. However if I include it, and just make it the token, without the WRAP bit at the start, I get an exception saying

<Error>
    <Code>401</Code>
    <Detail>MalformedToken: Invalid authorization header: The request is missing WRAP authorization credentials. TrackingId:7be2d7f0-c165-4658-8bf1-ea104c43defc_G28, SystemTracker:NoSystemTracker, Timestamp:2020-06-28T13:33:09</Detail>
</Error>

So it's like it's reading it then ignoring it?


Solution

  • If you want to list queues or topics we can use Azure service bus service rest api or Azure Resource Manager Rest API. For more details, please refer to the following steps

    • Azure service bus service rest api
    1. Generate SAS token. For more details, please refer to the document

      For example, I use python to create sas token

    import hmac
    import time
    import hashlib
    import base64
    import urllib
    sb_name='bowmantest'
    // your entity path such as $Resources/topics (list topics) $Resources/queues(list queues)
    topic='$Resources/topics' 
    url=urllib.parse.quote_plus("https://{}.servicebus.windows.net/{}".format(sb_name,topic))
    sas_value='' // your share access key 
    sas_name='RootManageSharedAccessKey' // your share access rule name 
    expiry = str(int(time.time() + 10000))
    to_sign =(url + '\n' + expiry).encode('utf-8') 
    sas = sas_value.encode('utf-8')
    signed_hmac_sha256 = hmac.HMAC(sas, to_sign, hashlib.sha256)
    signature = urllib.parse.quote(base64.b64encode(signed_hmac_sha256.digest()))
    auth_format = 'SharedAccessSignature sig={0}&se={1}&skn={2}&sr={3}'
    auth=auth_format.format(signature,expiry,sas_name,url)
    print(auth)
    
    
    1. Call the rest API

    1). list Queues

    GET https://<namespace name>.servicebus.windows.net/$Resources/queues
    
    Authorization <sas token>
    

    enter image description here

    2). List topics

    GET https://<namespace name>.servicebus.windows.net/$Resources/topics
    
    Authorization <sas token>
    

    enter image description here

    • Azure Resource Manager Rest API
    1. create a service principal and assign Azure RABC role to the sp(I use Azure CLI)
    az login
    #it will create a service principal and assign contributor role to the sp
    az ad sp create-for-rbac -n "jonsp2"
    

    enter image description here

    1. Get Azure AD token
    POST /{tenant}/oauth2/v2.0/token HTTP/1.1           //Line breaks for clarity
    Host: login.microsoftonline.com
    Content-Type: application/x-www-form-urlencoded
    
    client_id=<app id>
    &scope=https://management.azure.com/.default
    &client_secret=<app password>
    &grant_type=client_credentials
    
    1. call the rest API

    List Queues

    GET https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.ServiceBus/namespaces/{namespaceName}/queues?api-version=2017-04-01
    
    Authorization Bearer <AD token>
    

    enter image description here