<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Cloud-Milieu]]></title><description><![CDATA[Cloud-Milieu]]></description><link>https://blog.cloud-mili.eu</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1738622129059/03c1e31e-e273-452f-a386-5bd91e6db3d2.png</url><title>Cloud-Milieu</title><link>https://blog.cloud-mili.eu</link></image><generator>RSS for Node</generator><lastBuildDate>Thu, 16 Apr 2026 12:18:59 GMT</lastBuildDate><atom:link href="https://blog.cloud-mili.eu/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Fun with Microsoft MCP Server for Enterprise]]></title><description><![CDATA[You want to know what I did between Christmas and New Years Eve? Of course I spent time with the family, but that would be no content for a tech blog right?I tried out the Microsoft MCP Server for Enterprise (preview)
What is this for?
In general the...]]></description><link>https://blog.cloud-mili.eu/fun-with-microsoft-mcp-server-for-enterprise</link><guid isPermaLink="true">https://blog.cloud-mili.eu/fun-with-microsoft-mcp-server-for-enterprise</guid><category><![CDATA[mcp server]]></category><category><![CDATA[mcp]]></category><category><![CDATA[Entra ID]]></category><category><![CDATA[Visual Studio Code]]></category><dc:creator><![CDATA[Sven Lüders]]></dc:creator><pubDate>Fri, 09 Jan 2026 16:07:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1767918205054/a8d90c1b-9cfc-4a01-8c01-820a15772635.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You want to know what I did between Christmas and New Years Eve? Of course I spent time with the family, but that would be no content for a tech blog right?<br />I tried out the <a target="_blank" href="https://learn.microsoft.com/en-us/graph/mcp-server/overview"><strong>Microsoft MCP Server for Enterprise (preview)</strong></a></p>
<h2 id="heading-what-is-this-for">What is this for?</h2>
<p>In general the <strong>Model Context Protocol (MCP)</strong> is a standard that lets AI models securely and consistently access external tools, data, and services.</p>
<p>In our case the MCP is adressing GraphAPI. Its abilities is defined by its <a target="_blank" href="https://learn.microsoft.com/en-us/graph/mcp-server/get-started?tabs=portal%2Cvscode#list-of-mcp-server-scopes">MCP Server scopes</a>. Of course you know some of them, like User.Read.All or Organization.Read.All.<br />🔴First key takeaway: the MCP has read-only scopes. In case you need more details on scopes, have a look <a target="_blank" href="https://learn.microsoft.com/en-us/powershell/entra-powershell/how-to-manage-mcp-server-permissions?view=entra-powershell">here</a>.<br />🔴Next takeaway is about licensing: There are no extra cost or separate licenses. But the right licenses are required for the data you want to access (for example Entra ID P2 licenses for Privileged Identity Management data)</p>
<p>The process how the MCP works looks like this:</p>
<p><a target="_blank" href="https://learn.microsoft.com/en-us/graph/mcp-server/overview#how-it-works"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767917375121/9f267ed0-42d3-4e79-acb2-e4b025b23699.png" alt class="image--center mx-auto" /></a></p>
<p>You will recognize the single steps at the end of the post in my short ref case.</p>
<h2 id="heading-what-do-you-have-to-do">What do you have to do?</h2>
<p>Honestly - just follow the <a target="_blank" href="https://learn.microsoft.com/en-us/graph/mcp-server/get-started?tabs=http%2Cvscode">Microsoft article</a> because its on point. Let me outline the basic steps for you:</p>
<ol>
<li><p>Install <strong>Microsoft.Entra.Beta</strong> PowerShell module (version 1.0.13 or later):</p>
<pre><code class="lang-powershell"> <span class="hljs-built_in">Install-Module</span> Microsoft.Entra.Beta <span class="hljs-literal">-Force</span> <span class="hljs-literal">-AllowClobber</span>
</code></pre>
</li>
<li><p>To register the MCP Server, you have to connect to Entra and consent to the required permissions:</p>
<pre><code class="lang-powershell"> <span class="hljs-built_in">Connect-Entra</span> <span class="hljs-literal">-Scopes</span> <span class="hljs-string">'Application.ReadWrite.All'</span>, <span class="hljs-string">'Directory.Read.All'</span>, <span class="hljs-string">'DelegatedPermissionGrant.ReadWrite.All'</span>
</code></pre>
</li>
<li><p>Register the Microsoft MCP Server for Enterprise in your tenant and grant all permissions to Visual Studio Code:</p>
<pre><code class="lang-powershell"> <span class="hljs-built_in">Grant-EntraBetaMCPServerPermission</span> <span class="hljs-literal">-ApplicationName</span> VisualStudioCode
</code></pre>
</li>
<li><p>After the grant you will find some new Enterprise Applications:</p>
<p> | Name | Globally unique <strong>appId</strong> (client ID) |
 | --- | --- |
 | Microsoft MCP Server for Enterprise | <code>e8c77dc2-69b3-43f4-bc51-3213c9d915b4</code> |
 | Visual Studio Code | <code>aebc6443-996d-45c2-90f0-388ff96faa56</code> |</p>
