4

The question is quite similar to this one, but I need to concentrate on different issues.

Suppose I have an application with a large database (i.e. movie database). The user of the application should be able to add her own plugins and be able to run them.

The scenario could look like this:

  • launch the main app
  • place stats-plugin.jar in the /app/plugins directory
  • tell the main app to load the new plugin
  • tell the app to list the plugins
  • choose a plugin (e.g. the just installed one) and run it
  • the stats-plugin.jar queries the db about movies and counts the horror movies, returns the count
  • the main app presents the result


Each plugin could have a couple of standard methods (a common Plugin interface) that would be called, e.g. onInitialize , onRun etc.

What the main app needs to guarantee is that if the plugin crashes (e.g. divides by 0) the main app will remain stable (will show an error dialog for example, but won't crash itself). It should be also possible to limit the time of execution and check what operations the plugin is performing.

This all sums up to a sandboxed plugin environment. The most important things are: plugin-style extensibility and sandboxing the plugins - allowing only for safe operations (e.g. reading the DB, but not updating it).

The plugin doesn't have to be written in Java. It needs to be executable in some way... It could even be a JavaScript file.. if it is possible.

How would you approach such a task?

Community
  • 1
  • 1
emesx
  • 12,555
  • 10
  • 58
  • 91

4 Answers4

1

You should look into using a Security Manager, and perhaps defining some of your own permissions. There is already a set of commonly used permissions you can use when defining policies.

Note that read-only access to an RDBMS is unlikely to be within the scope of your Java environment. Instead, this is typically handled using a separate RDBMS user with specific permissions there. Your framework would need to connect to the DB using that user name.

Bruno
  • 119,590
  • 31
  • 270
  • 376
  • The RW operation is just an example. Assume that the app has public methods `read` and `write` (among others) and once the plugin is called, it can communicate with the main app (e.g. request records). On the other hand, non-bundle (not original) plugins are not allowed to call `write`. How to achieve this? Reflection? – emesx Jun 20 '12 at 17:44
  • 1
    Your framework should call `checkPermission` where needed (e.g. within your `read`/`write` methods perhaps), to handle your custom permissions. The policies can be restricted to certain classes depending on the locations (the code base): you'll have to make sure your classloaders set this properly when loading your plugin. This is likely to be quite a complex system overall. [This question](http://stackoverflow.com/q/502218/372643) should be of interest. – Bruno Jun 20 '12 at 17:55
  • Well, your adivice is probably a good one, but after a short research I wont allow java plugns at all ;) – emesx Jun 25 '12 at 15:48
1

It is possible to do things like that using your own Security Policy File and your own Security Manager. Basically, grant to your own jars AllPermission and to the plugin jars fewer permissions. That way, you won't be able to limit operations that are available to untrusted applets, though, so writing a thread that creates an endless loop or allocates 100GB of RAM is still possible.

For allowing DB access but only specific operations, you will have to provide your own API (which is in one of your trusted Jars) that will provide only trusted operations (like validate the SELECT statement first) and calls AccessController.doPrivileged afterwards if it is trusted to execute the operation. As untrusted code may not open socket connections (unless allowed for specific hosts), the code will not be able to mess with the DB that way.

However, implementing a security manager correctly can be tricky (there are often found bugs in implementations, like in Batik Squiggle lately), so having an emulated language (JavaScript/Rhino for example) might be safer.

mihi
  • 6,507
  • 1
  • 38
  • 48
0

You might be able to implement such a pluggable architecture using Java Authentication and Authorization Service . Using JAAS, you can execute the plugin with restricted access control rights. ACL can restrict opening socket connections, writing to file, opening database connections etc.,

For database access, you can provide the database connection to the plugin via JNDI datasource and configure the datasource using a DB user who can only read and not update the database.

sperumal
  • 1,499
  • 10
  • 14
-2

I don't think java is a suitable platform for running untrusted plugins. Once a plugin is running, it will be able to do everything the host program can do.

You need to create your own abstraction layer and sandbox of "safe" operations that you execute as part of the main program. The plugin can provide data which you interpret as a program. You cannot let the plugin run.

ddyer
  • 1,792
  • 19
  • 26