SharePoint DSC 1.9.0.0 is Released

The latest version of the SharePoint DSC module has been released this last Wednesday, October 5th. You can now obtain the latest bits of the module by running:

Install-Module SharePointDSC

If you wish to update the configurations on a given SharePoint farm to run these latest bits, make sure each .MOF file is first recompiled using the latest package and that the new module bits are copied to every server in the farm.

Here are some of the major changes that were introduced in this version:

  • SPServiceIdentity: A new DSC Resource has been introduced in the module to represent the managed account that is assigned to a service instance.
  • SPWebAppSiteUseAndDeletion: Fixed an issue with the scheduling where is was incorrectly setting the delays in weeks instead of in days.
  • SPWebAppGeneralSettings: Fixed an issue where web applications that weren’t assigned a TimeZone were incorrectly returning -1 instead of $null.
  • SPProductUpdate: Fixed an issue for updating a SharePoint 2013 farm were the resource was always complaining that the farm was missing the OSearch16 (SharePoint 2016 version).
  • Several other fixes related to the Get-TargetResource methods not properly returning values.

Along with the SharePointDSC 1.9.0.0 release, the SharePoint Orchestrator script for ReverseDSC, which allows you to extract the configuration out of an existing SharePoint 2013 or 2016 farm, has also been updated. To leanr more about what is new in the ReverseDSC Orchestrator Script, take a look at my previous blog post What’s New With SharePointDSC.Reverse 1.9.0.0

SharePoint DSC Gotchas and Best Practices

In the Microsoft Virtual Academy on SharePoint Automation with DSC my colleague Brian Farnhill and I recorded in June of 2017, we dedicated an entire module to SharePointDSC best practices. I thought I’d take a few minutes to put the items we discussed during that session on paper. This article will act as a list of the most frequent issues and problem encountered by people using SharePoint DSC. It will be updated as the tool evolves.

Frequent Issues

Installation of Prerequisites, Binaries or Language Pack is Stuck

Symptom:

This is one of the most frequent issue people encountered when starting off with SharePoint DSC. When running the configuration using Start-DSCConfiguration, or when in Pull mode, the installation seems to get stuck when trying to install components (prerequisites, binaries, or language pack). No errors are being thrown.

Most Likely Reason:

There is some level of User Account Control set on the installation file. In most cases this issues will happen when the installation is done from a Network Drive. Upon executing the installation of the component, windows triggers a prompt for the user to confirm the execution of an executable that was launched from an untrusted location, but because this was initiates from a background thread, it is impossible to ever approve that prompt and the installation gets stuck.

In order to test if this is your issue, launch a new PowerShell session, running as the user defined in the PsDscRunAsCredential parameter of the execution block. From there, run the following line of PowerShell. If there are any prompts that appear, that means that the installation is most likely stuck because of the User Account Control.

Start-Process -FilePath <Path to the Installer file> -Wait -PassThru

Solution:

The solution here is two fold. First off, we recommend you turn off the User Account Control feature for the user running the PsDscRunAsCredential installation block in your script. As a second step, launch Internet Explorer and go to Internet Explorer Settings. From there, go to the Security tab, click on the Local Intranet Zone, then click on the Sites button. In the prompt, click on the Advanced button, this will open the window that let’s you specify addresses to identify as being part of the Local Intranet Zone. In that window, type in the location of the Network share (or other common location) where the installer file is located, and click on Add.

Using a completely DSC based solution, you could use the xSystemSecurity module to disable the User Account Control prompt as follow:

# Make sure you import the module
Import-DSCResource -ModuleName "MSFT_xSystemSecurity"

# Put this in the node's configuration;
xUAC NeverNotifyAndDisableAll
{
    Setting = "NeverNotifyAndDisableAll"
}

Best Practices

Master Node

