From d12422bf68a1f71da2ad99a3d0fd17d6578384d9 Mon Sep 17 00:00:00 2001 From: Prachi Damle Date: Wed, 29 Jan 2014 23:47:08 -0800 Subject: [PATCH] Add policies to domain group for CreateNetwork usecase for a domain wide shared network --- .../orchestration/NetworkOrchestrator.java | 10 +++ .../acl/RoleBasedAPIAccessChecker.java | 14 +-- .../cloudstack/acl/api/AclApiService.java | 3 +- .../cloudstack/acl/api/AclApiServiceImpl.java | 88 +++++++++++++++++-- .../AddAclPermissionToAclPolicyCmd.java | 3 +- .../cloudstack/acl/AclApiServiceTest.java | 12 ++- .../apache/cloudstack/iam/api/IAMService.java | 2 +- .../iam/server/AclPolicyPermissionVO.java | 8 +- .../cloudstack/iam/server/IAMServiceImpl.java | 5 +- .../src/com/cloud/utils/db/EntityManager.java | 2 + 10 files changed, 119 insertions(+), 28 deletions(-) diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java index 85fa530e820..8857c001c8d 100755 --- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java @@ -36,6 +36,7 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.cloudstack.acl.AclEntityType; import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; @@ -43,6 +44,8 @@ import org.apache.cloudstack.framework.config.ConfigDepot; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.framework.messagebus.MessageBus; +import org.apache.cloudstack.framework.messagebus.PublishScope; import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.region.PortableIpDao; import org.apache.log4j.Logger; @@ -253,6 +256,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra protected IPAddressDao _publicIpAddressDao; @Inject protected IpAddressManager _ipAddrMgr; + @Inject + MessageBus _messageBus; List networkGurus; @@ -664,6 +669,11 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra if (domainId != null && aclType == ACLType.Domain) { _networksDao.addDomainToNetwork(id, domainId, subdomainAccess == null ? true : subdomainAccess); + //send event for storing the domain wide resource access + // remove its related ACL permission + Pair network = new Pair(AclEntityType.Network, id); + _messageBus.publish(_name, EntityManager.MESSAGE_ADD_DOMAIN_WIDE_ENTITY_EVENT, + PublishScope.LOCAL, network); } } }); diff --git a/services/iam/plugin/src/org/apache/cloudstack/acl/RoleBasedAPIAccessChecker.java b/services/iam/plugin/src/org/apache/cloudstack/acl/RoleBasedAPIAccessChecker.java index 5a322987140..01e3d752726 100644 --- a/services/iam/plugin/src/org/apache/cloudstack/acl/RoleBasedAPIAccessChecker.java +++ b/services/iam/plugin/src/org/apache/cloudstack/acl/RoleBasedAPIAccessChecker.java @@ -120,19 +120,19 @@ public class RoleBasedAPIAccessChecker extends AdapterBase implements APIChecker // add the system-domain capability _iamSrv.addAclPermissionToAclPolicy(new Long(Account.ACCOUNT_TYPE_ADMIN + 1), null, null, null, - "SystemCapability", null, Permission.Allow); + "SystemCapability", null, Permission.Allow, false); _iamSrv.addAclPermissionToAclPolicy(new Long(Account.ACCOUNT_TYPE_DOMAIN_ADMIN + 1), null, null, null, - "DomainCapability", null, Permission.Allow); + "DomainCapability", null, Permission.Allow, false); _iamSrv.addAclPermissionToAclPolicy(new Long(Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN + 1), null, null, null, - "DomainResourceCapability", null, Permission.Allow); + "DomainResourceCapability", null, Permission.Allow, false); // add permissions for public templates List pTmplts = _templateDao.listByPublic(); for (VMTemplateVO tmpl : pTmplts){ _iamSrv.addAclPermissionToAclPolicy(new Long(Account.ACCOUNT_TYPE_DOMAIN_ADMIN + 1), AclEntityType.VirtualMachineTemplate.toString(), - PermissionScope.RESOURCE.toString(), tmpl.getId(), "listTemplates", AccessType.UseEntry.toString(), Permission.Allow); + PermissionScope.RESOURCE.toString(), tmpl.getId(), "listTemplates", AccessType.UseEntry.toString(), Permission.Allow, false); _iamSrv.addAclPermissionToAclPolicy(new Long(Account.ACCOUNT_TYPE_NORMAL + 1), AclEntityType.VirtualMachineTemplate.toString(), - PermissionScope.RESOURCE.toString(), tmpl.getId(), "listTemplates", AccessType.UseEntry.toString(), Permission.Allow); + PermissionScope.RESOURCE.toString(), tmpl.getId(), "listTemplates", AccessType.UseEntry.toString(), Permission.Allow, false); } for (PluggableService service : _services) { @@ -256,11 +256,11 @@ public class RoleBasedAPIAccessChecker extends AdapterBase implements APIChecker if (entityTypes == null || entityTypes.length == 0) { _iamSrv.addAclPermissionToAclPolicy(policyId, null, permissionScope.toString(), new Long(AclPolicyPermission.PERMISSION_SCOPE_ID_CURRENT_CALLER), - apiName, (accessType == null) ? null : accessType.toString(), Permission.Allow); + apiName, (accessType == null) ? null : accessType.toString(), Permission.Allow, false); } else { for (AclEntityType entityType : entityTypes) { _iamSrv.addAclPermissionToAclPolicy(policyId, entityType.toString(), permissionScope.toString(), new Long(AclPolicyPermission.PERMISSION_SCOPE_ID_CURRENT_CALLER), - apiName, (accessType == null) ? null : accessType.toString(), Permission.Allow); + apiName, (accessType == null) ? null : accessType.toString(), Permission.Allow, false); } } diff --git a/services/iam/plugin/src/org/apache/cloudstack/acl/api/AclApiService.java b/services/iam/plugin/src/org/apache/cloudstack/acl/api/AclApiService.java index 8b964955d7a..45b39574f34 100644 --- a/services/iam/plugin/src/org/apache/cloudstack/acl/api/AclApiService.java +++ b/services/iam/plugin/src/org/apache/cloudstack/acl/api/AclApiService.java @@ -59,7 +59,8 @@ public interface AclApiService extends PluggableService { void removeAclPolicyFromAccounts(Long policyId, List accountIds); - AclPolicy addAclPermissionToAclPolicy(long aclPolicyId, String entityType, PermissionScope scope, Long scopeId, String action, Permission perm); + AclPolicy addAclPermissionToAclPolicy(long aclPolicyId, String entityType, PermissionScope scope, Long scopeId, + String action, Permission perm, Boolean recursive); AclPolicy removeAclPermissionFromAclPolicy(long aclPolicyId, String entityType, PermissionScope scope, Long scopeId, String action); diff --git a/services/iam/plugin/src/org/apache/cloudstack/acl/api/AclApiServiceImpl.java b/services/iam/plugin/src/org/apache/cloudstack/acl/api/AclApiServiceImpl.java index ee33620cc86..892a7bbb8e4 100644 --- a/services/iam/plugin/src/org/apache/cloudstack/acl/api/AclApiServiceImpl.java +++ b/services/iam/plugin/src/org/apache/cloudstack/acl/api/AclApiServiceImpl.java @@ -67,6 +67,8 @@ import com.cloud.domain.dao.DomainDao; import com.cloud.event.ActionEvent; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.network.dao.NetworkDomainDao; +import com.cloud.network.dao.NetworkDomainVO; import com.cloud.template.TemplateManager; import com.cloud.user.Account; import com.cloud.user.AccountManager; @@ -103,6 +105,9 @@ public class AclApiServiceImpl extends ManagerBase implements AclApiService, Man @Inject MessageBus _messageBus; + @Inject + NetworkDomainDao _networkDomainDao; + @Override public boolean configure(final String name, final Map params) throws ConfigurationException { _messageBus.subscribe(AccountManager.MESSAGE_ADD_ACCOUNT_EVENT, new MessageSubscriber() { @@ -118,10 +123,10 @@ public class AclApiServiceImpl extends ManagerBase implements AclApiService, Man AccountVO account = _accountDao.findById(accountId); Domain domain = _domainDao.findById(account.getDomainId()); if (domain != null) { - ListResponse domainGroups = listAclGroups(null, - "DomainGrp-" + domain.getUuid(), domain.getId(), null, null); - if (domainGroups.getResponses() != null) { - for (AclGroupResponse group : domainGroups.getResponses()) { + List domainGroups = listDomainGroup(domain); + + if (domainGroups != null) { + for (AclGroup group : domainGroups) { addAccountToAclGroup(accountId, new Long(group.getId())); } } @@ -161,9 +166,9 @@ public class AclApiServiceImpl extends ManagerBase implements AclApiService, Man if (templateId != null) { s_logger.debug("MessageBus message: new public template registered: " + templateId + ", grant permission to domain admin and normal user policies"); _iamSrv.addAclPermissionToAclPolicy(new Long(Account.ACCOUNT_TYPE_DOMAIN_ADMIN + 1), AclEntityType.VirtualMachineTemplate.toString(), - PermissionScope.RESOURCE.toString(), templateId, "listTemplates", AccessType.UseEntry.toString(), Permission.Allow); + PermissionScope.RESOURCE.toString(), templateId, "listTemplates", AccessType.UseEntry.toString(), Permission.Allow, false); _iamSrv.addAclPermissionToAclPolicy(new Long(Account.ACCOUNT_TYPE_NORMAL + 1), AclEntityType.VirtualMachineTemplate.toString(), - PermissionScope.RESOURCE.toString(), templateId, "listTemplates", AccessType.UseEntry.toString(), Permission.Allow); + PermissionScope.RESOURCE.toString(), templateId, "listTemplates", AccessType.UseEntry.toString(), Permission.Allow, false); } } }); @@ -181,6 +186,7 @@ public class AclApiServiceImpl extends ManagerBase implements AclApiService, Man } }); + _messageBus.subscribe(EntityManager.MESSAGE_GRANT_ENTITY_EVENT, new MessageSubscriber() { @Override public void onPublishMessage(String senderAddress, String subject, Object obj) { @@ -197,9 +203,58 @@ public class AclApiServiceImpl extends ManagerBase implements AclApiService, Man } }); + _messageBus.subscribe(EntityManager.MESSAGE_ADD_DOMAIN_WIDE_ENTITY_EVENT, new MessageSubscriber() { + @Override + public void onPublishMessage(String senderAddress, String subject, Object obj) { + Pair entity = (Pair) obj; + if (entity != null) { + addDomainWideResourceAccess(entity); + } + } + }); + return super.configure(name, params); } + private void addDomainWideResourceAccess(Pair entity) { + + String entityType = entity.first().toString(); + Long entityId = entity.second(); + + if (AclEntityType.Network.toString().equals(entityType)) { + NetworkDomainVO networkDomainMap = _networkDomainDao.getDomainNetworkMapByNetworkId(entityId); + if (networkDomainMap != null) { + createPolicyAndAddToDomainGroup("DomainWideNetwork-" + entityId, "domain wide network", entityType, + entityId, "listNetworks", AccessType.UseEntry, networkDomainMap.getDomainId(), + networkDomainMap.isSubdomainAccess()); + } + } else if (AclEntityType.AffinityGroup.toString().equals(entityType)) { + + } + + } + + private void createPolicyAndAddToDomainGroup(String policyName, String description, String entityType, + Long entityId, String action, AccessType accessType, Long domainId, Boolean recursive) { + + AclPolicy policy = _iamSrv.createAclPolicy(policyName, description, null); + _iamSrv.addAclPermissionToAclPolicy(policy.getId(), entityType, PermissionScope.RESOURCE.toString(), + entityId, action, accessType.toString(), Permission.Allow, recursive); + + List policyList = new ArrayList(); + policyList.add(new Long(policy.getId())); + + Domain domain = _domainDao.findById(domainId); + if (domain != null) { + List domainGroups = listDomainGroup(domain); + if (domainGroups != null) { + for (AclGroup group : domainGroups) { + _iamSrv.attachAclPoliciesToGroup(policyList, group.getId()); + } + } + } + } + @DB @Override @ActionEvent(eventType = EventTypes.EVENT_ACL_GROUP_CREATE, eventDescription = "Creating Acl Group", create = true) @@ -309,13 +364,15 @@ public class AclApiServiceImpl extends ManagerBase implements AclApiService, Man @DB @Override @ActionEvent(eventType = EventTypes.EVENT_ACL_POLICY_GRANT, eventDescription = "Granting acl permission to Acl Policy") - public AclPolicy addAclPermissionToAclPolicy(long aclPolicyId, String entityType, PermissionScope scope, Long scopeId, String action, Permission perm) { + public AclPolicy addAclPermissionToAclPolicy(long aclPolicyId, String entityType, PermissionScope scope, + Long scopeId, String action, Permission perm, Boolean recursive) { Class cmdClass = _apiServer.getCmdClass(action); AccessType accessType = null; if (BaseListCmd.class.isAssignableFrom(cmdClass)) { accessType = AccessType.ListEntry; } - return _iamSrv.addAclPermissionToAclPolicy(aclPolicyId, entityType, scope.toString(), scopeId, action, accessType.toString(), perm); + return _iamSrv.addAclPermissionToAclPolicy(aclPolicyId, entityType, scope.toString(), scopeId, action, + accessType.toString(), perm, recursive); } @DB @@ -426,6 +483,19 @@ public class AclApiServiceImpl extends ManagerBase implements AclApiService, Man } + public List listDomainGroup(Domain domain) { + + if (domain != null) { + String domainPath = domain.getPath(); + // search for groups + Pair, Integer> result = _iamSrv.listAclGroups(null, "DomainGrp-" + domain.getUuid(), + domainPath, null, null); + return result.first(); + } + return new ArrayList(); + + } + @Override public ListResponse listAclGroups(Long aclGroupId, String aclGroupName, Long domainId, Long startIndex, Long pageSize) { // acl check @@ -498,7 +568,7 @@ public class AclApiServiceImpl extends ManagerBase implements AclApiService, Man String description = "Policy to grant permission to " + entityType + entityId; policy = createAclPolicy(caller, aclPolicyName, description, null); // add permission to this policy - addAclPermissionToAclPolicy(policy.getId(), entityType, PermissionScope.RESOURCE, entityId, action, Permission.Allow); + addAclPermissionToAclPolicy(policy.getId(), entityType, PermissionScope.RESOURCE, entityId, action, Permission.Allow, false); } // attach this policy to list of accounts if not attached already Long policyId = policy.getId(); diff --git a/services/iam/plugin/src/org/apache/cloudstack/acl/api/command/AddAclPermissionToAclPolicyCmd.java b/services/iam/plugin/src/org/apache/cloudstack/acl/api/command/AddAclPermissionToAclPolicyCmd.java index 33cae754158..ec9596a9a7c 100644 --- a/services/iam/plugin/src/org/apache/cloudstack/acl/api/command/AddAclPermissionToAclPolicyCmd.java +++ b/services/iam/plugin/src/org/apache/cloudstack/acl/api/command/AddAclPermissionToAclPolicyCmd.java @@ -122,7 +122,8 @@ public class AddAclPermissionToAclPolicyCmd extends BaseAsyncCmd { InsufficientCapacityException, ServerApiException { CallContext.current().setEventDetails("Acl policy Id: " + getId()); // Only explicit ALLOW is supported for this release, no explicit deny - AclPolicy result = _aclApiSrv.addAclPermissionToAclPolicy(id, entityType, PermissionScope.valueOf(scope), scopeId, action, Permission.Allow); + AclPolicy result = _aclApiSrv.addAclPermissionToAclPolicy(id, entityType, PermissionScope.valueOf(scope), + scopeId, action, Permission.Allow, false); if (result != null) { AclPolicyResponse response = _aclApiSrv.createAclPolicyResponse(result); response.setResponseName(getCommandName()); diff --git a/services/iam/plugin/test/org/apache/cloudstack/acl/AclApiServiceTest.java b/services/iam/plugin/test/org/apache/cloudstack/acl/AclApiServiceTest.java index 676c0abaafd..4d418e59a9e 100644 --- a/services/iam/plugin/test/org/apache/cloudstack/acl/AclApiServiceTest.java +++ b/services/iam/plugin/test/org/apache/cloudstack/acl/AclApiServiceTest.java @@ -63,6 +63,7 @@ import com.cloud.user.UserVO; import com.cloud.user.dao.AccountDao; import com.cloud.utils.Pair; import com.cloud.utils.component.ComponentContext; +import com.cloud.network.dao.NetworkDomainDao; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(loader = AnnotationConfigContextLoader.class) @@ -272,13 +273,13 @@ public class AclApiServiceTest { when(_apiServer.getCmdClass("listVirtualMachines")).thenReturn(clz); when( _iamSrv.addAclPermissionToAclPolicy(policyId, AclEntityType.VirtualMachine.toString(), PermissionScope.RESOURCE.toString(), resId, "listVirtualMachines", - AccessType.ListEntry.toString(), Permission.Allow)).thenReturn(policy); - _aclSrv.addAclPermissionToAclPolicy(policyId, AclEntityType.VirtualMachine.toString(), PermissionScope.RESOURCE, resId, "listVirtualMachines", Permission.Allow); + AccessType.ListEntry.toString(), Permission.Allow, false)).thenReturn(policy); + _aclSrv.addAclPermissionToAclPolicy(policyId, AclEntityType.VirtualMachine.toString(), PermissionScope.RESOURCE, resId, "listVirtualMachines", Permission.Allow, false); Pair, Integer> policyList = new Pair, Integer>(policies, 1); List policyPerms = new ArrayList(); AclPolicyPermission perm = new AclPolicyPermissionVO(policyId, "listVirtualMachines", AclEntityType.VirtualMachine.toString(), AccessType.ListEntry.toString(), PermissionScope.RESOURCE.toString(), - resId, Permission.Allow); + resId, Permission.Allow, false); policyPerms.add(perm); when(_iamSrv.listAclPolicies(null, "policy1", callerDomainPath, 0L, 20L)).thenReturn(policyList); when(_iamSrv.listPolicyPermissions(policyId)).thenReturn(policyPerms); @@ -323,6 +324,11 @@ public class AclApiServiceTest { return Mockito.mock(AccountDao.class); } + @Bean + public NetworkDomainDao networkDomainDao() { + return Mockito.mock(NetworkDomainDao.class); + } + @Bean public AccountManager accountManager() { return Mockito.mock(AccountManager.class); diff --git a/services/iam/server/src/org/apache/cloudstack/iam/api/IAMService.java b/services/iam/server/src/org/apache/cloudstack/iam/api/IAMService.java index 76fab055efe..694abd5282d 100644 --- a/services/iam/server/src/org/apache/cloudstack/iam/api/IAMService.java +++ b/services/iam/server/src/org/apache/cloudstack/iam/api/IAMService.java @@ -59,7 +59,7 @@ public interface IAMService { void removeAclPolicyFromAccounts(Long policyId, List acctIds); AclPolicy addAclPermissionToAclPolicy(long aclPolicyId, String entityType, String scope, Long scopeId, - String action, String accessType, Permission perm); + String action, String accessType, Permission perm, Boolean recursive); AclPolicy removeAclPermissionFromAclPolicy(long aclPolicyId, String entityType, String scope, Long scopeId, String action); diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/AclPolicyPermissionVO.java b/services/iam/server/src/org/apache/cloudstack/iam/server/AclPolicyPermissionVO.java index 47576119a73..5d2a36b9294 100644 --- a/services/iam/server/src/org/apache/cloudstack/iam/server/AclPolicyPermissionVO.java +++ b/services/iam/server/src/org/apache/cloudstack/iam/server/AclPolicyPermissionVO.java @@ -60,9 +60,9 @@ public class AclPolicyPermissionVO implements AclPolicyPermission { @Column(name = "permission") @Enumerated(value = EnumType.STRING) private Permission permission; - + @Column(name = "recursive") - private Boolean recursive; + private Boolean recursive; @Column(name = GenericDao.REMOVED_COLUMN) private Date removed; @@ -173,9 +173,9 @@ public class AclPolicyPermissionVO implements AclPolicyPermission { public Date getCreated() { return created; } - + public Boolean isRecursive() { return recursive; } - + } diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/IAMServiceImpl.java b/services/iam/server/src/org/apache/cloudstack/iam/server/IAMServiceImpl.java index 9d8e2b4ca99..1dbfaef6764 100644 --- a/services/iam/server/src/org/apache/cloudstack/iam/server/IAMServiceImpl.java +++ b/services/iam/server/src/org/apache/cloudstack/iam/server/IAMServiceImpl.java @@ -543,7 +543,7 @@ public class IAMServiceImpl extends ManagerBase implements IAMService, Manager { @DB @Override public AclPolicy addAclPermissionToAclPolicy(long aclPolicyId, String entityType, String scope, Long scopeId, - String action, String accessType, Permission perm) { + String action, String accessType, Permission perm, Boolean recursive) { // get the Acl Policy entity AclPolicy policy = _aclPolicyDao.findById(aclPolicyId); if (policy == null) { @@ -555,7 +555,8 @@ public class IAMServiceImpl extends ManagerBase implements IAMService, Manager { AclPolicyPermissionVO permit = _policyPermissionDao.findByPolicyAndEntity(aclPolicyId, entityType, scope, scopeId, action, perm); if (permit == null) { // not there already - permit = new AclPolicyPermissionVO(aclPolicyId, action, entityType, accessType, scope, scopeId, perm, false); + permit = new AclPolicyPermissionVO(aclPolicyId, action, entityType, accessType, scope, scopeId, perm, + recursive); _policyPermissionDao.persist(permit); } return policy; diff --git a/utils/src/com/cloud/utils/db/EntityManager.java b/utils/src/com/cloud/utils/db/EntityManager.java index 3226e908c39..79ef2a0157a 100644 --- a/utils/src/com/cloud/utils/db/EntityManager.java +++ b/utils/src/com/cloud/utils/db/EntityManager.java @@ -72,5 +72,7 @@ public interface EntityManager { public void remove(Class entityType, K id); public static final String MESSAGE_REMOVE_ENTITY_EVENT = "Message.RemoveEntity.Event"; + public static final String MESSAGE_GRANT_ENTITY_EVENT = "Message.GrantEntity.Event"; + public static final String MESSAGE_ADD_DOMAIN_WIDE_ENTITY_EVENT = "Message.AddDomainWideEntity.Event"; }