Announcing posh-o365, a collection of PowerShell scripts for Office 365 management

I have a growing collection of PowerShell scripts for Office 365 management and, whilst I may not be the best scripter/coder out there (I’m pretty sure there are many people who could look at my scripts and say “there’s a better way to do that”), I’m open-sourcing them in the hope that others will contribute.

The current scripts are:

  • Connect-O365.ps1 – connect to multiple Office 365 sessions in a single PowerShell window.
  • Check-ODBQuotas.ps1 – checking a list of UPNs to see if their OneDrive for Business folders have been created and, if so, if their quotas need to be set.
  • Set-O365Licences.ps1 – setting usage locations and applying/removing licences for Office 365 users.
  • Set-ODBQuota.ps1 – setting a quota for a user’s OneDrive for Business folder.

More details on the use of these scripts can be found in the readme file for the project.

Others scripts are in development for:

  • Setting restrictions on audio/video settings in Skype for Business Online.

This collection is up on github under the name of posh-o365 and I’d be interested to hear what people think of these, and what other scripts might be useful for performing Office 365 management tasks at scale in an enterprise context.

Recovering data after Garmin crashed whilst saving activity

Yesterday was a beautiful day. Unfortunately I spent most of it in my home office but I did manage to get out on the bike for a quick ride before sunset (the first time I’ve worked at home in weeks, with a correspondingly low occurrence of exercise on a work day…).  Unfortunately, when I got home, my Garmin 810 cycle computer froze whilst saving my ride.

It actually needed a reset (holding the lap and power buttons together for about 5 seconds) before I could get it to respond at all but my biggest concern was whether my ride data had been lost (if it’s not on Strava, it didn’t happen).

The Garmin Connect app on my phone wouldn’t upload the ride, so I tried installing Garmin Express on a PC.  It decided that there was a file on my device that couldn’t be uploaded. Sadly, that file was the data from last night’s ride.

Garmin Express - Some files could not be uploaded to Garmin Connect

I ignored Garmin Express’s offer to remove the file and, thanks to Chesilboy’s post on the Garmin forums, I managed to rescue some of the data.

  1. First, I connected the Garmin to my PC and navigated to \Garmin\Activities.
  2. There, I located the .FIT file for the ride and copied it to somewhere safe.
  3. Next, I uploaded the .FIT file to Strava.
  4. Strava read the data, warning me that the file was damaged, possibly truncated and that some of the ride would be lost. Importantly though, it would use the data that could be read (as it happens, almost all of my ride – only missing the last 1.5 kilometres).
  5. At this point, I could export a GPX file and import it to Garmin Connect, but I’m not really that bothered about my records there (I find the site clunky and unreliable and I only really use it to get my data to Strava).

As Chesilboy notes, shame on Garmin for a) not keeping the data safe (why not write it throughout the activity) and b) actually offering to delete it! Thank goodness Strava is better at data processing!

Posh-git!

I’ve been writing quite a lot of PowerShell recently and I decided that I really should look into using some kind of source control system.  I’ve used Git before, integrating GitHub with VisualStudio and this time I wanted to integrate with the PowerShell ISE (by the way, if you don’t have a Windows 8.1 shortcut for the PowerShell ISE, Carlo/Happy SysAdmin describes how to find it).

It’s actually pretty straightforward using Keith Dahlby’s posh-git scripts (what a great name that is!) and GitHub Desktop. Jeff Yates has a post that describes the process but I found I needed to do a bit more to make it work for me…

My PowerShell ISE didn’t have a profile, so I created one and added the entries Jeff suggests but, even so, I was getting errors in my console:

Resolve-Path : Cannot find path ‘C:\Users\username\AppData\Local\GitHub\PoshGit_869d4c5159797755bc04749db47b166136e59132’ because it does not exist.
At C:\Users\username\AppData\Local\GitHub\shell.ps1:26 char:26
+ $env:github_posh_git = Resolve-Path “$env:LocalAppData\GitHub\PoshGit_869d4c51 …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\Users\username\…47b166136e59132:String) [Resolve-Path], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.ResolvePathCommand

Resolve-Path : Cannot find path ‘C:\profile.example.ps1’ because it does not exist.
At C:\users\username\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1:3 char:4
+ . (Resolve-Path “$env:github_posh_git\profile.example.ps1”)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\profile.example.ps1:String) [Resolve-Path], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.ResolvePathCommand

