Hello again! Brian here with a tip on something I suspect lots of folks need: redirecting SharePoint requests from HTTP to HTTPS.
Most of us already know the best practice is to use HTTPS for everything in SharePoint. There's not a whole lot of reason not to. The problem, though, is that users don't always enter HTTPS in their URLs. If they just enter the web application's URL in a browser without supplying the protocol, the browser will attempt to load the site using HTTP://. If, however, the site is only using HTTPS, then the request will fail. This will annoy the user, potentially eroding goodwill towards SharePoint (which is especially problematic if the user is an exec holding the checkbook).
One of the solutions to this issue is to allow the HTTP request but then immediately redirect the user to HTTPS. That way, users aren't interrupted, work can continue, and the remaining requests are secured via HTTPS as they ought to be. This is what Microsoft does with SharePoint Online. In this blog, I'm going to show you how to implement this redirect in a way that's simple, easy-to-run, and schedulable. Let's do it all with a single PowerShell script, shall we?
First off, let me make clear the major downside to this. In order to pull this off without using any 3rd-party tools, proxies, load-balancers, etc., it becomes necessary to allow inbound traffic on port 80. Obviously, in order to redirect from HTTP to HTTPS, the first call will be using port 80. Your load balancer or whatnot will need to be able to pass port 80 as well as port 443. It's not my favorite thing in the world, but I'm pretty sure it's necessary if you don't have a middleman to do the redirect for you.
The HTTP-to-HTTPS redirect will be accomplished using the URL Rewrite 2.0 module in IIS. This module uses rules defined in each IIS site (stored in the web.config file) to redirect the user to wherever you need them to go. In our case, we simply want to take the URL and switch it to HTTPS. We want to leave the URL entirely intact (except for the protocol, of course). Also, we want to deploy all of this in a way that's safe, uses best practices, is automated, and can be run repeatedly without concern. We also want this to be done in such a way as to be consistent from SharePoint server to SharePoint server. Desired State Configuration (DSC) would be awesome, but I'm assuming it's not available.
I have created a PowerShell script which will do all of this for us. It uses PowerShell Remoting to configure every farm server. We could limit the work to just the Web Servers (WFEs), but the nature of SharePoint is such that any of the farm servers could take on the Web Application Server role. Therefore, I want all of my farm servers to be configured as identically as possible in order to avoid any surprises down the road. Before running the script, make sure that each farm server is configured for PowerShell Remoting and is allowed to delegate credentials (Enable-WSManCredSSP -Role Server).
The script does the following at a high level.
1. Retrieve from the user a login and password (securely, of course) with admin rights in the OS and with SharePoint shell access. I recommend using the SharePoint setup account. If you want to schedule the script, you can make it so the script doesn't ask for the credentials interactively.
2. Configure the local server so that it can use PowerShell Remoting to connect to other servers and delegate credentials. This enables the remote servers to be able to run Web Platform Installer from a network share (instead of needing it installed locally on each server). If it's installed locally on each server, then the script can be adjusted to not need the credential above.
3. On each server in the farm, install the URL Rewrite 2.0 module
A. Use the SPWebConfigModification class/technique to add to the web.config file the XML needed to implement the redirect. We want to use SPWebConfigModification to make sure that each server with the Web Application Server role automatically gets the elements in its web.config file. The URL Rewrite module stores its configuration in the web.config file, so it's not necessary to go into IIS and manually configure the rules.
B. For every farm server which is currently running the Web Application Server role (is a WFE), add port 80 to the bindings if it isn't already there. Use the host header from the HTTPS binding when creating the new one.
Because of PowerShell Remoting, you only need to run the script from one farm server. It will automatically configure the other servers. There are some things to be considered, though.
The script uses the Web Platform Installer (WebPI) in order to deploy the URL Rewrite 2.0 module. It will download it from Microsoft, but it is possible to update the script to do an offline install if needed. The script needs to be updated with the path to the WebpiCmd.exe. This path is stored in the $WebPiCmd variable on line 215. If WebPI is installed locally on each server, use the local path to the file. If, however, you don't want WebPI deployed to each server then you can unpack it to a share and call it remotely. To do that:
1. Download the Web Platform Installer MSI (WebPlatformInstaller_amd64_en-US.msi) from Microsoft
2. From a command prompt, run the following (updating with your paths): msiexec /a "[path to download location]\WebPlatformInstaller_amd64_en-US.msi" /qb TARGETDIR="[target share path]\WebPlatformInstaller\"
Although this script will install the URL Rewrite 2.0 module on all farm servers and automatically add the web.config configurations needed, it can only configure the IIS bindings for the servers currently running the Web Application Server role (WFEs). There's nothing for it to update on the other farm servers since the IIS sites won't be there. Therefore, you will need to run this script each time the Web Application Server role is started on a server. It will update the bindings accordingly. Also, of course, run the script when a new server is added to the farm. To get around needing to remember to do this, you can simply schedule the script to run regularly on a farm server via something like Task Scheduler.
The script can be run as often as you like. With some small modifications (namely, using a stored credential instead of asking for it at runtime), you can even set it up as a schedule task to make sure that the redirects are always in place. Like I said, this can be useful to make sure all servers and sites are continually configured correctly.
The PowerShell script has been heavily commented, so please make sure to read through the comments to understand what's going on.
Got any questions about any of this? Does any of it not make sense? Want to know more about anything you see here or in the script? Having a problem with running the script? If so, please don't hesitate to post a question in the comments section below. I'll do my best to answer as quickly and as well as possible.