<p> The “server“ app ships a service principal with the endpoint <code>https://mcp.svc.cloud.microsoft/enterprise</code></p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767908833910/fba51734-f0ba-48d9-9539-2414935afe3a.png" alt class="image--center mx-auto" /></p>
<p> The “client“ app named “Visual Studio Code“ has the defined MCP scopes:</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767907327019/3169d855-e955-4f87-b4bb-6a50ba521430.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Connect to MCP using VS Code</p>
<p> Go for it and click <a target="_blank" href="https://vscode.dev/redirect/mcp/install?name=Microsoft%20MCP%20Server%20for%20Enterprise&amp;config=%7b%22name%22:%22Microsoft%20MCP%20Server%20for%20Enterprise%22%2c%22type%22:%22http%22%2c%22url%22:%22https://mcp.svc.cloud.microsoft/enterprise%22%7d">Install Microsoft MCP Server for Enterprise</a> to open VS Code's MCP install page:</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767908165109/f2a58d5f-778a-467d-b34c-a1647dfac1a4.png" alt class="image--center mx-auto" /></p>
<p>After a successfull authentication you and your MCP are set.</p>
<h2 id="heading-prompting">Prompting</h2>
<p>I have started prompting in VS Code by an easy idea: I asked to evaluate the oldest user logins.<br />It’s fun to see how natural language is translated to proper Graph calls and vice versa:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767909526967/7d0c10fe-a1a7-4691-a182-0213fff49903.png" alt class="image--center mx-auto" /></p>
<p>To understand the documented process above about how the MCP Server works, I created a short recording. Every M365 admin should relate these daily basic tasks:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/vdgkeM2E3co">https://youtu.be/vdgkeM2E3co</a></div>
<p> </p>
<h2 id="heading-monitoring">Monitoring</h2>
<p>Because of the Enterprise App you can easily monitor the Microsoft MCP Server activity logs with <a target="_blank" href="https://github.com/microsoft/EnterpriseMCP/?tab=readme-ov-file#logs">KQL</a>:</p>
<pre><code class="lang-plaintext">MicrosoftGraphActivityLogs
| where TimeGenerated &gt;= ago(30d)
| where AppId == "e8c77dc2-69b3-43f4-bc51-3213c9d915b4"
| project RequestId, TimeGenerated, UserId, RequestMethod, RequestUri, ResponseStatusCode
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767979306722/1c289067-3086-4399-a2f4-7766c339b61a.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-whats-next">What’s next?</h2>
<p>A next step I like to try, is to use a custom MCP client and not VS Code. In case this happens, I will let you know for sure. 😁<br />Another idea is to attach Azure Foundry as outlined <a target="_blank" href="https://github.com/mcp/microsoft/EnterpriseMCP">here</a>.<br />And the final takeaway: 🔴 In case you want more than just read stuff from your tenant - have a look at <a target="_blank" href="https://lokka.dev/">lokka.dev</a> or just be patient because write access is on the <a target="_blank" href="https://github.com/mcp/microsoft/EnterpriseMCP">roadmap</a>:</p>
<p><em>“Support for write operations is planned for a future release.“</em></p>
<p>And to optimize the preview service, you can <a target="_blank" href="https://forms.cloud.microsoft/pages/responsepage.aspx?id=v4j5cvGGr0GRqy180BHbR_moJKPUTstMhn24HC7OQadUQ0hLUUVUMVhBQlAyTkQzVDIyWjdZN0dIMC4u&amp;route=shorturl">give feedback here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Got lost in PowerShell module versions?]]></title><description><![CDATA[Hopefully I am not the only guy struggling with dll conflicts created by incompatible PowerShell modules and it`s different versions. I am not wondering about these circumstances because I assume every technical guy who’s scripting a bit is more crea...]]></description><link>https://blog.cloud-mili.eu/got-lost-in-powershell-module-versions</link><guid isPermaLink="true">https://blog.cloud-mili.eu/got-lost-in-powershell-module-versions</guid><category><![CDATA[Powershell]]></category><category><![CDATA[Scripting]]></category><dc:creator><![CDATA[Sven Lüders]]></dc:creator><pubDate>Mon, 29 Sep 2025 19:38:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1759174546015/f75d811d-fa4c-4cbc-b682-c4c37eef2bf0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hopefully I am not the only guy struggling with dll conflicts created by incompatible PowerShell modules and it`s different versions. I am not wondering about these circumstances because I assume every technical guy who’s scripting a bit is more creative than interested in house keeping. So over the time I update my PowerShell modules - also with a -Force parameter to be honest. Modules which I have just used once or twice remain on their place and of course I do not clean up my older versions - until now! Time has come to overcome the module chaos - and maybe you can use it for yourself:</p>
<p>But let’s start with the issue. Maybe you guys have encountered the following error:</p>
<p><code>Could not load file or assembly 'C:\Users\User\UsersOneDrive\Documents\PowerShell\Modules\ExchangeOnlineManagement\3.9.0\netCore\Microsoft.Identity.Client.dll'. The located assembly's manifest definition does not match the assembly reference.(0x80131040)</code></p>
<p>I faced that today (once again) after updating some modules. Thankfully I found an PowerShell module called <a target="_blank" href="https://github.com/KnudsenMorten/MicrosoftGraphPS"><strong>MicrosoftGraphPS</strong></a> created by Microsoft MVP <a target="_blank" href="http://aka.ms/morten">Morten Knudsen</a>.</p>
<p>To get your PowerShell house keeping done, just install the module (I just ran it in my user context):</p>
<pre><code class="lang-powershell"><span class="hljs-built_in">Install-Module</span> <span class="hljs-literal">-Name</span> MicrosoftGraphPS <span class="hljs-literal">-Repository</span> PSGallery <span class="hljs-literal">-Force</span> <span class="hljs-literal">-Scope</span> CurrentUser
</code></pre>
<p>Then you can run it with the following options:</p>
<ol>
<li><p>Show details only</p>
<pre><code class="lang-powershell"> Manage<span class="hljs-literal">-Version</span><span class="hljs-literal">-Microsoft</span>.Graph <span class="hljs-literal">-Scope</span> CurrentUser
</code></pre>
</li>
<li><p>Show details, install latest and clean-up old versions</p>
<pre><code class="lang-powershell"> Manage<span class="hljs-literal">-Version</span><span class="hljs-literal">-Microsoft</span>.Graph <span class="hljs-literal">-CleanupOldMicrosoftGraphVersions</span> <span class="hljs-literal">-Scope</span> CurrentUser
</code></pre>
</li>
<li><p>Install, Update and Clean-up older Microsoft Graph versions (except the latest available version)</p>
<pre><code class="lang-powershell"> Manage<span class="hljs-literal">-Version</span><span class="hljs-literal">-Microsoft</span>.Graph <span class="hljs-literal">-InstallLatestMicrosoftGraph</span> <span class="hljs-literal">-CleanupOldMicrosoftGraphVersions</span> <span class="hljs-literal">-Scope</span> CurrentUser
</code></pre>
</li>
</ol>
<p>I stick to these options because these are the most practical for me. There are some more enforce a re-installation or remove all versions of the Graph modules (but that’s not happening EVER 😜). Check out the readme of the module for further details. You can also use a scheduled task to implement an automatic update cycle. At the moment I think I stick to the manual process, but let’s see…</p>
<p>After firing these cmdlets everything worked again and all conflicts are gone. In my case 18 older versions were removed:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759171740541/ed874a62-3f98-4793-bbec-163529d60df5.png" alt class="image--center mx-auto" /></p>
<p>How do you manage your modules and compatibilities? Please comment your approach. And now enjoy being on the latest and greatest version - also of yourself 👑</p>
]]></content:encoded></item><item><title><![CDATA[Using Graph API for Entra Connect Sync version check]]></title><description><![CDATA[forgive me for not starting by what is a hybrid environment regarding Active Directory Domain Services (AD DS) and Entra ID. Let’s break it down to this:
Intro
If you want your objects in sync in both directories you can have to options:

Entra Conne...]]></description><link>https://blog.cloud-mili.eu/using-graph-api-for-entra-connect-sync-version-check</link><guid isPermaLink="true">https://blog.cloud-mili.eu/using-graph-api-for-entra-connect-sync-version-check</guid><category><![CDATA[Entra Connect Sync]]></category><category><![CDATA[Entra ID]]></category><category><![CDATA[graph api]]></category><category><![CDATA[Powershell]]></category><category><![CDATA[identity-management]]></category><category><![CDATA[Hybrid Cloud]]></category><dc:creator><![CDATA[Sven Lüders]]></dc:creator><pubDate>Fri, 28 Mar 2025 18:17:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1743185251734/cedaa8e7-e3ec-47ab-ac34-876056496cde.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>forgive me for not starting by what is a hybrid environment regarding Active Directory Domain Services (AD DS) and Entra ID. Let’s break it down to this:</p>
<h1 id="heading-intro">Intro</h1>
<p>If you want your objects in sync in both directories you can have to options:</p>
<ol>
<li><p>Entra Connect Sync (also known als Azure AD Connect in the good ol’ days)</p>
</li>
<li><p>Entra Cloud Sync</p>
</li>
</ol>
<p>Today’s post is about the Connect Sync service. Long story short: The engine enables synchronization between on-premises Active Directory, Entra ID, and other third-party systems, ensuring consistency across the entire identity ecosystem.</p>
<p>Key components include the <strong>Connector</strong>, which links to source directories and manages data flow, and the <strong>Synchronization Engine</strong>, which handles the logic of mapping and transforming identity data between systems. The <strong>Agent</strong> is a lightweight service installed on the server, responsible for executing synchronization tasks:</p>
<p><img src="https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/media/how-to-connect-sync-technical-concepts/scenario.png" alt="Technical Concepts" /></p>
<p>In case you want to learn more about it, I recommend:</p>
<ul>
<li><p><a target="_blank" href="https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/how-to-connect-sync-technical-concepts">Microsoft Entra Connect Sync: Technical concepts - Microsoft Entra ID | Microsoft Learn</a></p>
</li>
<li><p><a target="_blank" href="https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/concept-azure-ad-connect-sync-architecture">Microsoft Entra Connect Sync: Understanding the architecture - Azure - Microsoft Entra ID | Microsoft Learn</a></p>
</li>
</ul>
<h1 id="heading-issue">Issue</h1>
<p>Back to business - the sync engine has to be updated. <a target="_blank" href="https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/how-to-connect-install-automatic-upgrade#auto-upgrade-eligibility">Auto Upgrade</a> is eligible in some cases:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743177715777/96359690-4d29-4602-8e3d-4975d6503aa7.png" alt class="image--center mx-auto" /></p>
<p>Ok, great but this post is because if a “<a target="_blank" href="https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/reference-connect-version-history#breaking-change-on-entra-connect-sync"><strong>Breaking Change on Entra Connect Sync</strong></a>”:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743177979057/dc419631-b7eb-4a32-826e-6d90c738701c.png" alt class="image--center mx-auto" /></p>
<p>The latest version at the moment I am typing here is <a target="_blank" href="https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/reference-connect-version-history#241290"><strong>2.4.129.0</strong></a> and you have to have at least 2.4.18 (for commercial clouds) or 2.4.21.0 (for non-commercial clouds).<br />If you do not upgrade by the deadline of April 7,2025 the <a target="_blank" href="https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/harden-update-ad-fs-pingfederate?wt.mc_id=MVP_353010#expected-impacts">impacts</a> are:</p>
<ul>
<li><p>All authentication requests to Microsoft Entra ID on the Microsoft Entra Connect wizard will fail.</p>
</li>
<li><p>Configuration of Active Directory Federation Services (ADFS) scenarios through Microsoft Entra Connect wizard won't work.</p>
</li>
<li><p>Configuration of PingFederate scenarios through the Microsoft Entra Connect wizard won't work.</p>
</li>
</ul>
<p>But the good thing about that: The sync service will continue doing it’s job! ✅</p>
<h1 id="heading-using-graph-api">Using Graph API</h1>
<p>In case you want to automate the reporting on the Connect servers, where the agent is installed you should use Graph API. Back in the days I used the MSOL PowerShell module for that, but now this is gone, because of it’s <a target="_blank" href="https://techcommunity.microsoft.com/blog/microsoft-entra-blog/important-update-deprecation-of-azure-ad-powershell-and-msonline-powershell-modu/4094536">deprecation</a>. Since then I struggled finding the attributes which I was able to fetch back then by running:</p>
<pre><code class="lang-powershell"><span class="hljs-built_in">Get-MsolCompanyInformation</span> | <span class="hljs-built_in">select</span> DisplayName,InitialDomain,DirSyncClientMachineName,DirSyncClientVersion,DirSyncServiceAccount,DirectorySynchronizationEnabled, DirectorySynchronizationStatus, LastDirSyncTime, LastPasswordSyncTime
</code></pre>
<p>Especially the <strong>DirSyncClientVersion</strong> is the attribute I am looking for. Mapping old cmdlets to new ones can be done via <a target="_blank" href="https://learn.microsoft.com/en-us/powershell/microsoftgraph/azuread-msoline-cmdlet-map?view=graph-powershell-1.0&amp;pivots=msonline">Find Azure AD and MSOnline cmdlets in Microsoft Graph PowerShell | Microsoft Learn</a>. But both the <a target="_blank" href="https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.identity.directorymanagement/get-mgorganization">Get-MgOrganization</a> and the <a target="_blank" href="https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.beta.identity.directorymanagement/get-mgbetaorganization?view=graph-powershell-beta">Get-MgBetaOrganization</a> did not get me these insights. So I had a look at the native Graph API and found <strong>directory/onPremisesSynchronization.</strong></p>
<p>For quick access to Graph API, you should use <a target="_blank" href="https://aka.ms/ge">Graph Explorer</a> or Postman. So I called <a target="_blank" href="https://graph.microsoft.com/beta/directory/onPremisesSynchronization">https://graph.microsoft.com/beta/directory/onPremisesSynchronization</a> to get some insights:</p>
<pre><code class="lang-http"><span class="hljs-attribute">GET https://graph.microsoft.com/v1.0/directory/onPremisesSynchronization</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743182544805/faa7d355-5af5-4ec3-b5d4-9d5604f5d890.png" alt class="image--center mx-auto" /></p>
<p>Sadly, I did only get some configuration features. I just tried then the <strong>beta</strong> version of the API by calling:</p>
<pre><code class="lang-http"><span class="hljs-attribute">GET https://graph.microsoft.com/beta/directory/onPremisesSynchronization</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743182587531/769b89b1-4620-47b7-9d38-4adb09399285.png" alt class="image--center mx-auto" /></p>
<p>And there it is: <strong>synchronizationClientVersion‼️</strong></p>
<p>While writing this post, I checked the <a target="_blank" href="https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.beta.identity.directorymanagement/get-mgbetadirectoryonpremisesynchronization?view=graph-powershell-beta">Get-MgBetaDirectoryOnPremiseSynchronization</a>. And here we go:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743183565741/41d6cb10-3a19-4e28-a49f-f26bd27d0ab1.png" alt class="image--center mx-auto" /></p>
<p>Nevertheless: I hope, if someone looks for that attribute he will find it here 😁</p>
<p>Last but not least… <a target="_blank" href="https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/harden-update-ad-fs-pingfederate#consider-moving-to-microsoft-entra-cloud-sync">Consider moving to Microsoft Entra Cloud Sync</a>. This is where I come back to the beginning, mentioning Entra Cloud Sync as second option. This approach is a SaaS that works from the cloud and allows to set up and manage their sync preferences online. But before you migrate, please evaluate first, because Cloud Sync does not fully support all hybrid scenarios like Connect Sync: <a target="_blank" href="https://aka.ms/EvaluateSyncOptions">https://aka.ms/EvaluateSyncOptions</a></p>
<p><strong>Stay in sync</strong> 🔄️</p>
<p>…and follow for part two if you want to see how to script your report!</p>
]]></content:encoded></item><item><title><![CDATA[Remove invalid retention policy from SharePoint Online]]></title><description><![CDATA[Despite the common sense of using retention features in Microsoft 365 I never had trouble removing data if I had to. But last week I faced something new about invalid retention policies - but lets start from the beginning.
As we all know, sometimes t...]]></description><link>https://blog.cloud-mili.eu/remove-invalid-retention-policy-from-sharepoint-online</link><guid isPermaLink="true">https://blog.cloud-mili.eu/remove-invalid-retention-policy-from-sharepoint-online</guid><category><![CDATA[SharePoint Online]]></category><category><![CDATA[hold]]></category><category><![CDATA[compliance ]]></category><category><![CDATA[RetentionPolicy]]></category><category><![CDATA[Microsoft365]]></category><category><![CDATA[retention]]></category><category><![CDATA[PnP]]></category><category><![CDATA[Powershell]]></category><dc:creator><![CDATA[Sven Lüders]]></dc:creator><pubDate>Sat, 08 Feb 2025 13:13:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1739020887573/d4be876f-7834-49de-9e43-856c93fbd6a9.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Despite the common sense of using retention features in Microsoft 365 I never had trouble removing data if I had to. But last week I faced something new about invalid retention policies - but lets start from the beginning.</p>
<p>As we all know, sometimes things do not work as expected…in this case somebody uploaded a bunch of files resulting in extensive SharePoint storage usage. And of course the data has been deleted, but the site is configured for retention.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738873265907/1032f669-8c71-448f-a072-31c84cb9a4fc.png" alt class="image--center mx-auto" /></p>
<p>My general approach of deleting data, which is on hold is more or less the same:</p>
<ol>
<li><p>If there are Retention Policies in place, exclude the site or group from the retention policy.</p>
</li>
<li><p>Close existing eDiscovery cases with a hold</p>
</li>
<li><p>Disable Data loss prevention (DLP) policies, if there are some</p>
</li>
</ol>
<p>In my specific case I double-checked all parts of the game, but only had to set the retention policy exclusion. Five minutes later (after the policy status showed success) I browsed the Preservation Hold Library. Important to mention that this library keeps copies of all modified or deleted files as enforced by the Retention policy or eDiscovery holds. You can reach it by using “PreservationHoldLibrary“ as a suffix on your SharePoint site URL: <a target="_blank" href="https://YourDomain.sharepoint.com/sites/YourSite/PreservationHoldLibrary">https://TenantDomain.sharepoint.com/sites/SiteName/PreservationHoldLibrary</a></p>
<p>I tried to delete some files…and tried and tried. Every M365 admin knows that 5 minutes is not the appropriate period of time to get things changed. So I kept trying after 24 hours… But the error still told me very kind:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738916791673/73964ae2-cb8f-4ad0-9d63-195dcaf50d62.png" alt class="image--center mx-auto" /></p>
<p><em>“Request was cancelled by event received. If attempting to delete a non-empty folder, it’s possible that it’s on hold.”</em></p>
<p>Of course the status of the retention policy was showing success and not pending. So I assumed the group site is excluded. I also tried to get insights with PowerShell and used the <a target="_blank" href="https://learn.microsoft.com/en-us/powershell/module/exchange/invoke-holdremovalaction?view=exchange-ps">Invoke-HoldRemovalAction</a> cmdlet to find applied holds. But there were no holds applied, so I still had to search for them:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738930922225/a0d23b29-74b4-4ea5-89df-76e97aa8fe00.png" alt class="image--center mx-auto" /></p>
<p>The version history was still showing that the files are not expiring because they are on hold:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738931125709/5af188b5-b9b5-43e9-b2ae-56b40907dae7.png" alt class="image--center mx-auto" /></p>
<p>During a helpful Microsoft support case a guy told me to use the “Help &amp; support“ in the M365 Admin Center to find and remove invalid retention policies by searching for: <strong>Remove invalid retention policy from SharePoint or OneDrive</strong></p>
<p>Just run the test and magic happens: it shows the invalid policy, which still applies:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738872886765/98eeae09-190c-4d7d-8652-e3beef531860.png" alt class="image--center mx-auto" /></p>
<p>Just acknowledge and update in the wizard and there you go 🪄 Now I was ready to delete files and so I <a target="_blank" href="https://www.youtube.com/watch?v=QDYfEBY9NM4">let it be, let it be, let it be, let it be…</a> 🎶</p>
<p>Wow! Lesson learned - this thing is actually good for something!</p>
<p>And just in case you have to delete a lot of files use PowerShell with the <a target="_blank" href="https://pnp.github.io/powershell/">PNP module</a>.</p>
<pre><code class="lang-powershell"><span class="hljs-variable">$siteURL</span> = <span class="hljs-string">"https://yourtenant.sharepoint.com/sites/yoursite"</span>
<span class="hljs-variable">$listName</span> = <span class="hljs-string">"Preservation Hold Library"</span>

