Let me start by giving some background on the existing design and 
implementation and later argue how we can make admin's life easier. Sorry for 
the long email, I don't want people to miss anything I want to propose :)

Background
==========
At present, all the plugins which provide any sort of api has their own 
commands.properties file that is basically a mapping of apiname (which they 
provide but can be used irresponsibly) and role mask.

To check API access, the code that the same was moved out as plugin called 
StaticRoleBasedAPIAccessChecker in which checking is done based on role. This 
plugin assumes that it will somehow have a mapping of apiname and role mask.

To make this process generic we have a APIChecker interface;
    boolean checkAccess(User user, String apiCommandName) throws 
PermissionDeniedException;

Design
======
There may be multiple plugins which are called by for loop and they return:
        - true: if user is allowed
        - false: plugin is unable to handle that
        - exception: if operation is not allowed

Problem
======
Each plugin has a commands.properties file which has no use for the plugin 
itself, it's actually useful for the StaticRoleBasedAPIAccessChecker to get the 
apiname, role mask mapping on which basis it can do the checking. I can see 
moving out existing features as plugins and new features like API throttling, 
API discovery being implemented as plugins. It would be difficult and confusing 
for an admin to keep track to so many configuration files and to edit them. 
Further it's not dynamic enough, every time you want to change things in 
properties files admin would need to restart the management server.

Proposed Fix (aka make admin's life easier)
===========

1. Append this mapping in one single commands.properties file get rid of all 
the other commands.properties files, because the apiname:mask mapping is not 
for the plugin or mgmt server, it's just for the 
StaticRoleBasedAPIAccessChecker. This way an APIChecker plugin won't have to 
depend on other plugins and vice-versa. It would be a clear separation of 
policy local to a plugin. In future one can be free to implement another 
APIChecker which may be dynamic and instead of reading from a properties file, 
queries an API service. Plugin authors pl. comment?

2. Make online reloading easier. Implement an api (updateAccessChecker or 
something) with StaticRoleBasedAPIAccessChecker itself which an admin can call 
to reload the commands.properties mapping in case the admin changes it and 
wants the new policy to be reflected without having to restart mgmt server.

3. Each plugin (if they implement a service exposed via an API) would return a 
list of API cmd classes. Right now the code uses java reflections to grab the 
classes with @APICommand annotation and generate the mappings. This can be 
incorrect in case there is some component which was not loaded but exists in 
class path. Such plugins implement PluggableService which is a contract that 
implementing entity will have a way to return list of cmd classes.

Convention: We've to have a standard convention for writing plugins. So, plugin 
writers should use the @APICommand and other annotations for writing API cmd 
and response classes. The only artifacts from cloudstack they should depend on 
should be cloud-api and/or cloud-util. The plugins are not required to be under 
org.apache.cloudstack or com.cloud package names.

Future
=====

Online pluggable service: (Hugo, Alex and I talked about this during ccc12, we 
can do it in future maybe, but at least we should start packaging them 
separately)

As part of packaging, all plugins be bundled as separate debs/rpms, the core 
system (cloudstack-server) can depend on few ought-to have plugins.
The plugins get installed in a specific directory, say 
/usr/share/java/cloudstack/plugins. This directory is within class path of the 
server process.

If an admin trusts a plugin, he installs/place the jar in this directory, 
changes ACL either in /etc/cloud/commands.properties or depending upon the 
choice of APIChecker plugin and calls the an API to tell mgmt server to load 
the plugin. It would be tricky and some plugins may require restart.

Regards.

Reply via email to