http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c28450c1/services/iam/plugin/test/org/apache/cloudstack/iam/test/IAMApiServiceTest.java ---------------------------------------------------------------------- diff --git a/services/iam/plugin/test/org/apache/cloudstack/iam/test/IAMApiServiceTest.java b/services/iam/plugin/test/org/apache/cloudstack/iam/test/IAMApiServiceTest.java new file mode 100644 index 0000000..dc5c168 --- /dev/null +++ b/services/iam/plugin/test/org/apache/cloudstack/iam/test/IAMApiServiceTest.java @@ -0,0 +1,369 @@ +package org.apache.cloudstack.iam.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.UUID; + +import javax.inject.Inject; +import javax.naming.ConfigurationException; + +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.ComponentScan.Filter; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; +import org.springframework.core.type.classreading.MetadataReader; +import org.springframework.core.type.classreading.MetadataReaderFactory; +import org.springframework.core.type.filter.TypeFilter; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import org.apache.cloudstack.acl.IAMEntityType; +import org.apache.cloudstack.acl.PermissionScope; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.api.command.user.vm.ListVMsCmd; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.iam.IAMGroupResponse; +import org.apache.cloudstack.api.response.iam.IAMPermissionResponse; +import org.apache.cloudstack.api.response.iam.IAMPolicyResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.framework.messagebus.MessageBus; +import org.apache.cloudstack.iam.IAMApiService; +import org.apache.cloudstack.iam.IAMApiServiceImpl; +import org.apache.cloudstack.iam.api.IAMGroup; +import org.apache.cloudstack.iam.api.IAMPolicy; +import org.apache.cloudstack.iam.api.IAMPolicyPermission; +import org.apache.cloudstack.iam.api.IAMPolicyPermission.Permission; +import org.apache.cloudstack.iam.api.IAMService; +import org.apache.cloudstack.iam.server.IAMGroupVO; +import org.apache.cloudstack.iam.server.IAMPolicyPermissionVO; +import org.apache.cloudstack.iam.server.IAMPolicyVO; +import org.apache.cloudstack.test.utils.SpringUtils; + +import com.cloud.api.ApiServerService; +import com.cloud.domain.DomainVO; +import com.cloud.domain.dao.DomainDao; +import com.cloud.network.dao.NetworkDomainDao; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; +import com.cloud.user.AccountVO; +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.utils.db.EntityManager; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(loader = AnnotationConfigContextLoader.class) +public class IAMApiServiceTest { + + @Inject + IAMService _iamSrv; + + @Inject + DomainDao _domainDao; + + @Inject + IAMApiService _aclSrv; + + @Inject + AccountManager _accountMgr; + + @Inject + AccountDao _accountDao; + + @Inject + ApiServerService _apiServer; + + private static Account caller; + private static Long callerId; + private static String callerAccountName = "tester"; + private static Long callerDomainId = 3L; + private static String callerDomainPath = "/root/testdomain"; + private static DomainVO callerDomain; + + @BeforeClass + public static void setUpClass() throws ConfigurationException { + } + + @Before + public void setUp() { + ComponentContext.initComponentsLifeCycle(); + caller = new AccountVO(callerAccountName, callerDomainId, null, Account.ACCOUNT_TYPE_ADMIN, UUID.randomUUID().toString()); + callerId = caller.getId(); + callerDomain = new DomainVO(); + callerDomain.setPath(callerDomainPath); + UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString()); + CallContext.register(user, caller); + + when(_domainDao.findById(callerDomainId)).thenReturn(callerDomain); + doNothing().when(_accountMgr).checkAccess(caller, callerDomain); + } + + @Test + public void createIAMGroupTest() { + IAMGroup group = new IAMGroupVO("group1", "tester group1"); + List<IAMGroup> groups = new ArrayList<IAMGroup>(); + groups.add(group); + Pair<List<IAMGroup>, Integer> grpList = new Pair<List<IAMGroup>, Integer>(groups, 1); + when(_iamSrv.createIAMGroup("group1", "tester group1", callerDomainPath)).thenReturn(group); + when(_iamSrv.listIAMGroups(null, null, callerDomainPath, 0L, 20L)).thenReturn(grpList); + + IAMGroup createdGrp = _aclSrv.createIAMGroup(caller, "group1", "tester group1"); + assertNotNull("IAM group 'group1' failed to create ", createdGrp); + ListResponse<IAMGroupResponse> grpResp = _aclSrv.listIAMGroups(null, null, callerDomainId, 0L, 20L); + assertTrue("No. of response items should be one", grpResp.getCount() == 1); + IAMGroupResponse resp = grpResp.getResponses().get(0); + assertEquals("Error in created group name", "group1", resp.getName()); + } + + @Test + public void deleteIAMGroupTest() { + when(_iamSrv.deleteIAMGroup(1L)).thenReturn(true); + assertTrue("failed to delete acl group 1", _aclSrv.deleteIAMGroup(1L)); + } + + @Test + public void listIAMGroupTest() { + IAMGroup group = new IAMGroupVO("group1", "tester group1"); + List<IAMGroup> groups = new ArrayList<IAMGroup>(); + groups.add(group); + when(_iamSrv.listIAMGroups(callerId)).thenReturn(groups); + List<IAMGroup> grps = _aclSrv.listIAMGroups(callerId); + assertTrue(grps != null && grps.size() == 1); + IAMGroup grp = grps.get(0); + assertEquals("Error to retrieve group", "group1", grp.getName()); + } + + @Test + public void addRemoveAccountToGroupTest() { + IAMGroup group = new IAMGroupVO("group1", "tester group1"); + List<IAMGroup> groups = new ArrayList<IAMGroup>(); + groups.add(group); + Long groupId = group.getId(); + List<Long> acctIds = new ArrayList<Long>(); + AccountVO acct1 = new AccountVO(100L); + acct1.setAccountName("account1"); + AccountVO acct2 = new AccountVO(200L); + acct2.setAccountName("account2"); + acctIds.add(acct1.getId()); + acctIds.add(acct2.getId()); + when(_accountDao.findById(acct1.getId())).thenReturn(acct1); + when(_accountDao.findById(acct2.getId())).thenReturn(acct2); + when(_iamSrv.addAccountsToGroup(acctIds, groupId)).thenReturn(group); + when(_iamSrv.listAccountsByGroup(groupId)).thenReturn(acctIds); + Pair<List<IAMGroup>, Integer> grpList = new Pair<List<IAMGroup>, Integer>(groups, 1); + when(_iamSrv.listIAMGroups(null, "group1", callerDomainPath, 0L, 20L)).thenReturn(grpList); + _aclSrv.addAccountsToGroup(acctIds, groupId); + ListResponse<IAMGroupResponse> grpResp = _aclSrv.listIAMGroups(null, "group1", callerDomainId, 0L, 20L); + assertTrue("No. of response items should be one", grpResp.getCount() == 1); + IAMGroupResponse resp = grpResp.getResponses().get(0); + Set<String> acctNames = resp.getAccountNameList(); + assertEquals("There should be 2 accounts in the group", 2, acctNames.size()); + assertTrue("account1 should be assigned to the group", acctNames.contains("account1")); + assertTrue("account2 should be assigned to the group", acctNames.contains("account2")); + // remove "account2" from group1 + acctIds.remove(1); + List<Long> rmAccts = new ArrayList<Long>(); + rmAccts.add(acct2.getId()); + when(_iamSrv.removeAccountsFromGroup(rmAccts, groupId)).thenReturn(group); + _aclSrv.removeAccountsFromGroup(acctIds, groupId); + grpResp = _aclSrv.listIAMGroups(null, "group1", callerDomainId, 0L, 20L); + assertTrue("No. of response items should be one", grpResp.getCount() == 1); + resp = grpResp.getResponses().get(0); + acctNames = resp.getAccountNameList(); + assertEquals("There should be 1 accounts in the group", 1, acctNames.size()); + assertFalse("account2 should not belong to the group anymore", acctNames.contains("account2")); + } + + @Test + public void createIAMPolicyTest() { + IAMPolicy policy = new IAMPolicyVO("policy1", "tester policy1"); + List<IAMPolicy> policies = new ArrayList<IAMPolicy>(); + policies.add(policy); + Pair<List<IAMPolicy>, Integer> policyList = new Pair<List<IAMPolicy>, Integer>(policies, 1); + when(_iamSrv.createIAMPolicy("policy1", "tester policy1", null, callerDomainPath)).thenReturn(policy); + when(_iamSrv.listIAMPolicies(null, null, callerDomainPath, 0L, 20L)).thenReturn(policyList); + + IAMPolicy createdPolicy = _aclSrv.createIAMPolicy(caller, "policy1", "tester policy1", null); + assertNotNull("IAM policy 'policy1' failed to create ", createdPolicy); + ListResponse<IAMPolicyResponse> policyResp = _aclSrv.listIAMPolicies(null, null, callerDomainId, 0L, 20L); + assertTrue("No. of response items should be one", policyResp.getCount() == 1); + IAMPolicyResponse resp = policyResp.getResponses().get(0); + assertEquals("Error in created group name", "policy1", resp.getName()); + } + + @Test + public void deleteIAMPolicyTest() { + when(_iamSrv.deleteIAMPolicy(1L)).thenReturn(true); + assertTrue("failed to delete acl policy 1", _aclSrv.deleteIAMPolicy(1L)); + } + + @Test + public void listIAMPolicyTest() { + IAMPolicy policy = new IAMPolicyVO("policy1", "tester policy1"); + List<IAMPolicy> policies = new ArrayList<IAMPolicy>(); + policies.add(policy); + when(_iamSrv.listIAMPolicies(callerId)).thenReturn(policies); + List<IAMPolicy> polys = _aclSrv.listIAMPolicies(callerId); + assertTrue(polys != null && polys.size() == 1); + IAMPolicy p = polys.get(0); + assertEquals("Error to retrieve group", "policy1", p.getName()); + } + + @Test + public void addRemovePolicyToGroupTest() { + IAMGroup group = new IAMGroupVO("group1", "tester group1"); + List<IAMGroup> groups = new ArrayList<IAMGroup>(); + groups.add(group); + Long groupId = group.getId(); + List<Long> policyIds = new ArrayList<Long>(); + policyIds.add(100L); + policyIds.add(200L); + IAMPolicy policy1 = new IAMPolicyVO("policy1", "my first policy"); + IAMPolicy policy2 = new IAMPolicyVO("policy2", "my second policy"); + List<IAMPolicy> policies = new ArrayList<IAMPolicy>(); + policies.add(policy1); + policies.add(policy2); + when(_iamSrv.attachIAMPoliciesToGroup(policyIds, groupId)).thenReturn(group); + when(_iamSrv.listIAMPoliciesByGroup(groupId)).thenReturn(policies); + Pair<List<IAMGroup>, Integer> grpList = new Pair<List<IAMGroup>, Integer>(groups, 1); + when(_iamSrv.listIAMGroups(null, "group1", callerDomainPath, 0L, 20L)).thenReturn(grpList); + _aclSrv.attachIAMPoliciesToGroup(policyIds, groupId); + ListResponse<IAMGroupResponse> grpResp = _aclSrv.listIAMGroups(null, "group1", callerDomainId, 0L, 20L); + assertTrue("No. of response items should be one", grpResp.getCount() == 1); + IAMGroupResponse resp = grpResp.getResponses().get(0); + Set<String> policyNames = resp.getPolicyList(); + assertEquals("There should be 2 policies in the group", 2, policyNames.size()); + assertTrue("policy1 should be assigned to the group", policyNames.contains("policy1")); + assertTrue("policy2 should be assigned to the group", policyNames.contains("policy2")); + // remove "policy2" from group1 + policyIds.remove(1); + policies.remove(policy2); + when(_iamSrv.removeIAMPoliciesFromGroup(policyIds, groupId)).thenReturn(group); + _aclSrv.removeIAMPoliciesFromGroup(policyIds, groupId); + grpResp = _aclSrv.listIAMGroups(null, "group1", callerDomainId, 0L, 20L); + assertTrue("No. of response items should be one", grpResp.getCount() == 1); + resp = grpResp.getResponses().get(0); + policyNames = resp.getPolicyList(); + assertEquals("There should be 1 policy attached to the group", 1, policyNames.size()); + assertFalse("policy2 should not belong to the group anymore", policyNames.contains("policy2")); + } + + @Test + public void addRemovePermissionToPolicyTest() { + IAMPolicy policy = new IAMPolicyVO("policy1", "tester policy1"); + List<IAMPolicy> policies = new ArrayList<IAMPolicy>(); + policies.add(policy); + Long policyId = policy.getId(); + Long resId = 200L; + Class clz = ListVMsCmd.class; + when(_apiServer.getCmdClass("listVirtualMachines")).thenReturn(clz); + when( + _iamSrv.addIAMPermissionToIAMPolicy(policyId, IAMEntityType.VirtualMachine.toString(), + PermissionScope.RESOURCE.toString(), resId, "listVirtualMachines", + AccessType.UseEntry.toString(), Permission.Allow, false)).thenReturn(policy); + _aclSrv.addIAMPermissionToIAMPolicy(policyId, IAMEntityType.VirtualMachine.toString(), + PermissionScope.RESOURCE, resId, "listVirtualMachines", Permission.Allow, false); + Pair<List<IAMPolicy>, Integer> policyList = new Pair<List<IAMPolicy>, Integer>(policies, 1); + List<IAMPolicyPermission> policyPerms = new ArrayList<IAMPolicyPermission>(); + IAMPolicyPermission perm = new IAMPolicyPermissionVO(policyId, "listVirtualMachines", + IAMEntityType.VirtualMachine.toString(), AccessType.UseEntry.toString(), + PermissionScope.RESOURCE.toString(), + resId, Permission.Allow, false); + policyPerms.add(perm); + when(_iamSrv.listIAMPolicies(null, "policy1", callerDomainPath, 0L, 20L)).thenReturn(policyList); + when(_iamSrv.listPolicyPermissions(policyId)).thenReturn(policyPerms); + ListResponse<IAMPolicyResponse> policyResp = _aclSrv.listIAMPolicies(null, "policy1", callerDomainId, 0L, 20L); + assertTrue("No. of response items should be one", policyResp.getCount() == 1); + IAMPolicyResponse resp = policyResp.getResponses().get(0); + Set<IAMPermissionResponse> permList = resp.getPermissionList(); + assertTrue("Permission list should not be empty", permList != null && permList.size() > 0); + IAMPermissionResponse permResp = permList.iterator().next(); + assertEquals("There should be one permission for listVirtualMachines", "listVirtualMachines", permResp.getAction()); + + //remove permission from policy + policyPerms.remove(perm); + _aclSrv.removeIAMPermissionFromIAMPolicy(policyId, IAMEntityType.VirtualMachine.toString(), + PermissionScope.RESOURCE, resId, "listVirtualMachines"); + policyResp = _aclSrv.listIAMPolicies(null, "policy1", callerDomainId, 0L, 20L); + assertTrue("No. of response items should be one", policyResp.getCount() == 1); + resp = policyResp.getResponses().get(0); + permList = resp.getPermissionList(); + assertTrue("Permission list should be empty", permList != null && permList.size() == 0); + } + + @After + public void tearDown() { + } + + @Configuration + @ComponentScan(basePackageClasses = {IAMApiServiceImpl.class}, includeFilters = {@Filter(value = TestConfiguration.Library.class, type = FilterType.CUSTOM)}, useDefaultFilters = false) + public static class TestConfiguration extends SpringUtils.CloudStackTestConfiguration { + + @Bean + public DomainDao domainDao() { + return Mockito.mock(DomainDao.class); + } + + @Bean + public IAMService iamService() { + return Mockito.mock(IAMService.class); + } + + @Bean + public AccountDao accountDao() { + return Mockito.mock(AccountDao.class); + } + + @Bean + public NetworkDomainDao networkDomainDao() { + return Mockito.mock(NetworkDomainDao.class); + } + + @Bean + public AccountManager accountManager() { + return Mockito.mock(AccountManager.class); + } + + @Bean + public MessageBus messageBus() { + return Mockito.mock(MessageBus.class); + } + + @Bean + public EntityManager entityMgr() { + return Mockito.mock(EntityManager.class); + } + + @Bean + public ApiServerService apiServerService() { + return Mockito.mock(ApiServerService.class); + } + + public static class Library implements TypeFilter { + + @Override + public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException { + ComponentScan cs = TestConfiguration.class.getAnnotation(ComponentScan.class); + return SpringUtils.includedInBasePackageClasses(mdr.getClassMetadata().getClassName(), cs); + } + } + } +}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c28450c1/services/iam/plugin/test/resources/db.properties ---------------------------------------------------------------------- diff --git a/services/iam/plugin/test/resources/db.properties b/services/iam/plugin/test/resources/db.properties new file mode 100644 index 0000000..e1b5fe9 --- /dev/null +++ b/services/iam/plugin/test/resources/db.properties @@ -0,0 +1,75 @@ +# 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. + + +# management server clustering parameters, change cluster.node.IP to the machine IP address +# in which the management server(Tomcat) is running +cluster.node.IP=127.0.0.1 +cluster.servlet.port=9090 +region.id=1 + +# CloudStack database settings +db.cloud.username=cloud +db.cloud.password=cloud +db.root.password= +db.cloud.host=localhost +db.cloud.port=3306 +db.cloud.name=cloud + +# CloudStack database tuning parameters +db.cloud.maxActive=250 +db.cloud.maxIdle=30 +db.cloud.maxWait=10000 +db.cloud.autoReconnect=true +db.cloud.validationQuery=SELECT 1 +db.cloud.testOnBorrow=true +db.cloud.testWhileIdle=true +db.cloud.timeBetweenEvictionRunsMillis=40000 +db.cloud.minEvictableIdleTimeMillis=240000 +db.cloud.poolPreparedStatements=false +db.cloud.url.params=prepStmtCacheSize=517&cachePrepStmts=true&prepStmtCacheSqlLimit=4096 + +# usage database settings +db.usage.username=cloud +db.usage.password=cloud +db.usage.host=localhost +db.usage.port=3306 +db.usage.name=cloud_usage + +# usage database tuning parameters +db.usage.maxActive=100 +db.usage.maxIdle=30 +db.usage.maxWait=10000 +db.usage.autoReconnect=true + +# awsapi database settings +db.awsapi.username=cloud +db.awsapi.password=cloud +db.awsapi.host=localhost +db.awsapi.port=3306 +db.awsapi.name=cloudbridge + +# Simulator database settings +db.simulator.username=cloud +db.simulator.password=cloud +db.simulator.host=localhost +db.simulator.port=3306 +db.simulator.name=simulator +db.simulator.maxActive=250 +db.simulator.maxIdle=30 +db.simulator.maxWait=10000 +db.simulator.autoReconnect=true