SharePoint is a distributed system, meaning that not all components run on the same server, and that most of the content and configuration is actually stored in a SQL Server database, that all servers in the farm can access at any time. When you define a DSC configuration file, you should identify one of the servers in your farm to be what I refer to has your Master Node. this is the node on which you will define most of the components in the Farm. All other nodes, referred to as secondary nodes in this scenario, should only define resources that allow them to install the required binaries and updates, to join the farm, and the service instances to run on that server. All other components should ONLY be defined on the Master Node.For example, don’t go and define an SPSite entry on multiple node, it is not necessary. SPSite objects are defined in the Content Databases anyway, so you don’t need every server in the farm to attempt to create them.

Take another example where you wish to update the DSC definition of a certain feature on a Site Collection to be disabled instead of enabled. If you properly defined your configuration, you only have to update the DSC definition for that feature within a single node (Master Node) in the DSC configuration file, but let’s imagine you have it defined within every node instead. You now have to go and modify it multiple times within your configuration, and that opens the door to mistakes. Let’s say our farm has 3 servers, that you updated the feature’s definition for Server #1 and #2, but forgot to update the definition in server #3. To make things worst, you’ve set all 3 servers’ Local Configuration Manager (LCM) to be set to ApplyAndAutocorrect. We all know that by default, the ConfigurationMode for the LCM will check every 15 minutes to make sure it is in its desired state, but that 15 minutes may not happen exactly at the same time on each of the servers in the farm. Imagine that at 10h a.m., server one has its LCM kick in, and realize that the feature has to be turned on based on the new definition. It will go and disable the feature. Now, let’s pretend that server #3’s LCM kicks in at 10h05 a.m., but since that server doesn’t have the proper definition, it re-disables the feature that was just turned on 5 minutes ago by Server #1. You can see where this is going, and that can cause a lot of headaches for your admin team. DO NOT DECLARE components (other than SPFarm, SPIntall, SPInstallPrereqs, and SPServiceInstance) on more than one server in the configuration.

Use ApplyAndAutocorrect with Caution

We took a decision a few years back not to let SharePointDSC deal with content such as SPList, SPContentTypes, etc. However, we do deal with items such as SPSite and SPWeb that are stored in the Content Database. The real beauty behind SharePoint is that it lets users deal with their content as they see fit. Users can easily go and create a new list, play with it for a few days, and then decide to delete it after because their tests are done.

PowerShell Desired State Configuration is very powerful. When you set the Local Configuration Manager of a server to ApplyAndAutocorrect, the server will automatically attempt to bring itself back into its defined Desired State Configuration whenever it detects that it drifted away from that configuration. While this feature is very powerful, my recommendation is not to set the LCM in ApplyAndAutocorrect the moment your configuration includes either and SPWeb or SPSite resource declaration, unless you are absolutely certain and aware of what this will do to your environment.

Imagine the following scenario where you have an environment which declares 3 SPWeb (say Web1, Web2, and Web3), and for which the LCM is set to ApplyAndAutocorrect. Come spring, the Information Management (IM) team at your organization undertakes a major cleanup project where they want to get rid of sites that have not been active in the past 6 months. There 3 SPWeb sites defined in the configuration, have been identified by the IM team to be deleted. The IM manager goes in and deletes the 3 sites, then sends an email to the IM director to let him know that the cleanup has been done. Two weeks after the IM director stumbles upon SPWeb2, which the IM Manager claimed to have deleted 14 days ago. Well, the moment the site was originally deleted by the IM Manager, 15 minutes after, the LCM detected that it was no longer in its desired state, and since its LCM is set to ApplyAndAutocorrect, it automatically recreated the site. Imagine the confusion this can cause.

Do Not Have Multiple SPProductUpdate & SPConfigWizard Entries

The SPProductUpdate resource is responsible for installing the bits from a Cumulative or Public Update (.exe) onto a server. When using it in a script that configures a farm from the ground up, the recommendation is to have it executed right after the SPInstall bits have installed the SharePoint binaries, and right before using the SPFarm resource to join the server to the farm. You need to make sure that this resource is applied to EVERY server in the farm, therefore it needs to be defined for each node in your Configuration Script.

The SPConfigWizard resource is responsible for executing the PSconfig process on the servers, committing the bits back to the farm’s configuration database. Once again, it needs to be run on every server in the SharePoint farm, and should therefore appear in every node in your DSC config.

