Getting Hosts from Microsoft Intune MDM using Python

Getting Hosts from Microsoft Intune MDM using Python. Today I want to talk about Microsoft Intune. It is a Mobile Device Management platform.

Well, I think that the importance of MDM systems has become much higher than it was before the days of covid-19. Simply because a lot more people now work remotely using corporate laptops. And if these people don’t connect to the corporate network using a VPN, you most likely won’t see any activity from their devices in Active Directory. This means that you will not understand whether the device is active or not. And it will be impossible to get the correct security metrics for these devices.

Mobile device management is a solution to this problem as it maintains a connection between the laptop and the cloud server. MDM can collect various parameters from hosts, but for me the most important parameter is the timestamp. I will not describe all the features of Microsoft Intune here. Simply because at this stage they are not very interesting to me. The task I needed to solve was how to get the timestamp of the last activity for all hosts in Microsoft Intune using the official API. And since this is poorly documented, I want to share it with you.

Let’s start with authentication. The thing is that Intune API can use the same authentication method that I already described in the Microsoft Defender for Endpoint article. So, you need to go to Microsoft Azure and create an application. Then you need to set the permission for this app. And then it will be possible to make a post request and receive an authentication token. I won’t go into details on how to set up an Azure application, just see the previous article on Microsoft Defender for Endpoint. The only difference is that you need to request the intune -> get_data_warehouse permission.

All the rest is the same.

import requests

def get_token():
    body = {
        "resource": "https://api.manage.microsoft.com/",
        "client_id": azure_appId,
        "client_secret": azure_appSecret,
        "grant_type": "client_credentials"
    }
    response = requests.post("https://login.windows.net/" + azure_tenantId + "/oauth2/token", data=body)
    return response.json()["access_token"]

And it’s weird because the folks at Microsoft didn’t mention in the manual that you can use this for authentication, just some weird stuff about oauth2. You might think that Microsoft, one of the most cutting edge tech companies, would have the best guides. But this is not the case. At least for the Intune API.

Then the idea is that you use an authentication token in the headers and make requests to get hosts. But you should get a URL that will be unique to your organization, the easiest way to do this is to go to Reports -> Data Warehouse in the GUI (https://endpoint.microsoft.com/).

The rest is trivial, you will need to make one request and maybe deal with pagination, as I showed in the example below.

def get_devices(auth_token):
    headers = {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
        'Authorization': "Bearer " + auth_token
    }
    skip = 0
    top = 1000
    results = list()
    processing_machines_continue = True
    while processing_machines_continue:
        url = "https://XXXX.manage.microsoft.com/ReportingService/DataWarehouseFEService/devices?api-version=v1.0&$skip= " + str(
            skip) + " &$top=" + str(top)
        response = requests.get(url, headers=headers)
        if response.json()['value'] != list():
            results += response.json()['value']
            skip += top
        else:
            processing_machines_continue = False
    return results

Also I list the parameters that you can retrive using the API:

{'deviceKey': XXXX, 'deviceId': 'XXXX-XXXX-XXXX-XXXX-XXXX', 'deviceName': 'XXXX', 'deviceTypeKey': XXXX, 'deviceRegistrationStateKey': XXXX, 'ownerTypeKey': XXXX, 'enrolledDateTime': '2021-06-19T14:43:23.3597155Z', 'lastSyncDateTime': '2021-06-20T01:01:02.5280342Z', 'managementAgentKey': XXXX, 'managementStateKey': XXXX, 'azureADDeviceId': 'XXXX-XXXX-XXXX-XXXX-XXXX', 'azureADRegistered': True, 'deviceCategoryKey': None, 'deviceEnrollmentTypeKey': XXXX, 'complianceStateKey': None, 'osVersion': '10.0.19042.631', 'easDeviceId': 'XXXX', 'serialNumber': 'XXXX', 'userId': 'XXXX-XXXX-XXXX-XXXX-XXXX', 'rowLastModifiedDateTimeUTC': '2021-06-04T00:17:01.2070619Z', 'manufacturer': 'XXXX', 'model': 'XXXX', 'operatingSystem': 'Windows', 'isDeleted': False, 'androidSecurityPatchLevel': None, 'meid': None, 'isSupervised': 0, 'freeStorageSpaceInBytes': XXXX, 'totalStorageSpaceInBytes': XXXX, 'encryptionState': 0, 'subscriberCarrier': '', 'phoneNumber': None, 'imei': None, 'cellularTechnology': None, 'wiFiMacAddress': 'XXXX', 'ethernetMacAddress': 'XXXX', 'office365Version': None, 'windowsOsEdition': '48'}

8 thoughts on “Getting Hosts from Microsoft Intune MDM using Python

  1. Ibrahim

    Hello, thanks you for this share,

    I have a Inoic/cordova app which uses intune MDM, how can i do to retrieve the device data (imei, sn, upn etc.) ?

    if you have any documentation, can you share it with me? thank you !

    Reply
    1. Alexander Leonov Post author

      Hi Ibrahim! I haven’t tried to get this parameters yet. Don’t you see these parameters in DataWarehouseFEService/devices request output? And I only use the documentation publicly available on the site.

      Reply
      1. Ibrahim

        Thanks you for your answer,

        My GET request https://XXX.manage.microsoft.com/ReportingService/DataWarehouseFEService/devices?api-version=v1.0 in Postman give an errors, can you have any idea please ? thanks !

        {
        “ErrorCode”: “Forbidden”,
        “Message”: “{\r\n \”_version\”: 3,\r\n \”Message\”: \”An error has occurred – Operation ID (for customer support): 00000000-0000-0000-0000-000000000000 – Activity ID: 679XXXX-37c2-4ba3-90bf-xxx – Url: https://XXX.manage.microsoft.com/ReportingService/DataWarehouseFEService/devices?api-version=v1.0\”,\r\n \”CustomApiErrorPhrase\”: \”\”,\r\n \”RetryAfter\”: null,\r\n \”ErrorSourceService\”: \”\”,\r\n \”HttpHeaders\”: \”{\\\”WWW-Authenticate\\\”:\\\”Bearer realm=\\\\\\\”urn:intune:service,xxxxx73-f703-4a4e-85e4-58016xxxx3cfa7,fxxxx-59bf-4f0d-b1b2-0ef84ddfe3c7\\\\\\\”\\\”}\”\r\n}”,
        “Target”: null,
        “Details”: null,
        “InnerError”: null,
        “InstanceAnnotations”: []
        }

        Reply
        1. Alexander Leonov Post author

          Ibrahim, most likely you have a problem with Permissions granted for your app. Check them in portal.azure.com. Also, check that granted permissions have “Application” Type.

          Reply
          1. Ibrahim

            I added all permission but still the same problem.

            DeviceManagementManagedDevices.Read.All type “application “and “delegue”
            DeviceManagementManagedDevices.Read.All type ” application” and “delegue”

            get_data_warehouse. type “apllication”

            can i please contact you on google meet or Discord ? thank you.

  2. Pingback: Vulnerability Management news and publications #2 | Alexander V. Leonov

  3. Pingback: И тут было бы справедливо спросить: «А не ты ли, Александр, совсем недавно топил за эти самые облачные ИБ сервисы Microsoft, а теперь получаетс

  4. Pingback: How to get Antivirus-related Data from Microsoft Defender for Endpoint using Intune and Graph API | Alexander V. Leonov

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.