RDS 2012 Certificates. SSO. A website is trying to run a RemoteApp program.

The goal was to remove this dreaded end-user dialogue box:
A website is trying to run a RemoteApp program. Make sure that you trust the publisher before you connect to run the program.

Simple right? Wrong; especially when I came across many blogs attempting to address RDS certificate issues. This one post gets you 90% there but was not complete. Specifically, see the red section below.
Steps:

  1. Get a certificate (in my case, a GoDaddy wildcard cert)
  2. Assign the certificate to the RDS roles. Refer to this great post with screen shots.
  3. Extract the certificate thumbprint, remove the “Get-Childitem Cert:\LocalMachine\My” PowerShell command on your RDS server or follow the steps outlined on Morgan Simonsen’s blog. Make sure you properly format the thumbprint: no spaces, all caps.
  4. Create and assign a GPO for the following settings:
    1. Computer Configuration > Policies > Administrative Templates > Windows Components > Remote Desktop Services > Remote Desktop Connection Client > “Specify SHA1 thumbprints of certificates representing trusted .rdp publishers”.
      Under Options, paste the formatted thumbprint.
      Specify SHA1 thumbprints of certificates representing trusted .rdp publishers
    2. Computer Configuration > Policies > Administrative Templates > Windows Components > Remote Desktop Services > Remote Desktop Connection Client > “Allow .rdp files from valid publishers and user’s default .rdp settings”.
      Enable.
    3. Computer Configuration > Policies > Administrative Templates > System > Credentials Delegation > “Allow Delegating Default Credentials > “Allow Delegating Default Credentials”.
      Enable and add “TERMSRV/<insert your RDS gateway/server name>” (refer to the example text in the GPO editor).
      Allow Delegating Default Credentials 
    4. Yet after repeated gpupdate /force and a full reset of IE settings, the dialogue warning persisted. Then I stumbled across these two nuggets: here combined with 2nd post down here. The “Specify SHA1…” GPO was not adding the proper “PublisherBypassList” keys.
      The solution? Manually adding the “HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\PublisherBypassList” as a User Configuration GPO registry update.
      PublisherBypassList GPO
      Notice the key is the thumbprint above with an additional “00” placed at the end.
      PublisherBypassList regedit
      The easiest way to verify the key is to check the “Do not remind me….” on the RDS prompt. It will save the thumbprint for you in the proper format.
  5. For icing on the cake, enable single sign-on; see this excellent blog post or the official MSDN blog post“.

Enjoy. SSO RDS connections with no dialogue boxes or end-user warnings or prompts.

Publishing a legacy, 32-bit RemoteApp on Windows Server 2012 R2

In a separate upcoming post I will document our trials and security tribulations with Horizon Software and their Village Merchant Point of Sale system (i.e. cash registers with additional functionality).  Village Merchant is a SQL-based, 32-bit and, by the looks of the UI, a legacy Visual Basic app.

The two problems that I had to solve were:

  1. Installing legacy software on a shared-user Terminal/Remote App server.
  2. Running a RemoteApp executable from a remote (non-local) file share.

Solving Problem #1

To install, we had to go-back-in-time to something I had tried years ago and had forgotten.
“Use the CHANGE USER Command to Switch to Install Mode in Windows 2000 Terminal Services”.  Ironically, this commands lives on today.  Screenshots courtesy of this Microsoft blog page.

Switch Terminal Services to Install Mode

  1. Launch an elevated command prompt
  2. At the command prompt, type
    change user /install
  3. Press ENTER. The following message appears:
    User session is ready to install applications.
  4. Type exit, and then press ENTER.
  5. You are now in Change User Mode so go install programs or change settings that you want to propagate to all users.  Add or remove the programs that you want.

change user install terminal server

Switch Terminal Services to Execute Mode

  1. Again, launch an elevated command prompt
  2. At the command prompt, type
    change user /execute
  3. Press ENTER. The following message appears:
    User session is ready to execute applications.
  4. Type exit, and then press ENTER.
  5. You are now in Change User Mode so go install programs or change settings that you want to propagate to all users.  Add or remove the programs that you want.

That solved problem #1.  All users could manually launch the application.  And by “manually” I mean you had to launch the “MERCHANT.EXE” from the remote file share on the Horizon server from the full desktop UI.

Solving Problem #2

Again, the “MERCHANT.EXE” executable resides on another server and is accessed via SMB file share using the full UNC path.  E.g. \\<FQDN server name>\<shared name>\merchant.exe.

The problem is that in Windows Server 2012 R2, remote or non-local applications cannot be published by RemoteApps.  This challenge led me to this post at SpiceWorks on using a locally saved batch file to launch the remote executable.  Brilliant.

I created a local batch file (e.g. C:\<folder>\remoteapp.bat) all users could access and it contained one simple line:

@echo off
echo.
echo.
echo Launch Horizoning, please wait up to 10 seconds. . . .
echo.
echo.
PING -n 7 127.0.0.1 >nul
start "" "\\<FQDN server name>\<shared name>\merchant.exe" /MAX

The start command dates back to the OS/2 and 16-bit Windows days.  It launches an application from a command prompt; simple enough.  See here if you if you want to get fancy on window sizing, processor priority, etc.  The “ping” command resolved issues where Horizon would launch but not accept keyboard/mouse input.

When adding the remoteapp.bat batch file on the RemoteApp server, I also used the full UNC path; e.g. \\<RemoteApp server FQDN>\<folder>\remoteapp.bat (even though its a local batch file, if you ever add additional RemoteApp servers for your Collection, they will know where to locate the batch file).  Enjoy launching remote applications using RemoteApp.

