maritio_o
maritio_o

Reputation: 127

Is it possible to get the ASC location from the Azure Python SDK?

I am fetching a subscription's Secure Score using the Microsoft Azure Security Center (ASC) Management Client Library. All operations in the library state that

You should not instantiate directly this class, but create a Client instance that will create it for you and attach it as attribute.

Therefore, I am creating a SecurityCenter client with the following specification:

SecurityCenter(credentials, subscription_id, asc_location, base_url=None)

However, it seems to me like the only way to get the asc_location information properly is to use the SecurityCenter client to fetch it... The spec says the same as the quote above, You should not instantiate.... So I am stuck not being able to create the client because I need the ASC location to do so, and I need to create the client to get the ASC locations.

The documentation mentions

The location where ASC stores the data of the subscription. can be retrieved from Get locations

Googling and searching through the Python SDK docs for this "Get locations" gives me nothing (else than the REST API). Have I missed something? Are we supposed to hard-code the location like in this SO post or this GitHub issue from the SDK repository?

Upvotes: 2

Views: 465

Answers (3)

ajk
ajk

Reputation: 4603

I ran into this recently too, and initially did something based on @stanley-gong's answer. But it felt a bit awkward, and I checked to see how the Azure CLI does it. I noticed that they hardcode a value for asc_location:

def _cf_security(cli_ctx, **_):
    from azure.cli.core.commands.client_factory import get_mgmt_service_client
    from azure.mgmt.security import SecurityCenter


    return get_mgmt_service_client(cli_ctx, SecurityCenter, asc_location="centralus")

And the PR implementing that provides some more context:

we have a task to remove the asc_location from the initialization of the clients. currently we hide the asc_location usage from the user. centralus is a just arbitrary value and is our most common region.

So... maybe the dance of double-initializing a client or pulling a subscription's home region isn't buying us anything?

Upvotes: 0

cfchou
cfchou

Reputation: 1239

I recently came across this problem.

Based on my observation, I can use whatever location under my subscription to initiate SecurityCenter client. Then later client.locations.list() gives me exactly one ASC location.

# Any of SubscriptionClient.subscriptions.list_locations will do
location = 'eastasia'

client = SecurityCenter(
            credential, my_subscription_id,
            asc_location=location
        )

data = client.locations.list().next().as_dict()
pprint(f"Asc location: {data}")

In my case, the it's always westcentralus regardless my input was eastasia.

Note that you'll get exception if you use get instead of list

data = client.locations.get().as_dict()
pprint(f"Asc location: {data}")
# azure.core.exceptions.ResourceNotFoundError: (ResourceNotFound) Could not find location 'eastasia'

So what i did was a bit awkward,

  1. create a SecurityCenter client using a location under my subscription
  2. client.locations.list() to get ASC location
  3. Use the retrieved ASC location to create SecurityCenter client again.

Upvotes: 0

Stanley Gong
Stanley Gong

Reputation: 12153

As offical API reference list locations indicates:

The location of the responsible ASC of the specific subscription (home region). For each subscription there is only one responsible location.

It will not change, so you can hardcode this value if you already know the value of asc_location of your subscription.

But each subscription may have different asc_location values(my 2 Azure subscriptions have different asc_location value). So if you have a lot of Azure subscriptions, you can just query asc_location by API (as far as I know, this is the only way I can find to do this)and then use SDK to get the Secure Score, try the code below:

from azure.mgmt.security import SecurityCenter
from azure.identity import ClientSecretCredential
import requests
from requests.api import head, request 

TENANT_ID = ''
CLIENT = ''
KEY = ''
subscription_id= ''
getLocationsURL = "https://management.azure.com/subscriptions/"+subscription_id+"/providers/Microsoft.Security/locations?api-version=2015-06-01-preview"


credentials = ClientSecretCredential(
    client_id = CLIENT,
    client_secret = KEY,
    tenant_id = TENANT_ID
)

#request for asc_location for a subscription
azure_access_token = credentials.get_token('https://management.azure.com/.default')
r = requests.get(getLocationsURL,headers={"Authorization":"Bearer " +  azure_access_token.token}).json()
location = r['value'][0]['name']
print("location:" + location)

client = SecurityCenter(credentials, subscription_id, asc_location=location)
for score in client.secure_scores.list():
    print(score)

Result: enter image description here enter image description here

Upvotes: 1

Related Questions