<span class="hljs-comment"># install PNP module [https://pnp.github.io/powershell/articles/installation.html]</span>
<span class="hljs-built_in">Install-Module</span> PnP.PowerShell <span class="hljs-literal">-Scope</span> CurrentUser

<span class="hljs-comment"># register EntraID app for PnP PowerShell interactive login approach [https://pnp.github.io/powershell/articles/registerapplication.html]</span>
<span class="hljs-built_in">Register-PnPEntraIDAppForInteractiveLogin</span> <span class="hljs-literal">-ApplicationName</span> <span class="hljs-string">"PnP.App"</span> <span class="hljs-literal">-Tenant</span> yourtenant.onmicrosoft.com <span class="hljs-literal">-Interactive</span>

<span class="hljs-comment"># connect to SPO with PNP</span>
<span class="hljs-built_in">Connect-PnPOnline</span> <span class="hljs-literal">-Url</span> <span class="hljs-variable">$siteURL</span> <span class="hljs-literal">-Interactive</span> <span class="hljs-literal">-ClientId</span> &lt;client id of your Entra ID Application Registration&gt;

<span class="hljs-comment"># get list</span>
<span class="hljs-variable">$list</span> = <span class="hljs-built_in">Get-PnPList</span> <span class="hljs-literal">-Identity</span> <span class="hljs-variable">$listName</span> 

