Ramping up to Sensitivity Labels for SharePoint sites

Microsoft recently announced new Governance and Compliance capabilities during the SharePoint Conference in Las Vegas. This included the long-awaited support for Sensitivity labels in SharePoint sites and Groups and the ability to automate the protection of sites containing sensitive data. This post outlines the business value of this new capability, its practical use and an intermediate solution until the capability moves out of Private preview.

Using Sensitivity Labels for SharePoint sites is one of the capabilities that was already announced during the Ignite conference in 2018. Focusing on governance & security, I couldn’t have been more excited to learn the capability has moved into Private preview as mentioned in the blog post (updates to SharePoint security, administration and migration) following the keynote of the 2019 SharePoint Conference.

Lots of organizations are challenged with securing the environments in which employees (and external guests) collaborate with (sensitive) data. It’s no surprise that most organizations have a variety of collaborative workspaces, of which some are public (e.g. Communities of Practice or Professional Learning Communities in Education) and others are strictly for internal use or even highly confidential (restricted to a few).

Microsoft has documented four typical types in Secure SharePoint Online sites and files and the configuration for each type.

Each configuration details the appropriate settings for together different capabilities including (external) sharing, content labelling, Data Loss Prevention (DLP) policies and even data encryption through Azure Information Protection (AIP).

Combined with the Azure AD Premium capabilities to classify Office 365 Groups/Teams (create classifications for Office groups in your organization) and Conditional Access on site level (block or limit access to a specific SharePoint site or OneDrive), a decent solution could be implemented to govern and protect the different types of sites. However, the problem was that all these capabilities were mostly configured or applied manually.

In practice, a modern group powered SharePoint site (or Team) could be created and a certain classification label could be chosen for the site/group or Team, but this would not automatically implement certain security measures to protect sensitive data within each of the four types.

In the meanwhile, Sensitivity Labels have been introduced as the future-proof solution for the protection of data (emails and documents) across all devices and applications. Improvements are also incoming on how Sensitivity Labeled encrypted data can support things like co-authoring, working in Office and SharePoint Online and eventually even Microsoft Search.

A unified approach is coming

With the new and upcoming Sensitivity Labels for SharePoint sites, things are now starting to make sense. Based on data classifications that businesses are increasingly defining or refining, Microsoft will provide a single location to orchestrate labels and related measures to consistently protect data across devices and applications.

From the Security & Compliance admin portal(s), sensitivity labels can be defined and configured in regard to encryption, visualization of the labels in document headers, footers and watermarks and DLP through Windows Information Protection.

But this capability will now be extended to specify certain security measures for sites and groups.

Based on a specific sensitivity label (e.g. “Confidential”), external sharing can be disabled, privacy settings can be set to private and conditional access can set to web-only or blocked for non-compliant (Microsoft Intune). All automatically when creating a new site or when a label is applied to an existing one by a site owner or a SharePoint Online administrator.

While we’re waiting

Sadly, we must wait for this capability to move from Private to Public Preview and eventually General Available.

So how can we support organizations that have a requirement for protecting both data and sites and preferably in an automated way?

Without too much hassle, it’s possible to forge an automated solution leveraging Azure Functions and the power of the Office Development Patterns and Practices PowerShell module.

Conceptually, the Azure Function provides a timer job (running in a specified frequency) that enumerates all sites in a tenant and (re-)configures security measures based on the applied site classification label.

The logic within the Azure Function is based on PnP PowerShell. Authentication to Azure AD and SharePoint Online is required to configure specific settings. To ensure a secure approach, the client-id/client-secret pattern is followed.

Disclaimer

This solution is meant as an intermediate solution until sensitivity labels for sites and groups are available, so consider this upfront before making changes in Azure AD and Office 365.

Also, proficient knowledge of the capabilities and concepts like SharePoint Add-in are a must-have. Some settings could block access to actual data, so knowing the impact on the end-user is essential. Preferably test this setup in a pre-production tenant prior to using it in production.

Finally, this solution illustrates a basic concept and is meant to be experimental. It may not cover your entire set of requirements and it has not been tested exhaustively. So, some limitations or unexpected behavior may occur. The way this was setup has plenty of room for improvement, so any feedback is more than welcome.

Setup

To implement the intermediate solution, you can use the following steps:
Implement group classifications
As a prerequisite, group classifications need to be configured as described in the Microsoft documentation (create classifications for Office groups in your organization). To illustrate the example, use the following names for your labels:

