Sunday, August 25, 2019

Request Graph in a PowerShell script to get Azure AD Logs

Introduction

Azure Active Directory provides IT teams with two kinds of important reports (MS documentation):
  • Audit logs
    These logs track all the activity regarding Azure Active directory performed by users and administrators.
    Audit logs provide system activity information about users and group management, managed applications and directory activities.
  • Sign-ins
    These logs keep tracks of all the sign-ins to Azure. This is information about the usage of managed applications and user sign-in activities.
This is the logs retention duration of all these logs in Azure Active Directory (offical MS documentation here)
Report Azure AD Free Azure AD Basic Azure AD Premium P1 Azure AD Premium P2
Audit logs 7 days 7 days 30 days 30 days
Sign-ins N/A N/A 30 days 30 days
Azure MFA usage 30 days 30 days 30 days 30 days

It is thus useful and sometimes mandatory (for very secure activities, Army, Health, Banks, etc.) to save these logs longer. Microsoft and Azure specialists offer several approaches to do it (MS Documentation 1 and MS Documentation 2).
You can manually: You can also use powershell scripts to get the data. You can then store them as file, in databases, or any storage solution either in your private cloud or in Azure. : In this post, I will detail the last approach. It is not the newest one, using the certificate seems to be the newest way to get the logs programmatically, and linking the log to a storage account the most simple way to save them, but this post will show you how to request the Graph API using PowerShell and the credentials of an Azure App (Service Principal). Thus, we will:
  • Configure Azure to create an app and get the required App credentials to request the Graph API using PowerShell
  • Use the App client and secret to get the audit logs from Azure AD

1. Configuration actions in Azure Portal to create the App

Here is the official Microsoft documentation for reference. Portal UI has changed and it is not up to date yet. That's a reason why I published this post.

1.1. Prerequisites

To register an App that can be used in PowerShell to get Azure AD logs, you have to be:
  • Azure Administrator
  • Global Administrator
Here is a documentation for main security and admin roles in Azure

1.2. App creation

Sign in to Azure Portal and click on the active directory button in the left menu.



Then click on App Registration and Add.



In the "Register Application" pane, let default configuration. Just type the name of your App and for redirect url, you can use https://localhost.



When the App is registered, you are redirect on the App pane sumarizing main information. Notice that the Client ID has been defined.



1.3. Setting permission Microsoft Graph AuditLog.ReadAll for the app


We are now going to give permissions to the App in order to be able to access the Azure AD Audit and Sign-ins logs data using the App credentials in a PowerShell script.
Click on the API Permission item on the left menu.



Then click on "Add a permission" button, the "Request API Permissions" pane is opening, click on the Microsoft Graph panel.



Click on Application permission because we want to use the App credentials and permission within a PowerShell script. Actually, we have registered an Azure App, but we are only interested by the Service Principal of the App (roughly a service account), because we need credentials and permissions for a PowerShell script. Here is the Microsoft documentation about relationship between Azure App and Service Principal, if you want to know more on this topic.



Then, check AuditLog.ReadAll and click on "Add permissions" button.



You are led back to the "API Permissions" pane and notice that the set permission needs Administrator aproval, so, as you are an administrator, click on "Add admin consent" button.



A confirmation dialog is opening beacause granting permissions to an App can have dangerous security consequences.



When admin consent is done you can see that the granted permission is effective.



1.4. Setting permission Azure Active Directory Graph Directory.ReadAll for the app

Do exactly the same than above except...
that you choose Azure Directory graph pane...





and check Directory.ReadAll







You should obtain this screen at the end.



1.4. Setting secret for the App (Service Principal)

Now than whe have the App with its Service Principal Client ID and the required permissions for requesting Azure Active Directory Logs, it misses just a secret (password) to authenticate to Azure in a PowerShell script.
Click on "Certificates & secrets" item on the left menu, then on "New secret" button.



Give the secret a name and a duration.



When it's done you get a new secret. Cautionously copy and paste it in a file because the secret will be unvisible on the portal later for security concerns.



At this point, you have all you need to make a PowerShell script work: the App (Service Principal) with an ID, a secret and required permissions.



2. Requesting Azure AD Logs in PowerShell with the created App

Thanks to Bachoang, here is a github script ready to use:
Save the script in a ps1 file, open it with your favorite PowerShell editor.
Replace the client ID, client secret by those of the created App. Change the tenant domain name.
I also updated the Url of Graph API line 20:
$url = "https://graph.microsoft.com/v1.0/auditLogs/directoryAudits?\`$filter=eventTime gt $2daysago"

You can also update the file path line 26 if you want to get the Azure AD logs in a file in json format
Last, the new secret format is no longer 44 characthers as writen line 3, but 32.



Then, you can run the script and see the results in your PowerShell editor output.

3. Using Graph Explorer

I will finish this post by showing a way to track issues when requesting Graph if needed. You can use Graph Explorer.



Sign-in with your tenant admin account, paste the Graph Azure AD request and run the query. You can check that way that everything is all right regarding the Graph Url, an data availability and correctness.



2 comments:

Brajesh said...

Hey, Could you check if this API is still honoring the filter parameters correctly? I am trying so many combinations none of them working. Even graph explorer pulling wrong data

Like for this URL - it is giving me old data too.
https://graph.microsoft.com/v1.0/auditLogs/directoryAudits?\`$filter=activityDateTime ge 2020-02-24T18:39:36Z

Anonymous said...

I have a requirement to search the Directory Audit Logs for activity 'Delete group settings' within the past 15 days. I am using the following:

$url = 'https://graph.microsoft.com/beta/auditLogs/directoryAudits?$filter=activityDateTime ge ' + $16daysago + ' and activityDateTime lt '+ $Today

Once the search is complete I then filter for the activity.
This works when I search for 2-3 days worth of logs anything more than this powerhsell crashes.
I have tried to add an additional filter for 'activityDisplayName'to the $url but this does not work.
Can you please advise on how best to achieve this