It is obvious why you do not want to have more than one instance of the SPConfigWizard resource defined per server. There are no reasons why PSconfig should be ran multiple time on the server during a DSC consistency check. You also do not want to have more than one SPProductUpdate instance per server. Cumulative and Public updates are cumulative by nature, meaning that for example, you do not need to install the September 2017 Public update before installing the October 2017 Public Update. You simply install the October 2017 PU which contains all the bits from the previous updates as well. If you define multiple SPProductUpdate instances per server, the latest PU or CU will always overwrite the previous version, so you will end up installing old versions of patches, just so that they can be overwritten by more recent ones. Always remember to only have one instance of these two resources per node in your Configuration Script.

this article will be updated on an on-going basis.

What’s New in SharePointDSC.Reverse 1.9.0.0

The latest release of the ReverseDSC Orchestrator Script for SharePoint is the biggest release we’ve had so far and it is packed with new features that will make it even easier for users to migrate their on-premises SharePoint 2013 or 2016 Farms from their on-premises data centers to the cloud. This release drastically changes the way the orchestrator script does its extraction. The following is a complete list of all improvements that have been included in the latest release.

New Features

  • Configuration Data: A new ConfigurationData.psd1 file will be generated with all extractions. This external .psd1 file exposes all parameters that are specific to the source SharePoint environment. If you are planning on deploying a copy of the extracted SharePoint Farm into a new environment (Azure, on-premises, etc.), all you need to do is update the values contained in that file to reflect the destination environment. For more information regarding what parameters are now exposed in the Configuration Data, please refer to the Configuration Data wiki Page.
  • Extraction Modes: Previous versions of the Orchestrator Script would expose a -Lite switch, which allow the extraction process to skip certain DSC Resources such as the Timer Job States, Features, SPWeb, etc. In version 1.9.0.0, we introduce the concept of Extraction Modes, where each mode will capture a different set of DSC resources. to learn more about what set of DSC Resource will be extracted in each mode, please refer to Extraction Mode wiki page.
  • Full Installation: Previous versions of the Orchestrator Script extracted resources starting at the SPFarm level, meaning that the machines you were trying to replicate your environment on had to have the SharePoint bits installed on them already for the configuration to get applied. With the new version, the SPInstallPrereqs and SPInstall resources are automatically included in the configuration file. The Configuration Data files drives whether or not these are included in the compiled MOF file using the FullInstallation. parameter. If this parameter is set to $True in the configuration data, then the compiled MOF instances will attempt to install the SharePoint Prerequisites (using the Online Mode) and the binaries on the servers being configured.

New Resources Supported

SharePointDSC.Reverse 1.9.0.0 introduces support for the following Resources:

  • SPInstallPrereqs
  • SPInstall
  • SPMachineTranslationServiceApp

Deprecated Features

the following switches have been deprecated with the 1.9.0.0 Release. The equivalent result can now be achieved 9in most part) by using the -Mode Lite parameter.

  • -Lite
  • -SkipFeatures
  • -SkipWebs
  • -SkipHealthRules
  • -SkipSearchFileType
  • -SkipTimerJobState
  • -SkipUserProfile

SharePointDSC and ReverseDSC Microsoft Virtual Academy Session

In June of 2017, my colleague Brian Farnhill and I recorded a Full Day Microsoft Virtual Academy (MVA) session on Automating SharePoint with PowerShell Desired State Configuration. The recording is now available for free on the MVA site and covers the following topics:

  • Introduction to PowerShell Desired State Configuration
  • Advanced PowerShell DSC on-premises
  • Introduction to SharePointDSC
  • Azure Automation DSC with SharePoint
  • ReverseDSC for SharePoint
  • SharePointDSC Best Practices and Guidance

Click on the following link to watch the Full Session.

PowerShell Web Access to Manage SharePoint

In this article we will cover how you can deploy the PowerShell Web Access Gateway onto one of your SharePoint server to allow remote users to perform remote PowerShell operations. PowerShell Web Access is a feature that was introduced back with Windows Server 2012, and which provides the users with a Web Application mimicking the local PowerShell console, allowing them to run remote PowerShell commands against a server.

