Browse Tag

O365

Drew @ Ignite 2018

I can’t wait for Microsoft Ignite 2018 this year in Orlando. I was honored to be selected as featured speaker earlier this year for this event. The list of speakers and sessions this year is incredible and I can’t believe I am able to join them as a presenter again this year. If you aren’t able to attend, all sessions (including theaters!) will be live streamed. If there is one that you don’t want to miss make sure you make Jeff Teper’s collaboration keynote on Monday at 4:00 p.m.

This is an exciting time to be working in the Microsoft collaboration space. We have seen the explosion of Teams, the resurgence of SharePoint, the overwhelming adoption of the SharePoint Framework and so much more. I am sure the next set of announcements will not disappoint. 

My sessions

Session 1 – BRK3273 – From start to finish: How to create your modern SharePoint site provisioning solution

Tuesday, September 25 – 10:15 AM – 11:00 AM – OCCC W304 A-D

I am lucky to present this session with a good friend and great speaker Vlad Catrinescu.

Details: Creating modern SharePoint sites only takes a second but what if you want to customize or control that process? It can be a challenge to keep up with all the sites in an organization and can affecat support and governance of a SharePoint environment. In this session, learn how to use Microsoft’s latest tools such as Site Designs, Site Scripts, PnP Site Provisioning, PowerApps and Flow to create a full site provisioning system with custom templates, custom branding, and easy approval before creation!

Session 2 – THR2142 – What you need to know about managing OneDrive for Business

Wednesday, September 26 – 4:35 PM – 4:55 PM – Expo Theater #6

Details: OneDrive for Business is a key workload in Office 365 and should be an integral part of your collaboration strategy. OneDrive provides a cloud location to store, share, and sync your work files and then work with them from any device. OneDrive for Business management needs to be done to support the user and the administrator to ensure the content is always secure. What happens to OneDrive content when someone leaves? What devices have content synced to them? What limits are there and do the users know about them? Learn more about what management capabilities are available and which ones are needed within your enterprise.

Session 3 – Under the Hood Ignite special: Hub sites with Drew Madelung

Tuesday, September 25 – 2:00 PM – 2:45 PM – Immersion Zone Podcast 2

Details: Are you a fan of Under the Hood with Nick Brattoli, or do you want to learn how SharePoint hub sites are being implemented in the real world? If so, head over to the podcast center and listen to host Nick Brattoli and special guest Drew Madelung as they talk about their experiences. 

They discuss topics such as: 
• Changes organizations can make to their information architecture to take advantage of hub sites 
• Navigation schemas that are intuitive and scale well 
• Security and governance models 
• Tips and tricks to provision sites quickly 
• Challenges and workarounds 

Removing Permissions for Viewing Modern Personal Blogs in Office 365

A personal blog can be a great tool for you to contribute your thoughts and ideas. Office 365 provides the capability for everyone to have a personal blog that can be accessed via your profile page. 

When you create a new blog post this will be automatically be view-able by all employees. If you do not want to have this capability or manage this in any way it can be done via PowerShell. The example I put together will remove viewers access from all existing blogs so they can only be seen by the owner.

To get started we need a high level understanding of what these blogs are and how they work. I won’t go into all of the details of this because Benjamin Niaulin has already put it together in this great post:

The highlights to support this post are:

  • When a user follows the links to create a new blog post a new site collection is built with the managed path of /portals/personal with a site name of your user account
    • i.e. tenant.sharepoint.com/portals/personal/dmadelung
    • These are not viewable in any SP Admin center and Get-SPOSite will not work
  • Site collections are only built after a user initiates the creation so not all users will have one
  • Blog posts (stories) are creates at pages in the pages library on your site collection
  • Permissions are handled with SharePoint permissions and inherited down with a Contributors, Creators, and Viewers SharePoint Group
    • The viewers group includes “Everyone except external users” by default
  • The blogs are NOT deleted when a user leaves like their OneDrive site collection

And here are details the details from Microsoft around personal blog posts in Office 365:

Removing existing permissions via PowerShell

As this is all hosted in SharePoint there could be multiple ways that we can control these. Unfortunately I couldn’t find a way to control things as scale but there is a small UserVoice submission for it. What I wanted to ensure was that creators could still get to their content but no one else could view anything. The path I took to manage these was through PowerShell and CSOM (Client Side Object Model)

Here is link to the GitHub repo and I will break it down below along with the script.

Here are some key things to note:

  • I can not confirm that doing this is the best practice but it was the easiest way I found to control these without a any administrator controls available to us. 
  • This is currently built to run on demand but could be updated to run on a schedule via something like Azure Automation.
    • To catch everything it will need to run on a schedule because any future sites will not be caught.
  • This could be updated to be used as a reporting tool or identification tool for cleanup.
  • I would comment out the actual removal of the permissions and put some logging in to test before fully running.
    • Also if you have any changes please update the repo!
  • This queries the user profile service in SharePoint Online to get the full list of users which could be huge.
    • I didn’t test this on a very large environment so this could take awhile to run or need to be enhanced for scale.
  • All of the user profile gathering was copied from this post from Microsoft on how to display a list of OneDrive for Business site collections

To get started with CSOM & PowerShell with SharePoint Online here is a good blog post from Chris O’Brien. You can get the latest version of SharePoint Online CSOM here. If you download the nuget file you can change the file extension to .zip and extract the .dlls.

To utilize the script make sure you fill out the appropriate variables and more information about what this will do is below the script. Make sure you test any script you get online before you really run it!

# Use this script to remove viewer permissions from all user delve blogs that have been created
# A user will still be able to view their existing blogs and create blogs but people will not be able to see them
# This would allow you to choose in the future if you want to make them live
# 
# This could be updated to run on a schedule as this will not remove any new blogs that are created

### ENTER YOU VARIABLES HERE ###

#Path to the SP CSOM files 
$csomPath = "C:\...." 
################

#Prompt for parameters
#TenantDomain is beginning of "tenantdomain.sharepoint.com.."
$TenantDomain = Read-Host -Prompt "Tenant domain"
$AdminAccount = Read-Host -Prompt "Admin account"
$AdminPass = Read-Host -Prompt "Password for $AdminAccount" –AsSecureString

#Set SharePoint admin url
$AdminURI = "https://" + $TenantDomain + "-admin.sharepoint.com"

#Get CSOM files
Add-type -Path "$csomPath\Microsoft.SharePoint.Client.dll"
Add-type -Path "$csomPath\Microsoft.SharePoint.Client.Runtime.dll"

#Begin the process
$loadInfo1 = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
$loadInfo2 = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")
$loadInfo3 = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.UserProfiles")

#Set credentials for CSOM
$creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($AdminAccount, $AdminPass)

#Add the path of the User Profile Service to the SPO admin URL, then create a new webservice proxy to access it
$proxyaddr = "$AdminURI/_vti_bin/UserProfileService.asmx?wsdl"
$UserProfileService= New-WebServiceProxy -Uri $proxyaddr -UseDefaultCredential False
$UserProfileService.Credentials = $creds

#Set variables for authentication cookies
$strAuthCookie = $creds.GetAuthenticationCookie($AdminURI)
$uri = New-Object System.Uri($AdminURI)
$container = New-Object System.Net.CookieContainer
$container.SetCookies($uri, $strAuthCookie)
$UserProfileService.CookieContainer = $container

#Sets the first User profile, at index -1
$UserProfileResult = $UserProfileService.GetUserProfileByIndex(-1)

Write-Host "Starting- This could take a while."

#Getting total number of profiles
$NumProfiles = $UserProfileService.GetUserProfileCount()
$i = 1

#Create array to track users
$users = @()

