diff --git a/api/src/org/apache/cloudstack/api/APICommand.java b/api/src/org/apache/cloudstack/api/APICommand.java index 4d024c15a5d..7c9e6fec2e7 100644 --- a/api/src/org/apache/cloudstack/api/APICommand.java +++ b/api/src/org/apache/cloudstack/api/APICommand.java @@ -22,6 +22,8 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import org.apache.cloudstack.acl.RoleType; + @Retention(RetentionPolicy.RUNTIME) @Target({ TYPE }) public @interface APICommand { @@ -36,4 +38,6 @@ public @interface APICommand { boolean includeInApiDoc() default true; String since() default ""; + + RoleType[] authorized() default {}; } diff --git a/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java b/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java index affcf919daf..bf3acf5f427 100644 --- a/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java +++ b/plugins/acl/static-role-based/src/org/apache/cloudstack/acl/StaticRoleBasedAPIAccessChecker.java @@ -26,6 +26,7 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.cloudstack.api.APICommand; import org.apache.log4j.Logger; import com.cloud.exception.PermissionDeniedException; @@ -43,7 +44,10 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIC protected static final Logger s_logger = Logger.getLogger(StaticRoleBasedAPIAccessChecker.class); - private static Map> s_roleBasedApisMap = + Set commandsPropertiesOverrides = new HashSet(); + Map> commandsPropertiesRoleBasedApisMap = + new HashMap>(); + Map> annotationRoleBasedApisMap = new HashMap>(); List _services; @@ -51,8 +55,10 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIC protected StaticRoleBasedAPIAccessChecker() { super(); - for (RoleType roleType: RoleType.values()) - s_roleBasedApisMap.put(roleType, new HashSet()); + for (RoleType roleType: RoleType.values()) { + commandsPropertiesRoleBasedApisMap.put(roleType, new HashSet()); + annotationRoleBasedApisMap.put(roleType, new HashSet()); + } } @Override @@ -64,7 +70,10 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIC } RoleType roleType = _accountService.getRoleType(account); - boolean isAllowed = s_roleBasedApisMap.get(roleType).contains(commandName); + boolean isAllowed = commandsPropertiesOverrides.contains(commandName) ? + commandsPropertiesRoleBasedApisMap.get(roleType).contains(commandName) : + annotationRoleBasedApisMap.get(roleType).contains(commandName); + if (!isAllowed) { throw new PermissionDeniedException("The API does not exist or is blacklisted. Role type=" + roleType.toString() + " is not allowed to request the api: " + commandName); } @@ -80,15 +89,32 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIC return true; } + + @Override + public boolean start() { + for ( PluggableService service : _services ) { + for ( Class clz : service.getCommands() ) { + APICommand command = clz.getAnnotation(APICommand.class); + for ( RoleType role : command.authorized() ) { + Set commands = annotationRoleBasedApisMap.get(role); + if (!commands.contains(command.name())) + commands.add(command.name()); + } + } + } + return super.start(); + } + private void processMapping(Map configMap) { for (Map.Entry entry: configMap.entrySet()) { String apiName = entry.getKey(); String roleMask = entry.getValue(); + commandsPropertiesOverrides.add(apiName); try { short cmdPermissions = Short.parseShort(roleMask); for (RoleType roleType: RoleType.values()) { if ((cmdPermissions & roleType.getValue()) != 0) - s_roleBasedApisMap.get(roleType).add(apiName); + commandsPropertiesRoleBasedApisMap.get(roleType).add(apiName); } } catch (NumberFormatException nfe) { s_logger.info("Malformed key=value pair for entry: " + entry.toString()); @@ -104,4 +130,5 @@ public class StaticRoleBasedAPIAccessChecker extends AdapterBase implements APIC public void setServices(List _services) { this._services = _services; } + }