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-PSSessionConfigurationFile -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" -RunAsCredential "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.PNG

Connect 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!

One thought on “PowerShell Web Access to Manage SharePoint

Leave a Reply

Your email address will not be published. Required fields are marked *