#As long as the next User profile is NOT the one we started with (at -1)...
While ($UserProfileResult.NextValue -ne -1) 
{
    Write-Host "Reviewing profile $i of $NumProfiles"

    #Look for the Point Publishing Blog url object in the User Profile and retrieve it
    #It will be empty for users which it has not been created for

    #Get personal blog publishing URL
    $Prop = $UserProfileResult.UserProfile | Where-Object { $_.Name -eq "SPS-PointPublishingUrl" } 
    $Url= $Prop.Values[0].Value

    #Get user UPN - Can be used for reporting
    #$Prop = $userProfileResult.UserProfile | Where-Object { $_.Name -eq "SPS-UserPrincipalName"}
    #$Upn= $Prop.Values[0].Value

    #If the blog site exists then add it to an array to review
    if ($Url) {
        $users += $Url
    }

    #And now we check the next profile the same way...
    $UserProfileResult = $UserProfileService.GetUserProfileByIndex($UserProfileResult.NextValue)
    $i++
}

#Loop through all identified sites to remove blog viewers
foreach($user in $users){
    #Set blog site url
    $siteurl = "https://" + $TenantDomain + ".sharepoint.com" + $user

    #Connect to blog site collection
    $ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteurl)
    $ctx.Credentials = $Creds
 
    #Connect to web and get site groups
    $web = $ctx.Web
    $groups = $ctx.Web.SiteGroups
    $ctx.Load($web)
    $ctx.Load($groups)
    $ctx.ExecuteQuery()
    
    #Get the viewers group
    $group = $groups | where { $_.Title -eq "Viewers"}
    if($group){
        #Get the users in the viewers group
        $users = $group.Users
        $ctx.Load($users)
        $ctx.ExecuteQuery()

        #Remove all users from the viewers group
        foreach($u in $users){
            $group.Users.RemoveByLoginName($u.LoginName)
            $web.Update()
            $ctx.ExecuteQuery()
        }
    }
}

The end result will be that all existing blog sites will have anyone in the Viewers SharePoint Group removed

Before…

After..

Office 365 Groups Naming Policy

group1

Introduction

When Office 365 Groups were first released there was not an ability to control the names of Groups at all. One of the primary reasons for this was due to the cross workload functionality that make up Office 365 Groups. As a reminder, an Office 365 Group is the single Azure AD identity service that provides specific membership to Office 365 solutions like SharePoint, Exchange, Planner, Teams, etc. Within each of these workloads you have the ability to create and manage an Office 365 Group. If you make a change within one of workloads, for example SharePoint, there is communication between the workload and Azure AD with notifications on things like creation, changes, and deletions. 

With a separated system and Azure AD as the source, any policies need to be applied at the Azure AD level. As an example, an Exchange naming policy can be used (and at one point was the only option) for Office 365 Groups. If you set a naming policy within Exchange that would only work if you tried creating a group within Exchange. If I was on SharePoint Home and tried to create an Office 365 Group that naming policy would not trigger as I technically not working in Exchange. Exchange would learn about the Group after it is synced back to Azure AD but that would be too late. 

To resolve this issue Microsoft has released Office 365 Group naming policy capabilities at the Azure AD level. A naming policy is very important for proper control and a clean Global Address List (GAL). Since this is in Azure AD now the naming policy is applied to Groups that are created across workloads. 

Details

As I am writing this post in Dec 2017 this is currently still in Private Preview. 

Both of these currently can only be configured with PowerShell. The prerequisites for configuring these can be found in this post: Managing Office 365 Groups using Azure AD PowerShell V2.

The AzureADPreview PowerShell module version 2.0.0.137 is required.

Office 365 Group naming policies can be built using 2 different features and 1 is automatically maintained:

  • Custom blocked words
    • You can set specific blocked words that can be used within Group names. 
  • Prefix-Suffix naming policy
    • Using fixed strings or user attributes, you can add an automated prefix or suffix to a Group name. 
  • Microsoft Standard blocked words list
    • A set of words Microsoft manages that are not allowed. This includes your primary swear words. I tested quite a few good ones and they were all blocked automatically.

These administrators bypass or are exempt from the naming polices you configure but NOT the MS standard blocked words list:

  • Global Administrator
  • Partner Tier 1 Support
  • Partner Tier 2 Support
  • User Account Administrator
  • Directory Writers

