Custom plugin (jCasbin) for Geoserver

Hi there,

I am currently tasked with the integrating jCasbin(GitHub - casbin/jcasbin: An authorization library that supports access control models like ACL, RBAC, ABAC in Java) into Geoserver in order to use it for user authorization based on a central Casbin config file. The basic concept is to intercept incoming requests and validate against a given configuration. I followed the guide to implement an OWS service(Implementing a simple OWS service — GeoServer 2.27.x Developer Manual) and also looked at the “gs-kml” extension. My custom plugin compiles successfully but it is not recognized by Geoserver(v2.26.1)

My pom.xml looks like:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

  <modelVersion>4.0.0</modelVersion>

  <!-- set parent pom to community pom -->
  <parent>
    <groupId>org.geoserver</groupId>
    <artifactId>community</artifactId>
    <version>2.26.1</version>
    <!-- change this to the proper GeoServer version -->
  </parent>

  <groupId>org.geoserver</groupId>
  <artifactId>CasbinInterceptorForGeoserver</artifactId>
  <version>1.0</version>
  <packaging>jar</packaging>
  <name>Casbin Interceptor</name>

  <properties>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
  </properties>

  <!-- declare dependency on geoserver main -->
  <dependencies>
    <dependency>
      <groupId>org.geoserver</groupId>
      <artifactId>gs-main</artifactId>
      <version>2.26.1</version>
      <!-- change this to the proper GeoServer version -->
    </dependency>
    <dependency>
      <groupId>org.geoserver</groupId>
      <artifactId>gs-wms</artifactId>
      <version>2.26.1</version>
    </dependency>
    <dependency>
      <groupId>org.casbin</groupId>
      <artifactId>jcasbin</artifactId>
      <version>1.79.0</version>
    </dependency>
  </dependencies>

  <repositories>
    <repository>
      <snapshots>
        <enabled>true</enabled>
      </snapshots>
      <id>osgeo</id>
      <name>Osgeo Maven Repository</name>
      <url>https://repo.osgeo.org/repository/Geoserver-releases/</url>
    </repository>
  </repositories>
  <build>
    <resources>
      <resource>
        <directory>src/main/resources</directory>
        <includes>
          <include>**/*</include>
        </includes>
      </resource>
    </resources>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <source>21</source>
          <target>21</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

and my applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!-- 
 Copyright (c) 2013 OpenPlans - www.openplans.org. All rights reserved.
 This code is licensed under the GPL 2.0 license, available at the root
 application directory.
 -->
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="casbinWmsInterceptor"
        class="fresist.geoserver.casbin.CasbinWmsInterceptor">
        <constructor-arg ref="wms"/>
        <constructor-arg ref="webMapService"/>
    </bean>

    <!-- This creates a Service descriptor, which allows the org.geoserver.ows.Dispatcher
        to locate it. -->
    <bean id="casbinWmsInterceptorService-1.0.0" class="org.geoserver.platform.Service">
        <constructor-arg ref="wms"/>
        <constructor-arg ref="webMapService"/>        
    </bean>

</beans>

Any hints what might be still wrong are greatly appreciated :slight_smile:

Kind regards
Dominik

For a plugin to be found, it must contain a Spring Application context file, and declare in it one of the beans that are looked up as extension point by GeoServer. You refer to one in the mail, but I don’t see it in the repository?
The file must have the right name (applicationContext.xml) and be placed in the root of the jar file.

For example, in the KML module, this is the file:

and the extension point beans are the various “*OutputFormat” ones.

Mind, for a plugin that is trying to perform authorization, I would recommend against doing a service-by-service callback, it might get very tedious, and implement instead the extension point dedicated to authorization, called ResouceAccessManager.

You can referer to GeofenceAccessManager as an example implemntation that takes into consideration the data being requested, the current service being used, the user, and IP address and possibly more, to decide whether to allow access or not.

The callback is still useful for services that do not need to access local data to do their job, like WPS.

Cheers
Andrea

1 Like