The expression after ‘.’ in a pipeline element produced an object that was not valid. It must result in a command name, a script block, or a CommandInfo object.
At C:\users\username\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1:3 char:3
+ . (Resolve-Path “$env:github_posh_git\profile.example.ps1”)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : BadExpression

After some hunting around, and an attempt to install posh-git manually, I realised that the shell.ps1 script from Github Desktop was looking for posh-git in a folder at $env:LocalAppData\GitHub called PoshGit_869d4c5159797755bc04749db47b166136e59132 (I’m guessing that’s a GUID in the foldername, so it’s likely to be different for others). After copying a clone of posh-git to that folder and reloading my profile (. $profile), everything was working as it should to commit changes from within PowerShell.

Don’t waste time and money on third party security software: Windows Defender is just fine!

So far in my “series” of Windows 10 posts, I’ve written about refreshing or resetting the PC (to get a clean configuration) and about getting an Office 365 Home subscription for some productivity apps but I skipped one area that many people are sold products for… security software.

Actually, this is one of my major bug-bears. In the enterprise, I often see third party security products used but there’s only one reason I can see for that: management. Not just of the updates, but of quarantine for any infections that are caught.

Unfortunately, in the consumer space anti-virus products are often foisted onto unsuspecting consumers. Both the PCs I’ve bought for family in recent years have come with McAfee products installed (removed soon afterwards) and high street PC shops/office suppliers/supermarkets will happily sell alternatives.  I was particularly annoyed to see that, after my parents in-law went to a local “PC specialist” (because they thought I was too busy), Microsoft Security Essentials had been removed (from their Windows 7 PC) and replaced by AVG. Now, don’t get me wrong, there’s nothing wrong with AVG, except that, the last time I used the free version, it kept nagging to be upgraded to a paid one – and there’s simply no need to clog up the system with third party apps like this.

Reputable providers of consumer advice seem to be caught up in the trap too: I took a look at the Which? report for security software best buys and even their best free antivirus software guide doesn’t include the software built into the operating system – indeed it says:

“Two programs could interfere with one another causing problems. If you are installing a third party piece of security software make sure you uninstall Microsoft Defender.”

I’d put it a different way: don’t waste time and money on third party anti-virus software – just use Windows Defender!

  • Windows Defender scans for malicious software. The schedule for scans can be edited in Task Scheduler.
  • In Windows 10, Windows Defender is enabled by default. It will turn itself off if you install another antivirus application, but equally it can be left in place and will receive updates through the same mechanism as other Windows updates.
  • If Windows Defender finds a virus it can’t remove, it will prompt to download and run Windows Defender Offline. Once the download is complete, the PC will automatically restart into the recovery environment, where Defender will run a more complete scan and remove threats.

Other security features built into Windows (avoiding the need for third party products) include Windows Firewall (which helps to protect a PC from damage caused by worms or hackers attacking across a network) and SmartScreen (a phishing and malware filter implemented in several Microsoft products including Internet Explorer, Microsoft Edge, and inside Windows).

Find out more about the security settings in Windows 10 by searching for Security and Maintenance.

Windows 10 Control Panel - Security and Maintenance

Windows 10 Enterprise domain join options

When running Windows 10 setup from enterprise media, one of the options presented is to choose how you’ll connect Windows to your organisation.

  • Join Azure AD
  • Join a domain

You might ask, “where’s the option to just continue as normal and stay in a workgroup?” (as a non-domain-joined PC) but the explanatory text helps:

  • Join Azure AD if your organisation uses Office 365 or other business services from Microsoft.
  • If you plan to join the PC to a domain, a local account is created and then you can join a domain as in previous Windows OSes once setup is complete.

The “join a domain” option doesn’t actually join a domain at all – indeed, once you’ve elected to join a domain you can switch to signing in with a Microsoft account (and gain the benefits of settings being synchronised between PCs) as well as adding a workplace or school account (signing in to Office 365, for example), changing sign-in options, joining/leaving a domain and/or joining/leaving Azure AD (for administrators to manage the PC in line with policy).

Windows 10 - Accounts - Your Accounts

Windows 10 - Accounts - Signin Options

Windows 10 - Accounts - Work Access

Office 365 DNS settings in a hybrid environment

