-
Notifications
You must be signed in to change notification settings - Fork 3
MapServer 8.0 Config File
Author: Steve Lime
Contact: [email protected]
Status: In progress
Last update: 2021-03-31
Version: MapServer 8.0
Securing the MapServer CGI application requires setting environment variables at the web server level. While not particularly difficult it does require access to web server configuration files and the approach can vary greatly from platform to platform. In addition there are opportunities to improve overall MapServer security at the mapfile level by allowing a site administrator to set restrictions at a site level. For example:
- a registry of plugins can be defined centrally to limit what can be specified within a mapfile
- all mapfiles could be defined as immutable - so no runtime changes would be allowed site-wide
- validation patterns for common attributes - for consistency
While much of this could be done via environment variables it becomes cumbersome and error prone.
We propose introducing a mapserver config file (basically an ini file) that is loaded by the MapServer CGI at runtime and provides site-level configuration apart from what is done with a mapfile.
At present, a single environment variable (MS_CONFIG_FILE) is referenced to determine what config file to load. While it's somewhat ironic to propose using an environment variable to specify a configuration file that avoids setting environment variables - in this instance the approach allows different deployments on the same server to operate under different configs. It should be possible to set the config file via other mechanisms (e.g. at compile time) but that needs to be further investigated.
The config file would look similar to a mapfile with familiar SECTION ... END constructs. In fact, we can use the existing lexer to process the file without incurring the overhead of adding another parser or dependencies on other libraries. The configObj stucture is basically just a series of hashes (hashObj) used to group similar configuration elements. Currently it consists of:
- ENV: references to the various environment variables currently supports (e.g. MS_MAP_NO_PATH)
- MAPS: a curated list of mapfiles available identified by a key. If MS_MAP_NO_PATH is set then only those keys can be used with the CGI map parameter. This is currently supported via environment variables.
- PLUGINS: a curated list of plugins list of plugins identified by a key. This is new functionality.
Other sections could include METADATA and VALIDATION - places general purpose configuration information is held.
The current proof of concept implementation requires the config file. Upon successful loading of both the config and the map files the configObj is added to the mapObj as a read-only member so that it can be referenced as necessary. Destroying the mapObj does not destroy the configObj, that is done separately.
One challenge is that not all bits of MapServer code that reference environment variables (e.g. msFontCacheSetup() in fontcache.c) have access to the mapObj. One easy solution would be to push all key/value pairs defined in the ENV section into the environment using putenv() so that no changes would be needed elsewhere.
#
# Example Config File
#
CONFIG
ENV
# Available variables (https://mapserver.org/environment_variables.html):
# MS_MAP_PATTERN - regex used to validate map variable values
# MS_MAPFILE - default mapfile if no value is passed in the map variable
# MS_MAP_NO_PATH - limits access to a curated set of maps (by key)
MS_MAP_NO_PATH "true"
END
MAPS
MAP1 "/opt/mapserver/myapp/map1.map"
MAP2 "/opt/mapserver/myapp/map2.map"
END
END
This is primarily a resource to support the configuration of the MapServer CGI application. However...
- mapserver-config.cpp/mapserver-config.h: core implementation, defines loading function and helper functions (e.g. msConfigGetEnv()) that preserve backward-compatibility (check environment and then the config).
- mapserv.c: load config file, abort if not found.
- mapserver.h: add config member to mapObj struct.
- mapfile.c: initialize config member of mapObj struct to NULL.
- mapservutil.c: msCGILoadMap() uses msConfigGetEnv() instead of getenv(); adds configObj reference to mapObj.
- CMakeLists.txt: typical integration of new source files.
TBD
This depends largely on whether a config file is required or not. If required then this obvious represents a departure from previous versions of MapServer. This will need to be the case if we really want to improve configuration separation for certain parts of the mapfile, for example plugins.
The regression test suite would need its own config file added.
The intention is to improve overall security and ease of configuration. Config files would need to stored in trusted locations with access limited to appropriate individuals.
The config file will have to be read and processed incurring a bit of overhead. Although given the I/O associated with a typical MapServer request we would expect the impact to be relatively small.