Microsoft detailed information for the naming policy can be found here.


Custom blocked words

This is a comma separated list of words that you can configure. These words are blocked in Group names and aliases. Some examples of when you would want to configure blocked words:

  • Your department or business function names because you want to ensure you don’t have duplicate places for content
  • Regulatory words that you may have specific legal requirements around that you need to have more control over
  • Names of roles that you don’t want people to try to impersonate
  • Client, Vendor, or Competitor names

There are some things to know about these blocked words.

  • The checks are done AFTER appending the prefix/suffix to the Group name
    • If things like underscores (_) or dashes (-) are used in prefix/suffix they could stop your blocked word from working if there are no spaces
  • No sub-string searches are done
    • If “Drew” is the blocked word, “Andrew” would still work
  • Not case-sensitive
  • No character restrictions
  • No limit on the amount of words

Steps to set the Custom Blocked words

This is assuming you already have a directory settings template created, details in prior post, and connection information from the first section.

1 – Connect to Azure AD via PowerShell.

Connect-AzureAD

2 – Use comma delimited values for the blocked words.

$settings = Get-AzureADDirectorySetting | where-object {$_.displayname -eq “Group.Unified”}
$settings["CustomBlockedWordsList"] = "HR,Contoso,Payroll,CEO,CFO,CIO"
Set-AzureADDirectorySetting -Id $settings.Id -DirectorySetting $settings

3 – Review your updated settings; you can now see the default values for the directory settings object.

Get-AzureADDirectorySetting | ForEach Values


Prefix-Suffix naming policy

These can either be fixed strings or actually attributes from the user themselves. These 2 types of capabilities are stored within 1 overall string that is concatenated. Because of this, you must always have [GroupName] included in your setting. That is how you are able to have a prefix & a suffix. 

Some examples of using strings:

  • GRP [GroupName]
    • This puts the fixed string of “GRP ” before all of your Group names
  • #[GroupName] Group
    • This will put the # symbol at the front of the Group name for better sorting in the GAL and then ” Group” as a suffix for better clarity
    • Special characters are removed from the Alias
  • OGRP – [GroupName]
    • Dashes can be used for separation as spaces are removed automatically in the Group Alias (like the rest of the special characters). That means “OGRP – Drew” as a group name becomes “OGRP-Drew@domain.com” as the alias instead of “OGRPDrew@domain.com”.

The next type of thing you can add are Azure AD user attributes. The following attributes are supported: [Department], [Company], [Office], [StateOrProvince], [CountryOrRegion], [Title], [CountryCode]

Some examples of using attributes:

  • [Department] – [GroupName]
    • This will pull the users department stored in Azure AD before the Group name
  • [CountryCode] – GRP – [GroupName]
    • This will first put the Country Code stored in Azure AD followed by a fixed string and then the Group name

There are some things to know about using attributes.

  • The total prefix/suffix + string length is restricted to 53 characters
  • Empty attributes for users will be filled in with blank values. It is best to ensure your Azure AD information is fully established before using these attributes.
  • Extension attributes and custom attributes are not supported
    • If you put it in an unsupported attribute it just comes across as text

Steps to set the Prefix – Suffix naming policy

This is assuming you already have a directory settings template created, details in prior post.

1 – Use comma delimited values for the blocked words.

$settings = Get-AzureADDirectorySetting | where-object {$_.displayname -eq “Group.Unified”}
$settings["PrefixSuffixNamingRequirement"] = "GRP - [Department] - [GroupName]"
Set-AzureADDirectorySetting -Id $settings.Id -DirectorySetting $settings

2 – Review your updated settings; you can now see the default values for the directory settings object.

Get-AzureADDirectorySetting | ForEach Values


Microsoft standard blocked words

There are a lot of unprofessional words naturally in the English language that most likely should never be part of an Office 365 Group name. This includes a primary set of things like swear words and other inappropriate words that your imagination may be able to come up with. This is a single setting to turn on the blocked words or off. 

Steps to set the Microsoft blocked words

This is assuming you already have a directory settings template created, details in prior post, and connection information from the first section.