The Office 365 Admin Center does a great job of helping administrators determine the DNS settings that are required to use a domain with Office 365; however it’s far from perfect. One particular case when it doesn’t help much at all is if you have hybrid components – for example Exchange Hybrid or Lync/Skype for Business Hybrid (split domain). In scenarios such as this, you might not want the entries that Office 365 suggests, for example:

  • Exchange autodiscover must be defined with CNAME records in a hybrid environment – the use of SRV records is not supported.
  • The CNAME record to repoint autodiscover.domainname.tld to autodiscover.outlook.com is not required in an Exchange hybrid environment (it is only used for Exchange Online).
  • If mailflow is via the on-premises infrastructure (centralised routing), the SPF records for the Office 365 servers (v=spf1 include:spf.protection.outlook.com -all) are not required. In addition, no new MX records are required.
  • In a Lync/Skype for Business hybrid (split domain) environment the _sipfederationtls._tcp. domainname.tld and _sip._tls.domainname.tld SRV records should point to the on-premises access proxy and not to sipdir.online.lync.com as they would for a Skype for Business online implementation. sip, lync, lyncdiscover and lsweb entries will also remain pointing to the on-premises infrastructure.

Office 365 - disable DNS record checks for a domainUnfortunately, without these settings in place, Office 365 will continue to alert that there are issues with domains that may cause “possible service issues”. To prevent this, navigate to the domains section of the Office 365 Admin Center and click fix issues next to one of the domains that is reporting problems. Then, on the right-hand side of the page, click the checkbox next to “Don’t check this domain for incorrect DNS records”. Once this is set, Office 365 should stop alerting for domain issues.

Also, be aware that DNS tests at the Microsoft remote connectivity analyzer and also some of the Office 365 Health, Readiness and Connectivity checks, may appear to fail in a hybrid environment.

Overview of Azure AD synchronisation

Over the last few months, I’ve had the opportunity to work with a number of directories that are synchronised from on-premises Active Directory (AD) to Azure AD (AAD) – the directory service behind Office 365, Azure, Dynamics, Intune and other business-focused Microsoft online services.

I’ve learned a few things along the way (like that AAD synchronisation servers are disposable and shouldn’t be re-configured to sync with a different directory, as well as some steps for troubleshooting missing objects) but I thought I’d group a few more points together in this post.

DirSync -> AAD Sync -> AAD Connect

There have been various versions of what’s essentially the same tool (a customised implementation of Microsoft Identity Manager, previously known as Forefront Identity Manager and Microsoft Identity Integration Server – indeed the Synchronisation Manager is still named miisclient.exe) and Paul Wooldridge does a great job of summarising the current situation in his blog post for risual.

These days, there are very few reasons not to be using the latest version – Azure AD Connect – which massively simplifies the process of configuring the underlying Azure AD Synchronisation Services as well as including a number of optional preview features for new functionality. The one caveat is that it needs Windows Server 2012 or later.

Hardware, software and service accounts

Whilst there’s no reason a physical machine couldn’t be used, all of the Azure AD synchronisation servers I’ve worked on have been virtual.  The machine will require the following specification:

  • Windows Server 2008 or later (standalone or domain joined).
  • Microsoft .Net framework version 4.5.1.
  • PowerShell (v3 or later).
  • Local administrator privileges to install the software.
  • Unauthenticated Internet access (over port 443) to the Office 365 servers.
  • A regular user account to connect to AD and read the attributes for objects to be synchronised. This must be able to log on as a service and it will also need to be granted the following permissions in order to write back password hashes (for same sign on):
    • Replicating Directory Changes.
    • Replicating Directory Changes All.

Older versions of the tool allowed the administrator to define an account in the cloud whereas AAD Connect asks for credentials and creates its own service account (with a display name of On-Premises Directory Synchronization Service Account and an user name of Sync_syncservername_identifier@tenantname.onmicrosoft.com). Also, unlike previous versions the account is set with a password that will not expire (the PasswordNeverExpires and PasswordResetNotRequiredDuringActivate attributes are both set to $true).

Tools and commands

