You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by pr...@apache.org on 2012/10/24 23:11:19 UTC
git commit: Some ACL POC work
Updated Branches:
refs/heads/acl f16b5103d -> 3058520ab
Some ACL POC work
Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/3058520a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/3058520a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/3058520a
Branch: refs/heads/acl
Commit: 3058520ab3f09c31c142b41e37912e5ddd8d074a
Parents: f16b510
Author: Prachi Damle <pr...@cloud.com>
Authored: Thu Oct 18 13:32:45 2012 -0700
Committer: Prachi Damle <pr...@cloud.com>
Committed: Thu Oct 18 13:32:45 2012 -0700
----------------------------------------------------------------------
api/src/com/cloud/api/ACL.java | 31 +++++
api/src/com/cloud/api/commands/DeployVMCmd.java | 9 ++
server/src/com/cloud/api/ApiDispatcher.java | 126 +++++++++++++++++-
server/src/com/cloud/api/ApiServer.java | 11 ++-
4 files changed, 172 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/3058520a/api/src/com/cloud/api/ACL.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/api/ACL.java b/api/src/com/cloud/api/ACL.java
new file mode 100644
index 0000000..1f376e9
--- /dev/null
+++ b/api/src/com/cloud/api/ACL.java
@@ -0,0 +1,31 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.api;
+
+import static java.lang.annotation.ElementType.FIELD;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ FIELD })
+public @interface ACL {
+
+
+ Class<?> resourceType();
+}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/3058520a/api/src/com/cloud/api/commands/DeployVMCmd.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/api/commands/DeployVMCmd.java b/api/src/com/cloud/api/commands/DeployVMCmd.java
index f67ee8f..da9f3ea 100644
--- a/api/src/com/cloud/api/commands/DeployVMCmd.java
+++ b/api/src/com/cloud/api/commands/DeployVMCmd.java
@@ -26,6 +26,7 @@ import java.util.Map;
import org.apache.log4j.Logger;
+import com.cloud.api.ACL;
import com.cloud.api.ApiConstants;
import com.cloud.api.BaseAsyncCreateCmd;
import com.cloud.api.BaseCmd;
@@ -43,7 +44,10 @@ import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.host.Host;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.network.Network;
+import com.cloud.network.security.SecurityGroup;
import com.cloud.offering.DiskOffering;
import com.cloud.offering.ServiceOffering;
import com.cloud.template.VirtualMachineTemplate;
@@ -69,6 +73,7 @@ public class DeployVMCmd extends BaseAsyncCreateCmd {
@Parameter(name=ApiConstants.SERVICE_OFFERING_ID, type=CommandType.LONG, required=true, description="the ID of the service offering for the virtual machine")
private Long serviceOfferingId;
+ @ACL(resourceType=VirtualMachineTemplate.class)
@IdentityMapper(entityTableName="vm_template")
@Parameter(name=ApiConstants.TEMPLATE_ID, type=CommandType.LONG, required=true, description="the ID of the template for the virtual machine")
private Long templateId;
@@ -88,6 +93,7 @@ public class DeployVMCmd extends BaseAsyncCreateCmd {
private Long domainId;
//Network information
+ @ACL(resourceType=Network.class)
@IdentityMapper(entityTableName="networks")
@Parameter(name=ApiConstants.NETWORK_IDS, type=CommandType.LIST, collectionType=CommandType.LONG, description="list of network ids used by virtual machine. Can't be specified with ipToNetworkList parameter")
private List<Long> networkIds;
@@ -112,14 +118,17 @@ public class DeployVMCmd extends BaseAsyncCreateCmd {
@Parameter(name=ApiConstants.SSH_KEYPAIR, type=CommandType.STRING, description="name of the ssh key pair used to login to the virtual machine")
private String sshKeyPairName;
+ //@ACL(resourceType=Host.class)
@IdentityMapper(entityTableName="host")
@Parameter(name=ApiConstants.HOST_ID, type=CommandType.LONG, description="destination Host ID to deploy the VM to - parameter available for root admin only")
private Long hostId;
+ //@ACL(resourceType=SecurityGroup.class)
@IdentityMapper(entityTableName="security_group")
@Parameter(name=ApiConstants.SECURITY_GROUP_IDS, type=CommandType.LIST, collectionType=CommandType.LONG, description="comma separated list of security groups id that going to be applied to the virtual machine. Should be passed only when vm is created from a zone with Basic Network support. Mutually exclusive with securitygroupnames parameter")
private List<Long> securityGroupIdList;
+ //@ACL(resourceType=SecurityGroup.class)
@Parameter(name=ApiConstants.SECURITY_GROUP_NAMES, type=CommandType.LIST, collectionType=CommandType.STRING, description="comma separated list of security groups names that going to be applied to the virtual machine. Should be passed only when vm is created from a zone with Basic Network support. Mutually exclusive with securitygroupids parameter")
private List<String> securityGroupNameList;
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/3058520a/server/src/com/cloud/api/ApiDispatcher.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiDispatcher.java b/server/src/com/cloud/api/ApiDispatcher.java
index 8eade00..de7bdc6 100755
--- a/server/src/com/cloud/api/ApiDispatcher.java
+++ b/server/src/com/cloud/api/ApiDispatcher.java
@@ -22,6 +22,7 @@ import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
@@ -29,6 +30,7 @@ import java.util.regex.Matcher;
import org.apache.log4j.Logger;
+import com.cloud.acl.ControlledEntity;
import com.cloud.api.BaseCmd.CommandType;
import com.cloud.api.commands.ListEventsCmd;
import com.cloud.async.AsyncCommandQueued;
@@ -40,12 +42,17 @@ import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.utils.IdentityProxy;
+import com.cloud.network.dao.NetworkDao;
import com.cloud.server.ManagementServer;
+import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.user.Account;
+import com.cloud.user.AccountManager;
+import com.cloud.user.AccountService;
import com.cloud.user.UserContext;
import com.cloud.utils.DateUtil;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.component.PluggableService;
+import com.cloud.utils.db.GenericDao;
import com.cloud.utils.exception.CSExceptionErrorCode;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.uuididentity.dao.IdentityDao;
@@ -59,7 +66,10 @@ public class ApiDispatcher {
ComponentLocator _locator;
AsyncJobManager _asyncMgr;
IdentityDao _identityDao;
+ AccountManager _accountMgr;
+
+ Map<String, Class<? extends GenericDao>> _daoNameMap = new HashMap<String, Class<? extends GenericDao>>();
// singleton class
private static ApiDispatcher s_instance = new ApiDispatcher();
@@ -71,13 +81,30 @@ public class ApiDispatcher {
_locator = ComponentLocator.getLocator(ManagementServer.Name);
_asyncMgr = _locator.getManager(AsyncJobManager.class);
_identityDao = _locator.getDao(IdentityDao.class);
+ _accountMgr = _locator.getManager(AccountManager.class);
+
+ _daoNameMap.put("com.cloud.network.Network", NetworkDao.class);
+ _daoNameMap.put("com.cloud.template.VirtualMachineTemplate", VMTemplateDao.class);
+
+
}
public void dispatchCreateCmd(BaseAsyncCreateCmd cmd, Map<String, String> params) {
- setupParameters(cmd, params);
+ List<ControlledEntity> entitiesToAccess = new ArrayList<ControlledEntity>();
+ setupParameters(cmd, params, entitiesToAccess);
plugService(cmd);
+ if(!entitiesToAccess.isEmpty()){
+ //owner
+ Account caller = UserContext.current().getCaller();
+ Account owner = s_instance._accountMgr.getActiveAccountById(cmd.getEntityOwnerId());
+ s_instance._accountMgr.checkAccess(caller, null, true, owner);
+
+ for(ControlledEntity entity : entitiesToAccess)
+ s_instance._accountMgr.checkAccess(caller, null, true, entity);
+ }
+
try {
UserContext ctx = UserContext.current();
ctx.setAccountId(cmd.getEntityOwnerId());
@@ -118,8 +145,19 @@ public class ApiDispatcher {
}
public void dispatch(BaseCmd cmd, Map<String, String> params) {
- setupParameters(cmd, params);
+ List<ControlledEntity> entitiesToAccess = new ArrayList<ControlledEntity>();
+ setupParameters(cmd, params, entitiesToAccess);
ApiDispatcher.plugService(cmd);
+
+ if(!entitiesToAccess.isEmpty()){
+ //owner
+ Account caller = UserContext.current().getCaller();
+ Account owner = s_instance._accountMgr.getActiveAccountById(cmd.getEntityOwnerId());
+ s_instance._accountMgr.checkAccess(caller, null, true, owner);
+ for(ControlledEntity entity : entitiesToAccess)
+ s_instance._accountMgr.checkAccess(caller, null, true, entity);
+ }
+
try {
UserContext ctx = UserContext.current();
ctx.setAccountId(cmd.getEntityOwnerId());
@@ -270,8 +308,10 @@ public class ApiDispatcher {
}
}
- public static void setupParameters(BaseCmd cmd, Map<String, String> params) {
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public static void setupParameters(BaseCmd cmd, Map<String, String> params, List<ControlledEntity> entitiesToAccess) {
Map<String, Object> unpackedParams = cmd.unpackParams(params);
+
if (cmd instanceof BaseListCmd) {
Object pageSizeObj = unpackedParams.get(ApiConstants.PAGE_SIZE);
@@ -339,12 +379,90 @@ public class ApiDispatcher {
throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to execute API command " + cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8) + " due to invalid value. " + invEx.getMessage());
} catch (CloudRuntimeException cloudEx) {
// FIXME: Better error message? This only happens if the API command is not executable, which typically
-// means
+ //means
// there was
// and IllegalAccessException setting one of the parameters.
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Internal error executing API command " + cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8));
}
+
+
+ //check access on the resource this field points to
+ try {
+ ACL checkAccess = field.getAnnotation(ACL.class);
+ CommandType fieldType = parameterAnnotation.type();
+
+
+ if(checkAccess != null){
+ // Verify that caller can perform actions in behalf of vm owner
+ //acumulate all Controlled Entities together.
+ if(checkAccess.resourceType() != null){
+ Class<?> entity = checkAccess.resourceType();
+
+ if(ControlledEntity.class.isAssignableFrom(entity)){
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("entity name is:" + entity.getName());
+ }
+
+ if(s_instance._daoNameMap.containsKey(entity.getName())){
+ Class<? extends GenericDao> daoClass = s_instance._daoNameMap.get(entity.getName());
+ GenericDao daoClassInstance = s_instance._locator.getDao(daoClass);
+
+ //Check if the parameter type is a single Id or list of id's/name's
+ switch (fieldType) {
+ case LIST:
+ CommandType listType = parameterAnnotation.collectionType();
+ switch (listType) {
+ case LONG:
+ List<Long> listParam = new ArrayList<Long>();
+ listParam = (List)field.get(cmd);
+
+ for(Long entityId : listParam){
+ ControlledEntity entityObj = (ControlledEntity)daoClassInstance.findById(entityId);
+ entitiesToAccess.add(entityObj);
+ }
+ break;
+ /*case STRING:
+ List<String> listParam = new ArrayList<String>();
+ listParam = (List)field.get(cmd);
+ for(String entityName: listParam){
+ ControlledEntity entityObj = (ControlledEntity)daoClassInstance(entityId);
+ entitiesToAccess.add(entityObj);
+ }
+ break;
+ */
+ default:
+ break;
+ }
+ break;
+ case LONG:
+ Long entityId = (Long)field.get(cmd);
+ ControlledEntity entityObj = (ControlledEntity)daoClassInstance.findById(entityId);
+ entitiesToAccess.add(entityObj);
+ break;
+ default:
+ break;
+ }
+
+
+ }
+
+ }
+
+ }
+
+ }
+
+ } catch (IllegalArgumentException e) {
+ s_logger.error("Error initializing command " + cmd.getCommandName() + ", field " + field.getName() + " is not accessible.");
+ throw new CloudRuntimeException("Internal error initializing parameters for command " + cmd.getCommandName() + " [field " + field.getName() + " is not accessible]");
+ } catch (IllegalAccessException e) {
+ s_logger.error("Error initializing command " + cmd.getCommandName() + ", field " + field.getName() + " is not accessible.");
+ throw new CloudRuntimeException("Internal error initializing parameters for command " + cmd.getCommandName() + " [field " + field.getName() + " is not accessible]");
+ }
+
}
+
+ //check access on the entities.
}
@SuppressWarnings({ "unchecked", "rawtypes" })
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/3058520a/server/src/com/cloud/api/ApiServer.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java
index eb5e770..3186d95 100755
--- a/server/src/com/cloud/api/ApiServer.java
+++ b/server/src/com/cloud/api/ApiServer.java
@@ -81,6 +81,7 @@ import org.apache.http.protocol.ResponseDate;
import org.apache.http.protocol.ResponseServer;
import org.apache.log4j.Logger;
+import com.cloud.acl.ControlledEntity;
import com.cloud.api.response.ApiResponseSerializer;
import com.cloud.api.response.ExceptionResponse;
import com.cloud.api.response.ListResponse;
@@ -486,8 +487,16 @@ public class ApiServer implements HttpRequestHandler {
objectEntityTable = createCmd.getEntityTable();
params.put("id", objectId.toString());
} else {
- ApiDispatcher.setupParameters(cmdObj, params);
+ List<ControlledEntity> entitiesToAccess = new ArrayList<ControlledEntity>();
+ ApiDispatcher.setupParameters(cmdObj, params, entitiesToAccess);
ApiDispatcher.plugService(cmdObj);
+
+ if(!entitiesToAccess.isEmpty()){
+ Account owner = s_instance._accountMgr.getActiveAccountById(cmdObj.getEntityOwnerId());
+ s_instance._accountMgr.checkAccess(caller, null, true, owner);
+
+ s_instance._accountMgr.checkAccess(caller, null, true, (ControlledEntity[])entitiesToAccess.toArray());
+ }
}
BaseAsyncCmd asyncCmd = (BaseAsyncCmd) cmdObj;
RE: git commit: Some ACL POC work
Posted by Prachi Damle <Pr...@citrix.com>.
Hi David,
I am putting together the ideas currently and will provide a link to a document soon describing them.
Thanks,
Prachi
-----Original Message-----
From: David Nalley [mailto:david@gnsa.us]
Sent: Saturday, November 10, 2012 3:22 AM
To: cloudstack-dev@incubator.apache.org
Subject: Re: git commit: Some ACL POC work
Hi Prachi:
I am still trying to get caught up on my backlog of mail, is there a place where you've discussed some of these ACL ideas?
--David
On Wed, Oct 24, 2012 at 5:11 PM, <pr...@apache.org> wrote:
> Updated Branches:
> refs/heads/acl f16b5103d -> 3058520ab
>
>
> Some ACL POC work
>
>
> Project:
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo
> Commit:
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/305
> 8520a
> Tree:
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/30585
> 20a
> Diff:
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/30585
> 20a
>
> Branch: refs/heads/acl
> Commit: 3058520ab3f09c31c142b41e37912e5ddd8d074a
> Parents: f16b510
> Author: Prachi Damle <pr...@cloud.com>
> Authored: Thu Oct 18 13:32:45 2012 -0700
> Committer: Prachi Damle <pr...@cloud.com>
> Committed: Thu Oct 18 13:32:45 2012 -0700
>
> ----------------------------------------------------------------------
> api/src/com/cloud/api/ACL.java | 31 +++++
> api/src/com/cloud/api/commands/DeployVMCmd.java | 9 ++
> server/src/com/cloud/api/ApiDispatcher.java | 126 +++++++++++++++++-
> server/src/com/cloud/api/ApiServer.java | 11 ++-
> 4 files changed, 172 insertions(+), 5 deletions(-)
> ----------------------------------------------------------------------
>
>
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/30585
> 20a/api/src/com/cloud/api/ACL.java
> ----------------------------------------------------------------------
> diff --git a/api/src/com/cloud/api/ACL.java
> b/api/src/com/cloud/api/ACL.java new file mode 100644 index
> 0000000..1f376e9
> --- /dev/null
> +++ b/api/src/com/cloud/api/ACL.java
> @@ -0,0 +1,31 @@
> +// Licensed to the Apache Software Foundation (ASF) under one // or
> +more contributor license agreements. See the NOTICE file //
> +distributed with this work for additional information // regarding
> +copyright ownership. The ASF licenses this file // to you under the
> +Apache License, Version 2.0 (the // "License"); you may not use this
> +file except in compliance // with the License. You may obtain a copy
> +of the License at //
> +// http://www.apache.org/licenses/LICENSE-2.0
> +//
> +// Unless required by applicable law or agreed to in writing, //
> +software distributed under the License is distributed on an // "AS
> +IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either
> +express or implied. See the License for the // specific language
> +governing permissions and limitations // under the License.
> +package com.cloud.api;
> +
> +import static java.lang.annotation.ElementType.FIELD;
> +
> +import java.lang.annotation.Retention; import
> +java.lang.annotation.RetentionPolicy;
> +import java.lang.annotation.Target;
> +
> +@Retention(RetentionPolicy.RUNTIME)
> +@Target({ FIELD })
> +public @interface ACL {
> +
> +
> + Class<?> resourceType();
> +}
>
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/30585
> 20a/api/src/com/cloud/api/commands/DeployVMCmd.java
> ----------------------------------------------------------------------
> diff --git a/api/src/com/cloud/api/commands/DeployVMCmd.java
> b/api/src/com/cloud/api/commands/DeployVMCmd.java
> index f67ee8f..da9f3ea 100644
> --- a/api/src/com/cloud/api/commands/DeployVMCmd.java
> +++ b/api/src/com/cloud/api/commands/DeployVMCmd.java
> @@ -26,6 +26,7 @@ import java.util.Map;
>
> import org.apache.log4j.Logger;
>
> +import com.cloud.api.ACL;
> import com.cloud.api.ApiConstants;
> import com.cloud.api.BaseAsyncCreateCmd; import
> com.cloud.api.BaseCmd; @@ -43,7 +44,10 @@ import
> com.cloud.exception.InsufficientCapacityException;
> import com.cloud.exception.InvalidParameterValueException;
> import com.cloud.exception.ResourceAllocationException;
> import com.cloud.exception.ResourceUnavailableException;
> +import com.cloud.host.Host;
> import com.cloud.hypervisor.Hypervisor.HypervisorType;
> +import com.cloud.network.Network;
> +import com.cloud.network.security.SecurityGroup;
> import com.cloud.offering.DiskOffering; import
> com.cloud.offering.ServiceOffering;
> import com.cloud.template.VirtualMachineTemplate;
> @@ -69,6 +73,7 @@ public class DeployVMCmd extends BaseAsyncCreateCmd {
> @Parameter(name=ApiConstants.SERVICE_OFFERING_ID, type=CommandType.LONG, required=true, description="the ID of the service offering for the virtual machine")
> private Long serviceOfferingId;
>
> + @ACL(resourceType=VirtualMachineTemplate.class)
> @IdentityMapper(entityTableName="vm_template")
> @Parameter(name=ApiConstants.TEMPLATE_ID, type=CommandType.LONG, required=true, description="the ID of the template for the virtual machine")
> private Long templateId;
> @@ -88,6 +93,7 @@ public class DeployVMCmd extends BaseAsyncCreateCmd {
> private Long domainId;
>
> //Network information
> + @ACL(resourceType=Network.class)
> @IdentityMapper(entityTableName="networks")
> @Parameter(name=ApiConstants.NETWORK_IDS, type=CommandType.LIST, collectionType=CommandType.LONG, description="list of network ids used by virtual machine. Can't be specified with ipToNetworkList parameter")
> private List<Long> networkIds;
> @@ -112,14 +118,17 @@ public class DeployVMCmd extends BaseAsyncCreateCmd {
> @Parameter(name=ApiConstants.SSH_KEYPAIR, type=CommandType.STRING, description="name of the ssh key pair used to login to the virtual machine")
> private String sshKeyPairName;
>
> + //@ACL(resourceType=Host.class)
> @IdentityMapper(entityTableName="host")
> @Parameter(name=ApiConstants.HOST_ID, type=CommandType.LONG, description="destination Host ID to deploy the VM to - parameter available for root admin only")
> private Long hostId;
>
> + //@ACL(resourceType=SecurityGroup.class)
> @IdentityMapper(entityTableName="security_group")
> @Parameter(name=ApiConstants.SECURITY_GROUP_IDS, type=CommandType.LIST, collectionType=CommandType.LONG, description="comma separated list of security groups id that going to be applied to the virtual machine. Should be passed only when vm is created from a zone with Basic Network support. Mutually exclusive with securitygroupnames parameter")
> private List<Long> securityGroupIdList;
>
> + //@ACL(resourceType=SecurityGroup.class)
> @Parameter(name=ApiConstants.SECURITY_GROUP_NAMES, type=CommandType.LIST, collectionType=CommandType.STRING, description="comma separated list of security groups names that going to be applied to the virtual machine. Should be passed only when vm is created from a zone with Basic Network support. Mutually exclusive with securitygroupids parameter")
> private List<String> securityGroupNameList;
>
>
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/30585
> 20a/server/src/com/cloud/api/ApiDispatcher.java
> ----------------------------------------------------------------------
> diff --git a/server/src/com/cloud/api/ApiDispatcher.java
> b/server/src/com/cloud/api/ApiDispatcher.java
> index 8eade00..de7bdc6 100755
> --- a/server/src/com/cloud/api/ApiDispatcher.java
> +++ b/server/src/com/cloud/api/ApiDispatcher.java
> @@ -22,6 +22,7 @@ import java.text.ParseException; import
> java.util.ArrayList; import java.util.Calendar; import
> java.util.Date;
> +import java.util.HashMap;
> import java.util.List;
> import java.util.Map;
> import java.util.StringTokenizer;
> @@ -29,6 +30,7 @@ import java.util.regex.Matcher;
>
> import org.apache.log4j.Logger;
>
> +import com.cloud.acl.ControlledEntity;
> import com.cloud.api.BaseCmd.CommandType;
> import com.cloud.api.commands.ListEventsCmd;
> import com.cloud.async.AsyncCommandQueued;
> @@ -40,12 +42,17 @@ import
> com.cloud.exception.PermissionDeniedException;
> import com.cloud.exception.ResourceAllocationException;
> import com.cloud.exception.ResourceUnavailableException;
> import com.cloud.utils.IdentityProxy;
> +import com.cloud.network.dao.NetworkDao;
> import com.cloud.server.ManagementServer;
> +import com.cloud.storage.dao.VMTemplateDao;
> import com.cloud.user.Account;
> +import com.cloud.user.AccountManager; import
> +com.cloud.user.AccountService;
> import com.cloud.user.UserContext;
> import com.cloud.utils.DateUtil;
> import com.cloud.utils.component.ComponentLocator;
> import com.cloud.utils.component.PluggableService;
> +import com.cloud.utils.db.GenericDao;
> import com.cloud.utils.exception.CSExceptionErrorCode;
> import com.cloud.utils.exception.CloudRuntimeException;
> import com.cloud.uuididentity.dao.IdentityDao;
> @@ -59,7 +66,10 @@ public class ApiDispatcher {
> ComponentLocator _locator;
> AsyncJobManager _asyncMgr;
> IdentityDao _identityDao;
> + AccountManager _accountMgr;
>
> +
> + Map<String, Class<? extends GenericDao>> _daoNameMap = new
> + HashMap<String, Class<? extends GenericDao>>();
> // singleton class
> private static ApiDispatcher s_instance = new ApiDispatcher();
>
> @@ -71,13 +81,30 @@ public class ApiDispatcher {
> _locator = ComponentLocator.getLocator(ManagementServer.Name);
> _asyncMgr = _locator.getManager(AsyncJobManager.class);
> _identityDao = _locator.getDao(IdentityDao.class);
> + _accountMgr = _locator.getManager(AccountManager.class);
> +
> + _daoNameMap.put("com.cloud.network.Network", NetworkDao.class);
> + _daoNameMap.put("com.cloud.template.VirtualMachineTemplate",
> + VMTemplateDao.class);
> +
> +
> }
>
> public void dispatchCreateCmd(BaseAsyncCreateCmd cmd, Map<String,
> String> params) {
>
> - setupParameters(cmd, params);
> + List<ControlledEntity> entitiesToAccess = new ArrayList<ControlledEntity>();
> + setupParameters(cmd, params, entitiesToAccess);
> plugService(cmd);
>
> + if(!entitiesToAccess.isEmpty()){
> + //owner
> + Account caller = UserContext.current().getCaller();
> + Account owner = s_instance._accountMgr.getActiveAccountById(cmd.getEntityOwnerId());
> + s_instance._accountMgr.checkAccess(caller,
> + null, true, owner);
> +
> + for(ControlledEntity entity : entitiesToAccess)
> + s_instance._accountMgr.checkAccess(caller, null, true, entity);
> + }
> +
> try {
> UserContext ctx = UserContext.current();
> ctx.setAccountId(cmd.getEntityOwnerId());
> @@ -118,8 +145,19 @@ public class ApiDispatcher {
> }
>
> public void dispatch(BaseCmd cmd, Map<String, String> params) {
> - setupParameters(cmd, params);
> + List<ControlledEntity> entitiesToAccess = new ArrayList<ControlledEntity>();
> + setupParameters(cmd, params, entitiesToAccess);
> ApiDispatcher.plugService(cmd);
> +
> + if(!entitiesToAccess.isEmpty()){
> + //owner
> + Account caller = UserContext.current().getCaller();
> + Account owner = s_instance._accountMgr.getActiveAccountById(cmd.getEntityOwnerId());
> + s_instance._accountMgr.checkAccess(caller, null, true, owner);
> + for(ControlledEntity entity : entitiesToAccess)
> + s_instance._accountMgr.checkAccess(caller, null, true, entity);
> + }
> +
> try {
> UserContext ctx = UserContext.current();
> ctx.setAccountId(cmd.getEntityOwnerId());
> @@ -270,8 +308,10 @@ public class ApiDispatcher {
> }
> }
>
> - public static void setupParameters(BaseCmd cmd, Map<String, String> params) {
> + @SuppressWarnings({ "unchecked", "rawtypes" })
> + public static void setupParameters(BaseCmd cmd, Map<String,
> + String> params, List<ControlledEntity> entitiesToAccess) {
> Map<String, Object> unpackedParams =
> cmd.unpackParams(params);
> +
>
> if (cmd instanceof BaseListCmd) {
> Object pageSizeObj =
> unpackedParams.get(ApiConstants.PAGE_SIZE);
> @@ -339,12 +379,90 @@ public class ApiDispatcher {
> throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to execute API command " + cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8) + " due to invalid value. " + invEx.getMessage());
> } catch (CloudRuntimeException cloudEx) {
> // FIXME: Better error message? This only happens if
> the API command is not executable, which typically -// means
> + //means
> // there was
> // and IllegalAccessException setting one of the parameters.
> throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Internal error executing API command " + cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8));
> }
> +
> +
> + //check access on the resource this field points to
> + try {
> + ACL checkAccess = field.getAnnotation(ACL.class);
> + CommandType fieldType =
> + parameterAnnotation.type();
> +
> +
> + if(checkAccess != null){
> + // Verify that caller can perform actions in behalf of vm owner
> + //acumulate all Controlled Entities together.
> + if(checkAccess.resourceType() != null){
> + Class<?> entity =
> + checkAccess.resourceType();
> +
> + if(ControlledEntity.class.isAssignableFrom(entity)){
> + if (s_logger.isDebugEnabled()) {
> + s_logger.debug("entity name is:" + entity.getName());
> + }
> +
> + if(s_instance._daoNameMap.containsKey(entity.getName())){
> + Class<? extends GenericDao> daoClass = s_instance._daoNameMap.get(entity.getName());
> + GenericDao daoClassInstance =
> + s_instance._locator.getDao(daoClass);
> +
> + //Check if the parameter type is a single Id or list of id's/name's
> + switch (fieldType) {
> + case LIST:
> + CommandType listType = parameterAnnotation.collectionType();
> + switch (listType) {
> + case LONG:
> + List<Long> listParam = new ArrayList<Long>();
> +
> + listParam = (List)field.get(cmd);
> +
> + for(Long entityId : listParam){
> + ControlledEntity entityObj = (ControlledEntity)daoClassInstance.findById(entityId);
> + entitiesToAccess.add(entityObj);
> + }
> + break;
> + /*case STRING:
> + List<String> listParam = new ArrayList<String>();
> + listParam = (List)field.get(cmd);
> + for(String entityName: listParam){
> + ControlledEntity entityObj = (ControlledEntity)daoClassInstance(entityId);
> + entitiesToAccess.add(entityObj);
> + }
> + break;
> + */
> + default:
> + break;
> + }
> + break;
> + case LONG:
> + Long entityId = (Long)field.get(cmd);
> + ControlledEntity entityObj = (ControlledEntity)daoClassInstance.findById(entityId);
> + entitiesToAccess.add(entityObj);
> + break;
> + default:
> + break;
> + }
> +
> +
> + }
> +
> + }
> +
> + }
> +
> + }
> +
> + } catch (IllegalArgumentException e) {
> + s_logger.error("Error initializing command " + cmd.getCommandName() + ", field " + field.getName() + " is not accessible.");
> + throw new CloudRuntimeException("Internal error initializing parameters for command " + cmd.getCommandName() + " [field " + field.getName() + " is not accessible]");
> + } catch (IllegalAccessException e) {
> + s_logger.error("Error initializing command " + cmd.getCommandName() + ", field " + field.getName() + " is not accessible.");
> + throw new CloudRuntimeException("Internal error initializing parameters for command " + cmd.getCommandName() + " [field " + field.getName() + " is not accessible]");
> + }
> +
> }
> +
> + //check access on the entities.
> }
>
> @SuppressWarnings({ "unchecked", "rawtypes" })
>
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/30585
> 20a/server/src/com/cloud/api/ApiServer.java
> ----------------------------------------------------------------------
> diff --git a/server/src/com/cloud/api/ApiServer.java
> b/server/src/com/cloud/api/ApiServer.java
> index eb5e770..3186d95 100755
> --- a/server/src/com/cloud/api/ApiServer.java
> +++ b/server/src/com/cloud/api/ApiServer.java
> @@ -81,6 +81,7 @@ import org.apache.http.protocol.ResponseDate;
> import org.apache.http.protocol.ResponseServer;
> import org.apache.log4j.Logger;
>
> +import com.cloud.acl.ControlledEntity;
> import com.cloud.api.response.ApiResponseSerializer;
> import com.cloud.api.response.ExceptionResponse;
> import com.cloud.api.response.ListResponse;
> @@ -486,8 +487,16 @@ public class ApiServer implements HttpRequestHandler {
> objectEntityTable = createCmd.getEntityTable();
> params.put("id", objectId.toString());
> } else {
> - ApiDispatcher.setupParameters(cmdObj, params);
> + List<ControlledEntity> entitiesToAccess = new ArrayList<ControlledEntity>();
> + ApiDispatcher.setupParameters(cmdObj, params,
> + entitiesToAccess);
> ApiDispatcher.plugService(cmdObj);
> +
> + if(!entitiesToAccess.isEmpty()){
> + Account owner = s_instance._accountMgr.getActiveAccountById(cmdObj.getEntityOwnerId());
> +
> + s_instance._accountMgr.checkAccess(caller, null, true, owner);
> +
> + s_instance._accountMgr.checkAccess(caller, null, true, (ControlledEntity[])entitiesToAccess.toArray());
> + }
> }
>
> BaseAsyncCmd asyncCmd = (BaseAsyncCmd) cmdObj;
>
Re: git commit: Some ACL POC work
Posted by David Nalley <da...@gnsa.us>.
Hi Prachi:
I am still trying to get caught up on my backlog of mail, is there a
place where you've discussed some of these ACL ideas?
--David
On Wed, Oct 24, 2012 at 5:11 PM, <pr...@apache.org> wrote:
> Updated Branches:
> refs/heads/acl f16b5103d -> 3058520ab
>
>
> Some ACL POC work
>
>
> Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo
> Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/3058520a
> Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/3058520a
> Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/3058520a
>
> Branch: refs/heads/acl
> Commit: 3058520ab3f09c31c142b41e37912e5ddd8d074a
> Parents: f16b510
> Author: Prachi Damle <pr...@cloud.com>
> Authored: Thu Oct 18 13:32:45 2012 -0700
> Committer: Prachi Damle <pr...@cloud.com>
> Committed: Thu Oct 18 13:32:45 2012 -0700
>
> ----------------------------------------------------------------------
> api/src/com/cloud/api/ACL.java | 31 +++++
> api/src/com/cloud/api/commands/DeployVMCmd.java | 9 ++
> server/src/com/cloud/api/ApiDispatcher.java | 126 +++++++++++++++++-
> server/src/com/cloud/api/ApiServer.java | 11 ++-
> 4 files changed, 172 insertions(+), 5 deletions(-)
> ----------------------------------------------------------------------
>
>
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/3058520a/api/src/com/cloud/api/ACL.java
> ----------------------------------------------------------------------
> diff --git a/api/src/com/cloud/api/ACL.java b/api/src/com/cloud/api/ACL.java
> new file mode 100644
> index 0000000..1f376e9
> --- /dev/null
> +++ b/api/src/com/cloud/api/ACL.java
> @@ -0,0 +1,31 @@
> +// Licensed to the Apache Software Foundation (ASF) under one
> +// or more contributor license agreements. See the NOTICE file
> +// distributed with this work for additional information
> +// regarding copyright ownership. The ASF licenses this file
> +// to you under the Apache License, Version 2.0 (the
> +// "License"); you may not use this file except in compliance
> +// with the License. You may obtain a copy of the License at
> +//
> +// http://www.apache.org/licenses/LICENSE-2.0
> +//
> +// Unless required by applicable law or agreed to in writing,
> +// software distributed under the License is distributed on an
> +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> +// KIND, either express or implied. See the License for the
> +// specific language governing permissions and limitations
> +// under the License.
> +package com.cloud.api;
> +
> +import static java.lang.annotation.ElementType.FIELD;
> +
> +import java.lang.annotation.Retention;
> +import java.lang.annotation.RetentionPolicy;
> +import java.lang.annotation.Target;
> +
> +@Retention(RetentionPolicy.RUNTIME)
> +@Target({ FIELD })
> +public @interface ACL {
> +
> +
> + Class<?> resourceType();
> +}
>
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/3058520a/api/src/com/cloud/api/commands/DeployVMCmd.java
> ----------------------------------------------------------------------
> diff --git a/api/src/com/cloud/api/commands/DeployVMCmd.java b/api/src/com/cloud/api/commands/DeployVMCmd.java
> index f67ee8f..da9f3ea 100644
> --- a/api/src/com/cloud/api/commands/DeployVMCmd.java
> +++ b/api/src/com/cloud/api/commands/DeployVMCmd.java
> @@ -26,6 +26,7 @@ import java.util.Map;
>
> import org.apache.log4j.Logger;
>
> +import com.cloud.api.ACL;
> import com.cloud.api.ApiConstants;
> import com.cloud.api.BaseAsyncCreateCmd;
> import com.cloud.api.BaseCmd;
> @@ -43,7 +44,10 @@ import com.cloud.exception.InsufficientCapacityException;
> import com.cloud.exception.InvalidParameterValueException;
> import com.cloud.exception.ResourceAllocationException;
> import com.cloud.exception.ResourceUnavailableException;
> +import com.cloud.host.Host;
> import com.cloud.hypervisor.Hypervisor.HypervisorType;
> +import com.cloud.network.Network;
> +import com.cloud.network.security.SecurityGroup;
> import com.cloud.offering.DiskOffering;
> import com.cloud.offering.ServiceOffering;
> import com.cloud.template.VirtualMachineTemplate;
> @@ -69,6 +73,7 @@ public class DeployVMCmd extends BaseAsyncCreateCmd {
> @Parameter(name=ApiConstants.SERVICE_OFFERING_ID, type=CommandType.LONG, required=true, description="the ID of the service offering for the virtual machine")
> private Long serviceOfferingId;
>
> + @ACL(resourceType=VirtualMachineTemplate.class)
> @IdentityMapper(entityTableName="vm_template")
> @Parameter(name=ApiConstants.TEMPLATE_ID, type=CommandType.LONG, required=true, description="the ID of the template for the virtual machine")
> private Long templateId;
> @@ -88,6 +93,7 @@ public class DeployVMCmd extends BaseAsyncCreateCmd {
> private Long domainId;
>
> //Network information
> + @ACL(resourceType=Network.class)
> @IdentityMapper(entityTableName="networks")
> @Parameter(name=ApiConstants.NETWORK_IDS, type=CommandType.LIST, collectionType=CommandType.LONG, description="list of network ids used by virtual machine. Can't be specified with ipToNetworkList parameter")
> private List<Long> networkIds;
> @@ -112,14 +118,17 @@ public class DeployVMCmd extends BaseAsyncCreateCmd {
> @Parameter(name=ApiConstants.SSH_KEYPAIR, type=CommandType.STRING, description="name of the ssh key pair used to login to the virtual machine")
> private String sshKeyPairName;
>
> + //@ACL(resourceType=Host.class)
> @IdentityMapper(entityTableName="host")
> @Parameter(name=ApiConstants.HOST_ID, type=CommandType.LONG, description="destination Host ID to deploy the VM to - parameter available for root admin only")
> private Long hostId;
>
> + //@ACL(resourceType=SecurityGroup.class)
> @IdentityMapper(entityTableName="security_group")
> @Parameter(name=ApiConstants.SECURITY_GROUP_IDS, type=CommandType.LIST, collectionType=CommandType.LONG, description="comma separated list of security groups id that going to be applied to the virtual machine. Should be passed only when vm is created from a zone with Basic Network support. Mutually exclusive with securitygroupnames parameter")
> private List<Long> securityGroupIdList;
>
> + //@ACL(resourceType=SecurityGroup.class)
> @Parameter(name=ApiConstants.SECURITY_GROUP_NAMES, type=CommandType.LIST, collectionType=CommandType.STRING, description="comma separated list of security groups names that going to be applied to the virtual machine. Should be passed only when vm is created from a zone with Basic Network support. Mutually exclusive with securitygroupids parameter")
> private List<String> securityGroupNameList;
>
>
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/3058520a/server/src/com/cloud/api/ApiDispatcher.java
> ----------------------------------------------------------------------
> diff --git a/server/src/com/cloud/api/ApiDispatcher.java b/server/src/com/cloud/api/ApiDispatcher.java
> index 8eade00..de7bdc6 100755
> --- a/server/src/com/cloud/api/ApiDispatcher.java
> +++ b/server/src/com/cloud/api/ApiDispatcher.java
> @@ -22,6 +22,7 @@ import java.text.ParseException;
> import java.util.ArrayList;
> import java.util.Calendar;
> import java.util.Date;
> +import java.util.HashMap;
> import java.util.List;
> import java.util.Map;
> import java.util.StringTokenizer;
> @@ -29,6 +30,7 @@ import java.util.regex.Matcher;
>
> import org.apache.log4j.Logger;
>
> +import com.cloud.acl.ControlledEntity;
> import com.cloud.api.BaseCmd.CommandType;
> import com.cloud.api.commands.ListEventsCmd;
> import com.cloud.async.AsyncCommandQueued;
> @@ -40,12 +42,17 @@ import com.cloud.exception.PermissionDeniedException;
> import com.cloud.exception.ResourceAllocationException;
> import com.cloud.exception.ResourceUnavailableException;
> import com.cloud.utils.IdentityProxy;
> +import com.cloud.network.dao.NetworkDao;
> import com.cloud.server.ManagementServer;
> +import com.cloud.storage.dao.VMTemplateDao;
> import com.cloud.user.Account;
> +import com.cloud.user.AccountManager;
> +import com.cloud.user.AccountService;
> import com.cloud.user.UserContext;
> import com.cloud.utils.DateUtil;
> import com.cloud.utils.component.ComponentLocator;
> import com.cloud.utils.component.PluggableService;
> +import com.cloud.utils.db.GenericDao;
> import com.cloud.utils.exception.CSExceptionErrorCode;
> import com.cloud.utils.exception.CloudRuntimeException;
> import com.cloud.uuididentity.dao.IdentityDao;
> @@ -59,7 +66,10 @@ public class ApiDispatcher {
> ComponentLocator _locator;
> AsyncJobManager _asyncMgr;
> IdentityDao _identityDao;
> + AccountManager _accountMgr;
>
> +
> + Map<String, Class<? extends GenericDao>> _daoNameMap = new HashMap<String, Class<? extends GenericDao>>();
> // singleton class
> private static ApiDispatcher s_instance = new ApiDispatcher();
>
> @@ -71,13 +81,30 @@ public class ApiDispatcher {
> _locator = ComponentLocator.getLocator(ManagementServer.Name);
> _asyncMgr = _locator.getManager(AsyncJobManager.class);
> _identityDao = _locator.getDao(IdentityDao.class);
> + _accountMgr = _locator.getManager(AccountManager.class);
> +
> + _daoNameMap.put("com.cloud.network.Network", NetworkDao.class);
> + _daoNameMap.put("com.cloud.template.VirtualMachineTemplate", VMTemplateDao.class);
> +
> +
> }
>
> public void dispatchCreateCmd(BaseAsyncCreateCmd cmd, Map<String, String> params) {
>
> - setupParameters(cmd, params);
> + List<ControlledEntity> entitiesToAccess = new ArrayList<ControlledEntity>();
> + setupParameters(cmd, params, entitiesToAccess);
> plugService(cmd);
>
> + if(!entitiesToAccess.isEmpty()){
> + //owner
> + Account caller = UserContext.current().getCaller();
> + Account owner = s_instance._accountMgr.getActiveAccountById(cmd.getEntityOwnerId());
> + s_instance._accountMgr.checkAccess(caller, null, true, owner);
> +
> + for(ControlledEntity entity : entitiesToAccess)
> + s_instance._accountMgr.checkAccess(caller, null, true, entity);
> + }
> +
> try {
> UserContext ctx = UserContext.current();
> ctx.setAccountId(cmd.getEntityOwnerId());
> @@ -118,8 +145,19 @@ public class ApiDispatcher {
> }
>
> public void dispatch(BaseCmd cmd, Map<String, String> params) {
> - setupParameters(cmd, params);
> + List<ControlledEntity> entitiesToAccess = new ArrayList<ControlledEntity>();
> + setupParameters(cmd, params, entitiesToAccess);
> ApiDispatcher.plugService(cmd);
> +
> + if(!entitiesToAccess.isEmpty()){
> + //owner
> + Account caller = UserContext.current().getCaller();
> + Account owner = s_instance._accountMgr.getActiveAccountById(cmd.getEntityOwnerId());
> + s_instance._accountMgr.checkAccess(caller, null, true, owner);
> + for(ControlledEntity entity : entitiesToAccess)
> + s_instance._accountMgr.checkAccess(caller, null, true, entity);
> + }
> +
> try {
> UserContext ctx = UserContext.current();
> ctx.setAccountId(cmd.getEntityOwnerId());
> @@ -270,8 +308,10 @@ public class ApiDispatcher {
> }
> }
>
> - public static void setupParameters(BaseCmd cmd, Map<String, String> params) {
> + @SuppressWarnings({ "unchecked", "rawtypes" })
> + public static void setupParameters(BaseCmd cmd, Map<String, String> params, List<ControlledEntity> entitiesToAccess) {
> Map<String, Object> unpackedParams = cmd.unpackParams(params);
> +
>
> if (cmd instanceof BaseListCmd) {
> Object pageSizeObj = unpackedParams.get(ApiConstants.PAGE_SIZE);
> @@ -339,12 +379,90 @@ public class ApiDispatcher {
> throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unable to execute API command " + cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8) + " due to invalid value. " + invEx.getMessage());
> } catch (CloudRuntimeException cloudEx) {
> // FIXME: Better error message? This only happens if the API command is not executable, which typically
> -// means
> + //means
> // there was
> // and IllegalAccessException setting one of the parameters.
> throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Internal error executing API command " + cmd.getCommandName().substring(0, cmd.getCommandName().length() - 8));
> }
> +
> +
> + //check access on the resource this field points to
> + try {
> + ACL checkAccess = field.getAnnotation(ACL.class);
> + CommandType fieldType = parameterAnnotation.type();
> +
> +
> + if(checkAccess != null){
> + // Verify that caller can perform actions in behalf of vm owner
> + //acumulate all Controlled Entities together.
> + if(checkAccess.resourceType() != null){
> + Class<?> entity = checkAccess.resourceType();
> +
> + if(ControlledEntity.class.isAssignableFrom(entity)){
> + if (s_logger.isDebugEnabled()) {
> + s_logger.debug("entity name is:" + entity.getName());
> + }
> +
> + if(s_instance._daoNameMap.containsKey(entity.getName())){
> + Class<? extends GenericDao> daoClass = s_instance._daoNameMap.get(entity.getName());
> + GenericDao daoClassInstance = s_instance._locator.getDao(daoClass);
> +
> + //Check if the parameter type is a single Id or list of id's/name's
> + switch (fieldType) {
> + case LIST:
> + CommandType listType = parameterAnnotation.collectionType();
> + switch (listType) {
> + case LONG:
> + List<Long> listParam = new ArrayList<Long>();
> + listParam = (List)field.get(cmd);
> +
> + for(Long entityId : listParam){
> + ControlledEntity entityObj = (ControlledEntity)daoClassInstance.findById(entityId);
> + entitiesToAccess.add(entityObj);
> + }
> + break;
> + /*case STRING:
> + List<String> listParam = new ArrayList<String>();
> + listParam = (List)field.get(cmd);
> + for(String entityName: listParam){
> + ControlledEntity entityObj = (ControlledEntity)daoClassInstance(entityId);
> + entitiesToAccess.add(entityObj);
> + }
> + break;
> + */
> + default:
> + break;
> + }
> + break;
> + case LONG:
> + Long entityId = (Long)field.get(cmd);
> + ControlledEntity entityObj = (ControlledEntity)daoClassInstance.findById(entityId);
> + entitiesToAccess.add(entityObj);
> + break;
> + default:
> + break;
> + }
> +
> +
> + }
> +
> + }
> +
> + }
> +
> + }
> +
> + } catch (IllegalArgumentException e) {
> + s_logger.error("Error initializing command " + cmd.getCommandName() + ", field " + field.getName() + " is not accessible.");
> + throw new CloudRuntimeException("Internal error initializing parameters for command " + cmd.getCommandName() + " [field " + field.getName() + " is not accessible]");
> + } catch (IllegalAccessException e) {
> + s_logger.error("Error initializing command " + cmd.getCommandName() + ", field " + field.getName() + " is not accessible.");
> + throw new CloudRuntimeException("Internal error initializing parameters for command " + cmd.getCommandName() + " [field " + field.getName() + " is not accessible]");
> + }
> +
> }
> +
> + //check access on the entities.
> }
>
> @SuppressWarnings({ "unchecked", "rawtypes" })
>
> http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/3058520a/server/src/com/cloud/api/ApiServer.java
> ----------------------------------------------------------------------
> diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java
> index eb5e770..3186d95 100755
> --- a/server/src/com/cloud/api/ApiServer.java
> +++ b/server/src/com/cloud/api/ApiServer.java
> @@ -81,6 +81,7 @@ import org.apache.http.protocol.ResponseDate;
> import org.apache.http.protocol.ResponseServer;
> import org.apache.log4j.Logger;
>
> +import com.cloud.acl.ControlledEntity;
> import com.cloud.api.response.ApiResponseSerializer;
> import com.cloud.api.response.ExceptionResponse;
> import com.cloud.api.response.ListResponse;
> @@ -486,8 +487,16 @@ public class ApiServer implements HttpRequestHandler {
> objectEntityTable = createCmd.getEntityTable();
> params.put("id", objectId.toString());
> } else {
> - ApiDispatcher.setupParameters(cmdObj, params);
> + List<ControlledEntity> entitiesToAccess = new ArrayList<ControlledEntity>();
> + ApiDispatcher.setupParameters(cmdObj, params, entitiesToAccess);
> ApiDispatcher.plugService(cmdObj);
> +
> + if(!entitiesToAccess.isEmpty()){
> + Account owner = s_instance._accountMgr.getActiveAccountById(cmdObj.getEntityOwnerId());
> + s_instance._accountMgr.checkAccess(caller, null, true, owner);
> +
> + s_instance._accountMgr.checkAccess(caller, null, true, (ControlledEntity[])entitiesToAccess.toArray());
> + }
> }
>
> BaseAsyncCmd asyncCmd = (BaseAsyncCmd) cmdObj;
>