PWAScreen

The idea here is that we wish to let the development team access some of the SharePoint cmdlets remotely for them to run reports and extract valuable information from the server without having the admin group act as a middle man. While we want to let the Dev team execute remote PowerShell cmdlets, we want to restrict the set of operations they can call upon to cmdlets that start with “Get-SP” as well as the “Merge-SPLogFile” cmdlet.

Overview of the Environment

Throughout this article I will be using a SharePoint farm built in Azure IaaS that is made up of 3 servers: 1 SQL, 1 Web Front-End, and 1 Application server. The domain used will be contoso.com, and a Security Group named “DevTeam” has been defined in the Active Directory to group all members of the Development team.

You only need to deploy the PowerShell Web Access Gateway to 1 server in your farm. In our case, we will be deploying it onto the Application server.

Servers

SP2013-SQL -> SQL Server 2012 R2

SP2013-WFE01 -> Windows Server 2012 R2

SP2013-APP01 -> Windows Server 2012 R2

Installing the PowerShell Web Access Feature

The first step involved in deploying the PowerShell Web Access onto a server is to activate the PowerShell We Access feature on the box. In our case, we will connect to the SP2013-APP01 server, which will be hosting the PowerShell Web Access application, and will be adding the feature onto it. The feature can be installed using two different methods:

Activating the Feature

Option 1 – Using PowerShell

To install the feature using PowerShell, simply execute the following line of PowerShell:

Install-WindowsFeature -Name WindowsPowerShellWebAccess -ComputerName localhost -IncludeManagementTools

Option 2 – Using the Server Manager

Your second option is to open the Server Manager console on the server and to go to the Add Server Roles and Features section. On the Features page, scroll down to the Windows PowerShell group, and expand it. Make sure you check the Windows PowerShell Web Access feature, click Next and then Install.

Features

Installing the Application

Now that the feature is activated, we need to install the Web Application. Upon activating the feature on the server, several PowerShell modules specific to the PowerShell Web Access have been deployed to the server. You can take a look at the new cmdlets that are now exposed for the feature by running the following line of PowerShell:

Get-Command *PSWA*

pswacmdlet

The cmdlet we are interested in is named Install-PswaWebApplication which will take care of deploying and configuring the Web Application endpoints in IIS. By default, that cmdlet will try to deploy the PowerShell Web Access Application under the default IIS website which runs on port 80. Since you are most likely going to be reserving port 80 for SharePoint Web Applications, I recommend you go in IIS and create a new Web Site and bind it to a different port. In my Case, I will be creating a custom Web Site called “PWA” which will be running on port 88.

PWAIIS

We are now ready to call the installation cmdlet by passing it the name of our newly created Web Site as parameter. Also, note that for my example, I will be passing in the -UseTestCertificate switch to the cmdlet, which will create and assign a Self-Signed Certificate as an SSL endpoint to my PowerShell Web Access Application. In a production environment, it is recommended that you assign your own SSL certificate to secure the connection between the client OS and the host running the PowerShell Web Access Application.

To go ahead and configure the application, simply execute the following line of PowerShell on the server:

Install-PswaWebApplication -UseTestCertificate -WebSiteName “PWA” -WebApplicationName “PWA”

Install

That’s it! We have now properly configured our PowerShell Web Access Gateway onto our server. To verify that the installation worked as expected, simply launch a new Browser instance and navigate to: https://localhost/Pwa/ You should be presented with the PowerShell Web Access Gateway login page as shown in the following screenshot:

PSALogin.PNG

Now, something to watch out for is that if you already have a Web Application that leverages SSL (running on port 443), you will have to change the SSL binding of your newly created IIS Web Site to use another port number to prevent conflicts. In my case, none of my SharePoint Web Application were using SSL, so there were no conflicts to be prevented.

Granting Permissions

The only way to grant access to the PowerShell Web Access Gateway to a user or to a group of users is to create an PswaAuthorizationRule. In a nutshell, a PswaAuthorization is a mapping between a user or group to a set of PowerShell permissions. In a certain way, this represents what the Just Enough Administration (JEA) feature is trying to achieve. Just like for JEA, it involves creating a custom PowerShell file that will define what permissions the users will have against our PowerShell Web Access Gateway.

