DavidRa

How-to Guide LetsEncrypt a 2012 R2 Web Application Proxy

Implementing LetsEncrypt for end-to-end SSL across IIS and WAP

  1. DavidRa
    Overview

    With Chrome (and presumably Edge and Firefox in the future) beginning to move towards an "SSL preferred" world (and I anticipate a future move to "enforced SSL"), it's beginning to look like HTTPS will be required for most sites.

    Microsoft-centric environments generally have websites hosted on IIS - possibly plain webs, but also LOB applications, Exchange, SharePoint etc (yes, there's the cloud - but that doesn't suit all organisations).

    LetsEncrypt are moving towards production-ready status, offering free certificates with short expiry and automated renewal. Free, fully trusted certificates are available today, and there are Windows tools to generate and renew.

    Wouldn't it be nice if it were possible to do certificates for free, and still comply with security requirements (like reverse proxies in a DMZ for external users accessing websites)?

    With that in mind this guide presents an architecture and approach for ongoing support for SSL certificates that's scalable to dozens or hundreds of web applications and websites, can provide HA for applications and the reverse proxy layer, and takes little more time to set up than HTTP.

    Request Routing

    Part of what we're going to do is route certain requests to different servers. This allows for a server to host just the certificates and answer the HTTP requests from the LetsEncrypt servers, while existing web servers and application servers service all other requests.

    This diagram shows the data flows for HTTP and HTTPS:

    ARR+WAP Request Paths.png

    Server Architecture

    This guide assumes a traditional network environment - an internal zone for protected servers, a DMZ hosting servers that provide access to (some) internal systems, and firewalls between each zone. The distinction between a three-legged firewall and two separate firewalls does not impact on the solution.

    IIS+WAP Architecture.png

    Some assumptions about this environment for this guide:
    • We assume the environment must be highly available;
    • Shared content is stored on a file server cluster;
    • IIS servers are already configured to use a Central Certificate Store on the file server cluster, and the share is \\FSCluster\SSLStore;
    • Load balancers are not shown;
    • The Certificate Management host is separate (and presumably a VM) so that the configuration of web servers can be stateless;
    • We require (or desire) SSL end to end - not only for security, but to simplify the web applications (which may depend on the host header to create links or content, for example);
    • We have split-horizon DNS so that all public names resolve externally to the reverse proxies (or firewalls, if you're using NAT) and internally to the web servers;
    • We have a domain environment so that we can use a single user/password combination across all servers.
    LE Assumptions and Implications

    The LE architecture is not well suited to scaled or HA environments, and this drives some of the architecture and configuration.

    Most critically, the ACME protocol generally assume that a file (or set of files, one per name) can be written to the web server as part of the issuance and validation process.

    In a distributed environment, simple LE clients are not always capable of handling this - for example, if you wish to deploy a certificate to a set of half a dozen Exchange CAS hosts, in two datacenters - that's ... not easy. Instead, we're going to build this into the certificate management server.

    Reverse Proxy - Base Environment

    We're going to build and configure the reverse proxy to support obtaining and installing certificates. For this we need the IIS Server role, but only the minimum role services to support the reverse proxy:
    • Web-Application-Proxy
    • Web-Server
    • Web-WebServer
    • Web-Common-Http
    • Web-Http-Errors
    • Web-Static-Content
    • Web-Health
    • Web-Http-Logging
    • Web-Mgmt-Tools
    • Web-Mgmt-Console
    Once the role services are installed, open the IIS Management Console and use Web Platform Installer to install the Application Request Routing module - 3.0 was current at time of writing. It will add dependencies such as URL Rewrite. If you cannot run WebPI for the install you can install the components manually.

    We need to create two server farms. One will contain all the Certificate Management servers (all one of them) and one will contain the servers hosting real content for the web application.

    Farm-1.png

    Find the Server Farms node in the IIS Management console, and click Add Server Farm on the right.

    Farm-2.png

    I recommend using the site name as the farm name; it makes much of the rest of the UI more logical. However it is completely arbitrary.

    Farm-3.png

    Add the server(s) hosting the web application. Optionally, if necessary, change the httpPort and httpsPort to match the target webserver.

    Farm-4.png

    Repeat the process for the certificate management farm (although since this will serve only the LE challenges, select an appropriate name for the farm). You will see the following warning, because both Rewrite rules will process all requests. We'll fix that in a moment.

    Farm-5.png

    Navigate back to the server, now, and in the centre select URL Rewrite from the IIS group.

    Rewrite-1.png

    Ensure the Cert Management rule is at the top of the list of inbound rules, then edit the rule.

    Rewrite-2.png

    Change the Pattern to .well-known/acme-challenge/* and ensure the checkbox "Stop processing of subsequent rules" is ticked. Do not preface the pattern with the initial "/" - the rule will not work.

    That should permit basic access to the certificate and host validation URLs.

    Building the LE environment

    The next task will be to configure a server (org-certs.example.com) to obtain all the certificates and store them in the central store.

    Start by creating a domain user - I often use sa- as a prefix for the logon name of a service account, so this might be DOMAIN\sa-CertMgmt or similar. Use a logon name and secure password suited to your environment.

    Since you'll need an email address for LetsEncrypt, you may choose to assign that email address to the same Windows account to keep it consistent.

    You will need to grant it appropriate rights to the central certificate store share, admin rights to the certificate management server and administrative or delegated rights to your reverse proxies, at least. Use whatever process or standard matches your environment (DSC, GPO etc).

    Log on to the certificate management host as your service account. The LE client will create files under the AppData\Roaming profile directory to store configuration data, so you really need to run as the service account.

    First, you'll need to install the Web Server role - you need enough to serve static files, so install only these role services:
    • Web-Server
    • Web-WebServer
    • Web-Common-Http
    • Web-Http-Errors
    • Web-Static-Content
    • Web-Health
    • Web-Http-Logging
    • Web-Mgmt-Tools
    • Web-Mgmt-Console
    Install and Configure the LE Client

    Download the Let's Encrypt Simple Windows Client and extract to a folder - perhaps C:\LetsEncrypt but again, use your local environment standards.

    Edit letsencrypt.exe.config with your preferred text editor, and change the PFX password from empty to something secure - this password must match the password you configured for certificates in the Central SSL store on your web server farm.

    Original:
    Code:
          <setting name="PFXPassword" serializeAs="String">
            <value />
          </setting>
    Example:
    Code:
          <setting name="PFXPassword" serializeAs="String">
            <value>7wfRW2hajUMAtV04Lvb6ugxmYQXpBZHPkIEl5sN1ynzKeSJiCq93O8FGdTcorD</value>
          </setting>
    Run an Administrative command prompt and change to the folder containing the LE client:

    C:\Windows\System32> cd \LetsEncrypt
    C:\LetsEncrypt>

    Create the .well-known and acme-challenge directories, and copy the custom web.config into the acme-challenge directory:

    C:\LetsEncrypt> mkdir C:\InetPub\WWWRoot\.well-known\acme-challenge
    C:\LetsEncrypt> copy Web_Config.XML C:\InetPub\WWWRoot\.well-known\acme-challenge\web.config
    C:\LetsEncrypt>


    Run the LE client for the very first time, to complete a small amount of setup. You'll be asked to enter your email address and agree to the user agreement; then create a manual request for the appropriate hostnames:

    C:\LetsEncrypt> letsencrypt --san --centralsslstore \\FSCluster\SSLStore
    Let's Encrypt (Simple Windows ACME Client)
    Renewal Period: 60
    Certificate Store: WebHosting


    ACME Server: Boulder: The Let's Encrypt CA
    Using Centralized SSL Path: \\FSCluster\SSLStore
    Certificate Folder: C:\Users\sa-CertMgmt\AppData\Roaming\letsencrypt-win-simple\httpsacme-v01.api.letsencrypt.org


    Getting AcmeServerDirectory
    Enter an email address (not public, used for renewal fail notices): certmgmt@example.com
    Calling Register
    Do you agree to https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf? (Y/N) Y
    Updating Registration
    Saving Registration
    Saving Signer


    Scanning IIS Site Bindings for Hosts
    IIS Version not found in windows registry. Skipping scan.
    No targets found.


    W: Generate a certificate via WebDav and install it manually.
    F: Generate a certificate via FTP/ FTPS and install it manually.
    M: Generate a certificate manually.
    A: Get certificates for all hosts
    Q: Quit
    Which host do you want to get a certificate for: M
    Enter a host name: myweb.example.com
    Enter all Alternative Names seperated by a comma myweb.example.com,myweb2.example.com
    Enter a site path (the web root of the host for http authentication): C:\InetPub\WWWRoot


    Authorizing Identifier myweb.example.com Using Challenge Type http-01
    Writing challenge answer to C:\InetPub\WWWRoot\.well-known/acme-challenge/G0FRZLnDDL840KZ2ubj1TiGFQjQ-X_t6Rk2EFRQ7HJ8
    Answer should now be browsable at http://myweb.example.com/.well-known/acme-challenge/G0FRZLnDDL840KZ2ubj1TiGFQjQ-X_t6Rk2EFRQ7HJ8
    Submitting answer
    Refreshing authorization
    Authorization Result: valid


    Authorizing Identifier myweb2.example.com Using Challenge Type http-01
    Writing challenge answer to C:\InetPub\WWWRoot\.well-known/acme-challenge/weihgzBHIf4zZuujRzaabo3qf-DY0O1LA_DKJmMmfpo
    Answer should now be browsable at http://myweb2.example.com/.well-known/acme-challenge/weihgzBHIf4zZuujRzaabo3qf-DY0O1LA_DKJmMmfpo
    Submitting answer
    Refreshing authorization
    Authorization Result: valid


    Requesting Certificate
    Request Status: Created
    Saving Certificate to C:\Users\sa-CertMgmt\AppData\Roaming\letsencrypt-win-simple\httpsacme-v01.api.letsencrypt.org\myweb.example.com-crt.der
    Saving Issuer Certificate to C:\Users\sa-CertMgmt\AppData\Roaming\letsencrypt-win-simple\httpsacme-v01.api.letsencrypt.org\ca-009813F47513E5750B43E7431E971E44BD-crt.pem
    Requesting Certificate
    Request Status: Created
    Saving Certificate to C:\Users\sa-CertMgmt\AppData\Roaming\letsencrypt-win-simple\httpsacme-v01.api.letsencrypt.org\myweb.example.com-crt.der
    Saving Issuer Certificate to C:\Users\sa-CertMgmt\AppData\Roaming\letsencrypt-win-simple\httpsacme-v01.api.letsencrypt.org\ca-009813F47513E5750B43E7431E971E44BD-crt.pem
    Host: myweb.example.com
    Saving Certificate to \\FSCluster\SSLStore\myweb.example.com.pfx
    Host: myweb2.example.com
    Saving Certificate to \\FSCluster\SSLStore\myweb2.example.com.pfx
    WARNING: Unable to configure server software.

    Creating Task letsencrypt-win-simple httpsacme-v01.api.letsencrypt.org with Windows Task Scheduler at 9am every day.


    Do you want to specify the user the task will run as? (Y/N) N
    Renewal Scheduled Manual myweb.example.com (C:\InetPub\WWWRoot) Renew After 11/05/2016
    Press enter to continue.


    Congratulations, you now have a certificate for your web server. Now we need to import it to the reverse proxy.

    Reverse Proxy - Site Publishing

    Just to recap, we now have:
    • A reverse proxy sending our browsers to the main web servers for content, and sending the LE certificate processors to the certificate management server
    • The LE client generating and renewing certificates on the certificate management server
    • Certificates and private keys stored on the Central Store with a known, strong password
    • Main web servers using the central store for SSL certificates and keys
    We now need to configure the Web Application Proxy to handle SSL requests. Build your ADFS servers, and complete the basic configuration of the WAP role using your ADFS certificate.

    Load the Remote Access Management console and select the server.

    WAP-1.png

    On the right hand side, click Publish.

    WAP-2.png

    Click through to the Preauthentication tab.

    WAP-3.png

    Unless you're publishing Exchange, SharePoint or another OAuth2 application, you'll want to choose Pass-through, then Next.

    WAP-4.png

    Name the application according to the URL. For our guide, this will be myweb.example.com. Specify the external and internal URLs for the website - the recommendation here is that they match. This is where that assumption about split-horizon DNS is really important - the name in the backend server URL must resolve internally to the right server.

    For the certificate, select your ADFS certificate for now. We'll replace that with our scheduled script (below).

    WAP-5.png

    If you're going to publish a stack of applications, copy the PowerShell snippet for reuse. Click Publish.

    WAP-6.png

    Close the next window once it's complete.

    WAP-7.png

    Repeat this process for myweb2.example.com (with appropriate changes, naturally).

    Automating Certificate Updates

    Time for some PowerShell scripting. We're going to add a script to the Certificate Management server that:
    • Finds all the certificates on the Central SSL Store
    • Copies them to the Reverse Proxies
    • Imports the certificates and keys to the LocalMachine store
    • Reconfigures the web application to use the correct certificate
    The script is below. You'll need to change the variables defined at the top of the script, but otherwise it should "just work". Post in the discussion thread for this guide if it doesn't; include any error messages or output.

    Code:
    ## LetsEncrypt Integration for WAP
    ##
    ## David Rawling, 2016
    ## V-1.0
    ##
    
    # The network location of the central SSL store - PFX files
    $CentralStore = "\\FSCluster\SSLStore"
    # The local path on each WAP to store certificates
    $TargetPath = "C:\Certificates"
    # The network path to the directory listed above
    $SharePath = "\C$\Certificates"
    # The plaintext password used for the PFX files
    $Password = "7wfRW2hajUMAtV04Lvb6ugxmYQXpBZHPkIEl5sN1ynzKeSJiCq93O8FGdTcorD"
    # An array of the reverse proxy server names (use @("SRV1","SRV2") etc for multiples)
    $TargetServers = @("REVPROXY")
    
    $PFXPassword = ConvertTo-SecureString -String $Password -AsPlainText -Force
    
    ForEach ($Target in $TargetServers) {
      New-Item -ItemType Container ("\\" + $Target + $SharePath) -ErrorAction SilentlyContinue
      Copy-Item $CentralStore\* ("\\" + $Target + $SharePath) -Recurse
    
      $TargetSession = New-PSSession -ComputerName $Target -Authentication Kerberos
    
      Invoke-Command -Session $TargetSession -ScriptBlock {
      param($TargetPath, $PFXPassword)
      $CertFiles = Get-ChildItem -Path $TargetPath -Filter '*.pfx'
      ForEach ($CertFile in $CertFiles) {
      $Certificate = (Import-PfxCertificate -FilePath $CertFile.FullName -Password $PFXPassword -CertStoreLocation Cert:\LocalMachine\My -Verbose)
      $Thumbprint = $Certificate.ThumbPrint
      ForEach ($DNSName in $Certificate.DnsNameList) {
      $Subject = $DNSName.Punycode
      Get-WebApplicationProxyApplication -Name $Subject -Verbose | Set-WebApplicationProxyApplication -ExternalCertificateThumbprint $Thumbprint -Verbose
      }
      }
      } -ArgumentList $TargetPath, $PFXPassword
    
      Remove-PSSession -Session $TargetSession
    }
    
    Run this on your Certificate Management server, as your Cert Management service account, with Administrative rights. When it's completed, assuming no errors, refresh and check the published applications on the reverse proxies - they should now use the correct certificates.

    Permit SSL traffic from the Internet to your reverse proxy servers and you should have working SSL.

    Summary

    In this guide we configured web servers, Web Application Proxy servers and a certificate management server to automatically obtain and install certificates from LetsEncrypt.
    chilipepperz likes this.

Recent Updates

  1. Language fixes and minor corrections

Recent Reviews

  1. Patrick
    Patrick
    5/5,
    Great article David.