<span class="hljs-comment"># retrieves all list items from the list in pages of 1000 items and delete each item</span>
<span class="hljs-built_in">Get-PnPListItem</span> <span class="hljs-literal">-List</span> <span class="hljs-variable">$list</span> <span class="hljs-literal">-PageSize</span> <span class="hljs-number">1000</span> <span class="hljs-literal">-ScriptBlock</span> {
        <span class="hljs-keyword">Param</span>(<span class="hljs-variable">$items</span>)
        <span class="hljs-built_in">Invoke-PnPQuery</span> 
        } | <span class="hljs-built_in">ForEach-Object</span> {
            <span class="hljs-comment"># remove files without confirmation</span>
            <span class="hljs-built_in">Remove-PnPListItem</span> <span class="hljs-literal">-Identity</span> <span class="hljs-variable">$_</span> <span class="hljs-literal">-Force</span>
        }
</code></pre>
<p>Time for a shout-out for my favorite site about SharePoint is <a target="_blank" href="https://www.sharepointdiary.com/">https://www.sharepointdiary.com</a>. Finally don’t forget to remove the exclude setting in the retention policy afterwards 😉</p>
]]></content:encoded></item><item><title><![CDATA[Igor he’s alive!]]></title><description><![CDATA[Most people are thinking of Frankenstein, but my mind citates Redman with Smash Sumthin'. An awesome 2000 song and a great intro for a first post of an tech related blog, right? I mean it is like 1 or 0 in informatics: Alive or smashed.
Hoping this b...]]></description><link>https://blog.cloud-mili.eu/igor-hes-alive</link><guid isPermaLink="true">https://blog.cloud-mili.eu/igor-hes-alive</guid><category><![CDATA[first post]]></category><category><![CDATA[alive]]></category><category><![CDATA[Blogging]]></category><dc:creator><![CDATA[Sven Lüders]]></dc:creator><pubDate>Mon, 03 Feb 2025 22:11:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1733860676738/0a4ff21e-2690-4bdf-8d58-3846092620ff.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Most people are thinking of Frankenstein, but my mind citates <a target="_blank" href="https://www.youtube.com/watch?v=qdYEZncgz1M">Redman with Smash Sumthin'</a>. An awesome 2000 song and a great intro for a first post of an tech related blog, right? I mean it is like 1 or 0 in informatics: Alive or smashed.</p>
<p>Hoping this blog will be alive - even if it looks like Frankenstein itself…</p>
<hr />
<h2 id="heading-whats-the-idea-here">What`s the idea here?</h2>
<p>Even if I like the idea and the simplicity of the mentioned binary system, there is more than black and white in all our everyday. I stick to that concept except for this blog design and coffee. Coffee should always and only be black - and honestly Starbucks offers no coffee.</p>
<p>But well - in case I consult customers about Microsoft 365 or Azure services I try to grey-scale at least. Because most cases allow different ways of technical solutions. In my opinion the task of the consultant is to break down some technical options with its advantages and drawbacks for the customer. Best case scenario would be to implement the best suitable concept.<br />Now answering the header question: <strong>Creativity</strong></p>
<p>I want to share some exciting technical approaches or features out of the Microsoft universe. And of course there will be challenges, troubleshooting, drawbacks, issues and many more such things here, because everybody is aware of Microsoft`s well established blue screen of death, right? And that thing is absolutely the symbol of smash sumthin` …</p>
<hr />
<h2 id="heading-creativity-hm">Creativity, hm?!</h2>
<p>Yepp - because this is what all IT architects, consultants, engineers unites: finding inventive solutions.<br />As well as job titles, too.</p>
<p>But yes, the Microsoft universe is a big one and I am far to humble to think I know a lot of it - so what can you expect here? Some key skills of good consultants are demarcation and honesty, so I define some topics, which you will find here:</p>
<ul>
<li><p>Microsoft 365</p>
</li>
<li><p>Microsoft Entra</p>
</li>
<li><p>Microsoft Security</p>
</li>
<li><p>Scripting</p>
</li>
<li><p>Automation</p>
</li>
<li><p>Microsoft Microsoft</p>
</li>
</ul>
<p>and of course things I forgot and sarcasm as well.</p>
]]></content:encoded></item></channel></rss>