If you remember correctly, our scenario was that we wanted to prevent the Development team of an organization from using any cmdlets that don’t have a name starting with “Get-SP*”. The way to do this in PowerShell is to declare what we call PowerShell Session Configuration files (PSSessionConfigurationFile). A PowerShell Session Configuration File has an extensions of .pssc and defines what permissions users inheriting this Configuration will have against the PowerShell runspace.

To create a new PSSessionConfigurationFile, you can simply call the following PowerShell line of code:

New-PSSessionsConfigurationFile -Path <path>

ConfigFile.PNG

This will automatically create your .pssc file in the specified folder. This file by default will contain the skeleton of what properties it is possible for you to define:

pssc

Define Allowed CMDLets

The file above is where we would define the list of cmdlets we wish to let members of the Dev team use via our PowerShell Web Access Gateway. If you scroll down in the newly created .pssc file, you’ll see a property named VisibleCmdlets that is commented out. Simply uncomment this line and replace it with the following:

VisibleCmdlets = ‘Get-SP*’, ‘Out-Default’, ‘Get-Command’, ‘Get-Member’, ‘Merge-SPLogFile’

This will ensure the users can use any cmdlets whose name starts with “Get-SP”, as well as the Merge-SPLogFile. Get-Command and Get-Member are self-explainatory and can help provide additional valuable information to the end-users. Out-Default is required for the results of cmdlets to be printed back into the PowerShell Web Access session. if you forget to mention it, and a user tries to call Get-Command for example, while the command will execute fine on the remote server, no results will be printed back to the end user.

Import the SharePoint PowerShell bits

Now this is where you really have to jump through hoops to get the process working as expected for a SharePoint environment. Any SharePoint administrator knows that in order for a PowerShell session to be able to leverage the SharePoint cmdlets, you need to load the SharePoint Snapins into your session by using the following line of PowerShell (launching the SharePoint Management Shell does it automatically for you in the background):

Add-PSSnapin Microsoft.SharePoint.PowerShell

So how are we to make sure this snapin is available to our remote users’ sessions in the PowerShell Web Access? Well, one thing is for sure, you don’t want to add “Add-PSSnapin” as part of the allowed cmdlets in your PSSessionConfigurationFile. If you do, then automatically, users calling the Add-PSSnapin cmdlet to import the SharePoint cmdlets will get access to all cmdlets defined in the Snapin, even if we only allowed the Get-SP* ones. This is due to the order of operations. By default, when launching a new PowerShell Web Access session, it loads the available modules, then applies the VisibleCmdlets parameter to filter our the list of available cmdlets in the session. If users load the SharePoint cmdlets after the session has been loaded, then the VisibleCmdlets filter is not applied on whatever is being loaded after the fact.So bottom line, do not allow “Add-PSSnapin” as a visible cmdlet.

Here is what we need to do instead. If you pay a closer look to your .pssc configuration file, you’ll see that it defines another commented property named “ModulesToImport”. Uncomment out this property and replace it by the following line:

ModulesToImport = “Microsoft.SharePoint.PowerShell”

Seems simple enough right? Well it is not. Our problem is that Microsoft.SharePoint.PowerShell is a Snapin, and not a Module. Even if the documentation says ModuleToImport can load snapin, it doesn’t work for the SharePoint Snapin. So what are we to do? Well, we’ll need to cheat PowerShell by creating a bogus SharePoint module!

Create a Fake SharePoint Module

By default, PowerShell registers all modules in C:\Program Files\WindowsPowerShell\Modules, so what we need to do is open Windows Explorer and navigate to that location. In there, create anew empty folder named Microsoft.SharePoint.PowerShell (you see where this is going). In that newly created empty folder, add a new empty file named Microsoft.SharePoint.PowerShell.psm1 and enter the following line of PowerShell in it:

Add-PSSnapin Microsoft.SharePoint.PowerShell -EA SilentlyContinue

FakeModule

