diff --git a/.travis.yml b/.travis.yml index 365de7dcc2c..eb51ab9ec8b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -78,6 +78,7 @@ env: smoke/test_nested_virtualization smoke/test_network smoke/test_network_acl + smoke/test_network_permissions smoke/test_nic smoke/test_nic_adapter_type smoke/test_non_contigiousvlan @@ -131,7 +132,6 @@ env: - TESTS="component/test_acl_sharednetwork component/test_acl_sharednetwork_deployVM-impersonation - component/test_network_permissions component/test_user_private_gateway component/test_user_shared_network" diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/CreateIpv6FirewallRuleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/CreateIpv6FirewallRuleCmd.java index be158c9de02..6151b6a29db 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/CreateIpv6FirewallRuleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/CreateIpv6FirewallRuleCmd.java @@ -43,7 +43,12 @@ import com.cloud.network.rules.FirewallRule; import com.cloud.user.Account; import com.cloud.utils.net.NetUtils; -@APICommand(name = CreateIpv6FirewallRuleCmd.APINAME, description = "Creates an Ipv6 firewall rule in the given network (the network has to belong to VPC)", responseObject = FirewallRuleResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +@APICommand(name = CreateIpv6FirewallRuleCmd.APINAME, + description = "Creates an Ipv6 firewall rule in the given network (the network has to belong to VPC)", + responseObject = FirewallRuleResponse.class, + requestHasSensitiveInfo = false, + responseHasSensitiveInfo = false, + authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class CreateIpv6FirewallRuleCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreateIpv6FirewallRuleCmd.class.getName()); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/DeleteIpv6FirewallRuleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/DeleteIpv6FirewallRuleCmd.java index e7343a80d05..274f736a62b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/DeleteIpv6FirewallRuleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/DeleteIpv6FirewallRuleCmd.java @@ -16,6 +16,7 @@ // under the License. package org.apache.cloudstack.api.command.user.ipv6; +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiConstants; @@ -33,8 +34,12 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.rules.FirewallRule; import com.cloud.user.Account; -@APICommand(name = DeleteIpv6FirewallRuleCmd.APINAME, description = "Deletes a IPv6 firewall rule", responseObject = SuccessResponse.class, - requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +@APICommand(name = DeleteIpv6FirewallRuleCmd.APINAME, + description = "Deletes a IPv6 firewall rule", + responseObject = SuccessResponse.class, + requestHasSensitiveInfo = false, + responseHasSensitiveInfo = false, + authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class DeleteIpv6FirewallRuleCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteIpv6FirewallRuleCmd.class.getName()); public static final String APINAME = "deleteIpv6FirewallRule"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/ListIpv6FirewallRulesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/ListIpv6FirewallRulesCmd.java index 3f91f523edc..fc2714cf1bf 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/ListIpv6FirewallRulesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/ListIpv6FirewallRulesCmd.java @@ -34,8 +34,12 @@ import org.apache.log4j.Logger; import com.cloud.network.rules.FirewallRule; import com.cloud.utils.Pair; -@APICommand(name = ListIpv6FirewallRulesCmd.APINAME, description = "Lists all IPv6 firewall rules", responseObject = FirewallRuleResponse.class, - requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +@APICommand(name = ListIpv6FirewallRulesCmd.APINAME, + description = "Lists all IPv6 firewall rules", + responseObject = FirewallRuleResponse.class, + requestHasSensitiveInfo = false, + responseHasSensitiveInfo = false, + authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class ListIpv6FirewallRulesCmd extends BaseListTaggedResourcesCmd implements IListFirewallRulesCmd { public static final Logger s_logger = Logger.getLogger(ListIpv6FirewallRulesCmd.class.getName()); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/UpdateIpv6FirewallRuleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/UpdateIpv6FirewallRuleCmd.java index 8a05d02ae59..2295a17db83 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/UpdateIpv6FirewallRuleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/UpdateIpv6FirewallRuleCmd.java @@ -34,7 +34,12 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.rules.FirewallRule; import com.cloud.user.Account; -@APICommand(name = UpdateIpv6FirewallRuleCmd.APINAME, description = "Updates Ipv6 firewall rule with specified ID", responseObject = FirewallRuleResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +@APICommand(name = UpdateIpv6FirewallRuleCmd.APINAME, + description = "Updates Ipv6 firewall rule with specified ID", + responseObject = FirewallRuleResponse.class, + requestHasSensitiveInfo = false, + responseHasSensitiveInfo = false, + authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class UpdateIpv6FirewallRuleCmd extends BaseAsyncCustomIdCmd { public static final Logger s_logger = Logger.getLogger(UpdateIpv6FirewallRuleCmd.class.getName()); diff --git a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java index cb6e2a526d6..a3a3e4d9702 100644 --- a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java @@ -2022,7 +2022,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C if (Arrays.asList(Network.NetworkFilter.Shared, Network.NetworkFilter.All).contains(networkFilter)) { // get shared networks List sharedNetworks = listSharedNetworks(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, networkOfferingId, - aclType, skipProjectNetworks, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter, permittedAccounts); + aclType, true, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter, permittedAccounts); addNetworksToReturnIfNotExist(networksToReturn, sharedNetworks); } @@ -2035,23 +2035,23 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C if (Arrays.asList(Network.NetworkFilter.Domain, Network.NetworkFilter.AccountDomain, Network.NetworkFilter.All).contains(networkFilter)) { //add domain specific networks of domain + parent domains networksToReturn.addAll(listDomainSpecificNetworksByDomainPath(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, networkOfferingId, - aclType, skipProjectNetworks, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter, path, isRecursive)); + aclType, true, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter, path, isRecursive)); //add networks of subdomains if (domainId == null) { networksToReturn.addAll(listDomainLevelNetworks(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, networkOfferingId, - aclType, true, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter, caller.getDomainId(), true)); + aclType, true, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter, caller.getDomainId(), true)); } } if (Arrays.asList(Network.NetworkFilter.Shared, Network.NetworkFilter.All).contains(networkFilter)) { // get shared networks List sharedNetworks = listSharedNetworksByDomainPath(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, networkOfferingId, - aclType, skipProjectNetworks, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter, path, isRecursive); + aclType, true, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter, path, isRecursive); addNetworksToReturnIfNotExist(networksToReturn, sharedNetworks); } } } else { networksToReturn = _networksDao.search(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, networkOfferingId, - null, skipProjectNetworks, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter); + null, true, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter); } if (supportedServicesStr != null && !supportedServicesStr.isEmpty() && !networksToReturn.isEmpty()) { diff --git a/test/integration/component/test_network_ipv6.py b/test/integration/component/test_network_ipv6.py index 29afb8d97be..30734d73d95 100644 --- a/test/integration/component/test_network_ipv6.py +++ b/test/integration/component/test_network_ipv6.py @@ -209,6 +209,10 @@ class TestIpv6Network(cloudstackTestCase): def setUp(self): self.services = self.testClient.getParsedTestDataConfig() self.apiclient = self.testClient.getApiClient() + self.userapiclient = self.testClient.getUserApiClient( + UserName=self.account.name, + DomainName=self.account.domain + ) self.dbclient = self.testClient.getDbConnection() self.thread = None self.cleanup = [] @@ -266,10 +270,8 @@ class TestIpv6Network(cloudstackTestCase): def deployNetwork(self): self.services["network"]["networkoffering"] = self.network_offering.id self.network = Network.create( - self.apiclient, + self.userapiclient, self.services["network"], - self.account.name, - self.account.domainid, zoneid=self.zone.id ) self.cleanup.append(self.network) @@ -279,11 +281,9 @@ class TestIpv6Network(cloudstackTestCase): assert False, "get_test_template() failed to return template" self.services["virtual_machine"]["zoneid"] = self.zone.id self.virtual_machine = VirtualMachine.create( - self.apiclient, + self.userapiclient, self.services["virtual_machine"], templateid=self.template.id, - accountid=self.account.name, - domainid=self.account.domainid, networkids=self.network.id, serviceofferingid=self.service_offering.id ) @@ -541,11 +541,11 @@ class TestIpv6Network(cloudstackTestCase): "IPv6 gateway for VM %s NIC is empty" % nic.traffictype) def restartNetworkWithCleanup(self): - self.network.restart(self.apiclient, cleanup=True) + self.network.restart(self.userapiclient, cleanup=True) time.sleep(SLEEP_BEFORE_VR_CHANGES) def updateNetworkWithOffering(self): - self.network.update(self.apiclient, networkofferingid=self.network_offering_update.id) + self.network.update(self.userapiclient, networkofferingid=self.network_offering_update.id) time.sleep(SLEEP_BEFORE_VR_CHANGES) def createIpv6FirewallRuleInNetwork(self, network_id, traffic_type, source_cidr, dest_cidr, protocol, @@ -567,7 +567,7 @@ class TestIpv6Network(cloudstackTestCase): cmd.icmptype = icmp_type if icmp_code is not None: cmd.icmpcode = icmp_code - fw_rule = self.apiclient.createIpv6FirewallRule(cmd) + fw_rule = self.userapiclient.createIpv6FirewallRule(cmd) return fw_rule def deployRoutingTestResources(self): @@ -655,7 +655,7 @@ class TestIpv6Network(cloudstackTestCase): cmd = deleteIpv6FirewallRule.deleteIpv6FirewallRuleCmd() cmd.id = fw2.id - self.apiclient.deleteIpv6FirewallRule(cmd) + self.userapiclient.deleteIpv6FirewallRule(cmd) def createAndVerifyIpv6FirewallRule(self, traffic_type, source_cidr, dest_cidr, protocol, start_port, end_port, icmp_type, icmp_code, parsed_rule, delete=False): @@ -664,7 +664,7 @@ class TestIpv6Network(cloudstackTestCase): start_port, end_port, icmp_type, icmp_code) cmd = listIpv6FirewallRules.listIpv6FirewallRulesCmd() cmd.id = fw_rule.id - rules = self.apiclient.listIpv6FirewallRules(cmd) + rules = self.userapiclient.listIpv6FirewallRules(cmd) self.assertTrue( isinstance(rules, list), "Check listIpv6FirewallRules response returns a valid list" @@ -702,7 +702,7 @@ class TestIpv6Network(cloudstackTestCase): if delete == True: cmd = deleteIpv6FirewallRule.deleteIpv6FirewallRuleCmd() cmd.id = fw_rule.id - self.apiclient.deleteIpv6FirewallRule(cmd) + self.userapiclient.deleteIpv6FirewallRule(cmd) res = self.getRouterProcessStatus(self.getNetworkRouter(self.network), routerCmd) self.assertFalse(parsed_rule in res, "Firewall rule present in nft list chain failure despite delete for rule: %s" % parsed_rule) diff --git a/test/integration/smoke/test_network_ipv6.py b/test/integration/smoke/test_network_ipv6.py index 385ff636b16..41b7c85dea0 100644 --- a/test/integration/smoke/test_network_ipv6.py +++ b/test/integration/smoke/test_network_ipv6.py @@ -209,6 +209,10 @@ class TestIpv6Network(cloudstackTestCase): def setUp(self): self.services = self.testClient.getParsedTestDataConfig() self.apiclient = self.testClient.getApiClient() + self.userapiclient = self.testClient.getUserApiClient( + UserName=self.account.name, + DomainName=self.account.domain + ) self.dbclient = self.testClient.getDbConnection() self.thread = None self.cleanup = [] @@ -266,10 +270,8 @@ class TestIpv6Network(cloudstackTestCase): def deployNetwork(self): self.services["network"]["networkoffering"] = self.network_offering.id self.network = Network.create( - self.apiclient, + self.userapiclient, self.services["network"], - self.account.name, - self.account.domainid, zoneid=self.zone.id ) self.cleanup.append(self.network) @@ -279,11 +281,9 @@ class TestIpv6Network(cloudstackTestCase): assert False, "get_test_template() failed to return template" self.services["virtual_machine"]["zoneid"] = self.zone.id self.virtual_machine = VirtualMachine.create( - self.apiclient, + self.userapiclient, self.services["virtual_machine"], templateid=self.template.id, - accountid=self.account.name, - domainid=self.account.domainid, networkids=self.network.id, serviceofferingid=self.service_offering.id ) @@ -541,11 +541,11 @@ class TestIpv6Network(cloudstackTestCase): "IPv6 gateway for VM %s NIC is empty" % nic.traffictype) def restartNetworkWithCleanup(self): - self.network.restart(self.apiclient, cleanup=True) + self.network.restart(self.userapiclient, cleanup=True) time.sleep(SLEEP_BEFORE_VR_CHANGES) def updateNetworkWithOffering(self): - self.network.update(self.apiclient, networkofferingid=self.network_offering_update.id) + self.network.update(self.userapiclient, networkofferingid=self.network_offering_update.id) time.sleep(SLEEP_BEFORE_VR_CHANGES) def createIpv6FirewallRuleInNetwork(self, network_id, traffic_type, source_cidr, dest_cidr, protocol, @@ -567,7 +567,7 @@ class TestIpv6Network(cloudstackTestCase): cmd.icmptype = icmp_type if icmp_code is not None: cmd.icmpcode = icmp_code - fw_rule = self.apiclient.createIpv6FirewallRule(cmd) + fw_rule = self.userapiclient.createIpv6FirewallRule(cmd) return fw_rule def deployRoutingTestResources(self): @@ -655,7 +655,7 @@ class TestIpv6Network(cloudstackTestCase): cmd = deleteIpv6FirewallRule.deleteIpv6FirewallRuleCmd() cmd.id = fw2.id - self.apiclient.deleteIpv6FirewallRule(cmd) + self.userapiclient.deleteIpv6FirewallRule(cmd) def createAndVerifyIpv6FirewallRule(self, traffic_type, source_cidr, dest_cidr, protocol, start_port, end_port, icmp_type, icmp_code, parsed_rule, delete=False): @@ -664,7 +664,7 @@ class TestIpv6Network(cloudstackTestCase): start_port, end_port, icmp_type, icmp_code) cmd = listIpv6FirewallRules.listIpv6FirewallRulesCmd() cmd.id = fw_rule.id - rules = self.apiclient.listIpv6FirewallRules(cmd) + rules = self.userapiclient.listIpv6FirewallRules(cmd) self.assertTrue( isinstance(rules, list), "Check listIpv6FirewallRules response returns a valid list" @@ -702,7 +702,7 @@ class TestIpv6Network(cloudstackTestCase): if delete == True: cmd = deleteIpv6FirewallRule.deleteIpv6FirewallRuleCmd() cmd.id = fw_rule.id - self.apiclient.deleteIpv6FirewallRule(cmd) + self.userapiclient.deleteIpv6FirewallRule(cmd) res = self.getRouterProcessStatus(self.getNetworkRouter(self.network), routerCmd) self.assertFalse(parsed_rule in res, "Firewall rule present in nft list chain failure despite delete for rule: %s" % parsed_rule) diff --git a/test/integration/component/test_network_permissions.py b/test/integration/smoke/test_network_permissions.py similarity index 94% rename from test/integration/component/test_network_permissions.py rename to test/integration/smoke/test_network_permissions.py index b6c545f1027..1b4a331f260 100644 --- a/test/integration/component/test_network_permissions.py +++ b/test/integration/smoke/test_network_permissions.py @@ -758,3 +758,32 @@ class TestNetworkPermissions(cloudstackTestCase): command = """self.reset_network_permission({apiclient}, self.user_network, expected=True)""" self.exec_command("self.otheruser_apiclient", command, expected=False) self.exec_command("self.user_apiclient", command, expected=True) + + @attr(tags=["advanced"], required_hardware="false") + def test_05_list_networks_under_project(self): + """ Testing list networks under a project """ + self.create_network_permission(self.apiclient, self.user_network, self.domain_admin, self.project, expected=True) + self.list_network(self.apiclient, self.domain_admin, self.user_network, self.project, None, expected=True) + + self.remove_network_permission(self.apiclient, self.user_network, self.domain_admin, self.project, expected=True) + self.list_network(self.apiclient, self.domain_admin, self.user_network, self.project, None, expected=False) + + @attr(tags=["advanced"], required_hardware="false") + def test_06_list_networks_under_account(self): + """ Testing list networks under a domain admin account and user account """ + self.create_network_permission(self.apiclient, self.user_network, self.domain_admin, None, expected=True) + self.list_network(self.apiclient, self.domain_admin, self.user_network, None, None, expected=True) + self.list_network(self.domainadmin_apiclient, self.domain_admin, self.user_network, None, None, expected=True) + self.list_network(self.user_apiclient, self.domain_admin, self.user_network, None, None, expected=False) + + self.remove_network_permission(self.apiclient, self.user_network, self.domain_admin, None, expected=True) + self.list_network(self.apiclient, self.domain_admin, self.user_network, None, None, expected=False) + self.list_network(self.domainadmin_apiclient, self.domain_admin, self.user_network, None, None, expected=False) + + self.create_network_permission(self.apiclient, self.user_network, self.other_user, None, expected=True) + self.list_network(self.apiclient, self.other_user, self.user_network, None, None, expected=True) + self.list_network(self.otheruser_apiclient, self.other_user, self.user_network, None, None, expected=True) + + self.remove_network_permission(self.apiclient, self.user_network, self.other_user, None, expected=True) + self.list_network(self.apiclient, self.other_user, self.user_network, None, None, expected=False) + self.list_network(self.otheruser_apiclient, self.other_user, self.user_network, None, None, expected=False) \ No newline at end of file diff --git a/ui/src/views/network/VpcTiersTab.vue b/ui/src/views/network/VpcTiersTab.vue index d36fa9467d6..fb57c4d8685 100644 --- a/ui/src/views/network/VpcTiersTab.vue +++ b/ui/src/views/network/VpcTiersTab.vue @@ -569,7 +569,8 @@ export default { api('listLoadBalancers', { networkid: id, page: this.page, - pagesize: this.pageSize + pagesize: this.pageSize, + listAll: true }).then(json => { this.internalLB[id] = json.listloadbalancersresponse.loadbalancer || [] this.itemCounts.internalLB[id] = json.listloadbalancersresponse.count || 0