Mapserver can be used in a cascading manner to call to other services, potentially combining them and maybe re-projecting before serving out again.
Reasons for this might include:
- Re-projecting the map
- Accessing a secured WMS/WFS and then protecting it a different way
- Serving a WMS / WFS map out in a different way
This is all relatively simple using standard mapserver .MAP file if the WMS / WFS services you are calling to are unsecured. Then its simply a case of a layer like:
LAYER
NAME "MyLayer"
DEBUG 5
TYPE RASTER
STATUS ON
CONNECTION http://somedomain.com/WMSServer
CONNECTIONTYPE WMS
METADATA
"wms_title" "OSI"
"wms_srs" "EPSG:27700 EPSG:4326 EPSG:54004 EPSG:3978 EPSG:3857 EPSG:900913"
"wms_name" "1,2,3,4,5,6,7,8,9"
"wms_server_version" "1.1.1"
"wms_format" "image/png"
"wms_enable_request" "*"
END
PROJECTION
"init=epsg:900913"
END
END
However if the service you are calling is secured it gets a whole load more complicated. You might (as I did initially) think that all you have to do is change the map file to include the authorisation details such as
LAYER
NAME "MySecuredLayer"
DEBUG 5
TYPE RASTER
STATUS ON
CONNECTION https://somedomain.com/WMSServer
CONNECTIONTYPE WMS
METADATA
"wms_title" "OSI"
"wms_srs" "EPSG:27700 EPSG:4326 EPSG:54004 EPSG:3978 EPSG:3857 EPSG:900913"
"wms_name" "1,2,3,4,5,6,7,8,9"
"wms_server_version" "1.1.1"
"wms_format" "image/jpeg"
"wms_auth_username" "myUserName"
"wms_auth_password" "myPassword"
"wms_auth_type" "basic"
"wms_enable_request" "*"
END
PROJECTION
"init=epsg:900913"
END
END
Unfortunately that in itself doesn’t work (though the map file itself is correct). You are very strongly recommended to make sure you have DEBUG setup – at least while testing. So in addition to specifying the DEBUG level in the layer – you also need to include in the overall header of the MAP file a path to the log file
CONFIG "MS_ERRORFILE" "C:\\Mapserver\\ms_log.txt"
DEBUG 5
Running the above map file will create errors in the log file:
HTTP: request failed with curl error code 60 (SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed) for https://somedomain.com/WMSServer…
(If you get an error:
msHTTPExecuteRequests(): HTTP request error. HTTP: request failed with curl error code 1 (Protocol https not supported or disabled in libcurl)
Then you have a version of mapserver that is not compiled with the correct support and you need to change your version of mapserver (see below))
Basically the secure WMS call uses cURL libraries to do the call – and you have to register the certificate from the service you are calling.
What you need to do:
Make sure your version of mapserver supports https
Make sure you have a version of mapserver that supports https calls. Tamas builds (http://www.gisinternals.com/sdk/) seem to include the required libraries. I used release-1500-gdal-1-10-0-mapserver-6-2-1.zip though I’m sure other versions would work as well
Get the security certificate
Use OpenSSL (whcih is included in the mapserver distribution in bin\curl)
openssl s_client –connect somedomain:443 > c:\Temp\cert.txt
If all goes well – the cert.txt file will look something like this – and you need the bits from -----BEGIN CERTIFICATE----- to -----END CERTIFICATE-----
CONNECTED(00000190)
---
Certificate chain
0 s:/OU=Domain Control Validated/OU=COMODO SSL Wildcard/CN=*.osi.ie
i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO SSL CA
1 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO SSL CA
i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIE5DCCA8ygAwIBAgIQOhI8AlhJBZcVfKqx4ruAnzANBgkqhkiG9w0BAQUFADBw
.
9WspBdI6j1t8l+ZZGe1PXBIBaHlpXuazvlC5FpU93bKt7zaEJ1iU5XjIwB/H4ys1
Hsch6g7YXnw=
-----END CERTIFICATE-----
subject=/OU=Domain Control Validated/OU=COMODO SSL Wildcard/CN=*.osi.ie
issuer=/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO SSL CA
---
No client certificate CA names sent
---
SSL handshake has read 2675 bytes and written 536 bytes
---
New, TLSv1/SSLv3, Cipher is AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : AES256-SHA
Session-ID: 5F65EE6F4E78B564620101A5A706E7A259375B2277F430BC4578395780D14458
Session-ID-ctx:
Master-Key: 1C992E7CC5DFE1AF7B2D87295954D6A73A740E71BD81A2DB68546E61C055D0089FF1C91FB761F64CFE1BBD20B8411AE3
Key-Arg : None
PSK identity: None
PSK identity hint: None
Start Time: 1391380021
Timeout : 300 (sec)
Verify return code: 20 (unable to get local issuer certificate)
---
Add the security certificate to your local store
I copied the default file from bin\curl\curl-ca-bundle.crt into the main mapserver cgi-bin (or scripts) folder
Edit the curl-ca-bundle.crt file and add in your certificate (the bits from -----BEGIN CERTIFICATE----- to -----END CERTIFICATE-----)
Test your certificate
Check Curl.exe is in the same folder as your curl-ca-bundle.crt
1) I tested first with a call to getCapabilities:
curl -u MyUsername:MyPassword https://SomeDomain.com:443/WMSServer?REQUEST=GetCapabilities%26SERVICE=WMS
(Note I had to swap & for %26 0 i.e. url encode)
If this has worked you should see a normal getCapabilities text response
2) I then tested with an image call:
curl -u MyUsername:MyPassword https://SomeDomain.com:443/WMSServer?LAYERS=1%26REQUEST=GetMap%26SERVICE=WMS ……
If this works you should see a load of extended characters returned (i.e. an image displayed in the command window!)
Set a windows environment variable to point at the certificate store file
Previous tests have simply used the file in the same folder as the curl.exe, but when running for real mapserver must know where to find the certificate file.
Set the CURL_CA_BUNDLE environment variable to point at the certificate file
e.g. C:\Mapserver\cgi-bin\curl-ca-bundle.crt
Then you need to reboot the server to make sure the new environment setting is correctly used
Then test your map file
Now – at last – the map file which you thought should work originally should actually work and return you an image.
LAYER
NAME "MySecuredLayer"
DEBUG 5
TYPE RASTER
STATUS ON
CONNECTION https://somedomain.com/WMSServer
CONNECTIONTYPE WMS
METADATA
"wms_title" "OSI"
"wms_srs" "EPSG:27700 EPSG:4326 EPSG:54004 EPSG:3978 EPSG:3857 EPSG:900913"
"wms_name" "1,2,3,4,5,6,7,8,9"
"wms_server_version" "1.1.1"
"wms_format" "image/jpeg"
"wms_auth_username" "myUserName"
"wms_auth_password" "myPassword"
"wms_auth_type" "basic"
"wms_enable_request" "*"
END
PROJECTION
"init=epsg:900913"
END
END
If you look in the log file you should see:
Using CURL_CA_BUNDLE=C:\Mapserver\cgi-bin\curl-ca-bundle.crt
If not – check your environment variable setting
Other references
The above was put together from a variety of sources – including those below– useful additional refs include:
http://geographika.co.uk/setting-up-a-secure-cascading-wms-on-mapserver
http://www.mapserver.org/ogc/wxs_secure.html
http://trac.osgeo.org/mapserver/ticket/3070