The new permission in Graph API – Sites.Selected – is a step in the right direction. Since long we have been looking for ways of scoping the accesses to live up to the least privilege principle. It was either nothing or everything. I have tried out the new Sites.Selected permission and here are my findings.
First of all, if you haven’t heard about Sites.Selected, please visit these pages to find out more. I am skipping the introduction, since there are already good resources on that out there.
Once you have your Azure AD App and the admin consent for Graph Sites.Selected, all you need is the Azure AD Application Id and Site Collection Administrator on a particular site. The simplest way is to use PnP.PowerShell:
The only way to the application permissions is PowerShell or Graph, there is no indication on the site.
What about governance
A site collection administrator can grant Read or Write permissions on a site. It gives the desired granularity for application access. But on the other side, there is no way (as of writing) to get all the sites that an Azure AD Application has permissions to.
Which leads me to the biggest weakness of the today’s implementation. Of course, we can traverse through all the sites using powershell and get the summary of all application permissions. The problem is that it can be time consuming in a bigger where you have plenty of sites. Also, it requires that your account that runs the script is a Site Collection Administrator on every site, which is a complete opposite of the granularity goal that Sites.Selected permission tries to achieve.
With that you might end up with several applications that have Write permissions to many sites and you might not have any clue wether it is used or not, who has access to those applications and if they need it.
My wish is that:
There will be an api (graph) or azure cli (or similar) that can list all the sites that an application with Sites.Selected has access to, without me being a Site Collection Admin on every site.
There will be transparency in the user interface, so that users and site owners can see which applications can read and write content on their sites, the same way as we can see the members of a site.
Have you also got a legacy powershell script that loads SharePoint dlls and runs CSOM code directly? It’s quite easy to convert to PnP PowerShell. But if you run out of time and just need to execute the script, then I have a quick tip for you.
First of all, a CSOM script can be recognized by Add-Type commands (or Import-Module) plus the SharePoint dll paths.
The odds are high that you don’t have those directories and files, unless you run it on a SharePoint Server (who would do that at all?) or you have installed the SharePoint SDK.
SharePoint SDK can be downloaded and installed (as suggested here), but why would you want to do that? An easier way is just to locate the files that are distributed with the PnP.PowerShell module, let me show how to do that.
All the dlls are available from the PnP.PowerShell module directory:
So the only thing you need to do is to re-point the path from the original (the “GAC”) folder to the PnP.PowerShell folder. You don’t need to guess the folder. It’s easy.
Thanks to the PowerTip: Find the Path to a PowerShell Module (Scripting Guy) I could find a way to read the information dynamically, so it doesn’t matter where your folder actually is. The fact what version number the module has, what OS you run on, and whether or not you installed it for your user account only or for all users on your computer – allt that has impact on the folder location. So we need to read the right path and then use it in the Add-Type command.
The PnP.PowerShell is built on top of.NET Core and it works cross plattform, that’s better.
If your legacy script does not work with the newer PnP.PowerShell, you might need to install the older PnP PowerShell and adjust the module name in the script above accordingly.
The SharePoint SDK is built on top of .NET Framework (as of my understanding) and it can only be installed on a Windows machine.
The SharePoint SDK requires local administrator rights to be installed. The PnP.PowerShell can be installed for a user without beeing an administrator by adding -Scope CurrentUser (to the Install-Module), which makes the work much smoother.
If you have two or more versions of the PnP.PowerShell module installed, you have to adjust the script a little by loading only the latest version of the module:
$pnpModule=Get-Module PnP.PowerShell –ListAvailable |Sort-Object Version –Descending |Select-Object–First 1
That was a quick tip on how you can use the types from the original CSOM libraries when you don’t have time to convert a script to a PnP code or if there is some functionality that is not covered in PnP yet (not quite sure if there is something you cannot do with PnP that you can do with CSOM).
The good sides of that approach:
it can be a step towards rewriting a legacy script to a newer PnP.PowerShell
the dlls are up-to-date thanks to an easy way to update the PowerShell Module (Update-Module)
it is cross platform, meaning you can execute your legacy script on a linux or on a Mac as well, good for automation!
If you want to remove the Microsoft Teams Banner on your SharePoint Site, the only thing you need is to set a web property on a site: TeamifyHidden=TRUE. I’ll give you some guidance below. But before you do that, consider following:
If there is already a team created for a group connected site, the prompt won’t show up. Why fix something that is not a problem?
Only group owners will get the prompt, if they are few and they know what it is, it is better to let them to decide whether to create or not to create a team.
Only licensed users within your organization will be shown that choice. No external users or users without a license.
And the most important part: if any site owner selects “Don’t show me again” it will stop popping up for all other site owners. If you happen to have a manual step in the group creation process, then you can just click it away.
How to hide Teamify programmatically
Allright, if you still want to hide this prompt and you want to do it programmatically, you need to ensure that this web property is on every site collection root site.
Iterate through all sites
You can find a script for that on Microsoft Fasttrack github repository:
Performance and need for re-run. It iterates through all existing sites, meaning that it takes time to iterate through all of them and it requires that you run it again. In an organization with many new collaboration sites it might be a bad option.
Access to all sites. It requires SharePoint Admin, which is okay-ish, but it also requires that this admin account has access to all sites, in order to update the web property, which is not a good option when admins have a restricted access to actual sites due regulations.
CustomScript. CustomScript is disabled by default for a reason. Because it is a security risk. At least you should alter the script to reset the CustomScript setting on a site after you have changed the web property.
Hide Teamify site by site
You can of course hide the Teamify Prompt on a site without iterating. It is the same principle, but it doesn’t require iterating through all sites. You still need to be a SharePoint Administrator (or a Global Admin of course) in order to enable Custom Script. As in the case with all sites, you should reset the CustomScript to what it was.
Use GroupSiteManager Api
There is a new SharePoint Site API that you can call to hide a Teamify Prompt. All you need is to use the solution described in this sharepoint stackexchange answer:
This still requires that access to the site, but you will not need SharePoint Admin, nor will you need to change any CustomScript settings on a site. That’s better.
There are ways of hiding the Teamify Prompt on a site collection. If you do that you should include that step in some provisioning process, and not iterate through all sites. It is better to not alter the CustomScript settings at all. First of all it is best to ask yourself why you should disable something that is done for users and for a better user adoption. Also consider that usually only few will be shown that (group owners with a license and within the organization). The group owners can also hide it by clicking “Don’t show me again” and it will disappear for all other group owners.