Setting up a Secure Cascading WMS on MapServer
mapserver, security, wms
64bit, cURL, ssl
There a number of benefits to using a cascading WMS service ?” a WMS service that is read and then forwarded on through an intermediary WMS server:
you can cache the service (for example with TileCache) to greatly improve performance
your application need only worry about a single point of connection, using WMS layers aggregated from many different sources
you can add additional metadata missing from the source
services can be reprojected (using GDAL)
you can merge WMS layers together and server them out as a new map layer
There are also some negatives:
you have additional server configuration to set up and maintain
if you are not adding or changing the WMS service you should probably connect to the WMS service directly in the client applications, otherwise there will be a performance hit
caching may contravene the licensing agreement of the original WMS source
The rest of this post details the steps in setting up a cascading WMS using MapServer. You need MapServer 5.4.1 or higher to implement a secure cascaded WMS service. This example uses a 64-bit version of MapServer 5.6 taken from Tamas Szekeres’s autobuilds site installed in a C:\ms4w64 folder. It also assumes MapServer has been configured with SSL as detailed in another post. In this example I use IIS and Windows Server 2003.
Configuring a MapFile for a cascading WMS service is well-documented on the MapServer WMS Client page. An example is shown below. Note that this service is not reprojected, and the username and password can be passed through the metadata parameters.
LAYER ? NAME "MyLayer" ? TYPE RASTER ? STATUS OFF ? CONNECTION “https://webservices…” ? CONNECTIONTYPE WMS ? #DEBUG 5 #to debug the original layer ? METADATA ? "wms_srs" ? "EPSG:2157" ? "wms_name" ? "0" ? "wms_server_version"? "1.1.1" ? "wms_format" ? "image/png" ? "wms_auth_username" "username" ? "wms_auth_password" "password" ? "wms_bgcolor" "0xFFFFFF" ? END END
It is vital you set up debugging for the MapFile to see why a connection may be failing. You can set this by adding the following lines to the MapFile:
DEBUG 5 #debugging level between 1 and 5, 5 is the most detailed CONFIG "MS_ERRORFILE" "C:/ms4w64/tmp/ms.log" #path to log file - ensure IIS can write to this file
This can be removed once everything is working correctly.
Configuring SSL and MapServer (Part 1)
A secure WMS service is one that uses an https:// address, and may require a username and password. Setting up MapServer to connect using SSL is by far the trickiest part of the configuration. First of all I had to compile my own libcurl.dll to include OpenSSL. Otherwise I got the following error in the log file:
msHTTPExecuteRequests(): HTTP request error. HTTP: request failed with curl error code 1 (Protocol https not supported or disabled in libcurl)
Once I had the new libcurl.dll I replaced the existing file in the C:\ms4w64\bin folder (always make a back-up of the original files first!) with my freshly compiled version. I used Process Monitor to? see if I was missing any other DLLs ?” I was. The libcurl.dll required some additional OpenSSL DLLs to connect to https addresses. These DLLs were:
These too I copied into my C:\mapserver\bin folder from the openssl-1.0.0a\out32dll folder created when compiling libcurl.dll. Next I got the following error:
*HTTP: request failed with curl error code 60 (SSL certificate problem, verify that the CA cert is OK. Details:
verify failed) for https://…*
Getting a Security Certificate
I needed to get a valid certificate from the web service and point MapServer to this file. I was able to get a certificate by typing in the service;s https:// url in FireFox, and then selecting Tools > Page Info > Security > View Certificate > Details > Export. You can also right-click on the padlock icon at the bottom of the page to access the same option.
When exporting I selected the “X 509 Certificate with chain (PEM)” option. I tried an export without the “chain” but this didn’t allow me to connect.
I’d recommend trying to connect to the site independently of MapServer, so any issues can be narrowed to certificate problems rather than the MapServer configuration. I ran these tests on my development machine ?” a 32bit Windows XP laptop, following these steps:
1. Install a standalone version of cURL from the cURL download page (I used libcurl-7.19.3-win32-ssl-msvc.zip).
2. Save your security certificate with the filename curl-ca-bundle.crt in the same folder as you unzipped the curl.exe file. Placing it in the same folder, with this name, will mean the certificate can be read by cURL.
In a DOS window navigate to the folder with the curl.exe file and run the following command to see if the certificate works with the site. Add in some valid WMS parameters.
If you need to pass in a username and password to the service use:
If you get the following error:
(60) SSL certificate problem, verify that the CA cert is OK. Details:error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
It means your certificate is invalid. You can try the command with a /k switch to ignore the security and check that there isn’t a connection problem rather than a security problem:
curl https://username:firstname.lastname@example.org/wms?VERSION=1.1.1&REQUEST=... /k
If all went well with the certificate you should get a DOS window filled with random characters:
This is good! It is an image file viewed as text and means you have successfully returned an image from the secure WMS server.
Configuring SSL and MapServer (Part 2)
Now all that remains is to set up the certificate on the MapServer. There are some instructions here and more here. I got a little confused thinking I could point to the certificate file using a CONFIG command in the MapFile to set the environment variable. This is not the case.
It must be set? using a Windows environment variable (although you can set it in Apache if you’re not using IIS). It took a while for me to figure this out, but due to the beauty of OpenSource if you get too stuck you can search the sourcecode itself to see how parameters are used. The relevant sourcecode can be found here.
I created a new Windows environment variable CURL_CA_BUNDLE to point to the .crt file as shown below:
And this time in the log ?” success!
pixel preserving mode. | [Wed Jul 07 16:04:55 2010].838000 HTTP: Starting to prepare HTTP requests. | [Wed Jul 07 16:04:55 2010].838000 Using CURL_CA_BUNDLE=C:\ms4w64\bin\curl-ca-bundle.crt
Poor Image Quality?
Sometimes the WMS images lack the quality of the originals when run through a cascaded service. This post attributes it to either reprojection or incompatible output formats. In my case it was the latter. As the forum post writer says ?” if you aren’t reprojecting or adding information then using a proxy rather than a cascading WMS would be far more efficient.
My original MapFile OUTPUTFORMAT had worked perfectly for all my local WMS services, but with the cascaded service the aerial photography was blotchy.
I changed the OUTPUTFORMAT to the following settings and the images were back to good resolution.