Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
GSIP 19 - Per layer security
Allowing per layer security to complete the security offering started with service layer security Motivation Proposal Backwards Compatability Feedback Voting Links
Assigned to Release
This proposal will be implemented by 1.7.0-rc1 release
Under Discussion, In Progress, Completed, Rejected, Deferred
At the moment GeoServer only sports OGC service and service method security, many real world use cases need more granular control based on the data contents, and thus a layer based security. This proposal handles layer wide security only, per feature or per attribute security is out of the scope.
Proposal, user view
This project is to enhance the security subsystem in GeoServer to allow namespace-based and layer-based authorization for read/write access. The description of this work uses the term ‘layer’ to refer to either a GeoServer feature type or coverage.
Access permissions will be configurable by entries in a the GEOSERVERDATADIR/security/layers.properties property file, following the syntax already available for service level security:
- namespace indicates the name of the namespace. The wildcard * is used to indicate all namespaces (i.e. global scope).
- layer is the name of a feature type or coverage. The wildcard * is used to indicate all layers in the namespace.
- permission indicates the type of access permission *** ‘r’ - indicates read access permission *** ‘w’ - indicates write access permission
- ROLE#_ are the names of roles (defined in the user.properties file). The wildcard * is used to indicate the permission is applied to all users, including anonymous users.
- Each entry must have a unique combination of namespace, layer, and permission values.
- If a permission at the global level is not specified, global
permissions are assumed to allow read/write access, i.e.
**.**.r=\* and/or **.**.w=**** If a permission for a namespace is not specified, it inherits permissions from the global specification.
- If a permission for a layer is not specified, it inherits permissions from it’s namespace specification.
- If a user belongs to multiple roles, the least restrictive permission they inherit will apply.
Once security is in place:
- the web administration tool, as well as all the demos, will only display namespaces and layers that the current user is allowed to see;
- all the OGC services will handle out only the layers the user can see, if the current user does not have write permission, all attempts at writing will fail
To ease up implementation, GeoServer will behave as if the unauthorized layers are unavailable or physically read only. This also allows for better security (throwing an exception about the layer not being accessible discloses the layer is there). Any attempt to access a secured layer with not enough rights will be logged for administrators to evaluate security threats and for debugging purposes.
Example configuration protecting a single namespace and a single layer
The following entries demonstrate configuring GeoServer so that it is primarily a read-only server.
**.**.r=\* **.**.w=NO*ONE private.**.r=TRUSTED*ROLE private.\*.w=TRUSTED*ROLE topp.congress*district.w=STATE*LEGISLATORS
in this scenario here is the map of roles to permissions: | | private.* || topp.* || topp.congressdistrict || (all other namespaces) || | NOONE |(no access)_ | w | _ | w | | TRUSTEDROLE | r/w | r | r | r | | STATELEGISLATURES |*(no access)_ | r | r/w | r | | (all other users) | _(no access)_ | r | r | r |
Example configuration for locking down GeoServer
The following entries demonstrate configuring GeoServer so that it is locked down.
**.**.r=TRUSTED*ROLE **.**.w=TRUSTED*ROLE topp.**.r=** army.**.r=MILITAR*ROLE,TRUSTED*ROLE army.**.w=MILITAR*ROLE,TRUSTED*ROLE
in this scenario here is the map of roles to permissions: || || topp.* || army.* || (all other namespaces) || | TRUSTEDROLE | r/w | r/w | r/w | | MILITARROLE | r | r/w | _ | | | r |(no access)_ | _(no access)_ |
Example Configuration for something more complex
The following entries demonstrate configuring GeoServer with global~~, namepace~~, and layer-level permissions.
**.**.r=TRUSTED*ROLE **.**.w=NO*ONE topp.**.r=** topp.states.r=USA*CITIZEN*ROLE,LAND*MANAGER*ROLE,TRUSTED*ROLE topp.states.w=NO*ONE topp.poly*landmarks.w=LAND*MANAGER*ROLE topp.militar*bases.r=MILITAR*ROLE topp.militar*bases.w=MILITAR*ROLE
in this scenario here is the map of roles to permissions: || || topp.states || topp.polylandmarks || topp.militarbases || topp. || || | NO*ONE | w | r | _ | w | w | | TRUSTEDROLE | r | r | _ | r | r | | MILITARROLE | _ |r_ | r/w | r | _ | | USACITIZENROLE | r |r_ | _ | r |(no access)_ | | LANDMANAGERROLE | r | r/w | _ | r |(no access)_ | | (all other users) | *_ |*r_ | _ | r |(no access)_ |
Note: The topp.states.w=NO*ONE is not needed, because this permission would be inherited from the global level, i.e.
*.*.w=NO*ONE ``` ### Example of an Invalid Configuration File The following set of entries would not be valid because the namespace, layer, permission combinations of the entries are not unique.
Proposal, implementation ------------------------ The current security integration uses an Acegi based filter to perform authentication, Acegi then puts the result of the authentication in a ThreadLocal variable that can be accessed using `SecurityContextHolder.getContext ().getAuthentication ()`. This is already leveraged by the dispatcher, that performs the necessary service level checks. The idea is to replicate the same checks at the catalog level, by introducing a security wrapper as depicted in the following diagram: ![image](implementation.gif) The catalog wrapper would forward all calls to the actual catalog, and then filter out the results comparing them with the actual access level of the current user, in particular: * by removing all layers that the user is not authorized to see * by wrapping FeatureTypeInfo if the user is not authorized to write them (coverages are at the moment read only, so this does not apply) This leaves most of the GeoServer code completely security unaware, making development and maintenance easier compared to a solution that would move the security checks onto the services themselves. The catch is, in order to wrap the catalog, it must be split into an interface and an implementation. This is possible, and it’s going to be introduced along with the new configuration proposal, so this one will be implemented as soon as the new configuration proposal lands on trunk Relationship with service layer security ---------------------------------------- GeoServer 1.6.0+ sports service level security as described in the [user guide](http://geoserver.org/display/GEOSDOC/2.5) Security subsystem . The data level security builds on top of it, reusing user and role definitions found in `$GEOSERVER*DATA*DIR/security/users.properties`. Each request will be subject to both security checks, according to the following workflow: * the user gets authenticated using Acegi integration (at the moment, either form or HTTP basic authentication) * the service level security gets checked by the dispatcher, if access is denied, the request ends * the service will attempt to access the catalog, each of those attempts will be subjected to data level security restrictions So, to sum up, in order to successfully execute an OGC service call the user will have to be allowed to execute the requested service method and to access the data specified in the request. Feedback -------- This section should contain feedback provided by PSC members who may have a problem with the proposal. Backwards Compatibility ----------------------- The proposal has not backwards compatibility issues, the default layers.properties file will be empty, meaning all layers can be accessed by everyone. Voting ------ Andrea Aime: +1 Alessio Fabiani: +1 Justin Deoliveira: +1 Jody Garnett: +1 Saul Farber: Rob Atkinson: Links ----- [JIRA Task](http://jira.codehaus.org/browse/GEOS-1969)