Effectively what we are doing here, is cheat PowerShell into thinking it is loading a SharePoint module, making it load the .psm1 into the session, which in turns simply adds the Snapin to the session. Sneaky Sneaky!

Setting the Language Mode

The last thing remaining for our PowerShell Session Configuration File to be completed and secured is for us to restrict the PowerShell language components the users can use. By default, users will be able to declare variables and assign objects to them. You may not see this as an issue at first but think of the following scenario where a user defines a new variable called $web which he assigns an SPWeb object to by calling the following line of PowerShell:

$web= Get-SPWeb http://localhost

Because they have assigned the $web variable an object, they can leverage the power of the PowerShell language to make method calls onto that object. This means that there is nothing preventing them from calling the following lines of PowerShell:

$web = Get-SPWeb http://localhost

$web.Delete()

In summary, if we grant the users access to the full PowerShell object they can still call potentially dangerous methods on objects. In the example above, while we did our best to block the user from using the Remove-SPSite cmdlet, they can use a Get-* cmdlets to retrieve and object and then call the .Delete() method on it. Effectively this comes back to them having access to the Remove-SPSite cmdlet.

What we need to do to prevent this from happening is prevent them from leveraging the full PowerShell language in their PowerShell Web Access sessions. This is done by modifying the LanguageMode property in our .pssc configuration file and by setting its value to “NoLanguage”:

LanguageMode = “NoLanguage”

Full .pssc file

In summary, here is the full content of our .pssc PowerShell Session Configuration File we will be using in our example to restrict access to the Dev Team:

@{
SchemaVersion = ‘2.0.0.0’
GUID = ’78b552a2-34fa-43e5-b2b3-5a306907dc65′
LanguageMode = “NoLanguage”
SessionType = ‘Default’
VisibleCmdlets = ‘Get-SP*’, ‘Out-Default’, ‘Get-Command’, ‘Get-Member’, ‘Merge-SPLogFile’
ModulesToImport = “Microsoft.SharePoint.PowerShell”
}

Registering the PSSessionConfigurationFile

Once your .pssc file has been created, you need to register it in PowerShell. This is done by calling the following line of PowerShell:

Register-PSSessionConfiguration -Name “DevTeam” -Path <Path to the .pssc file> -RunAsCredentials <Farm account>

This will prompt you to confirm the credentials of your farm account, which is required to access the local farm remotely. Simply provide the requested credentials and accept the prompt to complete the registration of your custom PowerShell Session Configuration.

Register

Create the PowerShell Web Access Authorization Rule

We are almost there! The last thing left is to create the mapping between our Active Directory User Group and the custom PowerShell Session Configuration file we just created. This is done by adding a new PswaAuthorizationRule on the server. In our case, our user group in AD is named “contoso\DevTeam”, so in order to assign it permission to our custom DevTeam configuration file, we need to execute the following line of PowerShell and accept the prompt:

Add-PswaAuthorizationRule -ComputerName localhost -UserGroupName “Contoso\DevTeam” -ConfigurationName “DevTeam”

AddRule

Grant Local Permissions to the Remote Users

In order for your remote users to be able to connect to your PowerShell Web Access Gateway, they also need to be added to the local Remote Management Users group:

remoteperm

Otherwise they will be presented with an error stating “Access to the destination computer has been denied. Verify that you have access to the destination Windows PowerShell session configuration […]”

ErrorAccess.PNGConnect to the PowerShell Web Access Gateway

We are finally done. Everything is in place for your users to connect. In my case, I will be connecting as user Bob Houle (contoso\Bob.Houle) who’s part of the contoso\DevTeam group.

Navigate to the Gateway’s main page and provide the requested information (making sure you specify the name of the farm server onto which the PowerShell Web Access was deployed to). The most important section to fill in is hidden in the Optional connection settings section. It is the Configuration Name section in which you need to provide the name of the custom PowerShell Session Configuration we created (in our case DevTeam).

connect.PNG

Once connected, you should be able to run the Get-Command cmdlet to verify that you are only granted access to the cmdlets starting with Get-SP and to the Merge-SPLogFile one.

cmdlets.PNG

Enjoy!