Azure AD Connect is based on the Azure AD Synchronization Services framework which itself is evolved from Microsoft Identity Manager (formerly Forefront Identity Manager, Microsoft Identity Lifecycle Manager, Microsoft Identity Integration Server, Microsoft Metadirectory Server and Zoomit Via before that!). Not surprisingly, the underlying tools are the same ones used for these products!

  • The main tool is the Synchronization Service Manager (miisclient.exe), which is used to monitor synchronisation as well as to adjust the scope of synchronisation (more on that in a moment)
  • There’s also a Rules Editor (which I leave alone – indeed, directly editing the rules is not supported for AAD Connect)
  • A scheduled task is also created that runs the synchronisation process every 3 hours by default (you may want to reduce the timeout on this to avoid issues with long-running syncs too).
  • It’s possible to force a synchronisation from the command line. This can also be done from the Synchronization Service Manager or from Task Scheduler but the command line is easy! Simply run directorysyncclientcmd.exe delta (from an PowerShell session running as Administrator) or directorysyncclientcmd.exe initial to force a full synchronisation.

As for Powershell cmdlets, the documentation on the ADSync PowerShell module is pretty poor. I managed to extract a list of commands and their syntax but there’s no meaningful help text (at least not that I’ve found). I’ve also seen that the DirSync information on the synced attributes is better than the AAD Sync information (which warns it will be archived soon) and I haven’t found the equivalent AAD Connect information!

What gets synchronised?

For many organisations, not all of the directory needs to be synchronised. It’s possible to filter synchronisation by domain, organizational unit (OU), group membership, or directory attribute. Of these, group membership is generally only used in test (it quickly becomes tiresome to add users to a group to ensure that they are synced to the cloud) and OU filtering is the most common form I’ve seen. It’s also worth noting that the group membership option is new with Azure AD Connect and previous versions of the tool didn’t allow this.

Also note that, if the scope of synchronisation is changed, a full synchronisation is required as a delta will not pick up the new filtering arrangements.

Further reading

PowerShell cmdlets in the Azure ADSync module

MVP, Mike Crowley wrote a blog post last year that details the cmdlets for managing Azure AD Directory Synchronisation (DirSync). Unfortunately, the latest incarnation of DirSync (Azure AD Connect) uses a totally different set of commands (and they seem to me to be more complex to use – thank goodness the GUI is so good now).

I used Mike’s method to extract the details of the PowerShell cmdlets in the Azure ADSync module:

Import-Module ADSync
Get-Command -Module ADSync | Get-Help | Select name, synopsis | Export-Csv $env:userprofile\Desktop\DirSyncCmdlets.csv -NoTypeInformation

Unfortunately the help information is very sparse so the synopsis is missing.  Aaron Peterson has some extra information on the ADSync cmdlets but it seems we’ve gone backwards in terms of help…

My final attempt was Get-Command -Module ADSync | Select definition | Export-Csv $env:userprofile\Desktop\DirSyncCmdlets.csv -NoTypeInformation which allowed me to at least pull out the syntax for each cmdlet:

Add-ADSyncAADServiceAccount [-AADCredential]  [[-Name] ] []
Add-ADSyncAttributeFlowMapping [-SynchronizationRule]  [-AttributeFlowMappings] <List[AttributeFlowMapping]> [-Direction ] [-WhatIf] [-Confirm] []
Add-ADSyncAttributeFlowMapping [[-Source] <List[string]>] [-Destination]  [-FlowType]  [[-ValueMergeType] ] [-SynchronizationRule ] [-Expression ] [-ExecuteOnce] [-Direction ] [-WhatIf] [-Confirm] []
Add-ADSyncConnector [[-Connector] ] []
Add-ADSyncConnector [-Name]  [-Type]  [-Description ] [-ConnectivityParameterSettings ] [-GlobalParameterSettings ] [-HierarchyProvisioningMappings <Dictionary[string,string]>] [-Partitions <List[ConnectorPartition]>] [-PasswordManagementSettings ] []
Add-ADSyncConnectorAnchorConstructionSettings [-Connector]  [-ObjectClass]  [-Locked]  [-Attributes] <List[string]> []
Add-ADSyncConnectorAttributeInclusion [-Connector]  [-AttributeTypes] <List[string]> []
Add-ADSyncConnectorHierarchyProvisioningMapping [-Connector ] [-Mappings <Dictionary[string,string]>] []
Add-ADSyncConnectorHierarchyProvisioningMapping [-Connector]  [[-DNComponent] ] [[-ObjectClass] ] []
Add-ADSyncConnectorObjectInclusion [-Connector]  [-ObjectTypes] <List[string]> []
Add-ADSyncGlobalSettingsParameter [-GlobalSettings]  [-ParameterValuesTable]  []
Add-ADSyncGlobalSettingsParameter [-GlobalSettings]  [-Parameters] <List[ConfigurationParameter]> []
Add-ADSyncJoinConditionGroup [-SynchronizationRule]  [-JoinConditions] <List[JoinCondition]> [-WhatIf] [-Confirm] []
Add-ADSyncRule [-SynchronizationRule]  [-WhatIf] [-Confirm] []
Add-ADSyncRule -Name  -Connector  -Direction  -SourceObjectType  -TargetObjectType  [-Precedence ] [-PrecedenceAfter ] [-PrecedenceBefore ] [-Description ] [-Identifier ] [-ImmutableTag ] [-ScopeFilter <List[ScopeConditionGroup]>] [-JoinFilter <List[JoinConditionGroup]>] [-LinkType ] [-EnablePasswordSync] [-AttributeFlowMappings <List[AttributeFlowMapping]>] [-SoftDeleteExpiryInterval ] [-WhatIf] [-Confirm] []
Add-ADSyncRunProfile [-RunProfile]  []
Add-ADSyncRunProfile [-Name]  [-ConnectorIdentifier]  [-RunSteps <List[RunStep]>] []
Add-ADSyncRunProfile [-Name ] [-ConnectorIdentifier ] [-RunStepPartitionIdentifier ] [-RunStepTask ] [-RunStepObjectProcessLimit ] [-RunStepObjectDeleteLimit ] [-RunStepBatchSize ] [-RunStepLogType ] [-RunStepLogFile ] []
Add-ADSyncRunStep [-RunProfile]  [-PartitionIdentifier]  [-StepTask]  [-BatchSize ] [-ConnectorType ] [-Index ] [-LogType ] [-LogFile ] [-ObjectProcessLimit ] [-ObjectDeleteLimit ] [-PageSize ] [-Timeout ] []
Add-ADSyncScopeConditionGroup [-SynchronizationRule]  [-ScopeConditions] <List[ScopeCondition]> [-WhatIf] [-Confirm] []
Disable-ADSyncConnectorPartition [-Partitions] <List[ConnectorPartition]> [-Connector ] []
Disable-ADSyncConnectorPartition [-Connector]  [-Partition]  []
Disable-ADSyncConnectorPartitionHierarchy [-Connector]  [-Partition]  [-PartitionHierarchyNode]  []
Disable-ADSyncExportDeletionThreshold [-AADCredential]  [-WhatIf] [-Confirm] []
Enable-ADSyncConnectorPartition [-Partitions] <List[ConnectorPartition]> [-Connector ] []
Enable-ADSyncConnectorPartition [-Connector]  [-Partition]  []
Enable-ADSyncConnectorPartitionHierarchy [-Connector]  [-Partition]  [-PartitionHierarchyNode]  []
Enable-ADSyncExportDeletionThreshold [-AADCredential]  [-DeletionThreshold]  [-WhatIf] [-Confirm] []
Get-ADSyncAADPasswordResetConfiguration [-Connector]  []
Get-ADSyncAADPasswordSyncConfiguration [-SourceConnector]  []
Get-ADSyncConnector [-Identifier ] [-Name ] []
Get-ADSyncConnectorHierarchyProvisioningDNComponent [-Connector]  [[-ObjectType] ] [-ShowHidden] []
Get-ADSyncConnectorHierarchyProvisioningMapping [-Connector]  []
Get-ADSyncConnectorHierarchyProvisioningObjectClass [-DNComponent]  []
Get-ADSyncConnectorParameter -Type  [-Identifier ] [-Connector ] [-ScopeIdentifier ] []
Get-ADSyncConnectorPartition [-Connector]  [-Identifier ] [-Name ] []
Get-ADSyncConnectorPartitionHierarchy [-Connector]  [-Partition]  [-ParentPartitionHierarchyNode ] []
Get-ADSyncConnectorTypes []
Get-ADSyncGlobalSettings [-WhatIf] [-Confirm] []
Get-ADSyncGlobalSettingsParameter []
Get-ADSyncRule [[-Identifier] ] [-WhatIf] [-Confirm] []
Get-ADSyncRunProfile [-Connector]  []
Get-ADSyncRunProfile [-Identifier]  []
Get-ADSyncSchema [-Connector ] [-Identifier ] []
Get-ADSyncServerConfiguration [-Path]  []
New-ADSyncConnector [-Name]  [-Type]  [-Description ] [-ExtensionFileName ] []
New-ADSyncJoinCondition [-CSAttribute]  [-MVAttribute]  [[-CaseSensitive] ] [-WhatIf] [-Confirm] []
New-ADSyncRule [-Name]  [-Direction]  [-Connector]  [-SourceObjectType]  [-TargetObjectType]  [-LinkType]  [-Precedence ] [-EnablePasswordSync] [-PrecedenceAfter ] [-PrecedenceBefore ] [-Description ] [-ImmutableTag ] [-Identifier ] [-SoftDeleteExpiryInterval ] [-WhatIf] [-Confirm] []
New-ADSyncRunProfile [-Connector]  [-Name]  []
New-ADSyncScopeCondition [-Attribute]  [-ComparisonValue]  [-ComparisonOperator]  [-WhatIf] [-Confirm] []
Remove-ADSyncAADPasswordResetConfiguration [-Connector]  [[-AADCredential] ] []
Remove-ADSyncAADPasswordSyncConfiguration [-SourceConnector]  []
Remove-ADSyncAADServiceAccount [-AADCredential]  [-Name]  [-WhatIf] [-Confirm] []
Remove-ADSyncAttributeFlowMapping [-SynchronizationRule]  [-AttributeFlowMappings] <List[AttributeFlowMapping]> [-WhatIf] [-Confirm] []
Remove-ADSyncConnector [[-Connector] ] [-WhatIf] [-Confirm] []
Remove-ADSyncConnector [[-Identifier] ] [-WhatIf] [-Confirm] []
Remove-ADSyncConnector [[-Name] ] [-WhatIf] [-Confirm] []
Remove-ADSyncConnectorAnchorConstructionSettings [-Connector]  [-ObjectClass]  []
Remove-ADSyncConnectorAttributeInclusion [-Connector]  [-AttributeTypes] <List[string]> []
Remove-ADSyncConnectorHierarchyProvisioningMapping [-Connector]  [-DNComponent ] [-WhatIf] [-Confirm] []
Remove-ADSyncConnectorHierarchyProvisioningMapping [-DNComponent]  [-Connector ] [-DNComponents <List[string]>] [-WhatIf] [-Confirm] [
Remove-ADSyncConnectorObjectInclusion [-Connector]  [-ObjectTypes] <List[string]> []
Remove-ADSyncGlobalSettingsParameter [-GlobalSettings]  [-ParameterNames] <List[string]> []
Remove-ADSyncJoinConditionGroup [-SynchronizationRule]  [-Index]  [-WhatIf] [-Confirm] []
Remove-ADSyncRule [-SynchronizationRule]  [-WhatIf] [-Confirm] []
Remove-ADSyncRule [-Identifier]  [-WhatIf] [-Confirm] []
Remove-ADSyncRunProfile [-RunProfile]  [-WhatIf] [-Confirm] []
Remove-ADSyncRunStep [-RunProfile]  [-RunStep]  [-WhatIf] [-Confirm] [
Remove-ADSyncScopeConditionGroup [-SynchronizationRule]  [-Index]  [-WhatIf] [-Confirm] []
Search-ADSyncDirectoryObjects [[-ForestFqdn] ] [-AdConnectorId]  [[-PropertiesToRetrieve] <string[]>] [[-NamingContextType] ] [[-BaseDnType] ] [[-AdConnectorCredential] ] [[-BaseDn] ] [[-LdapFilter] ] [[-SearchScope] ] [-WhatIf] [-Confirm] []
Set-ADSyncAADCompanyFeature [-ConnectorName]  [-ForcePasswordResetOnLogonFeature ] [-PasswordHashSyncFeature ] []
Set-ADSyncAADPasswordResetConfiguration [-Connector]  [-Enable]  [[-AADCredential] ] []
Set-ADSyncAADPasswordSyncConfiguration [-SourceConnector]  [-TargetConnector]  [-Enable]  [[-PasswordAgentCredentials] ] []
Set-ADSyncAADPasswordSyncState [-ConnectorName]  [-Enable]  []
Set-ADSyncConnectorParameter -Type  [-Connector ] [-PartitionIdentifier ] [-RunProfileIdentifier ] [-RunStepIdentifier ] [-ParameterValues ] []
Set-ADSyncGlobalSettings [-GlobalSettings]  [-WhatIf] [-Confirm] []
Set-ADSyncSchema [-Schema]  []
Set-ADSyncSchema [-SchemaFile]  []
Set-ADSyncServerConfiguration [-Path]  []
Set-MIISADMAConfiguration [-Id]  -Credentials  -Forest  [-Container ] [-AllowUnreachableDomains] [-WhatIf] [-Confirm] []
Test-AdSyncUserHasPermissions [-ForestFqdn]  [-AdConnectorId]  [-AdConnectorCredential]  [-BaseDn]  [-PropertyType]  [-PropertyValue]  [-WhatIf] [-Confirm] []
Update-ADSyncConnectorPartition [-Connector]  []
Update-ADSyncConnectorSchema [-Connector]  [-WhatIf] [-Confirm] []
Update-ADSyncDRSCertificates [-DeviceWriteBackConnectorName]  [-AadConnectorName]  [-WhatIf] [-Confirm] []

Problems setting storage quotas in OneDrive for Business? Check that site collection storage management is set to manual!

A few weeks ago, I wrote a blog post about controlling OneDrive for Business syncing to prevent data copies on non-domain-joined PCs. Since then, I’ve had to add a post script to highlight a known issue with domain joined PCs failing to sync OneDrive for Business, even when added to a safe list, which is fixed by the 12 May 2015 update for OneDrive for Business (see Microsoft knowledge base article 2986244).

I also wrote in that post about problems setting storage quotas in OneDrive for Business using Set-SPOSite -Identity https://tenantname-my.sharepoint.com/personal/firstname_lastname_tenantname_onmicrosoft_com -StorageQuota 2048

Set-SPOSite : Cannot get site https://tenantname-my.sharepoint.com/personal/firstname_lastname_tenantname_onmicrosoft_com.
At line:1 char:1
+ Set-SPOSite -Identity
https://tenantname-my.sharepoint.com/personal/firstname_lastname …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Set-SPOSite], ServerException
+ FullyQualifiedErrorId : Microsoft.SharePoint.Client.ServerException,Microsoft.Online.SharePoint.PowerShell.SetSite

After raising a service request with Microsoft (which took over a week to be escalated after a few days of the initial team failing to resolve it) and then engaging the Microsoft Onboarding Center instead, I finally got to the bottom of the issue. The problem was that Site Collection Storage Management in SharePoint Online was set to Automatic. Once this was changed to Manual, I could successfully apply the quotas to users’ OneDrive for Business sites.

Office 365 (SharePoint Online) Site Collection Storage Management settings

As well as using PowerShell (Get-SPOSite -Identity https://tenantname-my.sharepoint.com/personal/firstname_lastname_tenantname_onmicrosoft_com), you can check the current storage quota in the browser, under Site settings, Storage Metrics:

One Drive for Business storage quota reduced to 2GB

Unfortunately this setting has to be applied on a per-user basis, after the user has already logged on to OneDrive for Business (which provisions the storage).

Adding Microsoft Azure services to an existing Office 365 tenant

If you have an Office 365 subscription, you use Microsoft Azure because Azure Active Directory is the underlying directory service – regardless of your chosen identity model (even if you use federated identity, you’ll sync your users to the cloud).

Within the Office 365 admin center, is an Azure AD link although, if you click on it you may find you need to sign up for an Azure subscription. Don’t worry about this – it’s just provisioning access to the management portal – and once you have access, you’ll find your Azure Active Directory and can configure settings like logon page branding, self-service password reset, multi-factor authentication, etc.

When I clicked though, I was confused to see that all I had was Active Directory and Settings – no virtual machines, SQL, networks, or anything other Azure services.

Azure - AD created by Office 365

So how do you go about adding Microsoft Azure services to an existing Office 365 tenant? I asked my colleague Tim Siddle (@brainchyldeuk) who told me the simplest way is to sign up for a free one-month Azure trial.

Even if that’s not available (in my case Azure said I already have a subscription), it will let you either sign up for a different offer (on a pay-as-you-go basis) or view existing subscriptions.

Azure - Free Trial is Not Available

After running through the PAYG subscription sign-up process, where I verified my phone number, supplied credit card details and agreed to the terms and conditions, my Azure management portal was looking much more complete and, as can be seen from the screen shot below, I now have two distinct subscriptions on the same account – one for my Access to Azure Active Directory (part of my Office 365 subscription) and one for Pay-As-You-Go access to other Azure services.

Azure - Management Portal showing multiple subscriptions

Finally, if you’re worried about what all this might cost, there’s an Azure pricing calculator.