$setting["ClassificationList"] = "Public, Internal, Confidential, Highly Confidential"

You can use different names depending on the terminology used in the organization and additional names can be added if needed. My recommendation would be to have a maximum of four names to keep things manageable. Also, please note that implementing this feature requires an Azure AD P1 license. Details on this can be found in Azure Active Directory pricing.

There are more group features linked to this license, including dynamic groups, group creation permission delegation, group naming policy, group expiration, usage guidelines, and default classification.

Once implemented (this may take a few minutes), the classification labels are available in SharePoint, Office 365 Groups (Outlook), Teams, Planner, Stream and Power BI.

Configure conditional access for SharePoint

To support specific conditional access requirements for sensitive SharePoint Sites, Azure AD Conditional Access needs to be configured. This requires an Azure AD P1 license, similar as the group classification labels.

Now I’m not an Conditional Access or Intune expert, but the basic guidance from Control access from unmanaged devices should be sufficient to illustrate the way sites can be secured for unmanaged devices. Obviously, prerequisites for Azure AD device join and Intune should be met in order to get this working properly.

The guidance in the article starts with a SharePoint Online tenant-level setting. For the purposes of this article, follow the instructions for “Block or limit access to a specific SharePoint site or OneDrive”.

This will create the required policies in the Azure AD Conditional Access control panel. Effectively and as such described in that segment of the article, this will allow full access from desktop apps, mobile apps, and the web as an organization-wide policy.

Notice the part about setting conditional access for a specific site using PowerShell. This is exactly the objective, extended with an automated configuration based on the classification label set for the site. So, this is not something we need to configure manually right now.

Register an application in Azure AD

In order to read the applied classification label for an Office 365 Group, and setting the privacy (for highly confidential sites), we need to connect to Azure AD. For a least privileged based solution, we need to register an application in the Azure AD Portal and set the proper permissions.

• Navigate to Azure AD in the Azure Portal using an administrator account;
• Click on “New registration” in “App-registrations” to get started;
• Provide a name, e.g. “SharePoint site classification management”;
• For “Supported account types”, choose “Accounts in this organizational directory only”;
• Click “Register” to create the registration;
• Afterwards, notice the “Application (client) ID” at the top. This is needed at a later stage;
• Click on “Add a permission” under “API permissions”;

• Click on the “Microsoft Graph” at the top and choose “Application permissions”;
• Choose “Group.ReadWrite.All” from the list and click “Add permissions”;
• Please note the notification bar asking you to grant consent for the admin permissions;
• Next, click on “New client secret” under “Certificates & secrets” and click on “Add” using default settings. Save the value for the Client Secret as we need it later. The value is only show in clear text directly after saving. It will be hidden at the next refresh of the page.

Register and Add-in in SharePoint Online

Similar as in Azure AD, we also need to authenticate against SharePoint Online to perform site protection settings. Detailed guidance for this can be found in Register SharePoint Add-ins. To generate the required App ID and Client Secret, follow the steps below:
• Navigate to “https://tenantname-admin.sharepoint.com/_layouts/15/AppRegNew.aspx”;
• Generate both the “Client ID” and “Client Secret” values and safe these for later use;
• For the title, type e.g. “SPO Site management”;
• “App domain” is “localhost” and “Redirect UR” is “https://localhost”;
• Click “Create” to generate the registration of the “Add-in”;
• Next, navigate to “https://tenantname-admin.sharepoint.com/_layouts/15/AppInv.aspx”;
• Look-up the registration with the “Client ID” saved earlier;
• For the “Permission Request XML”, enter the following xml:

<AppPermissionRequests AllowAppOnlyPolicy="true" >
     <AppPermissionRequest Scope="http://sharepoint/content/tenant" Right="FullControl" />
 </AppPermissionRequests>

Please note that this will provide full control to SharePoint Online on tenant-level;

• Click “Create” to save the permissions and trust the newly created add-in.

Create a timer triggered Azure Function

As a final step, we need to create an Azure Function in which a PowerShell script retrieves all Office 365 groups through a recurring schedule, and then sets site protection measures based on the applied classification label.
• Navigate to the Azure Portal as an administrator and create a new .Net based “Azure Function”. Disable “Application Insights” if required;
• Once created, ensure that the runtime is 1.x (under “Function app settings”) as we need to support additional PowerShell modules;
• Under “Application settings”, create entries for the previously saved client id’s and client secrets using the following names:
o AAD_AppId
o AAD_AppSecret
o SPO_AppId
o SPO_AppSecret
• Also create an entry called “SPO_tenant” using the Office 365 tenant name as a value;
• Don’t forget to save afterwards;
• Next, create a new timer-trigger based function, using “create your own custom function”;
• Enable experimental support to choose a PowerShell based option;
• Determine the schedule (Cron-job format) upfront or modify it later;
• After the function is created, the editor will show with default line in it;
• Paste the following PowerShell code into the editor and save it;

