-
Notifications
You must be signed in to change notification settings - Fork 751
Authorization framework internals
Each plugin must implement the IAuthorizationPlugin
interface which contains four methods:
-
void load ( void );
This method is called whenever the framework loads the plugin into memory
- watchdog service enabled and change was made (forced reload)
- deploy of the webapp
- configuration change (change of the plugin directory, ...)
-
void unload ( void );
This method is called whenever the framework destroys the plugin
- watchdog service enabled and change was made (forced reload) (the order is first unload the old instance then load the new one)
- undeploy of the webapp
-
boolean isAllowed(HttpServletRequest request, Project project);
This method gives a decision if the project should be allowed for the current request.
-
boolean isAllowed(HttpServletRequest request, Group group);
This analogically gives the same decision for the group.
Example plugin TruePlugin.java is included in the plugins
directory in the root of the Git repository.
All those methods are also described in the code.
Each is expected to implement some sort of a cache for the decisions when the underlying read operations for the user rights is expensive.
HttpServletRequest
object is the current request with all of its features
like: session, attributes, getUser()
, getPrincipal()
If you decide that your plugin uses some sort of sessions then you might want to reload the session as well when the authorization framework reloads your plugin. The framework tracks a number of reloads which is available for you as RuntimeEnvironment.getInstance().getPluginVersion() and you can check this number and invalidate your session if your version (tracked perhaps in your session) is different than this.
Custom classloader restricts the plugin to load only this classes from org.opengrok.indexer
package:
private final static String[] classWhitelist = new String[]{
"org.opengrok.indexer.configuration.Group",
"org.opengrok.indexer.configuration.Project",
"org.opengrok.indexer.configuration.RuntimeEnvironment",
"org.opengrok.indexer.authorization.IAuthorizationPlugin",
"org.opengrok.indexer.util.*",
"org.opengrok.indexer.logger.*",
};
And explicitly forbids these packages to be extended.
private final static String[] packageBlacklist = new String[]{
"java",
"javax",
"org.w3c",
"org.xml",
"org.omg",
"sun"
};
Also JVM can forbid you to extend some packages which are not meant to be extended.
The plugin class must be compiled to the .class file (and the it can be packaged into .jar file). The frameworks supports both .class and .jar files. For compiling you have to provide opengrok.jar
and the servlet api (HttpServletRequest
) in the classpath
Example (for the TruePlugin
which is included in the repository):
$ javac -classpath dist/opengrok.jar -d . plugins/TruePlugin.java
Then you can just drop the compiled .class
file into plugin directory and deploy the webapp.
If the plugin is a part of a package, then you have to copy the full directory path which is made
by the compiler relatively to the source file. For example, if the plugin directory configured in the web application is /var/opengrok/share/auth/plugins/
and the package of a plugin FooPlugin
is opengrok.auth.plugin
, then the plugin has to be copied to /var/opengrok/share/auth/plugins/opengrok/auth/plugin/FooPlugin.class
.
If anything goes wrong, you should find information in the logs of the application server.
The framework consists of three parts
-
PluginFramework
This is the plugin container
- performs the authorization decision
- cache the decisions so that for each request the particular
plugin's
isAllowed
for particular project/group is called only once
-
ProjectHelper
UI facade for filtered (authorized) projects/groups/repositories which should be ONLY used for displaying filtered information anywhere
- provides methods how to get filtered projects/groups/repositories
- cache the filtered results for each request so that it does not have to call the framework unnecessarily
-
AuthorizationFilter
Standard
javax.servlet.Filter
which is used for all urls to decide if the current request has access to the url- restricts user to go to forbidden xref/history/download etc. with 403 HTTP error
- reacts only when the url contains information about project (so it can decide per project)
Every HTTP 403 error is logged. But information about the user is missing because the decision is made by plugins and the filter does not know how to interpret the request to get the user from it.
When using IDE (e.g. IDEA) to build your plugin; you can face a problem when the framework does not load your .jar file with ClassFormatError
resulting to ClassNotFoundException
.
Possible solutions are:
- disable debugging symbols
- compile the .java files with
javac
manually and then package it into .jar manually (command above) - compile the .java files with
javac
manually and use this directory structure (without packaging)
This should solve the problem. If it does not then try to change the code.