The interface

IDS plugins have three interfaces to implement. Please see the Javadoc for details. The IDS has a two level storage model with main storage and an optional archive storage. The main storage deals with individual data files whereas the archive storage deals with zip files holding all the datafiles of a dataset. In addition the ZipMapperInterface must be implemented to define the structure of the Zip file which is used for downloads and for archive storage.

There are a number of abstract partial implementations provided - for example MainStorageWithoutArchive and MainStorageWithoutArchiveReadOnly which you may extend. These provide dummy implementations of calls which are not made in specific deployments.

Packaging

For Glassfish deployment the IDS expects to find its plugins in lib/applibs below the domain directory. The plugins must be packaged will all dependencies - because of the way the Glassfish classloader works and after deployment Glassfish must be redeployed. Please see the file storage plugin with source code as an example of how to do it.

Security considerations

When writing a plugin you have to provide methods that operate on your data: read it, check for its existence, write it, delete it and find information about it.

The call put(DsInfo dsInfo, String name, InputStream inputStream) in the MainStorageInterface is where you decide, using information about the data set that will hold the datafile and the name to be given to the datafile, a "location" value which is unique for your IDS instance and which can be used as an identifier to store and retrieve files. It will be some kind of path relative to the storage system you are using. The main danger is that someone will create a datafile object which has a location value which is not consistent with the policy you have defined in this "put" method. Such a location may cause data to be read that should be private or it could cause other people's data to be written or deleted.

The safe simple solution

The simplest way to protect against all such dangers is to enable the generation of a cryptographic hash in the ids.properties file. This results in the computation of a cryptographic hash which is appended to the location you return before storing the value in ICAT. The hash is based on the "id" of the datafile, the "location" value as seen by the plugin and a key known only to the IDS and which is defined in the ids.properties file. Each time the location from ICAT is passed to a plugin it is first check that the hash has the expected value and then the first part of the location field is passed to the plugin which will be guaranteed to be exactly what the original call to the put method returned. The plugin is not exposed to the hash at all. The value stored in icat is the location followed by the hash separated by a space. The hash value goes at the end to help with indexing in some cases.

Safe but restrictive solution

If for some reason you don't want to follow the solution described above there are two approaches which are also safe but restrictive:

Parts of a solution

If you don't want the safe solution and in addition you cannot work with the restrictions in the previous section then there are some things that you can do to help make things safer: