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.