Write-Output "PowerShell Timer trigger function executed at:$(get-date)";

#Connect to the SharePoint Online Admin portal
Connect-PnPOnline -Url "https://$($env:SPO_tenant)-admin.sharepoint.com" -AppId $env:SPO_AppId -AppSecret $env:SPO_AppSecret

#Get all groupconnected sites
$sites = Get-PnPTenantSite -Template 'GROUP#0' -Detailed

foreach ($site in $sites) {

    #Connect to SharePoint Online
    Connect-PnPOnline -Url $site.Url -AppId $env:SPO_AppId -AppSecret $env:SPO_AppSecret

    #Get the details for the current site
    $currentSite = Get-PnPSite -Includes GroupId,Classification

    #Connect to Unified group
    Connect-PnPOnline -AppId $env:AAD_AppId -AppSecret $env:AAD_AppSecret -AADDomain "$($env:SPO_tenant).onmicrosoft.com"

    #Configure the site according to the classification
    if ( $currentSite.classification -eq 'Highly confidential' ) {

        #Set the privacy options
        Write-Output "Ensuring privacy settings are set to Private for $($currentSite.Url) (current:$($group.Visibility))"
        $group = Get-PnPUnifiedGroup -Identity $currentSite.GroupId.Guid
        Set-PnPUnifiedGroup -Identity $currentSite.GroupId.Guid -IsPrivate:$true

        #Set the (external) sharing option: Disabled | ExistingExternalUserSharingOnly | ExternalUserSharingOnly | ExternalUserAndGuestSharing
        Write-Output "Ensuring (external) sharing is disabled for $($currentSite.Url)"
        Connect-PnPOnline -Url "https://$($env:SPO_tenant)-admin.sharepoint.com" -AppId $env:SPO_AppId -AppSecret $env:SPO_AppSecret
        Set-PnPSite -Identity $currentSite.Url -Sharing Disabled -DisableSharingForNonOwners:$true

        #Disable access requests
        Write-Output "Ensuring access requests are disabled for $($currentSite.Url)"
        $web = Get-PnPWeb
        $web.RequestAccessEmail = ''
        $web.SetUseAccessRequestDefaultAndUpdate($false)
        Invoke-PnPQuery

        #Set the conditional access policy (requires Azure AD P1 license): AllowFullAccess | LimitedAccess | BlockAccess
        $site = Get-PnPTenantSite -Url $currentSite.Url
        $site.ConditionalAccessPolicy = [Microsoft.Online.SharePoint.TenantManagement.SPOConditionalAccessPolicyType]::AllowLimitedAccess
        Invoke-PnPQuery

    }

} 

So, the PowerShell logic (which is super basic at this moment), will do the following for Group sites that are labelled as “Highly Confidential”:
• Set the Privacy setting of the site to Private;
• Disable (external) sharing;
• Disable access requests;
• Set the conditional access policy to blocked.

If you have other labels which require different protection settings, you can follow the same pattern.

At this point, the PowerShell script is saved in the Azure Function, but it is depending on the PnP PowerShell to function. We need to upload the module to the Azure Function. I could have written this here, but the guidance on Upload the PnP PowerShell module for your Azure Function is exactly what we need. Just be sure that you are using the latest version of the module.

Testing and stabilizing

After the module was uploaded, the Azure Function should start to work with the (default) 5-minute timer interval. You can click “Run” from the editor window to check if the script is working. Once the script completes, the sites with the “Highly Confidential” label should have been configured with more strict protection measures. Depending on the number of sites, the schedule might be adjusted to e.g. 60 minutes or less frequent.

Final thoughts

The solution was built as a temporary solution until Microsoft releases the sensitivity labels for SharePoint sites, so not too much effort was done in making it perfect. It was meant to fulfil a temporary requirement, so there’s room for improvement.

I’ve noticed some delay in displaying the new privacy settings on the SharePoint site, after the configuration was applied by the script. However, when checking the settings in the admin center, the privacy was set as expected.

Need help or do you have a question about the blog? Contact Andries den Haan!

Deel je enthousiasme