[Geoserver-devel] LayerGroups not in capabilities for non admin or unauthenticated users

Dear list,

I have a problem with geoserver and catalog mode HIDE (my prefered mode):
"Hides layers that the user does not have read access to, and behaves as
if a layer is read only if the user does not have write permissions.
The capabilities documents will not contain the layers the current user
cannot access."
(see
https://docs.geoserver.org/stable/en/user/security/layer.html#security-layer)

My situation is the following:

I have a workspace named "fbk" with read access for all (also
unauthenticated) users (fbk.*.r *),
with write access for users with ROLE_FBK_RW (fbk.*.w ROLE_FBK_RW) and
admin access fbk.*.a ROLE_FBK_ADMIN.
The workspace is isolated and not the standard workspace.
The service access for wms ist not restricted (wms.* *).

In this workspace I have 3 group layers each with 9 layers (total 27
layers).
If I connect from QGIS to geoserver
(http://localhost:8080/geoserver/fbk/wms)
- I get the 27 layers but no group layers if I am unauthenticated or
authenticated but not ADMIN
- I get the 3 group layers (and contained layers) if I am authenticated
as ADMIN

I think, this is not the expected behaviour and posted an issue:
Group Layer in Catalag Mode Hide not in capabilities when unauthenticated
see https://osgeo-org.atlassian.net/browse/GEOS-10032

I looked into the methods that get called on getCapabilities request.

org.geoserver.wms.capabilities.Capabilities_1_3_0_Transformer uses
handleLayers() (line 677) to create the lists of LayerInfo and
LayerGroupInfo objects for the capabilities document.
The filter value there is [Filter.INCLUDE AND [ workspace.name = fbk ]],
so layers from workspace fbk.

Then comes org.geoserver.security.SecureCatalogImpl [line: 1465] -
list(Class<T>, Filter, Integer, Integer, SortBy) into play.
Class<T> is one of my 3 LayerGroupInfo.

Here a securityFilter is created und passed to delegate.list() (line
1468): CloseableIterator<T> filtered = delegate.list(of, securityFilter,
offset, count, sortBy);
The result (filtered) is an array with my 3 LayerGroupInfoImpl if ADMIN,
or an empty array if unauthenticated or authenticated but not ADMIN.

securityFilter (line 1549 ff)
private <T extends CatalogInfo> Filter securityFilter(
final Class<T> infoType, final Filter filter) {

    final Authentication user = user\(\);
    if \(isAdmin\(user\)\) \{
        // no need to check for credentials if user is \_the\_

administrator
return filter;
}

    if \(MapInfo\.class\.isAssignableFrom\(infoType\)\) \{
        // these kind of objects are not secured
        return filter;
    \}

    Filter securityFilter =

this.accessManager.getSecurityFilter(user, infoType);

    // create a filter combined with the security credentials check
    return Predicates\.and\(filter, securityFilter\);
\}

"if (isAdmin(user)) { return filter" partially explains the behaviour,
that ADMIN sees the Layergroups.

this.accessManager.getSecurityFilter(user, infoType) uses
CatalogFilterAccessManager.getSecurityFilter(Authentication, Class<?
extends CatalogInfo>) (line 172)
There we can find on line 178:
convertedFilters.add(delegate.getSecurityFilter(user, clazz)); //
Delegate's filter
org.geoserver.security.impl.DefaultResourceAccessManager.getSecurityFilter
adds the filter [ resource.store.workspace.name = fbk ]

With this filter the list auf LayerGroupInfo gets empty and so no
Layergroups are in capabilities.
Maybe this filter [ resource.store.workspace.name = fbk ] is not
suitable for LayerGroupInfo (but LayerInfo)
In my understandig Layergroups have no store on there own.

If I comment out CatalogFilterAccessManager:178
(convertedFilters.add(delegate.getSecurityFilter(user, clazz)); ) I have
the expected behaviour.
Sure there are better solutions than just commentig it out.

Could anyone confirm this assessment?

Many thanks

Stefan

--
Dipl. Ing. Stefan Overkamp
overkamp@anonymised.com