{"id":59450,"date":"2026-10-29T10:02:20","date_gmt":"2026-10-29T00:02:20","guid":{"rendered":"https:\/\/www.cloudproinc.com.au\/index.php\/2026\/10\/29\/retiring-search-unifiedauditlog-without-breaking-audit-scripts\/"},"modified":"2026-10-29T10:03:53","modified_gmt":"2026-10-29T00:03:53","slug":"retiring-search-unifiedauditlog-without-breaking-audit-scripts","status":"publish","type":"post","link":"https:\/\/www.cloudproinc.com.au\/index.php\/2026\/10\/29\/retiring-search-unifiedauditlog-without-breaking-audit-scripts\/","title":{"rendered":"Retiring Search-UnifiedAuditLog Without Breaking Audit Scripts"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">In this blog post Retiring Search-UnifiedAuditLog Without Breaking Audit Scripts we will explain what is changing, why a simple command replacement will not work, and how to prepare your audit automation before the 15 October 2027 retirement date.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p class=\"wp-block-paragraph\">If your organisation uses PowerShell to export Microsoft 365 audit records, this change may affect security investigations, compliance reports and evidence supplied to insurers or auditors. The immediate risk is not that Microsoft is removing audit data. It is that the scripts used to find and export that data must be redesigned.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">At a high level, Search-UnifiedAuditLog is a PowerShell command that searches activity across services such as Exchange, SharePoint, OneDrive, Microsoft Teams and Microsoft Entra ID. The replacement is the Microsoft Graph AuditLogQuery API, which provides a structured way for applications to request the same central Microsoft 365 audit information.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Microsoft Graph is effectively a secure front door through which approved applications can access Microsoft cloud services. Instead of running one command and waiting for results, your script submits a search job, checks whether it has finished, and then downloads the records.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Why this is more than a PowerShell command change<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A common assumption is that IT teams can replace Search-UnifiedAuditLog with a new command and leave everything else untouched. Unfortunately, the two approaches work differently.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The existing command can return records directly during the PowerShell session. AuditLogQuery uses an asynchronous process, which means Microsoft completes the search in the background.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Create an audit search with a date range and filters.<\/li>\n<li>Save the unique query ID returned by Microsoft Graph.<\/li>\n<li>Check the query until its status becomes <code>succeeded<\/code> or <code>failed<\/code>.<\/li>\n<li>Download every page of matching records.<\/li>\n<li>Validate, transform and store the results.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">The query can move through states including <code>notStarted<\/code>, <code>running<\/code>, <code>succeeded<\/code>, <code>failed<\/code> and <code>cancelled<\/code>. Scripts must recognise these states rather than assuming that no immediate response means no audit activity was found.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This matters because a poorly rewritten script may appear to run successfully while exporting incomplete evidence.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Start by identifying the business processes at risk<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Do not begin with code. First, find every process that relies on Search-UnifiedAuditLog and document what would happen if it stopped working.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Look beyond scheduled PowerShell files. The command may also appear in incident response instructions, Microsoft Sentinel processes, compliance reporting, Power BI data preparation, cyber insurance evidence collection or scripts maintained by an external IT provider.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example, consider a 200-person professional services company that runs a nightly audit export. The export supports investigations into mailbox changes, file sharing and administrator activity.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If that job silently fails after retirement, the company may only discover the gap when responding to a security incident. What looked like a minor script issue can become days of manual work, delayed reporting and uncertainty about whether evidence is complete.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Our Search-UnifiedAuditLog retirement and migration plan provides a broader discovery and migration timeline. The priority here is making each replacement script reliable enough for production use.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Build around the new three-stage process<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The following simplified PowerShell example shows the main technology pattern. It uses Microsoft Graph v1.0 and requests audit records for a defined period.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Connect-MgGraph -Scopes &quot;AuditLogsQuery.Read.All&quot;\n\n$body = @{\n displayName = &quot;Daily Microsoft 365 audit export&quot;\n filterStartDateTime = (Get-Date).AddDays(-1).ToUniversalTime().ToString(&quot;o&quot;)\n filterEndDateTime = (Get-Date).ToUniversalTime().ToString(&quot;o&quot;)\n recordTypeFilters = @(\n &quot;exchangeAdmin&quot;,\n &quot;sharePointFileOperation&quot;,\n &quot;azureActiveDirectory&quot;\n )\n} | ConvertTo-Json\n\n$query = Invoke-MgGraphRequest `\n -Method POST `\n -Uri &quot;https:\/\/graph.microsoft.com\/v1.0\/security\/auditLog\/queries&quot; `\n -Body $body `\n -ContentType &quot;application\/json&quot;\n\n$queryId = $query.id\n\ndo {\n Start-Sleep -Seconds 10\n\n $status = Invoke-MgGraphRequest `\n -Method GET `\n -Uri &quot;https:\/\/graph.microsoft.com\/v1.0\/security\/auditLog\/queries\/$queryId&quot;\n\n} while ($status.status -in @(&quot;notStarted&quot;, &quot;running&quot;))\n\nif ($status.status -ne &quot;succeeded&quot;) {\n throw &quot;Audit search failed with status $($status.status)&quot;\n}\n\n$records = @()\n$nextPage = &quot;https:\/\/graph.microsoft.com\/v1.0\/security\/auditLog\/queries\/$queryId\/records&quot;\n\ndo {\n $page = Invoke-MgGraphRequest -Method GET -Uri $nextPage\n $records += $page.value\n $nextPage = $page.&#39;@odata.nextLink&#39;\n} while ($nextPage)\n\n$records | ConvertTo-Json -Depth 20 |\n Set-Content &quot;Microsoft365-AuditRecords.json&quot;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This example demonstrates the flow, but a production script needs stronger error handling, monitoring, secure authentication and result validation. Microsoft Graph returns audit records through a dedicated records endpoint, and larger result sets may be divided into multiple pages. Every page must be collected.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Use the minimum permissions required<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Search-UnifiedAuditLog usually runs through an administrator&#8217;s Exchange Online session. Graph automation generally uses an application identity, which is a dedicated digital identity for the script rather than a person&#8217;s account.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This is better for long-term automation, but only if it is configured safely. Avoid placing usernames, passwords or reusable application secrets directly inside PowerShell files.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Use a managed identity where the hosting platform supports it, or certificate-based authentication for unattended jobs. Store certificates and other sensitive material in a protected service such as Azure Key Vault.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Microsoft provides workload-specific permissions for areas including Exchange, SharePoint, OneDrive, Microsoft Entra ID and endpoints. Use the narrowest permission that supports the script rather than automatically granting access to every audit workload.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This reduces the damage that could occur if the application identity were compromised. It also supports the Essential Eight, the Australian government&#8217;s cybersecurity framework, by strengthening administrative access and protecting sensitive systems.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Test completeness rather than trusting record counts<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A successful status does not automatically prove that every expected event was exported. Microsoft Graph exposes properties that indicate the applicable record limit, an approximate returned count and whether that limit was exceeded.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If <code>isRecordCountLimitExceeded<\/code> is true, split the request into smaller time periods and run additional queries. Treat the approximate count as a useful warning signal, not as definitive evidence that the export is complete.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">During migration, run the old and new processes in parallel. Compare:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Record volumes for the same period.<\/li>\n<li>Users, operations and services represented.<\/li>\n<li>Timestamps and time-zone handling.<\/li>\n<li>Fields used by reports or security tools.<\/li>\n<li>Duplicate and missing record behaviour.<\/li>\n<li>The final file format and downstream imports.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Do not compare only the number of rows. Different output structures or filtering behaviour can produce similar totals while still omitting the events your organisation needs.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Plan for throttling and temporary failures<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Microsoft Graph protects the service by limiting excessive requests. When a script sends too many requests, it may receive an HTTP 429 response, which means it must pause before trying again.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Your script should follow the supplied retry period and gradually increase the delay after repeated failures. It should also distinguish between a temporary service issue and a permanent problem such as invalid permissions.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Avoid creating hundreds of small searches when fewer well-designed queries will work. Larger searches can be divided only when record limits or operational requirements make that necessary.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Store the query ID, date range, completion status, exported record count and file location for every run. These operational logs provide an evidence trail showing that the collection process ran and whether it completed successfully.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Give yourself time for parallel operation<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Microsoft&#8217;s retirement date may appear comfortably distant, but audit automation often contains years of undocumented assumptions. Reports may expect exact column names, security tools may depend on a particular JSON structure, and scheduled tasks may run under accounts nobody actively manages.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Our practical AuditLogQuery migration guide covers the wider delivery process. For individual scripts, aim to complete development early enough to allow at least several weeks of parallel testing.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">CloudProInc approaches this work as both a Microsoft Partner and a hands-on cloud security consultancy. With more than 20 years of enterprise IT experience, our focus is not simply making an API call work. It is protecting the reports, investigations and compliance outcomes that depend on the data.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The outcome is dependable audit evidence<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Moving from Search-UnifiedAuditLog to AuditLogQuery is an opportunity to fix fragile scripts, remove stored passwords and introduce proper monitoring. Done well, the result is a more dependable audit process with clearer permissions and better evidence of each successful export.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you are unsure where Search-UnifiedAuditLog is being used, or whether your replacement scripts will collect complete records, CloudProInc can review the current setup and help you plan the migration without turning it into a major project.<\/p>\n\n\n","protected":false},"excerpt":{"rendered":"<p>Search-UnifiedAuditLog retires in October 2027. Learn how to redesign audit scripts for Graph AuditLogQuery without losing evidence, reports or investigation capability.<\/p>\n","protected":false},"author":1,"featured_media":59452,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":true,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[13,14,30,37],"tags":[],"class_list":["post-59450","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog","category-microsoft-365","category-microsoft-graph-api","category-microsoft-purview"],"jetpack-related-posts":[{"id":59268,"url":"https:\/\/www.cloudproinc.com.au\/index.php\/2026\/10\/20\/search-unifiedauditlog-retirement-and-migration-plan-for-2027\/","url_meta":{"origin":59450,"position":0},"title":"Search-UnifiedAuditLog Retirement and Migration Plan for 2027","author":"CPI Staff","date":"October 20, 2026","format":false,"excerpt":"Microsoft will retire Search-UnifiedAuditLog on 15 October 2027. Here is a practical migration plan that protects audit reporting, investigations and compliance workflows.","rel":"","context":"In &quot;Blog&quot;","block_context":{"text":"Blog","link":"https:\/\/www.cloudproinc.com.au\/index.php\/category\/blog\/"},"img":{"alt_text":"","src":"\/wp-content\/uploads\/2026\/10\/search-unifiedauditlog-retirement-and-migration-plan-for-2027.png","width":350,"height":200,"srcset":"\/wp-content\/uploads\/2026\/10\/search-unifiedauditlog-retirement-and-migration-plan-for-2027.png 1x, \/wp-content\/uploads\/2026\/10\/search-unifiedauditlog-retirement-and-migration-plan-for-2027.png 1.5x, \/wp-content\/uploads\/2026\/10\/search-unifiedauditlog-retirement-and-migration-plan-for-2027.png 2x, \/wp-content\/uploads\/2026\/10\/search-unifiedauditlog-retirement-and-migration-plan-for-2027.png 3x, \/wp-content\/uploads\/2026\/10\/search-unifiedauditlog-retirement-and-migration-plan-for-2027.png 4x"},"classes":[]},{"id":59301,"url":"https:\/\/www.cloudproinc.com.au\/index.php\/2026\/10\/21\/a-practical-search-unifiedauditlog-migration-to-auditlogquery-api\/","url_meta":{"origin":59450,"position":1},"title":"A Practical Search-UnifiedAuditLog Migration to AuditLogQuery API","author":"CPI Staff","date":"October 21, 2026","format":false,"excerpt":"A practical migration plan for replacing Search-UnifiedAuditLog before October 2027 while protecting security investigations, compliance reporting and audit evidence.","rel":"","context":"In &quot;Blog&quot;","block_context":{"text":"Blog","link":"https:\/\/www.cloudproinc.com.au\/index.php\/category\/blog\/"},"img":{"alt_text":"","src":"\/wp-content\/uploads\/2026\/10\/a-practical-search-unifiedauditlog-migration-to-auditlogquery-api.png","width":350,"height":200,"srcset":"\/wp-content\/uploads\/2026\/10\/a-practical-search-unifiedauditlog-migration-to-auditlogquery-api.png 1x, \/wp-content\/uploads\/2026\/10\/a-practical-search-unifiedauditlog-migration-to-auditlogquery-api.png 1.5x, \/wp-content\/uploads\/2026\/10\/a-practical-search-unifiedauditlog-migration-to-auditlogquery-api.png 2x, \/wp-content\/uploads\/2026\/10\/a-practical-search-unifiedauditlog-migration-to-auditlogquery-api.png 3x, \/wp-content\/uploads\/2026\/10\/a-practical-search-unifiedauditlog-migration-to-auditlogquery-api.png 4x"},"classes":[]},{"id":58777,"url":"https:\/\/www.cloudproinc.com.au\/index.php\/2026\/10\/12\/microsoft-purview-for-ai-agents-labels-dlp-and-audit-controls\/","url_meta":{"origin":59450,"position":2},"title":"Microsoft Purview for AI Agents Labels DLP and Audit Controls","author":"CPI Staff","date":"October 12, 2026","format":false,"excerpt":"Learn how Purview extends data labels, leak prevention and audit controls to AI agents, reducing risk without stopping useful automation.","rel":"","context":"In &quot;AI Agents&quot;","block_context":{"text":"AI Agents","link":"https:\/\/www.cloudproinc.com.au\/index.php\/category\/ai-agents\/"},"img":{"alt_text":"","src":"\/wp-content\/uploads\/2026\/09\/microsoft-purview-for-ai-agents-labels-dlp-and-audit-controls.png","width":350,"height":200,"srcset":"\/wp-content\/uploads\/2026\/09\/microsoft-purview-for-ai-agents-labels-dlp-and-audit-controls.png 1x, \/wp-content\/uploads\/2026\/09\/microsoft-purview-for-ai-agents-labels-dlp-and-audit-controls.png 1.5x, \/wp-content\/uploads\/2026\/09\/microsoft-purview-for-ai-agents-labels-dlp-and-audit-controls.png 2x, \/wp-content\/uploads\/2026\/09\/microsoft-purview-for-ai-agents-labels-dlp-and-audit-controls.png 3x, \/wp-content\/uploads\/2026\/09\/microsoft-purview-for-ai-agents-labels-dlp-and-audit-controls.png 4x"},"classes":[]},{"id":469,"url":"https:\/\/www.cloudproinc.com.au\/index.php\/2026\/10\/12\/recover-deleted-or-lost-exchange-online-emails-to-pst\/","url_meta":{"origin":59450,"position":3},"title":"Recover Deleted or Lost Exchange Online Emails to PST","author":"CPI Staff","date":"October 12, 2026","format":false,"excerpt":"In this Exchange Online and Microsoft Purview article, we will show how to Recover Deleted or Lost Exchange Online Emails to PST. As a consulting company, we help many organisations comply with regulatory requirements like data retention documents, chat history, and emails. In the last two years, the Microsoft 365\u2026","rel":"","context":"In &quot;Blog&quot;","block_context":{"text":"Blog","link":"https:\/\/www.cloudproinc.com.au\/index.php\/category\/blog\/"},"img":{"alt_text":"","src":"\/wp-content\/uploads\/2024\/07\/How-to-Recover-Deleted-or-Lost-Exchange-Online-Emails-to-PST.webp","width":350,"height":200,"srcset":"\/wp-content\/uploads\/2024\/07\/How-to-Recover-Deleted-or-Lost-Exchange-Online-Emails-to-PST.webp 1x, \/wp-content\/uploads\/2024\/07\/How-to-Recover-Deleted-or-Lost-Exchange-Online-Emails-to-PST.webp 1.5x, \/wp-content\/uploads\/2024\/07\/How-to-Recover-Deleted-or-Lost-Exchange-Online-Emails-to-PST.webp 2x, \/wp-content\/uploads\/2024\/07\/How-to-Recover-Deleted-or-Lost-Exchange-Online-Emails-to-PST.webp 3x, \/wp-content\/uploads\/2024\/07\/How-to-Recover-Deleted-or-Lost-Exchange-Online-Emails-to-PST.webp 4x"},"classes":[]},{"id":58318,"url":"https:\/\/www.cloudproinc.com.au\/index.php\/2026\/10\/12\/how-to-clean-up-conditional-access-without-locking-out-users\/","url_meta":{"origin":59450,"position":4},"title":"How to Clean Up Conditional Access Without Locking Out Users","author":"CPI Staff","date":"October 12, 2026","format":false,"excerpt":"Messy Conditional Access policies create security gaps and support headaches. Here is a practical process for simplifying them without disrupting staff or locking out administrators.","rel":"","context":"In &quot;Blog&quot;","block_context":{"text":"Blog","link":"https:\/\/www.cloudproinc.com.au\/index.php\/category\/blog\/"},"img":{"alt_text":"","src":"\/wp-content\/uploads\/2026\/08\/how-to-clean-up-conditional-access-without-locking-out-users.png","width":350,"height":200,"srcset":"\/wp-content\/uploads\/2026\/08\/how-to-clean-up-conditional-access-without-locking-out-users.png 1x, \/wp-content\/uploads\/2026\/08\/how-to-clean-up-conditional-access-without-locking-out-users.png 1.5x, \/wp-content\/uploads\/2026\/08\/how-to-clean-up-conditional-access-without-locking-out-users.png 2x, \/wp-content\/uploads\/2026\/08\/how-to-clean-up-conditional-access-without-locking-out-users.png 3x, \/wp-content\/uploads\/2026\/08\/how-to-clean-up-conditional-access-without-locking-out-users.png 4x"},"classes":[]}],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"\/wp-content\/uploads\/2026\/10\/retiring-search-unifiedauditlog-without-breaking-audit-scripts.png","_links":{"self":[{"href":"https:\/\/www.cloudproinc.com.au\/index.php\/wp-json\/wp\/v2\/posts\/59450","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.cloudproinc.com.au\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.cloudproinc.com.au\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.cloudproinc.com.au\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cloudproinc.com.au\/index.php\/wp-json\/wp\/v2\/comments?post=59450"}],"version-history":[{"count":1,"href":"https:\/\/www.cloudproinc.com.au\/index.php\/wp-json\/wp\/v2\/posts\/59450\/revisions"}],"predecessor-version":[{"id":59451,"href":"https:\/\/www.cloudproinc.com.au\/index.php\/wp-json\/wp\/v2\/posts\/59450\/revisions\/59451"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.cloudproinc.com.au\/index.php\/wp-json\/wp\/v2\/media\/59452"}],"wp:attachment":[{"href":"https:\/\/www.cloudproinc.com.au\/index.php\/wp-json\/wp\/v2\/media?parent=59450"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cloudproinc.com.au\/index.php\/wp-json\/wp\/v2\/categories?post=59450"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cloudproinc.com.au\/index.php\/wp-json\/wp\/v2\/tags?post=59450"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}