Seafile HTTPS Install on Windows Server 2012 R2; Step-by-Step

A step-by-step tutorial on getting a functional Seafile Windows Server that does HTTP/HTTPS syncing (port 443 only) running on Windows Server 2012 R2 with IIS 8.5 and Seafile Windows Server 4.0.6.

I cannot provide screenshots for every step. I am only documenting what I did, what issues I encountered, and what was my final configuration.  These steps were based off of this post by Jeffrey Tay.

Step 1: Install Seafile Server for Windows. Specifically “Download and Setup Seafile Windows Server“.

Step 2: Install IIS. Courtesy to Jack Stromberg and this post which covers the install in brief. Make sure you can access the IIS default page at http://localhost/ to confirm IIS is running correctly.

Step 3: Install Application Request Routing (ARR) 3.0. Another post by Jack Stromberg covers the install. Download ARR 3.0 and follow steps 1-5 from Jack’s post under “Installing IIS Application Request Routing (ARR) 3”.

Step 4: (Optional) Generate and install your SSL certificate. I hesitate to make this optional, but please go get an SSL certificate. Self-signed certificates were problematic for me with Seafile and the hassle was not worth it.  A kudos to my hosting provider, EZPZ Hosting, who offers free, basic SSL certificates or Godaddy, or NameCheap, or Comodo; all work for a basic SSL certificate.

I’ll refer you to GoDaddy which has a simple write-up for generating the CSR Request and importing the certificate back into IIS. On the right side of the IIS Manager is where you launch the wizard to get the process started.

Step 3: Create your Seafile site. Create an empty directory for the “Physical path:” and select the “SSL certificate” that you created and imported in the prior step.  Note: the screenshot shows “Not selected”. This is where you select your imported certificate.

Step 5: Create a web.config file in the “Physical path:”. Note: other examples on the internet did not properly add the appendQueryString=”true” for both Seafile rules. The web.config first checks if HTTPS is being used, if not it redirects to HTTPS, then it checks to see if it is using the “seafhttp/” subdirectory and reverse proxies to http://127.0.0.1:8082, and lastly it reverse proxies everything else to http://127.0.0.1:8000.

Download the following web.config file (which has clean indenting) or, using Notepad, copy and paste the following into a new web.confg file (Warning: make sure Notepad did not append .txt upon saving):

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
 <location path="" overrideMode="Deny">
 </location>
 <system.webServer>
 <security>
 <requestFiltering allowDoubleEscaping="true" />
 </security>
 <rewrite>
 <rules>
 <clear />
 <rule name="Redirect to HTTPS" enabled="true" stopProcessing="true">
 <match url="(.*)" />
 <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
 <add input="{HTTPS}" pattern="^OFF$" />
 </conditions>
 <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
 </rule>
 <rule name="seafilehttp" stopProcessing="true">
 <match url="seafhttp/(.*)" />
 <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
 <action type="Rewrite" url="http://127.0.0.1:8082/{R:1}" appendQueryString="true" logRewrittenUrl="true" />
 </rule>
 <rule name="seafile" enabled="true" stopProcessing="true">
 <match url="(.*)" />
 <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
 <action type="Rewrite" url="http://localhost:8000/{R:1}" appendQueryString="true" logRewrittenUrl="true" />
 </rule>
 
 </rules>
 <outboundRules>
 <preConditions>
 <preCondition name="ResponseIsHtml1">
 <add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
 </preCondition>
 </preConditions>
 </outboundRules>
 </rewrite>
 <httpErrors errorMode="DetailedLocalOnly" />
 </system.webServer>
</configuration>

Step 6: Check “Enable Proxy” under AAR 3.0.  Refer to steps 1-6 courtesy of this article from Microsoft.

Step 7: Enable 2GB large uploads (30MB is the default) in IIS. Open an elevated/ Administrator command prompt and run:

c:\windows\system32\inetsrv\appcmd set config -section:requestFiltering -requestLimits.maxAllowedContentLength:2000000000

See Option 2 from this IPSWITCH knowledge base article.

Step 8: Make sure your Seafile config files are properly set.

In “seahub_settings.py” change and make sure you do not have a trailing “/” after seafhttp.

FILE_SERVER_ROOT = 'https://<your-domain-name>/seafhttp'

In “ccnet.conf” change the following and I have a trailing “/”

SERVICE_URL = https://<your-domain-name>

Step 7: Restart IIS, Seafile, and go test your new, secured, HTTP-sync-enabled Seafile server.

An easy way to test the IIS rewrite rules for seafhttp is trying the following two URLs; adding or removing the trailing “/”. I came across these debugging URLs from a Seafile support forum thread. It identified an error in my web.config that I posted above that was missing the trailing “seafhttp/”.

http://<your-domain-name>/seafhttp

should return “Sorry, but the requested page could not be found.” with the typical Seafile login UI header and footer.

http://<your-domain-name>/seafhttp/protocol-version

should return {“version”: 1} as text-only with no images.

Before trying HTTPS, make sure you can get HTTP working.  Once trying HTTPS, make sure your 2102R2 machine has the correct time.  It must be accurate for HTTPS.  Use NTP.

Here are a few supporting URLs that may be helpful in debugging HTTPS syncing:
Can’t download any file over mobile device
Seafile Protocol: Are ports 8082, 10001 and 12001 safe and/or necessary?
upgraded to new client (4.2.0) bad response 404 for protocol version
Problems using Seahub on non-root domain
Client always tries /seafhttp/protocol-version
Lighttpd rewrite issue (v1.4)