1 – Use comma delimited values for the blocked words.

$settings = Get-AzureADDirectorySetting | where-object {$_.displayname -eq “Group.Unified”}
$settings["EnableMSStandardBlockedWords"] = $true
Set-AzureADDirectorySetting -Id $settings.Id -DirectorySetting $settings

2 – Review your updated settings; you can now see the default values for the directory settings object.

Get-AzureADDirectorySetting | ForEach Values


And when you put it all together!

You get a blocked word of CEO and a naming policy pulling in a prefix of “GRP – ” with an Azure AD department of “NFL” and a suffix of ” – CEO”. You will also see the alias removing the spaces.


Where does the naming policy actually work?

As there are a lot of workloads across Office 365 that utilize Groups there are a lot of places that these policies need to work. Currently it is not supported in every workload. Microsoft has the detailed information for what is supported in their support article here

Here is the current breakdown in Dec 2017.

Where it works:

  • Outlook on the Web
  • Outlook Client – Doesn’t preview
  • Outlook Mobile – Doesn’t preview
  • Teams
  • SharePoint
  • Stream
  • Groups mobile app
  • Planner
  • Dynamics 365
  • Exchange PowerShell
  • Azure AD PowerShell
  • O365 Admin Center

Where it doesn’t:

  • Power BI workspace
  • Yammer
  • StaffHub
  • Azure AD Portal

Licensing

Any Office 365 subscription that has Exchange Online and SharePoint Online will support groups. That includes the Business Essentials and Business Premium plans, and the Enterprise E1, E3 and E5 plans.

There is a large collection of features that require specific types of Azure AD licenses. The Office 365 Groups naming policy requires Azure AD Premium P1 licenses for any users who are part of Office 365 Groups.

The full collection of licensing information is listed from Microsoft here.

SharePoint, OneDrive & Office 365 Collaboration Announcements from Ignite 2017

I will be keeping track of all of the announcements that I can keep up with around SharePoint, OneDrive, and the Office 365 collaboration space at Microsoft Ignite next week using Sway. Since I am using Sway you will be seeing my updates live as I type and publish them.  That means this will be an evergreen Sway and hopefully a 1 stop shop for anyone looking to catch up on all the great news coming out of Ignite. 

 

View When You Deleted an Office 365 Group

group1

Introduction

The ability for soft-delete and restore of an Office 365 Group has recently been released. I put together some information about that in my previous post here. Before this restoration was possible, when you deleted an Office 365 Group it was fully gone. Now we have the ability to view Groups that have been deleted and restore them using PowerShell.

The ability to restore was a great but there was a small gap for me when the cmdlets were first rolled out:

  • You have 30 days to restore an Office 365 Group but you didn’t know when an Office 365 Group was deleted. 

This would make building any logic around things like notifications or reporting a challenge as we could not tell which Groups were about to expire. 

This has been resolved by Microsoft and we now have the ability to see the Deleted Date and Time of an Office 365 Group for the 30 days it is retained using PowerShell. 


What you need to know

  • You can only view the deletion date via PowerShell
  • You can only view the deletion date of Groups that are in the pending permanent delete state that stays around for 30 days

Prerequisites:

  • Azure AD PowerShell V2 – Preview 
    • The release of the cmdlets that support Office 365 Group recovery are now available only in the preview cmdlets. 
    • I am writing this using version 2.0.0.110

Viewing when an Office 365 Group was deleted

1 – Connect to Azure AD via PowerShell (ensure you connect to Preview)

Connect-AzureAD

2 – Review the Office 365 Groups that have been deleted and when they were deleted

This will sort the Groups by their DeletedDateTime

Get-AzureADMSDeletedGroup | Sort-Object DeletedDateTime | Format-Table DisplayNAme, DeletedDateTime, Description, Visibility, Mail, ID

You are now good to go build something fancy like:

  • Build a report for admins to notify them weekly what Groups are being permanently deleted
  • Build a single page app to surface deleted Groups and allow users to recover them using an Azure Function