Skip to content

GSIP 218

Jody Garnett edited this page Jul 24, 2023 · 12 revisions

GSIP 218 - Control remote HTTP requests sent by GeoTools \ GeoServer

Overview

This is a refresh of the archived GSIP-218, introducing an SPI interface to evaluate whether selected GeoTools/GeoServer classes should be allowed access to a certain remote address.

GSIP-189 came with pull requests for GeoTools and GeoServer, that did not manage to get merged, and eventually bit-rot:

This GSIP is based on the same architecture, but updated for the current code base, and with a smaller initial scope.

Proposed By

Andrea Aime

Assigned to Release

This proposal is for GeoServer 2.24, to be backported on 2.23 and 2.22.

State

  • Under Discussion
  • In Progress
  • Completed
  • Rejected
  • Deferred

Motivation

There is several situations were GeoServer \ GeoTools will perform HTTP requests against a remote site, e.g. when parsing a XLM document or a WPS proceed doing an arbitrary HTTP GET or POST request.

We need to be able to allowlist the remote sites against which GeoTools \ GeoServer will perform HTTP requests. Roughly described this will require:

Create wrapper for the HTTP client that will take into account the sites allowlist, what already exists in GeoTools should be taken into account. Create new security menu to white list sites on GeoServer UI, this will require a mockup. Make the wrapper being used by the code that will issue the HTTP requests

Some example scenarios that have drawn attention to this new SPI interface

  1. WPS extension server-side requests.
  2. WMS GetMap SLD parameter handling.
  3. General XML processing (access to remote schemas)

Proposal

Low-level GeoTools changes

The proposal works around a new SPI interface, URLChecker, that can be used to check the validity of a path/URI/URL (hence the usage of a String):

public interface URLChecker {

    /** @return URLChecker name that best describes its purpose (e.g GML Schema evaluator etc) */
    String getName();

    /** @return Boolean flag indicating if this URLChecker should be used */
    boolean isEnabled();

     /**
      * Used to confirm location is allowed for use. 
      *
      * URLChecker is used to confirm if a location is allowed for use, returning {@true} when they recognize a location as permitted.
      * Several URLChecker instances are expected to be available, the location will be allowed if at least one URLChecker can confirm it is permitted for use.
      * 
      * @param location Location expressed as URL, URI or path.
      * @return {@code true} indicates the URLChecker can confirm the location is allowed for use, {@code false} indicates the URLChecker is unable to confirm.
      */
    boolean confirm(String location);
}

Checkers can be specialized on a specific type of URL/purpose, and will return false if they do not recognize the location, or they want to refuse access to it. At least one checker needs to provide a positive vote for the validation to pass.

The reason to use a String rather than a URL is that in some code paths the nature of the source is not entirely known (e.g. ImageIO can open "Object" sources, the code will check if they are URL/URI/String) and in some cases a location might not make for a valid URL (e.g., s3://myBucket/myEntry).

Lookup and application of checkers will be delegated to a URLCheckers class (reminiscent of Processors).

The actual call to it will follow different patterns based on the current context:

  • If the call site happens to use a GeoTools HttpClient, a SecureHTTPClient will be used for it, which checks the URLs for every HTTP method call
  • If the call site uses URL directly, or passes a String to an underlying library that actually performs the call, URLCheckers will be invoked directly before opening the source location.

GeoServer configuration

GeoServer will ship with one implementation of a URLChecker using a list of regular expressions, each one matching a group of hosts/URLs that GeoServer is allowed to connect to.

The configuration is going to be a new top level page in the Security section, here is a mockup:

image

Storage will be in a new $GEOSERVER_DATA_DIR/security/validLocations.xml, DAO will be using the usual suspects (Resource, XStream).

Initial implementation

The initial implementation will cover a few prominent functionalities that is receiving user-provided remote locations:

  • WMS remote SLD, where a GET request is executed against a user-provided URL.
  • WMS feature portrayal, where WMS can connect to a remote WFS server, whose location is provided as part of the GetMap request.
  • WPS remote inputs, which allow for both remote POST and GET requests to be executed.

Remote icon access, service cascading and XML parsing may not be covered by the initial implementation, but may come later as development resources are found, but will be based on the same framework.

Backwards Compatibility

The URL-checking functionality is going to be enabled by default on the main branch, which might cause installations using dynamic SLD or remote WPS sources to initially stop working, until the desired target hosts are included in the white list. Logs will clearly indicate actions to be taken in order to enable the logs, while error messages will be less releaving (as they will be read by all users, not just admins). For backports to stable/main, the system might be be disabled by default.

Another possibility is to disable by default, but have a visible warning for admins, similar to the existing ones about root user, default admin password, and weak encryption.

Feedback

RegEx makes an important feature "expert only", please consider making "prefix" the default approach with a prompt default of "http://localhost:8080/geoserver/ows?" to communicate intended use clearly. RegEx can still be available as a "expert" option.

Voting

Project Steering Committee:

  • Alessio Fabiani: +0
  • Andrea Aime: +1
  • Ian Turton:
  • Jody Garnett: +1
  • Jukka Rahkonen: +0
  • Kevin Smith: +0
  • Simone Giannecchini: +0
  • Torben Barsballe: +1
  • Nuno Oliveira: +1

Links

Clone this wiki locally