From 7e938fd2447cf65c6f8adbdf167754cca3625925 Mon Sep 17 00:00:00 2001 From: Kishan Kavala Date: Tue, 16 Apr 2013 16:48:56 +0530 Subject: [PATCH 01/14] CLOUDSTACK-763: Added APIs to create, delete and list NetworkACLlist. --- api/src/com/cloud/event/EventTypes.java | 5 + .../network/firewall/NetworkACLService.java | 16 ++- api/src/com/cloud/network/vpc/NetworkACL.java | 32 +++++ .../cloudstack/api/ResponseGenerator.java | 20 ++- .../user/network/CreateNetworkACLCmd.java | 6 +- .../user/network/CreateNetworkACLListCmd.java | 117 ++++++++++++++++++ .../user/network/DeleteNetworkACLCmd.java | 2 +- .../user/network/DeleteNetworkACLListCmd.java | 102 +++++++++++++++ .../user/network/ListNetworkACLListsCmd.java | 84 +++++++++++++ .../user/network/ListNetworkACLsCmd.java | 4 +- .../api/response/NetworkACLListResponse.java | 57 +++++++++ client/tomcatconf/applicationContext.xml.in | 1 + client/tomcatconf/commands.properties.in | 4 + .../src/com/cloud/api/ApiResponseHelper.java | 27 ++-- .../cloud/network/vpc/NetworkACLManager.java | 1 + .../network/vpc/NetworkACLManagerImpl.java | 41 +++++- .../com/cloud/network/vpc/NetworkACLVO.java | 78 ++++++++++++ .../cloud/network/vpc/dao/NetworkACLDao.java | 23 ++++ .../network/vpc/dao/NetworkACLDaoImpl.java | 35 ++++++ .../cloud/server/ManagementServerImpl.java | 3 + setup/db/create-schema.sql | 35 ++++++ 21 files changed, 667 insertions(+), 26 deletions(-) create mode 100644 api/src/com/cloud/network/vpc/NetworkACL.java create mode 100644 api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLListCmd.java create mode 100644 api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLListCmd.java create mode 100644 api/src/org/apache/cloudstack/api/command/user/network/ListNetworkACLListsCmd.java create mode 100644 api/src/org/apache/cloudstack/api/response/NetworkACLListResponse.java create mode 100644 server/src/com/cloud/network/vpc/NetworkACLVO.java create mode 100644 server/src/com/cloud/network/vpc/dao/NetworkACLDao.java create mode 100644 server/src/com/cloud/network/vpc/dao/NetworkACLDaoImpl.java diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java index 26c40abb4fb0..1b426dce0b8d 100755 --- a/api/src/com/cloud/event/EventTypes.java +++ b/api/src/com/cloud/event/EventTypes.java @@ -334,6 +334,11 @@ public class EventTypes { public static final String EVENT_VPC_DELETE = "VPC.DELETE"; public static final String EVENT_VPC_RESTART = "VPC.RESTART"; + // Network ACL + public static final String EVENT_NETWORK_ACL_CREATE = "NETWORK.ACL.CREATE"; + public static final String EVENT_NETWORK_ACL_UPDATE = "NETWORK.ACL.UPDATE"; + public static final String EVENT_NETWORK_ACL_DELETE = "NETWORK.ACL.DELETE"; + // VPC offerings public static final String EVENT_VPC_OFFERING_CREATE = "VPC.OFFERING.CREATE"; public static final String EVENT_VPC_OFFERING_UPDATE = "VPC.OFFERING.UPDATE"; diff --git a/api/src/com/cloud/network/firewall/NetworkACLService.java b/api/src/com/cloud/network/firewall/NetworkACLService.java index 97de496f64fa..8621e48d70ab 100644 --- a/api/src/com/cloud/network/firewall/NetworkACLService.java +++ b/api/src/com/cloud/network/firewall/NetworkACLService.java @@ -19,6 +19,9 @@ import java.util.List; +import com.cloud.network.vpc.NetworkACL; +import org.apache.cloudstack.api.command.user.network.CreateNetworkACLListCmd; +import org.apache.cloudstack.api.command.user.network.ListNetworkACLListsCmd; import org.apache.cloudstack.api.command.user.network.ListNetworkACLsCmd; import com.cloud.exception.NetworkRuleConflictException; @@ -28,14 +31,14 @@ import com.cloud.utils.Pair; public interface NetworkACLService { - FirewallRule getNetworkACL(long ruleId); + FirewallRule getNetworkACLItem(long ruleId); boolean applyNetworkACLs(long networkId, Account caller) throws ResourceUnavailableException; /** * @param createNetworkACLCmd * @return */ - FirewallRule createNetworkACL(FirewallRule acl) throws NetworkRuleConflictException; + FirewallRule createNetworkACLItem(FirewallRule acl) throws NetworkRuleConflictException; /** * @param ruleId * @param apply @@ -46,6 +49,13 @@ public interface NetworkACLService { * @param listNetworkACLsCmd * @return */ - Pair, Integer> listNetworkACLs(ListNetworkACLsCmd cmd); + Pair, Integer> listNetworkACLItems(ListNetworkACLsCmd cmd); + NetworkACL createNetworkACL(CreateNetworkACLListCmd cmd); + + NetworkACL getNetworkACL(long id); + + boolean deleteNetworkACL(long id); + + Pair,Integer> listNetworkACLs(ListNetworkACLListsCmd listNetworkACLListsCmd); } diff --git a/api/src/com/cloud/network/vpc/NetworkACL.java b/api/src/com/cloud/network/vpc/NetworkACL.java new file mode 100644 index 000000000000..8839ffd2b7c8 --- /dev/null +++ b/api/src/com/cloud/network/vpc/NetworkACL.java @@ -0,0 +1,32 @@ +// 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.network.vpc; + +import org.apache.cloudstack.api.InternalIdentity; + +public interface NetworkACL extends InternalIdentity{ + String getDescription(); + + String getUuid(); + + Long getVpcId(); + + long getId(); + + String getName(); +} diff --git a/api/src/org/apache/cloudstack/api/ResponseGenerator.java b/api/src/org/apache/cloudstack/api/ResponseGenerator.java index 3433003cbed7..7e72202fd222 100644 --- a/api/src/org/apache/cloudstack/api/ResponseGenerator.java +++ b/api/src/org/apache/cloudstack/api/ResponseGenerator.java @@ -20,9 +20,17 @@ import java.util.EnumSet; import java.util.List; +<<<<<<< HEAD import com.cloud.vm.NicSecondaryIp; import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.affinity.AffinityGroupResponse; +======= +import com.cloud.network.vpc.NetworkACL; +import com.cloud.network.vpc.PrivateGateway; +import com.cloud.network.vpc.StaticRoute; +import com.cloud.network.vpc.Vpc; +import com.cloud.network.vpc.VpcOffering; +>>>>>>> CLOUDSTACK-763: Added APIs to create, delete and list NetworkACLlist. import org.apache.cloudstack.api.ApiConstants.HostDetails; import org.apache.cloudstack.api.ApiConstants.VMDetails; import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd; @@ -132,10 +140,6 @@ import com.cloud.network.rules.StickinessPolicy; import com.cloud.network.security.SecurityGroup; import com.cloud.network.security.SecurityRule; -import com.cloud.network.vpc.PrivateGateway; -import com.cloud.network.vpc.StaticRoute; -import com.cloud.network.vpc.Vpc; -import com.cloud.network.vpc.VpcOffering; import com.cloud.offering.DiskOffering; import com.cloud.offering.NetworkOffering; import com.cloud.offering.ServiceOffering; @@ -353,11 +357,17 @@ LBHealthCheckResponse createLBHealthCheckPolicyResponse(List cidrs){ public void execute() throws ResourceUnavailableException { UserContext callerContext = UserContext.current(); boolean success = false; - FirewallRule rule = _networkACLService.getNetworkACL(getEntityId()); + FirewallRule rule = _networkACLService.getNetworkACLItem(getEntityId()); try { UserContext.current().setEventDetails("Rule Id: " + getEntityId()); success = _networkACLService.applyNetworkACLs(rule.getNetworkId(), callerContext.getCaller()); @@ -157,7 +157,7 @@ public void execute() throws ResourceUnavailableException { // State is different after the rule is applied, so get new object here NetworkACLResponse aclResponse = new NetworkACLResponse(); if (rule != null) { - aclResponse = _responseGenerator.createNetworkACLResponse(rule); + aclResponse = _responseGenerator.createNetworkACLItemResponse(rule); setResponseObject(aclResponse); } aclResponse.setResponseName(getCommandName()); @@ -256,7 +256,7 @@ public void create() { } try { - FirewallRule result = _networkACLService.createNetworkACL(this); + FirewallRule result = _networkACLService.createNetworkACLItem(this); setEntityId(result.getId()); setEntityUuid(result.getUuid()); } catch (NetworkRuleConflictException ex) { diff --git a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLListCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLListCmd.java new file mode 100644 index 000000000000..9c714971203b --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLListCmd.java @@ -0,0 +1,117 @@ +// 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 org.apache.cloudstack.api.command.user.network; + +import com.cloud.event.EventTypes; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.vpc.NetworkACL; +import com.cloud.network.vpc.Vpc; +import com.cloud.user.Account; +import com.cloud.user.UserContext; +import org.apache.cloudstack.api.*; +import org.apache.cloudstack.api.response.NetworkACLListResponse; +import org.apache.cloudstack.api.response.VpcResponse; +import org.apache.log4j.Logger; + +@APICommand(name = "createNetworkACLList", description = "Creates a Network ACL for the given VPC", +responseObject = NetworkACLListResponse.class) +public class CreateNetworkACLListCmd extends BaseAsyncCreateCmd { + public static final Logger s_logger = Logger.getLogger(CreateNetworkACLListCmd.class.getName()); + + private static final String s_name = "createnetworkacllistresponse"; + + // /////////////////////////////////////////////////// + // ////////////// API parameters ///////////////////// + // /////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "Name of the network ACL List") + private String name; + + @Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "Description of the network ACL List") + private String description; + + @Parameter(name = ApiConstants.VPC_ID, type = CommandType.UUID, required = true, entityType = VpcResponse.class, description = "Id of the VPC associated with this network ACL List") + private Long vpcId; + + // /////////////////////////////////////////////////// + // ///////////////// Accessors /////////////////////// + // /////////////////////////////////////////////////// + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public Long getVpcId() { + return vpcId; + } + + // /////////////////////////////////////////////////// + // ///////////// API Implementation/////////////////// + // /////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public void create() { + NetworkACL result = _networkACLService.createNetworkACL(this); + setEntityId(result.getId()); + setEntityUuid(result.getUuid()); + } + + @Override + public void execute() throws ResourceUnavailableException { + UserContext callerContext = UserContext.current(); + boolean success = false; + NetworkACL acl = _networkACLService.getNetworkACL(getEntityId()); + if(acl != null){ + NetworkACLListResponse aclResponse = _responseGenerator.createNetworkACLResponse(acl); + setResponseObject(aclResponse); + aclResponse.setResponseName(getCommandName()); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create network ACL"); + } + } + + @Override + public long getEntityOwnerId() { + Vpc vpc = _vpcService.getVpc(getVpcId()); + if (vpc == null) { + throw new InvalidParameterValueException("Invalid vpcId is given"); + } + + Account account = _accountService.getAccount(vpc.getAccountId()); + return account.getId(); + } + + @Override + public String getEventType() { + return EventTypes.EVENT_NETWORK_ACL_CREATE; + } + + @Override + public String getEventDescription() { + return "Creating Network ACL with id: "+getEntityUuid(); + } +} diff --git a/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLCmd.java index 2a2444b3e1ba..272a12926d49 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLCmd.java @@ -80,7 +80,7 @@ public String getEventDescription() { @Override public long getEntityOwnerId() { if (ownerId == null) { - FirewallRule rule = _networkACLService.getNetworkACL(id); + FirewallRule rule = _networkACLService.getNetworkACLItem(id); if (rule == null) { throw new InvalidParameterValueException("Unable to find network ACL by id=" + id); } else { diff --git a/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLListCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLListCmd.java new file mode 100644 index 000000000000..f5024759e2eb --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLListCmd.java @@ -0,0 +1,102 @@ +// 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 org.apache.cloudstack.api.command.user.network; + +import com.cloud.async.AsyncJob; +import com.cloud.event.EventTypes; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.rules.FirewallRule; +import com.cloud.network.vpc.NetworkACL; +import com.cloud.network.vpc.Vpc; +import com.cloud.user.UserContext; +import org.apache.cloudstack.api.*; +import org.apache.cloudstack.api.response.AccountResponse; +import org.apache.cloudstack.api.response.FirewallRuleResponse; +import org.apache.cloudstack.api.response.NetworkACLListResponse; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.log4j.Logger; + +@APICommand(name = "deleteNetworkACLList", description="Deletes a Network ACL", responseObject=SuccessResponse.class) +public class DeleteNetworkACLListCmd extends BaseAsyncCmd { + public static final Logger s_logger = Logger.getLogger(DeleteNetworkACLListCmd.class.getName()); + private static final String s_name = "deletenetworkacllistresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = NetworkACLListResponse.class, + required=true, description="the ID of the network ACL") + private Long id; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getId() { + return id; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + @Override + public String getCommandName() { + return s_name; + } + + @Override + public String getEventType() { + return EventTypes.EVENT_NETWORK_ACL_DELETE; + } + + @Override + public String getEventDescription() { + return ("Deleting Network ACL id=" + id); + } + + @Override + public long getEntityOwnerId() { + NetworkACL acl = _networkACLService.getNetworkACL(id); + if (acl == null) { + throw new InvalidParameterValueException("Unable to find network ACL by id=" + id); + } else { + long vpcId = acl.getVpcId(); + Vpc vpc = _vpcService.getVpc(vpcId); + if(vpc != null){ + return vpc.getAccountId(); + } else { + throw new InvalidParameterValueException("Unable to find VPC associated with network ACL by id=" + id); + } + } + } + + @Override + public void execute() throws ResourceUnavailableException { + UserContext.current().setEventDetails("Network ACL Id: " + id); + boolean result = _networkACLService.deleteNetworkACL(id); + + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete network ACL"); + } + } +} + diff --git a/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkACLListsCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkACLListsCmd.java new file mode 100644 index 000000000000..b043eed6ab42 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkACLListsCmd.java @@ -0,0 +1,84 @@ +// 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 org.apache.cloudstack.api.command.user.network; + +import com.cloud.network.rules.FirewallRule; +import com.cloud.network.vpc.NetworkACL; +import com.cloud.utils.Pair; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseListTaggedResourcesCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.*; +import org.apache.log4j.Logger; + +import java.util.ArrayList; +import java.util.List; + +@APICommand(name = "listNetworkACLLists", description="Lists all network ACLs", responseObject=NetworkACLListResponse.class) +public class ListNetworkACLListsCmd extends BaseListTaggedResourcesCmd { + public static final Logger s_logger = Logger.getLogger(ListNetworkACLListsCmd.class.getName()); + + private static final String s_name = "listnetworkacllistsresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = NetworkACLResponse.class, + description="Lists network ACL with the specified ID.") + private Long id; + + @Parameter(name=ApiConstants.NETWORK_ID, type=CommandType.UUID, entityType = NetworkResponse.class, + description="list network ACLs by network Id") + private Long networkId; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getNetworkId() { + return networkId; + } + + public Long getId() { + return id; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public void execute(){ + Pair,Integer> result = _networkACLService.listNetworkACLs(this); + ListResponse response = new ListResponse(); + List aclResponses = new ArrayList(); + + for (NetworkACL acl : result.first()) { + NetworkACLListResponse aclResponse = _responseGenerator.createNetworkACLResponse(acl); + aclResponses.add(aclResponse); + } + response.setResponses(aclResponses, result.second()); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } +} diff --git a/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkACLsCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkACLsCmd.java index d166974e7d16..93842d5c58bf 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkACLsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkACLsCmd.java @@ -79,12 +79,12 @@ public String getCommandName() { @Override public void execute(){ - Pair,Integer> result = _networkACLService.listNetworkACLs(this); + Pair,Integer> result = _networkACLService.listNetworkACLItems(this); ListResponse response = new ListResponse(); List aclResponses = new ArrayList(); for (FirewallRule acl : result.first()) { - NetworkACLResponse ruleData = _responseGenerator.createNetworkACLResponse(acl); + NetworkACLResponse ruleData = _responseGenerator.createNetworkACLItemResponse(acl); aclResponses.add(ruleData); } response.setResponses(aclResponses, result.second()); diff --git a/api/src/org/apache/cloudstack/api/response/NetworkACLListResponse.java b/api/src/org/apache/cloudstack/api/response/NetworkACLListResponse.java new file mode 100644 index 000000000000..34878510a940 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/response/NetworkACLListResponse.java @@ -0,0 +1,57 @@ +// 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 org.apache.cloudstack.api.response; + +import com.cloud.network.vpc.NetworkACL; +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; + +import java.util.List; + +@EntityReference(value = NetworkACL.class) +public class NetworkACLListResponse extends BaseResponse { + @SerializedName(ApiConstants.ID) @Param(description="the ID of the ACL") + private String id; + + @SerializedName(ApiConstants.NAME) @Param(description="the Name of the ACL") + private String name; + + @SerializedName(ApiConstants.DESCRIPTION) @Param(description="Description of the ACL") + private String description; + + @SerializedName(ApiConstants.VPC_ID) @Param(description="Id of the VPC this ACL is associated with") + private String vpcId; + + public void setId(String id) { + this.id = id; + } + + public void setName(String name) { + this.name = name; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setVpcId(String vpcId) { + this.vpcId = vpcId; + } +} diff --git a/client/tomcatconf/applicationContext.xml.in b/client/tomcatconf/applicationContext.xml.in index 36f232c737c3..961bd3b21618 100644 --- a/client/tomcatconf/applicationContext.xml.in +++ b/client/tomcatconf/applicationContext.xml.in @@ -246,6 +246,7 @@ + diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index 687c3c16c751..5c49cb17b0e2 100644 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -435,6 +435,10 @@ deletePrivateGateway=1 createNetworkACL=15 deleteNetworkACL=15 listNetworkACLs=15 +createNetworkACLList=15 +deleteNetworkACLList=15 +listNetworkACLLists=15 + #### Static route commands createStaticRoute=15 diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index d7eaa2604b13..619c9bb1ef4e 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -34,6 +34,11 @@ import javax.inject.Inject; +import com.cloud.network.vpc.NetworkACL; +import com.cloud.network.vpc.PrivateGateway; +import com.cloud.network.vpc.StaticRoute; +import com.cloud.network.vpc.Vpc; +import com.cloud.network.vpc.VpcOffering; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.affinity.AffinityGroup; @@ -80,6 +85,7 @@ import org.apache.cloudstack.api.response.LBStickinessResponse; import org.apache.cloudstack.api.response.LDAPConfigResponse; import org.apache.cloudstack.api.response.LoadBalancerResponse; +import org.apache.cloudstack.api.response.NetworkACLListResponse; import org.apache.cloudstack.api.response.NetworkACLResponse; import org.apache.cloudstack.api.response.NetworkOfferingResponse; import org.apache.cloudstack.api.response.NetworkResponse; @@ -223,10 +229,6 @@ import com.cloud.network.security.SecurityGroupVO; import com.cloud.network.security.SecurityRule; import com.cloud.network.security.SecurityRule.SecurityRuleType; -import com.cloud.network.vpc.PrivateGateway; -import com.cloud.network.vpc.StaticRoute; -import com.cloud.network.vpc.Vpc; -import com.cloud.network.vpc.VpcOffering; import com.cloud.offering.DiskOffering; import com.cloud.offering.NetworkOffering; import com.cloud.offering.ServiceOffering; @@ -2530,7 +2532,7 @@ public FirewallResponse createFirewallResponse(FirewallRule fwRule) { } @Override - public NetworkACLResponse createNetworkACLResponse(FirewallRule networkACL) { + public NetworkACLResponse createNetworkACLItemResponse(FirewallRule networkACL) { NetworkACLResponse response = new NetworkACLResponse(); response.setId(networkACL.getUuid()); @@ -3719,8 +3721,6 @@ public Long getAffinityGroupId(String groupName, long accountId) { } } - - @Override public IsolationMethodResponse createIsolationMethodResponse(IsolationType method) { IsolationMethodResponse response = new IsolationMethodResponse(); @@ -3728,4 +3728,17 @@ public IsolationMethodResponse createIsolationMethodResponse(IsolationType metho response.setObjectName("isolationmethod"); return response; } + + public NetworkACLListResponse createNetworkACLResponse(NetworkACL networkACL) { + NetworkACLListResponse response = new NetworkACLListResponse(); + response.setId(networkACL.getUuid()); + response.setName(networkACL.getName()); + response.setDescription(networkACL.getDescription()); + Vpc vpc = ApiDBUtils.findVpcById(networkACL.getVpcId()); + if(vpc != null){ + response.setVpcId(vpc.getUuid()); + } + response.setObjectName("networkacllist"); + return response; + } } diff --git a/server/src/com/cloud/network/vpc/NetworkACLManager.java b/server/src/com/cloud/network/vpc/NetworkACLManager.java index 91891c01cc89..515c25117736 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLManager.java +++ b/server/src/com/cloud/network/vpc/NetworkACLManager.java @@ -22,6 +22,7 @@ import com.cloud.network.firewall.NetworkACLService; import com.cloud.network.rules.FirewallRule; import com.cloud.user.Account; +import org.apache.cloudstack.api.command.user.network.CreateNetworkACLListCmd; public interface NetworkACLManager extends NetworkACLService{ diff --git a/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java b/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java index cb4486696ded..b00f8a15a313 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java +++ b/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java @@ -24,6 +24,9 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.network.vpc.dao.NetworkACLDao; +import org.apache.cloudstack.api.command.user.network.CreateNetworkACLListCmd; +import org.apache.cloudstack.api.command.user.network.ListNetworkACLListsCmd; import org.apache.cloudstack.api.command.user.network.ListNetworkACLsCmd; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -85,6 +88,8 @@ public class NetworkACLManagerImpl extends ManagerBase implements NetworkACLMana VpcManager _vpcMgr; @Inject ResourceTagDao _resourceTagDao; + @Inject + NetworkACLDao _networkACLDao; @Override public boolean applyNetworkACLs(long networkId, Account caller) throws ResourceUnavailableException { @@ -93,7 +98,7 @@ public boolean applyNetworkACLs(long networkId, Account caller) throws ResourceU } @Override - public FirewallRule createNetworkACL(FirewallRule acl) throws NetworkRuleConflictException { + public FirewallRule createNetworkACLItem(FirewallRule acl) throws NetworkRuleConflictException { if (acl.getSourceCidrList() == null && (acl.getPurpose() == Purpose.Firewall || acl.getPurpose() == Purpose.NetworkACL)) { _firewallDao.loadSourceCidrs((FirewallRuleVO)acl); } @@ -174,7 +179,7 @@ protected FirewallRule createNetworkACL(Account caller, String xId, Integer port txn.commit(); - return getNetworkACL(newRule.getId()); + return getNetworkACLItem(newRule.getId()); } @@ -320,7 +325,7 @@ protected boolean revokeNetworkACL(long ruleId, boolean apply, Account caller, l @Override - public FirewallRule getNetworkACL(long ACLId) { + public FirewallRule getNetworkACLItem(long ACLId) { FirewallRule rule = _firewallDao.findById(ACLId); if (rule != null && rule.getPurpose() == Purpose.NetworkACL) { return rule; @@ -330,7 +335,7 @@ public FirewallRule getNetworkACL(long ACLId) { @Override - public Pair,Integer> listNetworkACLs(ListNetworkACLsCmd cmd) { + public Pair,Integer> listNetworkACLItems(ListNetworkACLsCmd cmd) { Long networkId = cmd.getNetworkId(); Long id = cmd.getId(); String trafficType = cmd.getTrafficType(); @@ -438,5 +443,31 @@ public boolean revokeAllNetworkACLsForNetwork(long networkId, long userId, Accou return success; } - + + @Override + public NetworkACL createNetworkACL(CreateNetworkACLListCmd cmd){ + NetworkACLVO acl = new NetworkACLVO(cmd.getName(), cmd.getDescription(), cmd.getVpcId()); + _networkACLDao.persist(acl); + return acl; + } + + @Override + public NetworkACL getNetworkACL(long id) { + return _networkACLDao.findById(id); + } + + @Override + public boolean deleteNetworkACL(long id) { + return _networkACLDao.remove(id); + } + + @Override + public Pair, Integer> listNetworkACLs(ListNetworkACLListsCmd listNetworkACLListsCmd) { + SearchBuilder sb = _networkACLDao.createSearchBuilder(); + SearchCriteria sc = sb.create(); + Filter filter = new Filter(NetworkACLVO.class, "id", false, null, null); + Pair, Integer> acls = _networkACLDao.searchAndCount(sc, filter); + return new Pair, Integer>(acls.first(), acls.second()); + } + } diff --git a/server/src/com/cloud/network/vpc/NetworkACLVO.java b/server/src/com/cloud/network/vpc/NetworkACLVO.java new file mode 100644 index 000000000000..29afc006f465 --- /dev/null +++ b/server/src/com/cloud/network/vpc/NetworkACLVO.java @@ -0,0 +1,78 @@ +// 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.network.vpc; + +import javax.persistence.*; +import java.util.UUID; + +@Entity +@Table(name="network_acl") +public class NetworkACLVO implements NetworkACL{ + + @Id + @GeneratedValue(strategy= GenerationType.IDENTITY) + @Column(name="id") + private long id; + + @Column(name="vpc_id") + Long vpcId; + + @Column(name="uuid") + private String uuid; + + @Column(name="name") + private String name; + + @Column(name="description") + private String description; + + protected NetworkACLVO(){ + } + + protected NetworkACLVO(String name, String description, long vpcId){ + this.uuid = UUID.randomUUID().toString(); + this.name = name; + this.description = description; + this.vpcId = vpcId; + } + + @Override + public String getDescription() { + return description; + } + + @Override + public String getUuid() { + return uuid; + } + + @Override + public Long getVpcId() { + return vpcId; + } + + @Override + public long getId() { + return id; + } + + @Override + public String getName() { + return name; + } +} diff --git a/server/src/com/cloud/network/vpc/dao/NetworkACLDao.java b/server/src/com/cloud/network/vpc/dao/NetworkACLDao.java new file mode 100644 index 000000000000..fb2b331256c3 --- /dev/null +++ b/server/src/com/cloud/network/vpc/dao/NetworkACLDao.java @@ -0,0 +1,23 @@ +// 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.network.vpc.dao; + +import com.cloud.network.vpc.NetworkACLVO; +import com.cloud.utils.db.GenericDao; + +public interface NetworkACLDao extends GenericDao{ +} diff --git a/server/src/com/cloud/network/vpc/dao/NetworkACLDaoImpl.java b/server/src/com/cloud/network/vpc/dao/NetworkACLDaoImpl.java new file mode 100644 index 000000000000..fd3308d176fc --- /dev/null +++ b/server/src/com/cloud/network/vpc/dao/NetworkACLDaoImpl.java @@ -0,0 +1,35 @@ +// 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.network.vpc.dao; + +import com.cloud.network.vpc.NetworkACLVO; +import com.cloud.utils.db.DB; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import org.springframework.stereotype.Component; + +import javax.ejb.Local; + +@Component +@Local(value = NetworkACLDao.class) +@DB(txn = false) +public class NetworkACLDaoImpl extends GenericDaoBase implements NetworkACLDao{ + + protected NetworkACLDaoImpl() { + } + +} diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index da8f30ed7598..037bf283cc88 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -2549,6 +2549,9 @@ public List> getCommands() { cmdList.add(ListAffinityGroupTypesCmd.class); cmdList.add(ListNetworkIsolationMethodsCmd.class); + cmdList.add(CreateNetworkACLListCmd.class); + cmdList.add(DeleteNetworkACLListCmd.class); + cmdList.add(ListNetworkACLListsCmd.class); return cmdList; } diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index b1feb0228363..832ecc6540f2 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -196,6 +196,8 @@ DROP TABLE IF EXISTS `cloud`.`vm_network_map`; DROP TABLE IF EXISTS `cloud`.`netapp_volume`; DROP TABLE IF EXISTS `cloud`.`netapp_pool`; DROP TABLE IF EXISTS `cloud`.`netapp_lun`; +DROP TABLE IF EXISTS `cloud`.`network_acl`; +DROP TABLE IF EXISTS `cloud`.`network_acl_item`; CREATE TABLE `cloud`.`version` ( `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT COMMENT 'id', @@ -268,6 +270,7 @@ CREATE TABLE `cloud`.`networks` ( `removed` datetime COMMENT 'date removed if not null', `specify_ip_ranges` int(1) unsigned NOT NULL DEFAULT 0 COMMENT 'true if the network provides an ability to define ip ranges', `vpc_id` bigint unsigned COMMENT 'vpc this network belongs to', + `network_acl_id` bigint unsigned COMMENT 'network acl id', PRIMARY KEY (`id`), CONSTRAINT `fk_networks__network_offering_id` FOREIGN KEY (`network_offering_id`) REFERENCES `network_offerings`(`id`), CONSTRAINT `fk_networks__data_center_id` FOREIGN KEY (`data_center_id`) REFERENCES `data_center`(`id`) ON DELETE CASCADE, @@ -2475,5 +2478,37 @@ CREATE TABLE `cloud`.`nicira_nvp_nic_map` ( CONSTRAINT `fk_nicira_nvp_nic_map__nic` FOREIGN KEY(`nic`) REFERENCES `nics`(`uuid`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE `cloud`.`network_acl` ( + `id` bigint unsigned NOT NULL auto_increment COMMENT 'id', + `name` varchar(255) NOT NULL COMMENT 'name of the network acl', + `uuid` varchar(40), + `vpc_id` bigint unsigned COMMENT 'vpc this network acl belongs to', + `description` varchar(1024), + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `cloud`.`network_acl_item` ( + `id` bigint unsigned NOT NULL auto_increment COMMENT 'id', + `uuid` varchar(40), + `network_acl_id` bigint unsigned NOT NULL COMMENT 'network acl id', + `start_port` int(10) COMMENT 'starting port of a port range', + `end_port` int(10) COMMENT 'end port of a port range', + `state` char(32) NOT NULL COMMENT 'current state of this rule', + `protocol` char(16) NOT NULL default 'TCP' COMMENT 'protocol to open these ports for', + `account_id` bigint unsigned NOT NULL COMMENT 'owner id', + `domain_id` bigint unsigned NOT NULL COMMENT 'domain id', + `xid` char(40) NOT NULL COMMENT 'external id', + `created` datetime COMMENT 'Date created', + `icmp_code` int(10) COMMENT 'The ICMP code (if protocol=ICMP). A value of -1 means all codes for the given ICMP type.', + `icmp_type` int(10) COMMENT 'The ICMP type (if protocol=ICMP). A value of -1 means all types.', + `type` varchar(10) NOT NULL DEFAULT 'USER', + `traffic_type` char(32) COMMENT 'the traffic type of the rule, can be Ingress or Egress', + PRIMARY KEY (`id`), + CONSTRAINT `fk_network_acl_item__account_id` FOREIGN KEY(`account_id`) REFERENCES `account`(`id`) ON DELETE CASCADE, + CONSTRAINT `fk_network_acl_item__domain_id` FOREIGN KEY(`domain_id`) REFERENCES `domain`(`id`) ON DELETE CASCADE, + CONSTRAINT `fk_network_acl_item__acl_id` FOREIGN KEY(`network_acl_id`) REFERENCES `network_acl`(`id`) ON DELETE CASCADE, + CONSTRAINT `uc_network_acl_item__uuid` UNIQUE (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + SET foreign_key_checks = 1; From b5e9a2a06765aa75760aeec83123a759d35e900c Mon Sep 17 00:00:00 2001 From: Kishan Kavala Date: Tue, 16 Apr 2013 16:58:21 +0530 Subject: [PATCH 02/14] CLOUDSTACK-763: Moved schema changes to 41to42 upgrade script --- setup/db/create-schema.sql | 34 --------------------------------- setup/db/db/schema-410to420.sql | 34 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 832ecc6540f2..37c2352c7ecd 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -196,8 +196,6 @@ DROP TABLE IF EXISTS `cloud`.`vm_network_map`; DROP TABLE IF EXISTS `cloud`.`netapp_volume`; DROP TABLE IF EXISTS `cloud`.`netapp_pool`; DROP TABLE IF EXISTS `cloud`.`netapp_lun`; -DROP TABLE IF EXISTS `cloud`.`network_acl`; -DROP TABLE IF EXISTS `cloud`.`network_acl_item`; CREATE TABLE `cloud`.`version` ( `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT COMMENT 'id', @@ -2478,37 +2476,5 @@ CREATE TABLE `cloud`.`nicira_nvp_nic_map` ( CONSTRAINT `fk_nicira_nvp_nic_map__nic` FOREIGN KEY(`nic`) REFERENCES `nics`(`uuid`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -CREATE TABLE `cloud`.`network_acl` ( - `id` bigint unsigned NOT NULL auto_increment COMMENT 'id', - `name` varchar(255) NOT NULL COMMENT 'name of the network acl', - `uuid` varchar(40), - `vpc_id` bigint unsigned COMMENT 'vpc this network acl belongs to', - `description` varchar(1024), - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -CREATE TABLE `cloud`.`network_acl_item` ( - `id` bigint unsigned NOT NULL auto_increment COMMENT 'id', - `uuid` varchar(40), - `network_acl_id` bigint unsigned NOT NULL COMMENT 'network acl id', - `start_port` int(10) COMMENT 'starting port of a port range', - `end_port` int(10) COMMENT 'end port of a port range', - `state` char(32) NOT NULL COMMENT 'current state of this rule', - `protocol` char(16) NOT NULL default 'TCP' COMMENT 'protocol to open these ports for', - `account_id` bigint unsigned NOT NULL COMMENT 'owner id', - `domain_id` bigint unsigned NOT NULL COMMENT 'domain id', - `xid` char(40) NOT NULL COMMENT 'external id', - `created` datetime COMMENT 'Date created', - `icmp_code` int(10) COMMENT 'The ICMP code (if protocol=ICMP). A value of -1 means all codes for the given ICMP type.', - `icmp_type` int(10) COMMENT 'The ICMP type (if protocol=ICMP). A value of -1 means all types.', - `type` varchar(10) NOT NULL DEFAULT 'USER', - `traffic_type` char(32) COMMENT 'the traffic type of the rule, can be Ingress or Egress', - PRIMARY KEY (`id`), - CONSTRAINT `fk_network_acl_item__account_id` FOREIGN KEY(`account_id`) REFERENCES `account`(`id`) ON DELETE CASCADE, - CONSTRAINT `fk_network_acl_item__domain_id` FOREIGN KEY(`domain_id`) REFERENCES `domain`(`id`) ON DELETE CASCADE, - CONSTRAINT `fk_network_acl_item__acl_id` FOREIGN KEY(`network_acl_id`) REFERENCES `network_acl`(`id`) ON DELETE CASCADE, - CONSTRAINT `uc_network_acl_item__uuid` UNIQUE (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - SET foreign_key_checks = 1; diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index c8ac1ecfc2e7..53a1de848d0e 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -1143,3 +1143,37 @@ CREATE TABLE `cloud`.`account_vnet_map` ( ALTER TABLE `cloud`.`op_dc_vnet_alloc` ADD COLUMN account_vnet_map_id bigint unsigned; ALTER TABLE `cloud`.`op_dc_vnet_alloc` ADD CONSTRAINT `fk_op_dc_vnet_alloc__account_vnet_map_id` FOREIGN KEY `fk_op_dc_vnet_alloc__account_vnet_map_id` (`account_vnet_map_id`) REFERENCES `account_vnet_map` (`id`); + +CREATE TABLE `cloud`.`network_acl` ( + `id` bigint unsigned NOT NULL auto_increment COMMENT 'id', + `name` varchar(255) NOT NULL COMMENT 'name of the network acl', + `uuid` varchar(40), + `vpc_id` bigint unsigned COMMENT 'vpc this network acl belongs to', + `description` varchar(1024), + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `cloud`.`network_acl_item` ( + `id` bigint unsigned NOT NULL auto_increment COMMENT 'id', + `uuid` varchar(40), + `network_acl_id` bigint unsigned NOT NULL COMMENT 'network acl id', + `start_port` int(10) COMMENT 'starting port of a port range', + `end_port` int(10) COMMENT 'end port of a port range', + `state` char(32) NOT NULL COMMENT 'current state of this rule', + `protocol` char(16) NOT NULL default 'TCP' COMMENT 'protocol to open these ports for', + `account_id` bigint unsigned NOT NULL COMMENT 'owner id', + `domain_id` bigint unsigned NOT NULL COMMENT 'domain id', + `xid` char(40) NOT NULL COMMENT 'external id', + `created` datetime COMMENT 'Date created', + `icmp_code` int(10) COMMENT 'The ICMP code (if protocol=ICMP). A value of -1 means all codes for the given ICMP type.', + `icmp_type` int(10) COMMENT 'The ICMP type (if protocol=ICMP). A value of -1 means all types.', + `type` varchar(10) NOT NULL DEFAULT 'USER', + `traffic_type` char(32) COMMENT 'the traffic type of the rule, can be Ingress or Egress', + PRIMARY KEY (`id`), + CONSTRAINT `fk_network_acl_item__account_id` FOREIGN KEY(`account_id`) REFERENCES `account`(`id`) ON DELETE CASCADE, + CONSTRAINT `fk_network_acl_item__domain_id` FOREIGN KEY(`domain_id`) REFERENCES `domain`(`id`) ON DELETE CASCADE, + CONSTRAINT `fk_network_acl_item__acl_id` FOREIGN KEY(`network_acl_id`) REFERENCES `network_acl`(`id`) ON DELETE CASCADE, + CONSTRAINT `uc_network_acl_item__uuid` UNIQUE (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +ALTER TABLE `cloud`.`networks` add column `network_acl_id` bigint unsigned COMMENT 'network acl id'; From 373029cd6f08955ba470623ca57c2a2ae3f0d8b2 Mon Sep 17 00:00:00 2001 From: Kishan Kavala Date: Tue, 23 Apr 2013 10:54:44 +0530 Subject: [PATCH 03/14] CLOUDSTACK-763: Added replaceNetworkACLList API. Added support for ACL action allow/deny and also number --- .../com/cloud/agent/api/to/NetworkACLTO.java | 35 +- api/src/com/cloud/event/EventTypes.java | 3 + api/src/com/cloud/network/Network.java | 1 + api/src/com/cloud/network/NetworkProfile.java | 7 + .../element/NetworkACLServiceProvider.java | 3 +- .../network/firewall/NetworkACLService.java | 15 +- api/src/com/cloud/network/vpc/NetworkACL.java | 3 +- .../com/cloud/network/vpc/NetworkACLItem.java | 87 ++++ .../apache/cloudstack/api/ApiConstants.java | 1 + .../cloudstack/api/ResponseGenerator.java | 14 +- .../user/network/CreateNetworkACLCmd.java | 107 ++--- .../user/network/CreateNetworkACLListCmd.java | 6 +- .../user/network/DeleteNetworkACLCmd.java | 7 +- .../user/network/DeleteNetworkACLListCmd.java | 4 +- .../user/network/ListNetworkACLListsCmd.java | 12 +- .../user/network/ListNetworkACLsCmd.java | 15 +- .../network/ReplaceNetworkACLListCmd.java | 107 +++++ .../api/response/NetworkACLItemResponse.java | 106 +++++ .../api/response/NetworkACLListResponse.java | 57 --- .../api/response/NetworkACLResponse.java | 78 +--- client/tomcatconf/applicationContext.xml.in | 1 + client/tomcatconf/commands.properties.in | 1 + .../api/routing/SetNetworkACLCommand.java | 19 +- .../src/com/cloud/network/dao/NetworkDao.java | 2 + .../com/cloud/network/dao/NetworkDaoImpl.java | 9 + .../src/com/cloud/network/dao/NetworkVO.java | 12 + server/src/com/cloud/api/ApiDBUtils.java | 28 +- .../src/com/cloud/api/ApiResponseHelper.java | 26 +- .../com/cloud/network/NetworkManagerImpl.java | 4 +- .../element/VpcVirtualRouterElement.java | 8 +- .../network/firewall/FirewallManagerImpl.java | 4 +- .../VpcVirtualNetworkApplianceManager.java | 7 +- ...VpcVirtualNetworkApplianceManagerImpl.java | 29 +- .../cloud/network/vpc/NetworkACLItemDao.java | 44 ++ .../cloud/network/vpc/NetworkACLItemVO.java | 198 ++++++++ .../cloud/network/vpc/NetworkACLManager.java | 9 +- .../network/vpc/NetworkACLManagerImpl.java | 424 ++++++++---------- .../com/cloud/network/vpc/NetworkACLVO.java | 10 + .../vpc/dao/NetworkACLItemDaoImpl.java | 147 ++++++ .../cloud/server/ManagementServerImpl.java | 1 + setup/db/db/schema-410to420.sql | 9 +- 41 files changed, 1139 insertions(+), 521 deletions(-) create mode 100644 api/src/com/cloud/network/vpc/NetworkACLItem.java create mode 100644 api/src/org/apache/cloudstack/api/command/user/network/ReplaceNetworkACLListCmd.java create mode 100644 api/src/org/apache/cloudstack/api/response/NetworkACLItemResponse.java delete mode 100644 api/src/org/apache/cloudstack/api/response/NetworkACLListResponse.java create mode 100644 server/src/com/cloud/network/vpc/NetworkACLItemDao.java create mode 100644 server/src/com/cloud/network/vpc/NetworkACLItemVO.java create mode 100644 server/src/com/cloud/network/vpc/dao/NetworkACLItemDaoImpl.java diff --git a/api/src/com/cloud/agent/api/to/NetworkACLTO.java b/api/src/com/cloud/agent/api/to/NetworkACLTO.java index 8818e13de4a4..48de40ce5010 100644 --- a/api/src/com/cloud/agent/api/to/NetworkACLTO.java +++ b/api/src/com/cloud/agent/api/to/NetworkACLTO.java @@ -20,10 +20,10 @@ import java.util.ArrayList; import java.util.List; +import com.cloud.network.vpc.NetworkACLItem; +import com.cloud.network.vpc.NetworkACLItem.TrafficType; import org.apache.cloudstack.api.InternalIdentity; -import com.cloud.network.rules.FirewallRule; -import com.cloud.network.rules.FirewallRule.TrafficType; import com.cloud.utils.net.NetUtils; @@ -37,15 +37,16 @@ public class NetworkACLTO implements InternalIdentity { private List cidrList; private Integer icmpType; private Integer icmpCode; - private FirewallRule.TrafficType trafficType; - + private TrafficType trafficType; + String action; + int number; protected NetworkACLTO() { } public NetworkACLTO(long id,String vlanTag, String protocol, Integer portStart, Integer portEnd, boolean revoked, - boolean alreadyAdded, List cidrList, Integer icmpType,Integer icmpCode,TrafficType trafficType) { + boolean alreadyAdded, List cidrList, Integer icmpType,Integer icmpCode,TrafficType trafficType, boolean allow, int number) { this.vlanTag = vlanTag; this.protocol = protocol; @@ -70,12 +71,20 @@ public NetworkACLTO(long id,String vlanTag, String protocol, Integer portStart, this.icmpType = icmpType; this.icmpCode = icmpCode; this.trafficType = trafficType; + + if(allow){ + this.action = "ACCEPT"; + } else { + this.action = "DROP"; + } + + this.number = number; } - public NetworkACLTO(FirewallRule rule, String vlanTag, FirewallRule.TrafficType trafficType ) { + public NetworkACLTO(NetworkACLItem rule, String vlanTag, NetworkACLItem.TrafficType trafficType ) { this(rule.getId(), vlanTag, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(), - rule.getState() == FirewallRule.State.Revoke, rule.getState() == FirewallRule.State.Active, - rule.getSourceCidrList() ,rule.getIcmpType(), rule.getIcmpCode(),trafficType); + rule.getState() == NetworkACLItem.State.Revoke, rule.getState() == NetworkACLItem.State.Active, + rule.getSourceCidrList() ,rule.getIcmpType(), rule.getIcmpCode(),trafficType, rule.getAction() == NetworkACLItem.Action.Allow, rule.getNumber()); } public long getId() { @@ -121,7 +130,15 @@ public boolean isAlreadyAdded() { return alreadyAdded; } - public FirewallRule.TrafficType getTrafficType() { + public TrafficType getTrafficType() { return trafficType; } + + public String getAction() { + return action; + } + + public int getNumber(){ + return number; + } } diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java index 1b426dce0b8d..63611edce8e3 100755 --- a/api/src/com/cloud/event/EventTypes.java +++ b/api/src/com/cloud/event/EventTypes.java @@ -338,6 +338,9 @@ public class EventTypes { public static final String EVENT_NETWORK_ACL_CREATE = "NETWORK.ACL.CREATE"; public static final String EVENT_NETWORK_ACL_UPDATE = "NETWORK.ACL.UPDATE"; public static final String EVENT_NETWORK_ACL_DELETE = "NETWORK.ACL.DELETE"; + public static final String EVENT_NETWORK_ACL_REPLACE = "NETWORK.ACL.REPLACE"; + public static final String EVENT_NETWORK_ACL_ITEM_CREATE = "NETWORK.ACL.ITEM.CREATE"; + public static final String EVENT_NETWORK_ACL_ITEM_DELETE = "NETWORK.ACL.ITEM.DELETE"; // VPC offerings public static final String EVENT_VPC_OFFERING_CREATE = "VPC.OFFERING.CREATE"; diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java index 4472dbacc53f..0b20122f0598 100644 --- a/api/src/com/cloud/network/Network.java +++ b/api/src/com/cloud/network/Network.java @@ -324,4 +324,5 @@ public void setIp6Address(String ip6Address) { */ Long getVpcId(); + Long getNetworkACLId(); } diff --git a/api/src/com/cloud/network/NetworkProfile.java b/api/src/com/cloud/network/NetworkProfile.java index 2f56645139c5..568edf7c9ec9 100644 --- a/api/src/com/cloud/network/NetworkProfile.java +++ b/api/src/com/cloud/network/NetworkProfile.java @@ -52,6 +52,7 @@ public class NetworkProfile implements Network { private boolean restartRequired; private boolean specifyIpRanges; private Long vpcId; + private Long networkAclId; public NetworkProfile(Network network) { this.id = network.getId(); @@ -81,6 +82,7 @@ public NetworkProfile(Network network) { this.restartRequired = network.isRestartRequired(); this.specifyIpRanges = network.getSpecifyIpRanges(); this.vpcId = network.getVpcId(); + this.networkAclId = network.getNetworkACLId(); } public String getDns1() { @@ -236,6 +238,11 @@ public Long getVpcId() { return vpcId; } + @Override + public Long getNetworkACLId() { + return networkAclId; + } + @Override public void setTrafficType(TrafficType type) { this.trafficType = type; diff --git a/api/src/com/cloud/network/element/NetworkACLServiceProvider.java b/api/src/com/cloud/network/element/NetworkACLServiceProvider.java index 4073b07ba1ba..dac0a25c668a 100644 --- a/api/src/com/cloud/network/element/NetworkACLServiceProvider.java +++ b/api/src/com/cloud/network/element/NetworkACLServiceProvider.java @@ -21,6 +21,7 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Network; import com.cloud.network.rules.FirewallRule; +import com.cloud.network.vpc.NetworkACLItem; public interface NetworkACLServiceProvider extends NetworkElement{ @@ -30,6 +31,6 @@ public interface NetworkACLServiceProvider extends NetworkElement{ * @return * @throws ResourceUnavailableException */ - boolean applyNetworkACLs(Network config, List rules) throws ResourceUnavailableException; + boolean applyNetworkACLs(Network config, List rules) throws ResourceUnavailableException; } diff --git a/api/src/com/cloud/network/firewall/NetworkACLService.java b/api/src/com/cloud/network/firewall/NetworkACLService.java index 8621e48d70ab..ae46d83cc9f1 100644 --- a/api/src/com/cloud/network/firewall/NetworkACLService.java +++ b/api/src/com/cloud/network/firewall/NetworkACLService.java @@ -20,36 +20,37 @@ import java.util.List; import com.cloud.network.vpc.NetworkACL; +import com.cloud.network.vpc.NetworkACLItem; +import org.apache.cloudstack.api.command.user.network.CreateNetworkACLCmd; import org.apache.cloudstack.api.command.user.network.CreateNetworkACLListCmd; import org.apache.cloudstack.api.command.user.network.ListNetworkACLListsCmd; import org.apache.cloudstack.api.command.user.network.ListNetworkACLsCmd; import com.cloud.exception.NetworkRuleConflictException; import com.cloud.exception.ResourceUnavailableException; -import com.cloud.network.rules.FirewallRule; import com.cloud.user.Account; import com.cloud.utils.Pair; public interface NetworkACLService { - FirewallRule getNetworkACLItem(long ruleId); - boolean applyNetworkACLs(long networkId, Account caller) throws ResourceUnavailableException; + NetworkACLItem getNetworkACLItem(long ruleId); + boolean applyNetworkACLtoNetworks(long aclId, Account caller) throws ResourceUnavailableException; /** * @param createNetworkACLCmd * @return */ - FirewallRule createNetworkACLItem(FirewallRule acl) throws NetworkRuleConflictException; + NetworkACLItem createNetworkACLItem(CreateNetworkACLCmd aclItemCmd) throws NetworkRuleConflictException; /** * @param ruleId * @param apply * @return */ - boolean revokeNetworkACL(long ruleId, boolean apply); + boolean revokeNetworkACLItem(long ruleId, boolean apply); /** * @param listNetworkACLsCmd * @return */ - Pair, Integer> listNetworkACLItems(ListNetworkACLsCmd cmd); + Pair, Integer> listNetworkACLItems(ListNetworkACLsCmd cmd); NetworkACL createNetworkACL(CreateNetworkACLListCmd cmd); @@ -58,4 +59,6 @@ public interface NetworkACLService { boolean deleteNetworkACL(long id); Pair,Integer> listNetworkACLs(ListNetworkACLListsCmd listNetworkACLListsCmd); + + boolean replaceNetworkACL(long aclId, long networkId); } diff --git a/api/src/com/cloud/network/vpc/NetworkACL.java b/api/src/com/cloud/network/vpc/NetworkACL.java index 8839ffd2b7c8..1b171e31de6e 100644 --- a/api/src/com/cloud/network/vpc/NetworkACL.java +++ b/api/src/com/cloud/network/vpc/NetworkACL.java @@ -17,9 +17,10 @@ package com.cloud.network.vpc; +import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.api.InternalIdentity; -public interface NetworkACL extends InternalIdentity{ +public interface NetworkACL extends InternalIdentity, ControlledEntity{ String getDescription(); String getUuid(); diff --git a/api/src/com/cloud/network/vpc/NetworkACLItem.java b/api/src/com/cloud/network/vpc/NetworkACLItem.java new file mode 100644 index 000000000000..9cce1875d90c --- /dev/null +++ b/api/src/com/cloud/network/vpc/NetworkACLItem.java @@ -0,0 +1,87 @@ +// 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.network.vpc; + +import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +import java.util.List; + +public interface NetworkACLItem extends InternalIdentity { + + String getUuid(); + + Action getAction(); + + int getNumber(); + + enum NetworkACLType { + System, // The pre-defined rules created by admin, in the system wide + User // the rules created by user, to a specific ip + } + + enum State { + Staged, // Rule been created but has never got through network rule conflict detection. Rules in this state can not be sent to network elements. + Add, // Add means the rule has been created and has gone through network rule conflict detection. + Active, // Rule has been sent to the network elements and reported to be active. + Revoke // Revoke means this rule has been revoked. If this rule has been sent to the network elements, the rule will be deleted from database. + } + + enum TrafficType { + Ingress, + Egress + } + + enum Action { + Allow, + Deny + } + + /** + * @return first port of the source port range. + */ + Integer getSourcePortStart(); + + /** + * @return last port of the source prot range. If this is null, that means only one port is mapped. + */ + Integer getSourcePortEnd(); + + /** + * @return protocol to open these ports for. + */ + String getProtocol(); + + State getState(); + + long getACLId(); + + Integer getIcmpCode(); + + Integer getIcmpType(); + + List getSourceCidrList(); + + NetworkACLType getType(); + + /** + * @return + */ + TrafficType getTrafficType(); + +} diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java index d57fe058d932..5083981ccb2d 100755 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -484,6 +484,7 @@ public class ApiConstants { public static final String AFFINITY_GROUP_NAMES = "affinitygroupnames"; public static final String ASA_INSIDE_PORT_PROFILE = "insideportprofile"; public static final String AFFINITY_GROUP_ID = "affinitygroupid"; + public static final String ACL_ID = "aclid"; public enum HostDetails { all, capacity, events, stats, min; diff --git a/api/src/org/apache/cloudstack/api/ResponseGenerator.java b/api/src/org/apache/cloudstack/api/ResponseGenerator.java index 7e72202fd222..211fb92fd750 100644 --- a/api/src/org/apache/cloudstack/api/ResponseGenerator.java +++ b/api/src/org/apache/cloudstack/api/ResponseGenerator.java @@ -20,17 +20,15 @@ import java.util.EnumSet; import java.util.List; -<<<<<<< HEAD -import com.cloud.vm.NicSecondaryIp; -import org.apache.cloudstack.affinity.AffinityGroup; -import org.apache.cloudstack.affinity.AffinityGroupResponse; -======= import com.cloud.network.vpc.NetworkACL; +import com.cloud.network.vpc.NetworkACLItem; import com.cloud.network.vpc.PrivateGateway; import com.cloud.network.vpc.StaticRoute; import com.cloud.network.vpc.Vpc; import com.cloud.network.vpc.VpcOffering; ->>>>>>> CLOUDSTACK-763: Added APIs to create, delete and list NetworkACLlist. +import com.cloud.vm.NicSecondaryIp; +import org.apache.cloudstack.affinity.AffinityGroup; +import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.api.ApiConstants.HostDetails; import org.apache.cloudstack.api.ApiConstants.VMDetails; import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd; @@ -361,13 +359,13 @@ LBHealthCheckResponse createLBHealthCheckPolicyResponse(List getSourceCidrList() { } public long getVpcId() { - Network network = _networkService.getNetwork(getNetworkId()); - if (network == null) { - throw new InvalidParameterValueException("Invalid networkId is given"); + Long vpcId = null; + + if(getACLId() != null){ + NetworkACL acl = _networkACLService.getNetworkACL(getACLId()); + if(acl == null){ + throw new InvalidParameterValueException("Invalid aclId is given"); + } + vpcId = acl.getVpcId(); + } else if(getNetworkId() != null){ + Network network = _networkService.getNetwork(getNetworkId()); + if (network == null) { + throw new InvalidParameterValueException("Invalid networkId is given"); + } + vpcId = network.getVpcId(); } - Long vpcId = network.getVpcId(); if (vpcId == null) { - throw new InvalidParameterValueException("Can create network ACL only for the network belonging to the VPC"); + throw new InvalidParameterValueException("Can create network ACL only for the ACL belonging to the VPC"); } return vpcId; } - @Override - public FirewallRule.TrafficType getTrafficType() { + public NetworkACLItem.TrafficType getTrafficType() { if (trafficType == null) { - return FirewallRule.TrafficType.Ingress; + return NetworkACLItem.TrafficType.Ingress; } - for (FirewallRule.TrafficType type : FirewallRule.TrafficType.values()) { + for (NetworkACLItem.TrafficType type : NetworkACLItem.TrafficType.values()) { if (type.toString().equalsIgnoreCase(trafficType)) { return type; } @@ -149,13 +163,13 @@ public void setSourceCidrList(List cidrs){ public void execute() throws ResourceUnavailableException { UserContext callerContext = UserContext.current(); boolean success = false; - FirewallRule rule = _networkACLService.getNetworkACLItem(getEntityId()); + NetworkACLItem rule = _networkACLService.getNetworkACLItem(getEntityId()); try { UserContext.current().setEventDetails("Rule Id: " + getEntityId()); - success = _networkACLService.applyNetworkACLs(rule.getNetworkId(), callerContext.getCaller()); + success = _networkACLService.applyNetworkACLtoNetworks(rule.getACLId(), callerContext.getCaller()); // State is different after the rule is applied, so get new object here - NetworkACLResponse aclResponse = new NetworkACLResponse(); + NetworkACLItemResponse aclResponse = new NetworkACLItemResponse(); if (rule != null) { aclResponse = _responseGenerator.createNetworkACLItemResponse(rule); setResponseObject(aclResponse); @@ -163,36 +177,16 @@ public void execute() throws ResourceUnavailableException { aclResponse.setResponseName(getCommandName()); } finally { if (!success || rule == null) { - _networkACLService.revokeNetworkACL(getEntityId(), true); + _networkACLService.revokeNetworkACLItem(getEntityId(), true); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create network ACL"); } } } - @Override - public long getId() { - throw new UnsupportedOperationException("database id can only provided by VO objects"); - } - - @Override - public String getXid() { - // FIXME: We should allow for end user to specify Xid. - return null; - } - - - @Override - public String getUuid() { - // TODO Auto-generated method stub - return null; - } - - @Override public Long getSourceIpAddressId() { return null; } - @Override public Integer getSourcePortStart() { if (publicStartPort != null) { return publicStartPort.intValue(); @@ -200,7 +194,6 @@ public Integer getSourcePortStart() { return null; } - @Override public Integer getSourcePortEnd() { if (publicEndPort == null) { if (publicStartPort != null) { @@ -213,18 +206,11 @@ public Integer getSourcePortEnd() { return null; } - @Override - public Purpose getPurpose() { - return Purpose.Firewall; - } - - @Override - public State getState() { + public NetworkACLItem.State getState() { throw new UnsupportedOperationException("Should never call me to find the state"); } - @Override - public long getNetworkId() { + public Long getNetworkId() { return networkId; } @@ -239,7 +225,6 @@ public long getEntityOwnerId() { return account.getId(); } - @Override public long getDomainId() { Vpc vpc = _vpcService.getVpc(getVpcId()); return vpc.getDomainId(); @@ -256,7 +241,7 @@ public void create() { } try { - FirewallRule result = _networkACLService.createNetworkACLItem(this); + NetworkACLItem result = _networkACLService.createNetworkACLItem(this); setEntityId(result.getId()); setEntityUuid(result.getUuid()); } catch (NetworkRuleConflictException ex) { @@ -268,16 +253,15 @@ public void create() { @Override public String getEventType() { - return EventTypes.EVENT_FIREWALL_OPEN; + return EventTypes.EVENT_NETWORK_ACL_ITEM_CREATE; } @Override public String getEventDescription() { - Network network = _networkService.getNetwork(networkId); - return ("Createing Network ACL for Netowrk: " + network + " for protocol:" + this.getProtocol()); + //Network network = _networkService.getNetwork(networkId); + return ("Creating Network ACL Item for protocol:" + this.getProtocol()); } - @Override public long getAccountId() { Vpc vpc = _vpcService.getVpc(getVpcId()); return vpc.getAccountId(); @@ -293,7 +277,6 @@ public Long getSyncObjId() { return getNetworkId(); } - @Override public Integer getIcmpCode() { if (icmpCode != null) { return icmpCode; @@ -303,7 +286,6 @@ public Integer getIcmpCode() { return null; } - @Override public Integer getIcmpType() { if (icmpType != null) { return icmpType; @@ -314,14 +296,8 @@ public Integer getIcmpType() { return null; } - @Override - public Long getRelated() { - return null; - } - - @Override - public FirewallRuleType getType() { - return FirewallRuleType.User; + public NetworkACLType getType() { + return NetworkACLType.User; } @Override @@ -329,4 +305,7 @@ public AsyncJob.Type getInstanceType() { return AsyncJob.Type.FirewallRule; } + public Long getACLId() { + return aclId; + } } diff --git a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLListCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLListCmd.java index 9c714971203b..0cc460d2b788 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLListCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLListCmd.java @@ -24,12 +24,12 @@ import com.cloud.user.Account; import com.cloud.user.UserContext; import org.apache.cloudstack.api.*; -import org.apache.cloudstack.api.response.NetworkACLListResponse; +import org.apache.cloudstack.api.response.NetworkACLResponse; import org.apache.cloudstack.api.response.VpcResponse; import org.apache.log4j.Logger; @APICommand(name = "createNetworkACLList", description = "Creates a Network ACL for the given VPC", -responseObject = NetworkACLListResponse.class) +responseObject = NetworkACLResponse.class) public class CreateNetworkACLListCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreateNetworkACLListCmd.class.getName()); @@ -86,7 +86,7 @@ public void execute() throws ResourceUnavailableException { boolean success = false; NetworkACL acl = _networkACLService.getNetworkACL(getEntityId()); if(acl != null){ - NetworkACLListResponse aclResponse = _responseGenerator.createNetworkACLResponse(acl); + NetworkACLResponse aclResponse = _responseGenerator.createNetworkACLResponse(acl); setResponseObject(aclResponse); aclResponse.setResponseName(getCommandName()); } else { diff --git a/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLCmd.java index 272a12926d49..2f882303ffe1 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLCmd.java @@ -16,6 +16,7 @@ // under the License. package org.apache.cloudstack.api.command.user.network; +import com.cloud.network.vpc.NetworkACLItem; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -80,11 +81,11 @@ public String getEventDescription() { @Override public long getEntityOwnerId() { if (ownerId == null) { - FirewallRule rule = _networkACLService.getNetworkACLItem(id); + NetworkACLItem rule = _networkACLService.getNetworkACLItem(id); if (rule == null) { throw new InvalidParameterValueException("Unable to find network ACL by id=" + id); } else { - ownerId = rule.getAccountId(); + //ownerId = rule.getAccountId(); } } return ownerId; @@ -93,7 +94,7 @@ public long getEntityOwnerId() { @Override public void execute() throws ResourceUnavailableException { UserContext.current().setEventDetails("Network ACL Id: " + id); - boolean result = _networkACLService.revokeNetworkACL(id, true); + boolean result = _networkACLService.revokeNetworkACLItem(id, true); if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLListCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLListCmd.java index f5024759e2eb..42ecd8d155d5 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLListCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLListCmd.java @@ -27,7 +27,7 @@ import org.apache.cloudstack.api.*; import org.apache.cloudstack.api.response.AccountResponse; import org.apache.cloudstack.api.response.FirewallRuleResponse; -import org.apache.cloudstack.api.response.NetworkACLListResponse; +import org.apache.cloudstack.api.response.NetworkACLResponse; import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.log4j.Logger; @@ -40,7 +40,7 @@ public class DeleteNetworkACLListCmd extends BaseAsyncCmd { //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// - @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = NetworkACLListResponse.class, + @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = NetworkACLResponse.class, required=true, description="the ID of the network ACL") private Long id; diff --git a/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkACLListsCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkACLListsCmd.java index b043eed6ab42..55d61477ece7 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkACLListsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkACLListsCmd.java @@ -23,13 +23,15 @@ import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListTaggedResourcesCmd; import org.apache.cloudstack.api.Parameter; -import org.apache.cloudstack.api.response.*; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.NetworkACLResponse; +import org.apache.cloudstack.api.response.NetworkResponse; import org.apache.log4j.Logger; import java.util.ArrayList; import java.util.List; -@APICommand(name = "listNetworkACLLists", description="Lists all network ACLs", responseObject=NetworkACLListResponse.class) +@APICommand(name = "listNetworkACLLists", description="Lists all network ACLs", responseObject=NetworkACLResponse.class) public class ListNetworkACLListsCmd extends BaseListTaggedResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListNetworkACLListsCmd.class.getName()); @@ -70,11 +72,11 @@ public String getCommandName() { @Override public void execute(){ Pair,Integer> result = _networkACLService.listNetworkACLs(this); - ListResponse response = new ListResponse(); - List aclResponses = new ArrayList(); + ListResponse response = new ListResponse(); + List aclResponses = new ArrayList(); for (NetworkACL acl : result.first()) { - NetworkACLListResponse aclResponse = _responseGenerator.createNetworkACLResponse(acl); + NetworkACLResponse aclResponse = _responseGenerator.createNetworkACLResponse(acl); aclResponses.add(aclResponse); } response.setResponses(aclResponses, result.second()); diff --git a/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkACLsCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkACLsCmd.java index 93842d5c58bf..53e19d72f71b 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkACLsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkACLsCmd.java @@ -19,20 +19,21 @@ import java.util.ArrayList; import java.util.List; +import com.cloud.network.vpc.NetworkACLItem; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListTaggedResourcesCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.FirewallRuleResponse; import org.apache.cloudstack.api.response.ListResponse; -import org.apache.cloudstack.api.response.NetworkACLResponse; +import org.apache.cloudstack.api.response.NetworkACLItemResponse; import org.apache.cloudstack.api.response.NetworkResponse; import org.apache.log4j.Logger; import com.cloud.network.rules.FirewallRule; import com.cloud.utils.Pair; -@APICommand(name = "listNetworkACLs", description="Lists all network ACLs", responseObject=NetworkACLResponse.class) +@APICommand(name = "listNetworkACLs", description="Lists all network ACL items", responseObject=NetworkACLItemResponse.class) public class ListNetworkACLsCmd extends BaseListTaggedResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListNetworkACLsCmd.class.getName()); @@ -79,12 +80,12 @@ public String getCommandName() { @Override public void execute(){ - Pair,Integer> result = _networkACLService.listNetworkACLItems(this); - ListResponse response = new ListResponse(); - List aclResponses = new ArrayList(); + Pair,Integer> result = _networkACLService.listNetworkACLItems(this); + ListResponse response = new ListResponse(); + List aclResponses = new ArrayList(); - for (FirewallRule acl : result.first()) { - NetworkACLResponse ruleData = _responseGenerator.createNetworkACLItemResponse(acl); + for (NetworkACLItem acl : result.first()) { + NetworkACLItemResponse ruleData = _responseGenerator.createNetworkACLItemResponse(acl); aclResponses.add(ruleData); } response.setResponses(aclResponses, result.second()); diff --git a/api/src/org/apache/cloudstack/api/command/user/network/ReplaceNetworkACLListCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/ReplaceNetworkACLListCmd.java new file mode 100644 index 000000000000..78e0b1a61f31 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/network/ReplaceNetworkACLListCmd.java @@ -0,0 +1,107 @@ +// 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 org.apache.cloudstack.api.command.user.network; + +import com.cloud.event.EventTypes; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.vpc.NetworkACL; +import com.cloud.network.vpc.Vpc; +import com.cloud.user.UserContext; +import org.apache.cloudstack.api.*; +import org.apache.cloudstack.api.response.NetworkACLResponse; +import org.apache.cloudstack.api.response.NetworkResponse; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.log4j.Logger; + +@APICommand(name = "replaceNetworkACLList", description="Replaces ACL associated with a Network", responseObject=SuccessResponse.class) +public class ReplaceNetworkACLListCmd extends BaseAsyncCmd { + public static final Logger s_logger = Logger.getLogger(ReplaceNetworkACLListCmd.class.getName()); + private static final String s_name = "replacenetworkacllistresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.ACL_ID, type=CommandType.UUID, entityType = NetworkACLResponse.class, + required=true, description="the ID of the network ACL") + private long aclId; + + @Parameter(name=ApiConstants.NETWORK_ID, type=CommandType.UUID, entityType = NetworkResponse.class, + required=true, description="the ID of the network") + private long networkId; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public long getAclId() { + return aclId; + } + + public long getNetworkId(){ + return networkId; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + @Override + public String getCommandName() { + return s_name; + } + + @Override + public String getEventType() { + return EventTypes.EVENT_NETWORK_ACL_REPLACE; + } + + @Override + public String getEventDescription() { + return ("Associating Network ACL id=" + aclId+ " with Network id="+ networkId); + } + + @Override + public long getEntityOwnerId() { + NetworkACL acl = _networkACLService.getNetworkACL(aclId); + if (acl == null) { + throw new InvalidParameterValueException("Unable to find network ACL by id=" + aclId); + } else { + long vpcId = acl.getVpcId(); + Vpc vpc = _vpcService.getVpc(vpcId); + if(vpc != null){ + return vpc.getAccountId(); + } else { + throw new InvalidParameterValueException("Unable to find VPC associated with network ACL by id=" + aclId); + } + } + } + + @Override + public void execute() throws ResourceUnavailableException { + UserContext.current().setEventDetails("Network ACL Id: " + aclId); + boolean result = _networkACLService.replaceNetworkACL(aclId, networkId); + + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to replace network ACL"); + } + } +} + diff --git a/api/src/org/apache/cloudstack/api/response/NetworkACLItemResponse.java b/api/src/org/apache/cloudstack/api/response/NetworkACLItemResponse.java new file mode 100644 index 000000000000..d40acbf0ac14 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/response/NetworkACLItemResponse.java @@ -0,0 +1,106 @@ +// 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 org.apache.cloudstack.api.response; + +import java.util.List; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +@SuppressWarnings("unused") +public class NetworkACLItemResponse extends BaseResponse { + @SerializedName(ApiConstants.ID) @Param(description="the ID of the ACL Item") + private String id; + + @SerializedName(ApiConstants.PROTOCOL) @Param(description="the protocol of the ACL") + private String protocol; + + @SerializedName(ApiConstants.START_PORT) @Param(description="the starting port of ACL's port range") + private String startPort; + + @SerializedName(ApiConstants.END_PORT) @Param(description = "the ending port of ACL's port range") + private String endPort; + + @SerializedName(ApiConstants.TRAFFIC_TYPE) @Param(description="the traffic type for the ACL") + private String trafficType; + + @SerializedName(ApiConstants.STATE) @Param(description="the state of the rule") + private String state; + + @SerializedName(ApiConstants.CIDR_LIST) @Param(description="the cidr list to forward traffic from") + private String cidrList; + + @SerializedName(ApiConstants.ICMP_TYPE) @Param(description= "type of the icmp message being sent") + private Integer icmpType; + + @SerializedName(ApiConstants.ICMP_CODE) @Param(description = "error code for this icmp message") + private Integer icmpCode; + + @SerializedName(ApiConstants.TAGS) @Param(description="the list of resource tags associated with the network ACLs", + responseObject = ResourceTagResponse.class) + private List tags; + + @SerializedName(ApiConstants.ACL_ID) @Param(description="the ID of the ACL this item belongs to") + private String aclId; + + public void setId(String id) { + this.id = id; + } + + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + public void setStartPort(String startPort) { + this.startPort = startPort; + } + + public void setEndPort(String endPort) { + this.endPort = endPort; + } + + public void setState(String state) { + this.state = state; + } + + public void setCidrList(String cidrList) { + this.cidrList = cidrList; + } + + public void setIcmpType(Integer icmpType) { + this.icmpType = icmpType; + } + + public void setIcmpCode(Integer icmpCode) { + this.icmpCode = icmpCode; + } + + public void setTrafficType(String trafficType) { + this.trafficType = trafficType; + } + + public void setTags(List tags) { + this.tags = tags; + } + + public void setAclId(String aclId) { + this.aclId = aclId; + } +} diff --git a/api/src/org/apache/cloudstack/api/response/NetworkACLListResponse.java b/api/src/org/apache/cloudstack/api/response/NetworkACLListResponse.java deleted file mode 100644 index 34878510a940..000000000000 --- a/api/src/org/apache/cloudstack/api/response/NetworkACLListResponse.java +++ /dev/null @@ -1,57 +0,0 @@ -// 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 org.apache.cloudstack.api.response; - -import com.cloud.network.vpc.NetworkACL; -import com.cloud.serializer.Param; -import com.google.gson.annotations.SerializedName; -import org.apache.cloudstack.api.ApiConstants; -import org.apache.cloudstack.api.BaseResponse; -import org.apache.cloudstack.api.EntityReference; - -import java.util.List; - -@EntityReference(value = NetworkACL.class) -public class NetworkACLListResponse extends BaseResponse { - @SerializedName(ApiConstants.ID) @Param(description="the ID of the ACL") - private String id; - - @SerializedName(ApiConstants.NAME) @Param(description="the Name of the ACL") - private String name; - - @SerializedName(ApiConstants.DESCRIPTION) @Param(description="Description of the ACL") - private String description; - - @SerializedName(ApiConstants.VPC_ID) @Param(description="Id of the VPC this ACL is associated with") - private String vpcId; - - public void setId(String id) { - this.id = id; - } - - public void setName(String name) { - this.name = name; - } - - public void setDescription(String description) { - this.description = description; - } - - public void setVpcId(String vpcId) { - this.vpcId = vpcId; - } -} diff --git a/api/src/org/apache/cloudstack/api/response/NetworkACLResponse.java b/api/src/org/apache/cloudstack/api/response/NetworkACLResponse.java index b45b43cf6eca..12ca38b222ac 100644 --- a/api/src/org/apache/cloudstack/api/response/NetworkACLResponse.java +++ b/api/src/org/apache/cloudstack/api/response/NetworkACLResponse.java @@ -16,84 +16,42 @@ // under the License. package org.apache.cloudstack.api.response; -import java.util.List; - +import com.cloud.network.vpc.NetworkACL; +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; -import com.cloud.serializer.Param; -import com.google.gson.annotations.SerializedName; +import java.util.List; -@SuppressWarnings("unused") +@EntityReference(value = NetworkACL.class) public class NetworkACLResponse extends BaseResponse { @SerializedName(ApiConstants.ID) @Param(description="the ID of the ACL") private String id; - @SerializedName(ApiConstants.PROTOCOL) @Param(description="the protocol of the ACL") - private String protocol; - - @SerializedName(ApiConstants.START_PORT) @Param(description="the starting port of ACL's port range") - private String startPort; - - @SerializedName(ApiConstants.END_PORT) @Param(description = "the ending port of ACL's port range") - private String endPort; - - @SerializedName(ApiConstants.TRAFFIC_TYPE) @Param(description="the traffic type for the ACL") - private String trafficType; - - @SerializedName(ApiConstants.STATE) @Param(description="the state of the rule") - private String state; - - @SerializedName(ApiConstants.CIDR_LIST) @Param(description="the cidr list to forward traffic from") - private String cidrList; - - @SerializedName(ApiConstants.ICMP_TYPE) @Param(description= "type of the icmp message being sent") - private Integer icmpType; + @SerializedName(ApiConstants.NAME) @Param(description="the Name of the ACL") + private String name; - @SerializedName(ApiConstants.ICMP_CODE) @Param(description = "error code for this icmp message") - private Integer icmpCode; + @SerializedName(ApiConstants.DESCRIPTION) @Param(description="Description of the ACL") + private String description; - @SerializedName(ApiConstants.TAGS) @Param(description="the list of resource tags associated with the network ACLs", - responseObject = ResourceTagResponse.class) - private List tags; + @SerializedName(ApiConstants.VPC_ID) @Param(description="Id of the VPC this ACL is associated with") + private String vpcId; public void setId(String id) { this.id = id; } - public void setProtocol(String protocol) { - this.protocol = protocol; - } - - public void setStartPort(String startPort) { - this.startPort = startPort; - } - - public void setEndPort(String endPort) { - this.endPort = endPort; - } - - public void setState(String state) { - this.state = state; - } - - public void setCidrList(String cidrList) { - this.cidrList = cidrList; - } - - public void setIcmpType(Integer icmpType) { - this.icmpType = icmpType; - } - - public void setIcmpCode(Integer icmpCode) { - this.icmpCode = icmpCode; + public void setName(String name) { + this.name = name; } - public void setTrafficType(String trafficType) { - this.trafficType = trafficType; + public void setDescription(String description) { + this.description = description; } - public void setTags(List tags) { - this.tags = tags; + public void setVpcId(String vpcId) { + this.vpcId = vpcId; } } diff --git a/client/tomcatconf/applicationContext.xml.in b/client/tomcatconf/applicationContext.xml.in index 961bd3b21618..997b944553ed 100644 --- a/client/tomcatconf/applicationContext.xml.in +++ b/client/tomcatconf/applicationContext.xml.in @@ -247,6 +247,7 @@ + diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index 5c49cb17b0e2..4e10527cd748 100644 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -437,6 +437,7 @@ deleteNetworkACL=15 listNetworkACLs=15 createNetworkACLList=15 deleteNetworkACLList=15 +replaceNetworkACLList=15 listNetworkACLLists=15 diff --git a/core/src/com/cloud/agent/api/routing/SetNetworkACLCommand.java b/core/src/com/cloud/agent/api/routing/SetNetworkACLCommand.java index dba7354c8f24..d876c61fb4b4 100644 --- a/core/src/com/cloud/agent/api/routing/SetNetworkACLCommand.java +++ b/core/src/com/cloud/agent/api/routing/SetNetworkACLCommand.java @@ -17,6 +17,9 @@ package com.cloud.agent.api.routing; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -42,11 +45,17 @@ public NetworkACLTO[] getRules() { public String[][] generateFwRules() { String [][] result = new String [2][]; Set toAdd = new HashSet(); + List aclList = Arrays.asList(rules); + Collections.sort(aclList, new Comparator() { + @Override + public int compare(NetworkACLTO acl1, NetworkACLTO acl2) { + return acl1.getNumber() > acl2.getNumber() ? 1 : -1; + } + }); - - for (NetworkACLTO aclTO: rules) { - /* example : Ingress:tcp:80:80:0.0.0.0/0:,Egress:tcp:220:220:0.0.0.0/0:, - * each entry format Ingress/Egress:protocol:start port: end port:scidrs: + for (NetworkACLTO aclTO: aclList) { + /* example : Ingress:tcp:80:80:0.0.0.0/0:ACCEPT:,Egress:tcp:220:220:0.0.0.0/0:DROP:, + * each entry format Ingress/Egress:protocol:start port: end port:scidrs:action: * reverted entry format Ingress/Egress:reverted:0:0:0: */ if (aclTO.revoked() == true) @@ -80,7 +89,7 @@ public String[][] generateFwRules() { firstEntry = false; } } - sb.append(":"); + sb.append(":").append(aclTO.getAction()).append(":"); String aclRuleEntry = sb.toString(); toAdd.add(aclRuleEntry); diff --git a/engine/schema/src/com/cloud/network/dao/NetworkDao.java b/engine/schema/src/com/cloud/network/dao/NetworkDao.java index 1d3f0b84aa61..43cabe751f6d 100644 --- a/engine/schema/src/com/cloud/network/dao/NetworkDao.java +++ b/engine/schema/src/com/cloud/network/dao/NetworkDao.java @@ -111,4 +111,6 @@ public interface NetworkDao extends GenericDao , StateDao listNetworksByAccount(long accountId, long zoneId, Network.GuestType type, boolean isSystem); List listRedundantNetworks(); + + List listByAclId(long aclId); } diff --git a/engine/schema/src/com/cloud/network/dao/NetworkDaoImpl.java b/engine/schema/src/com/cloud/network/dao/NetworkDaoImpl.java index 1bc8973bc50c..5b3b526b640b 100644 --- a/engine/schema/src/com/cloud/network/dao/NetworkDaoImpl.java +++ b/engine/schema/src/com/cloud/network/dao/NetworkDaoImpl.java @@ -104,6 +104,7 @@ protected void init() { AllFieldsSearch.and("physicalNetwork", AllFieldsSearch.entity().getPhysicalNetworkId(), Op.EQ); AllFieldsSearch.and("broadcastUri", AllFieldsSearch.entity().getBroadcastUri(), Op.EQ); AllFieldsSearch.and("vpcId", AllFieldsSearch.entity().getVpcId(), Op.EQ); + AllFieldsSearch.and("aclId", AllFieldsSearch.entity().getNetworkACLId(), Op.EQ); SearchBuilder join1 = _ntwkOffDao.createSearchBuilder(); join1.and("isSystem", join1.entity().isSystemOnly(), Op.EQ); join1.and("isRedundant", join1.entity().getRedundantRouter(), Op.EQ); @@ -618,4 +619,12 @@ public List listRedundantNetworks() { sc.setJoinParameters("offerings", "isRedundant", true); return listBy(sc, null); } + + @Override + public List listByAclId(long aclId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("aclId", aclId); + + return listBy(sc, null); + } } diff --git a/engine/schema/src/com/cloud/network/dao/NetworkVO.java b/engine/schema/src/com/cloud/network/dao/NetworkVO.java index 77b40c8a5c90..664bc7759972 100644 --- a/engine/schema/src/com/cloud/network/dao/NetworkVO.java +++ b/engine/schema/src/com/cloud/network/dao/NetworkVO.java @@ -163,6 +163,9 @@ public class NetworkVO implements Network { @Column(name="ip6_cidr") String ip6Cidr; + @Column(name="network_acl_id") + Long networkACLId; + public NetworkVO() { this.uuid = UUID.randomUUID().toString(); } @@ -540,4 +543,13 @@ public String getIp6Gateway() { public void setIp6Gateway(String ip6Gateway) { this.ip6Gateway = ip6Gateway; } + + public void setNetworkACLId(Long networkACLId) { + this.networkACLId = networkACLId; + } + + @Override + public Long getNetworkACLId() { + return networkACLId; + } } diff --git a/server/src/com/cloud/api/ApiDBUtils.java b/server/src/com/cloud/api/ApiDBUtils.java index b8eea12b4cf3..ac48c024c75a 100755 --- a/server/src/com/cloud/api/ApiDBUtils.java +++ b/server/src/com/cloud/api/ApiDBUtils.java @@ -26,6 +26,18 @@ import javax.inject.Inject; import com.cloud.network.rules.LoadBalancer; +import com.cloud.network.vpc.NetworkACL; +import com.cloud.network.vpc.StaticRouteVO; +import com.cloud.network.vpc.VpcGatewayVO; +import com.cloud.network.vpc.VpcManager; +import com.cloud.network.vpc.VpcOffering; +import com.cloud.network.vpc.VpcProvisioningService; +import com.cloud.network.vpc.VpcVO; +import com.cloud.network.vpc.dao.NetworkACLDao; +import com.cloud.network.vpc.dao.StaticRouteDao; +import com.cloud.network.vpc.dao.VpcDao; +import com.cloud.network.vpc.dao.VpcGatewayDao; +import com.cloud.network.vpc.dao.VpcOfferingDao; import com.cloud.region.ha.GlobalLoadBalancingRulesService; import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.affinity.AffinityGroupResponse; @@ -185,16 +197,6 @@ import com.cloud.network.security.SecurityGroupManager; import com.cloud.network.security.SecurityGroupVO; import com.cloud.network.security.dao.SecurityGroupDao; -import com.cloud.network.vpc.StaticRouteVO; -import com.cloud.network.vpc.VpcGatewayVO; -import com.cloud.network.vpc.VpcManager; -import com.cloud.network.vpc.VpcOffering; -import com.cloud.network.vpc.VpcProvisioningService; -import com.cloud.network.vpc.VpcVO; -import com.cloud.network.vpc.dao.StaticRouteDao; -import com.cloud.network.vpc.dao.VpcDao; -import com.cloud.network.vpc.dao.VpcGatewayDao; -import com.cloud.network.vpc.dao.VpcOfferingDao; import com.cloud.offering.DiskOffering; import com.cloud.offering.NetworkOffering; import com.cloud.offering.ServiceOffering; @@ -394,6 +396,7 @@ public class ApiDBUtils { static AffinityGroupDao _affinityGroupDao; static AffinityGroupJoinDao _affinityGroupJoinDao; static GlobalLoadBalancingRulesService _gslbService; + static NetworkACLDao _networkACLDao; @Inject private ManagementServer ms; @Inject public AsyncJobManager asyncMgr; @@ -502,6 +505,7 @@ public class ApiDBUtils { @Inject private AffinityGroupDao affinityGroupDao; @Inject private AffinityGroupJoinDao affinityGroupJoinDao; @Inject private GlobalLoadBalancingRulesService gslbService; + @Inject private NetworkACLDao networkACLDao; @PostConstruct void init() { @@ -611,6 +615,7 @@ void init() { _gslbService = gslbService; // Note: stats collector should already have been initialized by this time, otherwise a null instance is returned _statsCollector = StatsCollector.getInstance(); + _networkACLDao = networkACLDao; } // /////////////////////////////////////////////////////////// @@ -1286,6 +1291,9 @@ public static VpcOffering findVpcOfferingById(long offeringId){ return _vpcOfferingDao.findById(offeringId); } + public static NetworkACL findByNetworkACLId(long aclId){ + return _networkACLDao.findById(aclId); + } public static AsyncJob findAsyncJobById(long jobId){ return _asyncJobDao.findById(jobId); diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 619c9bb1ef4e..f966ea0ee6ab 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -34,6 +34,13 @@ import javax.inject.Inject; +import com.cloud.network.vpc.NetworkACL; +import com.cloud.network.vpc.NetworkACLItem; +import com.cloud.network.vpc.PrivateGateway; +import com.cloud.network.vpc.StaticRoute; +import com.cloud.network.vpc.Vpc; +import com.cloud.network.vpc.VpcOffering; +import com.cloud.vm.*; import com.cloud.network.vpc.NetworkACL; import com.cloud.network.vpc.PrivateGateway; import com.cloud.network.vpc.StaticRoute; @@ -85,7 +92,7 @@ import org.apache.cloudstack.api.response.LBStickinessResponse; import org.apache.cloudstack.api.response.LDAPConfigResponse; import org.apache.cloudstack.api.response.LoadBalancerResponse; -import org.apache.cloudstack.api.response.NetworkACLListResponse; +import org.apache.cloudstack.api.response.NetworkACLItemResponse; import org.apache.cloudstack.api.response.NetworkACLResponse; import org.apache.cloudstack.api.response.NetworkOfferingResponse; import org.apache.cloudstack.api.response.NetworkResponse; @@ -2532,8 +2539,8 @@ public FirewallResponse createFirewallResponse(FirewallRule fwRule) { } @Override - public NetworkACLResponse createNetworkACLItemResponse(FirewallRule networkACL) { - NetworkACLResponse response = new NetworkACLResponse(); + public NetworkACLItemResponse createNetworkACLItemResponse(NetworkACLItem networkACL) { + NetworkACLItemResponse response = new NetworkACLItemResponse(); response.setId(networkACL.getUuid()); response.setProtocol(networkACL.getProtocol()); @@ -2550,9 +2557,9 @@ public NetworkACLResponse createNetworkACLItemResponse(FirewallRule networkACL) response.setTrafficType(networkACL.getTrafficType().toString()); - FirewallRule.State state = networkACL.getState(); + NetworkACLItem.State state = networkACL.getState(); String stateToSet = state.toString(); - if (state.equals(FirewallRule.State.Revoke)) { + if (state.equals(NetworkACLItem.State.Revoke)) { stateToSet = "Deleting"; } @@ -2561,6 +2568,11 @@ public NetworkACLResponse createNetworkACLItemResponse(FirewallRule networkACL) response.setState(stateToSet); + NetworkACL acl = ApiDBUtils.findByNetworkACLId(networkACL.getACLId()); + if(acl != null){ + response.setAclId(acl.getUuid()); + } + //set tag information List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.NetworkACL, networkACL.getId()); List tagResponses = new ArrayList(); @@ -3729,8 +3741,8 @@ public IsolationMethodResponse createIsolationMethodResponse(IsolationType metho return response; } - public NetworkACLListResponse createNetworkACLResponse(NetworkACL networkACL) { - NetworkACLListResponse response = new NetworkACLListResponse(); + public NetworkACLResponse createNetworkACLResponse(NetworkACL networkACL) { + NetworkACLResponse response = new NetworkACLResponse(); response.setId(networkACL.getUuid()); response.setName(networkACL.getName()); response.setDescription(networkACL.getDescription()); diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index a995661b9ce5..6dc96333d17d 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -2665,7 +2665,7 @@ protected boolean reprogramNetworkRules(long networkId, Account caller, NetworkV } //apply network ACLs - if (!_networkACLMgr.applyNetworkACLs(networkId, caller)) { + if (!_networkACLMgr.applyNetworkACL(networkId, caller)) { s_logger.warn("Failed to reapply network ACLs as a part of of network id=" + networkId + " restart"); success = false; } @@ -3136,7 +3136,7 @@ private boolean cleanupNetworkResources(long networkId, Account caller, long cal //revoke all network ACLs for network try { - if (_networkACLMgr.revokeAllNetworkACLsForNetwork(networkId, callerUserId, caller)) { + if (_networkACLMgr.revokeACLItemsForNetwork(networkId, callerUserId, caller)) { s_logger.debug("Successfully cleaned up NetworkACLs for network id=" + networkId); } else { success = false; diff --git a/server/src/com/cloud/network/element/VpcVirtualRouterElement.java b/server/src/com/cloud/network/element/VpcVirtualRouterElement.java index 08443698ea0b..8b0c58ae86b4 100644 --- a/server/src/com/cloud/network/element/VpcVirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VpcVirtualRouterElement.java @@ -25,6 +25,7 @@ import javax.ejb.Local; import javax.inject.Inject; +import com.cloud.network.vpc.*; import org.apache.log4j.Logger; import com.cloud.dc.DataCenter; @@ -48,11 +49,6 @@ import com.cloud.network.router.VirtualRouter.Role; import com.cloud.network.router.VpcVirtualNetworkApplianceManager; import com.cloud.network.rules.FirewallRule; -import com.cloud.network.vpc.PrivateGateway; -import com.cloud.network.vpc.StaticRouteProfile; -import com.cloud.network.vpc.Vpc; -import com.cloud.network.vpc.VpcGateway; -import com.cloud.network.vpc.VpcManager; import com.cloud.offering.NetworkOffering; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.DomainRouterVO; @@ -390,7 +386,7 @@ public boolean applyIps(Network network, List ipAddre } @Override - public boolean applyNetworkACLs(Network config, List rules) throws ResourceUnavailableException { + public boolean applyNetworkACLs(Network config, List rules) throws ResourceUnavailableException { if (canHandle(config, Service.NetworkACL)) { List routers = _routerDao.listByNetworkAndRole(config.getId(), Role.VIRTUAL_ROUTER); if (routers == null || routers.isEmpty()) { diff --git a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java index 4ad8868b86a6..20a45de01857 100644 --- a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java +++ b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java @@ -574,7 +574,7 @@ public boolean applyRules(Network network, Purpose purpose, List deployVirtualRouterInVpc(Vpc vpc, DeployDestination dest, A * @return * @throws ResourceUnavailableException */ - boolean applyNetworkACLs(Network network, List rules, List routers) + boolean applyNetworkACLs(Network network, List rules, List routers) throws ResourceUnavailableException; /** diff --git a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java index ebf2d4257e3e..1d901d9d428a 100644 --- a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java @@ -27,6 +27,7 @@ import javax.ejb.Local; import javax.inject.Inject; +import com.cloud.network.vpc.*; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -93,16 +94,6 @@ import com.cloud.network.rules.FirewallRule; import com.cloud.network.rules.FirewallRule.Purpose; import com.cloud.network.rules.FirewallRuleVO; -import com.cloud.network.vpc.NetworkACLManager; -import com.cloud.network.vpc.PrivateGateway; -import com.cloud.network.vpc.PrivateIpAddress; -import com.cloud.network.vpc.PrivateIpVO; -import com.cloud.network.vpc.StaticRoute; -import com.cloud.network.vpc.StaticRouteProfile; -import com.cloud.network.vpc.Vpc; -import com.cloud.network.vpc.VpcGateway; -import com.cloud.network.vpc.VpcManager; -import com.cloud.network.vpc.VpcVO; import com.cloud.network.vpc.dao.PrivateIpDao; import com.cloud.network.vpc.dao.StaticRouteDao; import com.cloud.network.vpc.dao.VpcDao; @@ -704,7 +695,7 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile rules, List routers) + public boolean applyNetworkACLs(Network network, final List rules, List routers) throws ResourceUnavailableException { if (rules == null || rules.isEmpty()) { s_logger.debug("No network ACLs to be applied for network " + network.getId()); @@ -719,14 +710,14 @@ public boolean execute(Network network, VirtualRouter router) throws ResourceUna } - protected boolean sendNetworkACLs(VirtualRouter router, List rules, long guestNetworkId) + protected boolean sendNetworkACLs(VirtualRouter router, List rules, long guestNetworkId) throws ResourceUnavailableException { Commands cmds = new Commands(OnError.Continue); createNetworkACLsCommands(rules, router, cmds, guestNetworkId); return sendCommandsToRouter(router, cmds); } - private void createNetworkACLsCommands(List rules, VirtualRouter router, Commands cmds, + private void createNetworkACLsCommands(List rules, VirtualRouter router, Commands cmds, long guestNetworkId) { List rulesTO = null; String guestVlan = null; @@ -739,11 +730,11 @@ private void createNetworkACLsCommands(List rules, Virtu if (rules != null) { rulesTO = new ArrayList(); - for (FirewallRule rule : rules) { - if (rule.getSourceCidrList() == null && (rule.getPurpose() == Purpose.Firewall || rule.getPurpose() == Purpose.NetworkACL)) { - _firewallDao.loadSourceCidrs((FirewallRuleVO)rule); - } - NetworkACLTO ruleTO = new NetworkACLTO(rule, guestVlan, rule.getTrafficType()); + for (NetworkACLItem rule : rules) { +// if (rule.getSourceCidrList() == null && (rule.getPurpose() == Purpose.Firewall || rule.getPurpose() == Purpose.NetworkACL)) { +// _firewallDao.loadSourceCidrs((FirewallRuleVO)rule); +// } + NetworkACLTO ruleTO = new NetworkACLTO((NetworkACLItemVO)rule, guestVlan, rule.getTrafficType()); rulesTO.add(ruleTO); } } @@ -929,7 +920,7 @@ protected void finalizeNetworkRulesForNetwork(Commands cmds, DomainRouterVO rout if (router.getVpcId() != null) { if (_networkModel.isProviderSupportServiceInNetwork(guestNetworkId, Service.NetworkACL, Provider.VPCVirtualRouter)) { - List networkACLs = _networkACLMgr.listNetworkACLs(guestNetworkId); + List networkACLs = _networkACLMgr.listNetworkACLItems(guestNetworkId); s_logger.debug("Found " + networkACLs.size() + " network ACLs to apply as a part of VPC VR " + router + " start for guest network id=" + guestNetworkId); if (!networkACLs.isEmpty()) { diff --git a/server/src/com/cloud/network/vpc/NetworkACLItemDao.java b/server/src/com/cloud/network/vpc/NetworkACLItemDao.java new file mode 100644 index 000000000000..739aa8cb7416 --- /dev/null +++ b/server/src/com/cloud/network/vpc/NetworkACLItemDao.java @@ -0,0 +1,44 @@ +// 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.network.vpc; + +import com.cloud.utils.db.GenericDao; + +import java.util.List; + +/* + * Data Access Object for network_acl_item table + */ +public interface NetworkACLItemDao extends GenericDao { + + List listByACLAndNotRevoked(long aclId); + + boolean setStateToAdd(NetworkACLItemVO rule); + + boolean revoke(NetworkACLItemVO rule); + + boolean releasePorts(long ipAddressId, String protocol, int[] ports); + + List listByACL(long aclId); + + List listSystemRules(); + + List listByACLTrafficTypeAndNotRevoked(long aclId, NetworkACLItemVO.TrafficType trafficType); + List listByACLTrafficType(long aclId, NetworkACLItemVO.TrafficType trafficType); + + void loadSourceCidrs(NetworkACLItemVO rule); +} diff --git a/server/src/com/cloud/network/vpc/NetworkACLItemVO.java b/server/src/com/cloud/network/vpc/NetworkACLItemVO.java new file mode 100644 index 000000000000..9b2463187a93 --- /dev/null +++ b/server/src/com/cloud/network/vpc/NetworkACLItemVO.java @@ -0,0 +1,198 @@ +// 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.network.vpc; + +import com.cloud.network.rules.FirewallRule; +import com.cloud.utils.db.GenericDao; +import com.cloud.utils.net.NetUtils; + +import javax.persistence.*; +import java.util.Date; +import java.util.List; +import java.util.UUID; + +@Entity +@Table(name="network_acl_item") +public class NetworkACLItemVO implements NetworkACLItem { + + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="id") + long id; + + @Column(name="start_port", updatable=false) + Integer sourcePortStart; + + @Column(name="end_port", updatable=false) + Integer sourcePortEnd; + + @Column(name="protocol", updatable=false) + String protocol = NetUtils.TCP_PROTO; + + @Enumerated(value=EnumType.STRING) + @Column(name="state") + State state; + + @Column(name=GenericDao.CREATED_COLUMN) + Date created; + + @Column(name="acl_id") + Long ACLId; + + @Column(name="icmp_code") + Integer icmpCode; + + @Column(name="icmp_type") + Integer icmpType; + + @Column(name="type") + @Enumerated(value=EnumType.STRING) + NetworkACLType type; + + @Column(name="traffic_type") + @Enumerated(value=EnumType.STRING) + TrafficType trafficType; + + + // This is a delayed load value. If the value is null, + // then this field has not been loaded yet. + // Call firewallrules dao to load it. + @Transient + List sourceCidrs; + + @Column(name="uuid") + String uuid; + + public void setSourceCidrList(List sourceCidrs) { + this.sourceCidrs=sourceCidrs; + } + + @Override + public List getSourceCidrList() { + return sourceCidrs; + } + + @Override + public long getId() { + return id; + } + + @Override + public Integer getSourcePortStart() { + return sourcePortStart; + } + + @Override + public Integer getSourcePortEnd() { + return sourcePortEnd; + } + + @Override + public String getProtocol() { + return protocol; + } + + public void setState(State state) { + this.state = state; + } + + @Override + public State getState() { + return state; + } + + @Override + public long getACLId() { + return ACLId; + } + + @Override + public NetworkACLType getType() { + return type; + } + public Date getCreated() { + return created; + } + + protected NetworkACLItemVO() { + this.uuid = UUID.randomUUID().toString(); + } + + public NetworkACLItemVO(Integer portStart, Integer portEnd, String protocol, + long aclId, List sourceCidrs, Integer icmpCode, + Integer icmpType, TrafficType trafficType) { + this.sourcePortStart = portStart; + this.sourcePortEnd = portEnd; + this.protocol = protocol; + this.ACLId = aclId; + this.state = State.Staged; + this.icmpCode = icmpCode; + this.icmpType = icmpType; + this.sourceCidrs = sourceCidrs; + this.uuid = UUID.randomUUID().toString(); + this.type = NetworkACLType.User; + this.trafficType = trafficType; + } + + + public NetworkACLItemVO(int port, String protocol, long aclId, List sourceCidrs, Integer icmpCode, Integer icmpType) { + this(port, port, protocol, aclId, sourceCidrs, icmpCode, icmpType, null); + } + + @Override + public String toString() { + return new StringBuilder("Rule[").append(id).append("-").append("NetworkACL").append("-").append(state).append("]").toString(); + } + + @Override + public Integer getIcmpCode() { + return icmpCode; + } + + @Override + public Integer getIcmpType() { + return icmpType; + } + + @Override + public String getUuid() { + return this.uuid; + } + + @Override + public Action getAction() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public int getNumber() { + return 0; //To change body of implemented methods use File | Settings | File Templates. + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public void setType(NetworkACLType type) { + this.type = type; + } + + @Override + public TrafficType getTrafficType() { + return trafficType; + } +} diff --git a/server/src/com/cloud/network/vpc/NetworkACLManager.java b/server/src/com/cloud/network/vpc/NetworkACLManager.java index 515c25117736..dba91b2f254d 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLManager.java +++ b/server/src/com/cloud/network/vpc/NetworkACLManager.java @@ -22,6 +22,7 @@ import com.cloud.network.firewall.NetworkACLService; import com.cloud.network.rules.FirewallRule; import com.cloud.user.Account; +import com.cloud.utils.db.DB; import org.apache.cloudstack.api.command.user.network.CreateNetworkACLListCmd; @@ -34,8 +35,12 @@ public interface NetworkACLManager extends NetworkACLService{ * @return * @throws ResourceUnavailableException */ - boolean revokeAllNetworkACLsForNetwork(long networkId, long userId, Account caller) throws ResourceUnavailableException; + boolean revokeACLItemsForNetwork(long networkId, long userId, Account caller) throws ResourceUnavailableException; - List listNetworkACLs(long guestNtwkId); + List listNetworkACLItems(long guestNtwkId); + boolean applyNetworkACL(long networkId, Account caller) throws ResourceUnavailableException; + + @DB + void revokeRule(NetworkACLItemVO rule, Account caller, long userId, boolean needUsageEvent); } diff --git a/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java b/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java index b00f8a15a313..a345cc680f0e 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java +++ b/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java @@ -24,7 +24,12 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.NetworkVO; +import com.cloud.network.element.NetworkACLServiceProvider; import com.cloud.network.vpc.dao.NetworkACLDao; +import com.cloud.network.vpc.NetworkACLItem.State; +import org.apache.cloudstack.api.command.user.network.CreateNetworkACLCmd; import org.apache.cloudstack.api.command.user.network.CreateNetworkACLListCmd; import org.apache.cloudstack.api.command.user.network.ListNetworkACLListsCmd; import org.apache.cloudstack.api.command.user.network.ListNetworkACLsCmd; @@ -42,13 +47,7 @@ import com.cloud.network.Network.Service; import com.cloud.network.NetworkModel; import com.cloud.network.Networks; -import com.cloud.network.dao.FirewallRulesDao; import com.cloud.network.firewall.NetworkACLService; -import com.cloud.network.rules.FirewallManager; -import com.cloud.network.rules.FirewallRule; -import com.cloud.network.rules.FirewallRule.Purpose; -import com.cloud.network.rules.FirewallRule.TrafficType; -import com.cloud.network.rules.FirewallRuleVO; import com.cloud.projects.Project.ListProjectResourcesCriteria; import com.cloud.server.ResourceTag.TaggedResourceType; import com.cloud.tags.ResourceTagVO; @@ -79,10 +78,6 @@ public class NetworkACLManagerImpl extends ManagerBase implements NetworkACLMana @Inject AccountManager _accountMgr; @Inject - FirewallManager _firewallMgr; - @Inject - FirewallRulesDao _firewallDao; - @Inject NetworkModel _networkMgr; @Inject VpcManager _vpcMgr; @@ -90,51 +85,128 @@ public class NetworkACLManagerImpl extends ManagerBase implements NetworkACLMana ResourceTagDao _resourceTagDao; @Inject NetworkACLDao _networkACLDao; + @Inject + NetworkACLItemDao _networkACLItemDao; + @Inject + List _networkAclElements; + @Inject + NetworkModel _networkModel; + @Inject + NetworkDao _networkDao; + + + @Override + public boolean revokeACLItemsForNetwork(long networkId, long userId, Account caller) throws ResourceUnavailableException { + Network network = _networkDao.findById(networkId); + List aclItems = _networkACLItemDao.listByACL(network.getNetworkACLId()); + if (aclItems.isEmpty()) { + s_logger.debug("Found no network ACL Items for network id=" + networkId); + return true; + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Releasing " + aclItems.size() + " Network ACL Items for network id=" + networkId); + } + + for (NetworkACLItemVO aclItem : aclItems) { + // Mark all Network ACLs rules as Revoke, but don't revoke them yet - we have to revoke all rules for ip, no + // need to send them one by one + revokeNetworkACLItem(aclItem.getId(), false, caller, Account.ACCOUNT_ID_SYSTEM); + } + + //List ACLsToRevoke = _networkACLItemDao.listByNetwork(networkId); + + // now send everything to the backend + boolean success = applyNetworkACL(network.getNetworkACLId(), caller); + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Successfully released Network ACLs for network id=" + networkId + " and # of rules now = " + + aclItems.size()); + } + + return success; + } + + @Override + public List listNetworkACLItems(long guestNtwkId) { + Network network = _networkMgr.getNetwork(guestNtwkId); + return _networkACLItemDao.listByACL(network.getNetworkACLId()); + } @Override - public boolean applyNetworkACLs(long networkId, Account caller) throws ResourceUnavailableException { - List rules = _firewallDao.listByNetworkAndPurpose(networkId, Purpose.NetworkACL); - return _firewallMgr.applyFirewallRules(rules, false, caller); + public NetworkACLItem getNetworkACLItem(long ruleId) { + return _networkACLItemDao.findById(ruleId); } @Override - public FirewallRule createNetworkACLItem(FirewallRule acl) throws NetworkRuleConflictException { - if (acl.getSourceCidrList() == null && (acl.getPurpose() == Purpose.Firewall || acl.getPurpose() == Purpose.NetworkACL)) { - _firewallDao.loadSourceCidrs((FirewallRuleVO)acl); + public boolean applyNetworkACLtoNetworks(long aclId, Account caller) throws ResourceUnavailableException { + boolean handled = false; + List rules = _networkACLItemDao.listByACL(aclId); + //Find all networks using this ACL + List networks = _networkDao.listByAclId(aclId); + for(NetworkVO network : networks){ + applyNetworkACL(network.getId(), caller); } - return createNetworkACL(UserContext.current().getCaller(), acl.getXid(), acl.getSourcePortStart(), - acl.getSourcePortEnd(), acl.getProtocol(), acl.getSourceCidrList(), acl.getIcmpCode(), - acl.getIcmpType(), null, acl.getType(), acl.getNetworkId(), acl.getTrafficType()); + return handled; } - @DB - @ActionEvent(eventType = EventTypes.EVENT_FIREWALL_OPEN, eventDescription = "creating firewall rule", create = true) - protected FirewallRule createNetworkACL(Account caller, String xId, Integer portStart, - Integer portEnd, String protocol, List sourceCidrList, Integer icmpCode, Integer icmpType, - Long relatedRuleId, FirewallRule.FirewallRuleType type, long networkId, TrafficType trafficType) throws NetworkRuleConflictException { - - Network network = _networkMgr.getNetwork(networkId); - if (network == null) { - throw new InvalidParameterValueException("Can't find network by id"); + @Override + public boolean applyNetworkACL(long networkId, Account caller) throws ResourceUnavailableException { + Network network = _networkDao.findById(networkId); + boolean handled = false; + List rules = _networkACLItemDao.listByACL(network.getNetworkACLId()); + for (NetworkACLServiceProvider element: _networkAclElements) { + Network.Provider provider = element.getProvider(); + boolean isAclProvider = _networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.NetworkACL, provider); + if (!isAclProvider) { + continue; + } + handled = element.applyNetworkACLs(network, rules); + if (handled) + break; + } + return handled; + } + + @Override + public NetworkACLItem createNetworkACLItem(CreateNetworkACLCmd aclItemCmd) throws NetworkRuleConflictException { + if (aclItemCmd.getSourceCidrList() == null) { + //_networkACLItemDao.loadSourceCidrs(aclItemCmd); } - - if (network.getVpcId() == null) { - throw new UnsupportedOperationException("Network ACL rules are supported just for VPC networks"); + return createNetworkACLItem(UserContext.current().getCaller(), aclItemCmd.getSourcePortStart(), + aclItemCmd.getSourcePortEnd(), aclItemCmd.getProtocol(), aclItemCmd.getSourceCidrList(), aclItemCmd.getIcmpCode(), + aclItemCmd.getIcmpType(), null, aclItemCmd.getType(), aclItemCmd.getNetworkId(), aclItemCmd.getTrafficType(), aclItemCmd.getACLId()); + } + + @DB + @ActionEvent(eventType = EventTypes.EVENT_NETWORK_ACL_ITEM_CREATE, eventDescription = "creating network ACL Item", create = true) + protected NetworkACLItem createNetworkACLItem(Account caller, Integer portStart, Integer portEnd, String protocol, List sourceCidrList, + Integer icmpCode, Integer icmpType, Long relatedRuleId, NetworkACLItem.NetworkACLType type, + Long networkId, NetworkACLItem.TrafficType trafficType, Long aclId) throws NetworkRuleConflictException { + + if(aclId == null){ + Network network = _networkMgr.getNetwork(networkId); + if (network == null) { + throw new InvalidParameterValueException("Can't find network by id"); + } + aclId = network.getNetworkACLId(); + + if (aclId == null) { + throw new InvalidParameterValueException("Network is not associated with any ACL"); + } } - - Vpc vpc = _vpcMgr.getVpc(network.getVpcId()); + + NetworkACL networkACL = _networkACLDao.findById(aclId); + + Vpc vpc = _vpcMgr.getVpc(networkACL.getVpcId()); Account aclOwner = _accountMgr.getAccount(vpc.getAccountId()); - + //check if the caller can access vpc _accountMgr.checkAccess(caller, null, false, vpc); //check if the acl can be created for this network - _accountMgr.checkAccess(aclOwner, AccessType.UseNetwork, false, network); - - if (!_networkMgr.areServicesSupportedInNetwork(networkId, Service.NetworkACL)) { - throw new InvalidParameterValueException("Service " + Service.NetworkACL + " is not supported in network " + network); - } - + _accountMgr.checkAccess(aclOwner, AccessType.ModifyEntry, false, networkACL); + // icmp code and icmp type can't be passed in for any other protocol rather than icmp if (!protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO) && (icmpCode != null || icmpType != null)) { throw new InvalidParameterValueException("Can specify icmpCode and icmpType for ICMP protocol only"); @@ -142,8 +214,8 @@ protected FirewallRule createNetworkACL(Account caller, String xId, Integer port if (protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO) && (portStart != null || portEnd != null)) { throw new InvalidParameterValueException("Can't specify start/end port when protocol is ICMP"); - } - + } + //validate icmp code and type if (icmpType != null) { if (icmpType.longValue() != -1 && !NetUtils.validateIcmpType(icmpType.longValue())) { @@ -157,35 +229,33 @@ protected FirewallRule createNetworkACL(Account caller, String xId, Integer port } } - validateNetworkACL(caller, network, portStart, portEnd, protocol); + validateNetworkACLItem(caller, portStart, portEnd, protocol); Transaction txn = Transaction.currentTxn(); txn.start(); - FirewallRuleVO newRule = new FirewallRuleVO(xId, null, portStart, portEnd, protocol.toLowerCase(), networkId, - aclOwner.getAccountId(), aclOwner.getDomainId(), Purpose.NetworkACL, sourceCidrList, icmpCode, icmpType, - relatedRuleId, trafficType); + NetworkACLItemVO newRule = new NetworkACLItemVO(portStart, portEnd, protocol.toLowerCase(), aclId, sourceCidrList, icmpCode, icmpType, trafficType); newRule.setType(type); - newRule = _firewallDao.persist(newRule); + newRule = _networkACLItemDao.persist(newRule); - if (type == FirewallRule.FirewallRuleType.User) { - detectNetworkACLConflict(newRule); + if (type == NetworkACLItem.NetworkACLType.User) { + //ToDo: Is this required now with?? + //detectNetworkACLConflict(newRule); } - if (!_firewallDao.setStateToAdd(newRule)) { + if (!_networkACLItemDao.setStateToAdd(newRule)) { throw new CloudRuntimeException("Unable to update the state to add for " + newRule); } - UserContext.current().setEventDetails("Rule Id: " + newRule.getId()); + UserContext.current().setEventDetails("ACL Item Id: " + newRule.getId()); txn.commit(); return getNetworkACLItem(newRule.getId()); } - - - protected void validateNetworkACL(Account caller, Network network, Integer portStart, Integer portEnd, - String proto) { - + + protected void validateNetworkACLItem(Account caller, Integer portStart, Integer portEnd, + String proto) { + if (portStart != null && !NetUtils.isValidPort(portStart)) { throw new InvalidParameterValueException("publicPort is an invalid value: " + portStart); } @@ -197,125 +267,35 @@ protected void validateNetworkACL(Account caller, Network network, Integer portS if (portStart != null && portEnd != null && portStart > portEnd) { throw new InvalidParameterValueException("Start port can't be bigger than end port"); } - - if (network.getTrafficType() != Networks.TrafficType.Guest) { - throw new InvalidParameterValueException("Network ACL can be created just for networks of type " + Networks.TrafficType.Guest); - } - - // Verify that the network guru supports the protocol specified - Map caps = _networkMgr.getNetworkServiceCapabilities(network.getId(), Service.NetworkACL); - - - if (caps != null) { - String supportedProtocols = caps.get(Capability.SupportedProtocols).toLowerCase(); - if (!supportedProtocols.contains(proto.toLowerCase())) { - throw new InvalidParameterValueException("Protocol " + proto + " is not supported by the network " + network); - } - } else { - throw new InvalidParameterValueException("No capabilities are found for network " + network); - } } - - protected void detectNetworkACLConflict(FirewallRuleVO newRule) throws NetworkRuleConflictException { - if (newRule.getPurpose() != Purpose.NetworkACL) { - return; - } - - List rules = _firewallDao.listByNetworkPurposeTrafficTypeAndNotRevoked(newRule.getNetworkId(), - Purpose.NetworkACL, newRule.getTrafficType()); - assert (rules.size() >= 1) : "For network ACLs, we now always first persist the rule and then check for " + - "network conflicts so we should at least have one rule at this point."; - - for (FirewallRuleVO rule : rules) { - if (rule.getId() == newRule.getId() || !rule.getProtocol().equalsIgnoreCase(newRule.getProtocol())) { - continue; // Skips my own rule and skip the rule if the protocol is different - } - - // if one cidr overlaps another, do port veirficatino - boolean duplicatedCidrs = false; - // Verify that the rules have different cidrs - _firewallDao.loadSourceCidrs(rule); - List ruleCidrList = rule.getSourceCidrList(); - List newRuleCidrList = newRule.getSourceCidrList(); - if (ruleCidrList == null || newRuleCidrList == null) { - continue; - } - - for (String newCidr : newRuleCidrList) { - for (String ruleCidr : ruleCidrList) { - if (NetUtils.isNetworksOverlap(newCidr, ruleCidr)) { - duplicatedCidrs = true; - break; - } - if (duplicatedCidrs) { - break; - } - } - } - - if (newRule.getProtocol().equalsIgnoreCase(NetUtils.ICMP_PROTO) - && newRule.getProtocol().equalsIgnoreCase(rule.getProtocol())) { - if ((newRule.getIcmpCode().longValue() == rule.getIcmpCode().longValue() - || rule.getIcmpCode().longValue() == -1 || newRule.getIcmpCode().longValue() == -1) - && (newRule.getIcmpType().longValue() == rule.getIcmpType().longValue() - || rule.getIcmpType().longValue() == -1 || newRule.getIcmpType().longValue() == -1) - && newRule.getProtocol().equalsIgnoreCase(rule.getProtocol()) && duplicatedCidrs) { - throw new InvalidParameterValueException("New network ACL conflicts with existing network ACL id=" + rule.getId()); - } - } - - boolean notNullPorts = (newRule.getSourcePortStart() != null && newRule.getSourcePortEnd() != null && - rule.getSourcePortStart() != null && rule.getSourcePortEnd() != null); - if (!notNullPorts) { - continue; - } else if (duplicatedCidrs - && ((rule.getSourcePortStart().intValue() <= newRule.getSourcePortStart().intValue() - && rule.getSourcePortEnd().intValue() >= newRule.getSourcePortStart().intValue()) - || (rule.getSourcePortStart().intValue() <= newRule.getSourcePortEnd().intValue() - && rule.getSourcePortEnd().intValue() >= newRule.getSourcePortEnd().intValue()) - || (newRule.getSourcePortStart().intValue() <= rule.getSourcePortStart().intValue() - && newRule.getSourcePortEnd().intValue() >= rule.getSourcePortStart().intValue()) - || (newRule.getSourcePortStart().intValue() <= rule.getSourcePortEnd().intValue() - && newRule.getSourcePortEnd().intValue() >= rule.getSourcePortEnd().intValue()))) { - - throw new NetworkRuleConflictException("The range specified, " + newRule.getSourcePortStart() + "-" - + newRule.getSourcePortEnd() + ", conflicts with rule " + rule.getId() - + " which has " + rule.getSourcePortStart() + "-" + rule.getSourcePortEnd()); - - } - } - - if (s_logger.isDebugEnabled()) { - s_logger.debug("No network rule conflicts detected for " + newRule + " against " + (rules.size() - 1) - + " existing network ACLs"); - } - } - @Override - public boolean revokeNetworkACL(long ruleId, boolean apply) { + public boolean revokeNetworkACLItem(long ruleId, boolean apply) { Account caller = UserContext.current().getCaller(); long userId = UserContext.current().getCallerUserId(); - return revokeNetworkACL(ruleId, apply, caller, userId); + return revokeNetworkACLItem(ruleId, apply, caller, userId); } - - @ActionEvent(eventType = EventTypes.EVENT_FIREWALL_CLOSE, eventDescription = "revoking firewall rule", async = true) - protected boolean revokeNetworkACL(long ruleId, boolean apply, Account caller, long userId) { - FirewallRuleVO rule = _firewallDao.findById(ruleId); - if (rule == null || rule.getPurpose() != Purpose.NetworkACL) { - throw new InvalidParameterValueException("Unable to find " + ruleId + " having purpose " + Purpose.NetworkACL); + @ActionEvent(eventType = EventTypes.EVENT_NETWORK_ACL_DELETE, eventDescription = "revoking network acl", async = true) + protected boolean revokeNetworkACLItem(long ruleId, boolean apply, Account caller, long userId) { + + NetworkACLItemVO rule = _networkACLItemDao.findById(ruleId); + if (rule == null) { + throw new InvalidParameterValueException("Unable to find network ACL Item" + ruleId); } - - _accountMgr.checkAccess(caller, null, true, rule); - _firewallMgr.revokeRule(rule, caller, userId, false); + // _accountMgr.checkAccess(caller, null, true, rule); + + revokeRule(rule, caller, userId, false); boolean success = false; if (apply) { - List rules = _firewallDao.listByNetworkAndPurpose(rule.getNetworkId(), Purpose.NetworkACL); - success = _firewallMgr.applyFirewallRules(rules, false, caller); + try { + success = applyNetworkACL(rule.getACLId(), caller); + } catch (ResourceUnavailableException e) { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } } else { success = true; } @@ -323,19 +303,9 @@ protected boolean revokeNetworkACL(long ruleId, boolean apply, Account caller, l return success; } - - @Override - public FirewallRule getNetworkACLItem(long ACLId) { - FirewallRule rule = _firewallDao.findById(ACLId); - if (rule != null && rule.getPurpose() == Purpose.NetworkACL) { - return rule; - } - return null; - } - @Override - public Pair,Integer> listNetworkACLItems(ListNetworkACLsCmd cmd) { + public Pair, Integer> listNetworkACLItems(ListNetworkACLsCmd cmd) { Long networkId = cmd.getNetworkId(); Long id = cmd.getId(); String trafficType = cmd.getTrafficType(); @@ -344,7 +314,7 @@ public Pair,Integer> listNetworkACLItems(ListNetwor Account caller = UserContext.current().getCaller(); List permittedAccounts = new ArrayList(); - Ternary domainIdRecursiveListProject = + Ternary domainIdRecursiveListProject = new Ternary(cmd.getDomainId(), cmd.isRecursive(), null); _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, cmd.listAll(), false); @@ -352,15 +322,14 @@ public Pair,Integer> listNetworkACLItems(ListNetwor Boolean isRecursive = domainIdRecursiveListProject.second(); ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); - Filter filter = new Filter(FirewallRuleVO.class, "id", false, cmd.getStartIndex(), cmd.getPageSizeVal()); - SearchBuilder sb = _firewallDao.createSearchBuilder(); - _accountMgr.buildACLSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); + Filter filter = new Filter(NetworkACLItemVO.class, "id", false, cmd.getStartIndex(), cmd.getPageSizeVal()); + SearchBuilder sb = _networkACLItemDao.createSearchBuilder(); + // _accountMgr.buildACLSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); sb.and("id", sb.entity().getId(), Op.EQ); - sb.and("networkId", sb.entity().getNetworkId(), Op.EQ); - sb.and("purpose", sb.entity().getPurpose(), Op.EQ); + //sb.and("networkId", sb.entity().getNetworkId(), Op.EQ); sb.and("trafficType", sb.entity().getTrafficType(), Op.EQ); - + if (tags != null && !tags.isEmpty()) { SearchBuilder tagSearch = _resourceTagDao.createSearchBuilder(); for (int count=0; count < tags.size(); count++) { @@ -373,8 +342,8 @@ public Pair,Integer> listNetworkACLItems(ListNetwor sb.join("tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER); } - SearchCriteria sc = sb.create(); - _accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); + SearchCriteria sc = sb.create(); + // _accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); if (id != null) { sc.setParameters("id", id); @@ -383,11 +352,11 @@ public Pair,Integer> listNetworkACLItems(ListNetwor if (networkId != null) { sc.setParameters("networkId", networkId); } - + if (trafficType != null) { sc.setParameters("trafficType", trafficType); } - + if (tags != null && !tags.isEmpty()) { int count = 0; sc.setJoinParameters("tagSearch", "resourceType", TaggedResourceType.NetworkACL.toString()); @@ -395,57 +364,15 @@ public Pair,Integer> listNetworkACLItems(ListNetwor sc.setJoinParameters("tagSearch", "key" + String.valueOf(count), key); sc.setJoinParameters("tagSearch", "value" + String.valueOf(count), tags.get(key)); count++; - } - } - - sc.setParameters("purpose", Purpose.NetworkACL); - - Pair, Integer> result = _firewallDao.searchAndCount(sc, filter); - return new Pair, Integer>(result.first(), result.second()); - } - - - @Override - public List listNetworkACLs(long guestNtwkId) { - return _firewallDao.listByNetworkAndPurpose(guestNtwkId, Purpose.NetworkACL); - } - - - @Override - public boolean revokeAllNetworkACLsForNetwork(long networkId, long userId, Account caller) throws ResourceUnavailableException { - - List ACLs = _firewallDao.listByNetworkAndPurpose(networkId, Purpose.NetworkACL); - - if (ACLs.isEmpty()) { - s_logger.debug("Found no network ACLs for network id=" + networkId); - return true; - } - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Releasing " + ACLs.size() + " Network ACLs for network id=" + networkId); - } - - for (FirewallRuleVO ACL : ACLs) { - // Mark all Network ACLs rules as Revoke, but don't revoke them yet - we have to revoke all rules for ip, no - // need to send them one by one - revokeNetworkACL(ACL.getId(), false, caller, Account.ACCOUNT_ID_SYSTEM); - } - - List ACLsToRevoke = _firewallDao.listByNetworkAndPurpose(networkId, Purpose.NetworkACL); - - // now send everything to the backend - boolean success = _firewallMgr.applyFirewallRules(ACLsToRevoke, false, caller); - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Successfully released Network ACLs for network id=" + networkId + " and # of rules now = " - + ACLs.size()); + } } - return success; + Pair, Integer> result = _networkACLItemDao.searchAndCount(sc, filter); + return new Pair, Integer>(result.first(), result.second()); } @Override - public NetworkACL createNetworkACL(CreateNetworkACLListCmd cmd){ + public NetworkACL createNetworkACL(CreateNetworkACLListCmd cmd) { NetworkACLVO acl = new NetworkACLVO(cmd.getName(), cmd.getDescription(), cmd.getVpcId()); _networkACLDao.persist(acl); return acl; @@ -470,4 +397,41 @@ public Pair, Integer> listNetworkACLs(ListNetworkACLL return new Pair, Integer>(acls.first(), acls.second()); } + @Override + public boolean replaceNetworkACL(long aclId, long networkId) { + NetworkVO network = _networkDao.findById(networkId); + network.setNetworkACLId(aclId); + return _networkDao.update(networkId, network); + } + + @Override + @DB + public void revokeRule(NetworkACLItemVO rule, Account caller, long userId, boolean needUsageEvent) { + if (caller != null) { + //_accountMgr.checkAccess(caller, null, true, rule); + } + + Transaction txn = Transaction.currentTxn(); + boolean generateUsageEvent = false; + + txn.start(); + if (rule.getState() == State.Staged) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Found a rule that is still in stage state so just removing it: " + rule); + } + _networkACLItemDao.remove(rule.getId()); + generateUsageEvent = true; + } else if (rule.getState() == State.Add || rule.getState() == State.Active) { + rule.setState(State.Revoke); + _networkACLItemDao.update(rule.getId(), rule); + generateUsageEvent = true; + } + +/* if (generateUsageEvent && needUsageEvent) { + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NET_RULE_DELETE, rule.getAccountId(), 0, rule.getId(), + null, rule.getClass().getName(), rule.getUuid()); + }*/ + + txn.commit(); + } } diff --git a/server/src/com/cloud/network/vpc/NetworkACLVO.java b/server/src/com/cloud/network/vpc/NetworkACLVO.java index 29afc006f465..374ba15142b8 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLVO.java +++ b/server/src/com/cloud/network/vpc/NetworkACLVO.java @@ -75,4 +75,14 @@ public long getId() { public String getName() { return name; } + + @Override + public long getAccountId() { + return 0; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public long getDomainId() { + return 0; //To change body of implemented methods use File | Settings | File Templates. + } } diff --git a/server/src/com/cloud/network/vpc/dao/NetworkACLItemDaoImpl.java b/server/src/com/cloud/network/vpc/dao/NetworkACLItemDaoImpl.java new file mode 100644 index 000000000000..69810e021f05 --- /dev/null +++ b/server/src/com/cloud/network/vpc/dao/NetworkACLItemDaoImpl.java @@ -0,0 +1,147 @@ +// 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.network.vpc.dao; + +import com.cloud.network.dao.FirewallRulesCidrsDao; +import com.cloud.network.dao.IPAddressDao; +import com.cloud.network.dao.IPAddressVO; +import com.cloud.network.vpc.NetworkACLItem; +import com.cloud.network.vpc.NetworkACLItem.State; +import com.cloud.network.vpc.NetworkACLItemDao; +import com.cloud.network.vpc.NetworkACLItemVO; +import com.cloud.server.ResourceTag.TaggedResourceType; +import com.cloud.tags.dao.ResourceTagDao; +import com.cloud.utils.db.DB; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.GenericSearchBuilder; +import com.cloud.utils.db.JoinBuilder; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Func; +import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.db.Transaction; +import org.springframework.stereotype.Component; + +import javax.ejb.Local; +import javax.inject.Inject; +import java.util.List; + +@Component +@Local(value = NetworkACLItemDao.class) +@DB(txn = false) +public class NetworkACLItemDaoImpl extends GenericDaoBase implements NetworkACLItemDao { + + protected final SearchBuilder AllFieldsSearch; + protected final SearchBuilder NotRevokedSearch; + protected final SearchBuilder ReleaseSearch; + protected SearchBuilder VmSearch; + protected final SearchBuilder SystemRuleSearch; + protected final GenericSearchBuilder RulesByIpCount; + + @Inject protected FirewallRulesCidrsDao _firewallRulesCidrsDao; + @Inject ResourceTagDao _tagsDao; + @Inject IPAddressDao _ipDao; + + protected NetworkACLItemDaoImpl() { + super(); + + AllFieldsSearch = createSearchBuilder(); + AllFieldsSearch.and("protocol", AllFieldsSearch.entity().getProtocol(), Op.EQ); + AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), Op.EQ); + AllFieldsSearch.and("id", AllFieldsSearch.entity().getId(), Op.EQ); + AllFieldsSearch.and("aclId", AllFieldsSearch.entity().getACLId(), Op.EQ); + AllFieldsSearch.and("trafficType", AllFieldsSearch.entity().getTrafficType(), Op.EQ); + AllFieldsSearch.done(); + + NotRevokedSearch = createSearchBuilder(); + NotRevokedSearch.and("state", NotRevokedSearch.entity().getState(), Op.NEQ); + NotRevokedSearch.and("protocol", NotRevokedSearch.entity().getProtocol(), Op.EQ); + NotRevokedSearch.and("sourcePortStart", NotRevokedSearch.entity().getSourcePortStart(), Op.EQ); + NotRevokedSearch.and("sourcePortEnd", NotRevokedSearch.entity().getSourcePortEnd(), Op.EQ); + NotRevokedSearch.and("aclId", NotRevokedSearch.entity().getACLId(), Op.EQ); + NotRevokedSearch.and("trafficType", NotRevokedSearch.entity().getTrafficType(), Op.EQ); + NotRevokedSearch.done(); + + ReleaseSearch = createSearchBuilder(); + ReleaseSearch.and("protocol", ReleaseSearch.entity().getProtocol(), Op.EQ); + ReleaseSearch.and("ports", ReleaseSearch.entity().getSourcePortStart(), Op.IN); + ReleaseSearch.done(); + + SystemRuleSearch = createSearchBuilder(); + SystemRuleSearch.and("type", SystemRuleSearch.entity().getType(), Op.EQ); + SystemRuleSearch.done(); + + RulesByIpCount = createSearchBuilder(Long.class); + RulesByIpCount.select(null, Func.COUNT, RulesByIpCount.entity().getId()); + RulesByIpCount.done(); + } + + + @Override + public List listByACLAndNotRevoked(long aclId) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public boolean setStateToAdd(NetworkACLItemVO rule) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("id", rule.getId()); + sc.setParameters("state", State.Staged); + + rule.setState(State.Add); + + return update(rule, sc) > 0; + } + + @Override + public boolean revoke(NetworkACLItemVO rule) { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public boolean releasePorts(long ipAddressId, String protocol, int[] ports) { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public List listByACL(long aclId) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("aclId", aclId); + + return listBy(sc); + } + + @Override + public List listSystemRules() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public List listByACLTrafficTypeAndNotRevoked(long aclId, NetworkACLItem.TrafficType trafficType) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public List listByACLTrafficType(long aclId, NetworkACLItem.TrafficType trafficType) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void loadSourceCidrs(NetworkACLItemVO rule) { + //To change body of implemented methods use File | Settings | File Templates. + } +} diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 037bf283cc88..b98b53f16a03 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -2552,6 +2552,7 @@ public List> getCommands() { cmdList.add(CreateNetworkACLListCmd.class); cmdList.add(DeleteNetworkACLListCmd.class); cmdList.add(ListNetworkACLListsCmd.class); + cmdList.add(ReplaceNetworkACLListCmd.class); return cmdList; } diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index 53a1de848d0e..49f32b183562 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -1156,23 +1156,18 @@ CREATE TABLE `cloud`.`network_acl` ( CREATE TABLE `cloud`.`network_acl_item` ( `id` bigint unsigned NOT NULL auto_increment COMMENT 'id', `uuid` varchar(40), - `network_acl_id` bigint unsigned NOT NULL COMMENT 'network acl id', + `acl_id` bigint unsigned NOT NULL COMMENT 'network acl id', `start_port` int(10) COMMENT 'starting port of a port range', `end_port` int(10) COMMENT 'end port of a port range', `state` char(32) NOT NULL COMMENT 'current state of this rule', `protocol` char(16) NOT NULL default 'TCP' COMMENT 'protocol to open these ports for', - `account_id` bigint unsigned NOT NULL COMMENT 'owner id', - `domain_id` bigint unsigned NOT NULL COMMENT 'domain id', - `xid` char(40) NOT NULL COMMENT 'external id', `created` datetime COMMENT 'Date created', `icmp_code` int(10) COMMENT 'The ICMP code (if protocol=ICMP). A value of -1 means all codes for the given ICMP type.', `icmp_type` int(10) COMMENT 'The ICMP type (if protocol=ICMP). A value of -1 means all types.', `type` varchar(10) NOT NULL DEFAULT 'USER', `traffic_type` char(32) COMMENT 'the traffic type of the rule, can be Ingress or Egress', PRIMARY KEY (`id`), - CONSTRAINT `fk_network_acl_item__account_id` FOREIGN KEY(`account_id`) REFERENCES `account`(`id`) ON DELETE CASCADE, - CONSTRAINT `fk_network_acl_item__domain_id` FOREIGN KEY(`domain_id`) REFERENCES `domain`(`id`) ON DELETE CASCADE, - CONSTRAINT `fk_network_acl_item__acl_id` FOREIGN KEY(`network_acl_id`) REFERENCES `network_acl`(`id`) ON DELETE CASCADE, + CONSTRAINT `fk_network_acl_item__acl_id` FOREIGN KEY(`acl_id`) REFERENCES `network_acl`(`id`) ON DELETE CASCADE, CONSTRAINT `uc_network_acl_item__uuid` UNIQUE (`uuid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; From 2b723b42cce9fb695499bf3e7a411074bb3c59d3 Mon Sep 17 00:00:00 2001 From: Kishan Kavala Date: Wed, 24 Apr 2013 18:07:22 +0530 Subject: [PATCH 04/14] CLOUDSTACK-763: Fixed source CIDR and apply ACL items --- .../com/cloud/agent/api/to/NetworkACLTO.java | 6 +- .../network/firewall/NetworkACLService.java | 2 +- .../com/cloud/network/vpc/NetworkACLItem.java | 7 -- .../apache/cloudstack/api/ApiConstants.java | 1 + .../user/network/CreateNetworkACLCmd.java | 33 +++----- .../user/network/DeleteNetworkACLCmd.java | 30 +++---- .../api/response/NetworkACLItemResponse.java | 4 +- .../com/cloud/network/NetworkManagerImpl.java | 2 +- .../cloud/network/vpc/NetworkACLItemDao.java | 5 -- .../cloud/network/vpc/NetworkACLItemVO.java | 70 +++++++++------- .../cloud/network/vpc/NetworkACLManager.java | 7 +- .../network/vpc/NetworkACLManagerImpl.java | 82 ++++++++++++++----- .../vpc/dao/NetworkACLItemDaoImpl.java | 41 +--------- setup/db/db/schema-410to420.sql | 4 +- 14 files changed, 142 insertions(+), 152 deletions(-) diff --git a/api/src/com/cloud/agent/api/to/NetworkACLTO.java b/api/src/com/cloud/agent/api/to/NetworkACLTO.java index 48de40ce5010..bd91f7782786 100644 --- a/api/src/com/cloud/agent/api/to/NetworkACLTO.java +++ b/api/src/com/cloud/agent/api/to/NetworkACLTO.java @@ -72,10 +72,10 @@ public NetworkACLTO(long id,String vlanTag, String protocol, Integer portStart, this.icmpCode = icmpCode; this.trafficType = trafficType; - if(allow){ - this.action = "ACCEPT"; - } else { + if(!allow){ this.action = "DROP"; + } else { + this.action = "ACCEPT"; } this.number = number; diff --git a/api/src/com/cloud/network/firewall/NetworkACLService.java b/api/src/com/cloud/network/firewall/NetworkACLService.java index ae46d83cc9f1..779e54ebd0bc 100644 --- a/api/src/com/cloud/network/firewall/NetworkACLService.java +++ b/api/src/com/cloud/network/firewall/NetworkACLService.java @@ -33,7 +33,7 @@ public interface NetworkACLService { NetworkACLItem getNetworkACLItem(long ruleId); - boolean applyNetworkACLtoNetworks(long aclId, Account caller) throws ResourceUnavailableException; + boolean applyNetworkACL(long aclId, Account caller) throws ResourceUnavailableException; /** * @param createNetworkACLCmd diff --git a/api/src/com/cloud/network/vpc/NetworkACLItem.java b/api/src/com/cloud/network/vpc/NetworkACLItem.java index 9cce1875d90c..308696c50240 100644 --- a/api/src/com/cloud/network/vpc/NetworkACLItem.java +++ b/api/src/com/cloud/network/vpc/NetworkACLItem.java @@ -30,11 +30,6 @@ public interface NetworkACLItem extends InternalIdentity { int getNumber(); - enum NetworkACLType { - System, // The pre-defined rules created by admin, in the system wide - User // the rules created by user, to a specific ip - } - enum State { Staged, // Rule been created but has never got through network rule conflict detection. Rules in this state can not be sent to network elements. Add, // Add means the rule has been created and has gone through network rule conflict detection. @@ -77,8 +72,6 @@ enum Action { List getSourceCidrList(); - NetworkACLType getType(); - /** * @return */ diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java index 5083981ccb2d..194bbc0c66e6 100755 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -485,6 +485,7 @@ public class ApiConstants { public static final String ASA_INSIDE_PORT_PROFILE = "insideportprofile"; public static final String AFFINITY_GROUP_ID = "affinitygroupid"; public static final String ACL_ID = "aclid"; + public static final String NUMBER = "number"; public enum HostDetails { all, capacity, events, stats, min; diff --git a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java index b6c0eb6c7c36..b806a598cb97 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java @@ -21,7 +21,6 @@ import com.cloud.network.vpc.NetworkACL; import com.cloud.network.vpc.NetworkACLItem; -import com.cloud.network.vpc.NetworkACLItem.NetworkACLType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -88,14 +87,16 @@ public class CreateNetworkACLCmd extends BaseAsyncCreateCmd { "can be Ingress or Egress, defaulted to Ingress if not specified") private String trafficType; + @Parameter(name=ApiConstants.NUMBER, type=CommandType.INTEGER, description="The network of the vm the ACL will be created for") + private Integer number; + + @Parameter(name=ApiConstants.ACTION, type=CommandType.STRING, description="scl entry action, allow or deny") + private String action; + // /////////////////////////////////////////////////// // ///////////////// Accessors /////////////////////// // /////////////////////////////////////////////////// - public Long getIpAddressId() { - return null; - } - public String getProtocol() { return protocol.trim(); } @@ -155,8 +156,12 @@ public String getCommandName() { return s_name; } - public void setSourceCidrList(List cidrs){ - cidrlist = cidrs; + public String getAction() { + return action; + } + + public Integer getNumber() { + return number; } @Override @@ -166,7 +171,7 @@ public void execute() throws ResourceUnavailableException { NetworkACLItem rule = _networkACLService.getNetworkACLItem(getEntityId()); try { UserContext.current().setEventDetails("Rule Id: " + getEntityId()); - success = _networkACLService.applyNetworkACLtoNetworks(rule.getACLId(), callerContext.getCaller()); + success = _networkACLService.applyNetworkACL(rule.getACLId(), callerContext.getCaller()); // State is different after the rule is applied, so get new object here NetworkACLItemResponse aclResponse = new NetworkACLItemResponse(); @@ -183,10 +188,6 @@ public void execute() throws ResourceUnavailableException { } } - public Long getSourceIpAddressId() { - return null; - } - public Integer getSourcePortStart() { if (publicStartPort != null) { return publicStartPort.intValue(); @@ -206,10 +207,6 @@ public Integer getSourcePortEnd() { return null; } - public NetworkACLItem.State getState() { - throw new UnsupportedOperationException("Should never call me to find the state"); - } - public Long getNetworkId() { return networkId; } @@ -296,10 +293,6 @@ public Integer getIcmpType() { return null; } - public NetworkACLType getType() { - return NetworkACLType.User; - } - @Override public AsyncJob.Type getInstanceType() { return AsyncJob.Type.FirewallRule; diff --git a/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLCmd.java index 2f882303ffe1..faf46308d92e 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLCmd.java @@ -25,6 +25,7 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.AccountResponse; import org.apache.cloudstack.api.response.FirewallRuleResponse; +import org.apache.cloudstack.api.response.NetworkACLItemResponse; import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.log4j.Logger; @@ -44,7 +45,7 @@ public class DeleteNetworkACLCmd extends BaseAsyncCmd { //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// - @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = FirewallRuleResponse.class, + @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = NetworkACLItemResponse.class, required=true, description="the ID of the network ACL") private Long id; @@ -70,7 +71,7 @@ public String getCommandName() { @Override public String getEventType() { - return EventTypes.EVENT_FIREWALL_CLOSE; + return EventTypes.EVENT_NETWORK_ACL_ITEM_DELETE; } @Override @@ -80,15 +81,19 @@ public String getEventDescription() { @Override public long getEntityOwnerId() { - if (ownerId == null) { + return 2L; +/* if (ownerId == null) { NetworkACLItem rule = _networkACLService.getNetworkACLItem(id); if (rule == null) { throw new InvalidParameterValueException("Unable to find network ACL by id=" + id); } else { - //ownerId = rule.getAccountId(); + + NetworkACL acl = _networkACLService + rule.getACLId(); + } } - return ownerId; + return ownerId;*/ } @Override @@ -104,20 +109,5 @@ public void execute() throws ResourceUnavailableException { } } - - @Override - public String getSyncObjType() { - return BaseAsyncCmd.networkSyncObject; - } - - @Override - public Long getSyncObjId() { - return _firewallService.getFirewallRule(id).getNetworkId(); - } - - @Override - public AsyncJob.Type getInstanceType() { - return AsyncJob.Type.FirewallRule; - } } diff --git a/api/src/org/apache/cloudstack/api/response/NetworkACLItemResponse.java b/api/src/org/apache/cloudstack/api/response/NetworkACLItemResponse.java index d40acbf0ac14..177c42b04128 100644 --- a/api/src/org/apache/cloudstack/api/response/NetworkACLItemResponse.java +++ b/api/src/org/apache/cloudstack/api/response/NetworkACLItemResponse.java @@ -18,13 +18,15 @@ import java.util.List; +import com.cloud.network.vpc.NetworkACLItem; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; import com.cloud.serializer.Param; import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.EntityReference; -@SuppressWarnings("unused") +@EntityReference(value = NetworkACLItem.class) public class NetworkACLItemResponse extends BaseResponse { @SerializedName(ApiConstants.ID) @Param(description="the ID of the ACL Item") private String id; diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 6dc96333d17d..d1d929ca1342 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -2665,7 +2665,7 @@ protected boolean reprogramNetworkRules(long networkId, Account caller, NetworkV } //apply network ACLs - if (!_networkACLMgr.applyNetworkACL(networkId, caller)) { + if (!_networkACLMgr.applyACLToNetwork(networkId, caller)) { s_logger.warn("Failed to reapply network ACLs as a part of of network id=" + networkId + " restart"); success = false; } diff --git a/server/src/com/cloud/network/vpc/NetworkACLItemDao.java b/server/src/com/cloud/network/vpc/NetworkACLItemDao.java index 739aa8cb7416..d24f082b5bee 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLItemDao.java +++ b/server/src/com/cloud/network/vpc/NetworkACLItemDao.java @@ -31,14 +31,9 @@ public interface NetworkACLItemDao extends GenericDao { boolean revoke(NetworkACLItemVO rule); - boolean releasePorts(long ipAddressId, String protocol, int[] ports); - List listByACL(long aclId); - List listSystemRules(); - List listByACLTrafficTypeAndNotRevoked(long aclId, NetworkACLItemVO.TrafficType trafficType); List listByACLTrafficType(long aclId, NetworkACLItemVO.TrafficType trafficType); - void loadSourceCidrs(NetworkACLItemVO rule); } diff --git a/server/src/com/cloud/network/vpc/NetworkACLItemVO.java b/server/src/com/cloud/network/vpc/NetworkACLItemVO.java index 9b2463187a93..5df97a960982 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLItemVO.java +++ b/server/src/com/cloud/network/vpc/NetworkACLItemVO.java @@ -21,9 +21,7 @@ import com.cloud.utils.net.NetUtils; import javax.persistence.*; -import java.util.Date; -import java.util.List; -import java.util.UUID; +import java.util.*; @Entity @Table(name="network_acl_item") @@ -59,31 +57,50 @@ public class NetworkACLItemVO implements NetworkACLItem { @Column(name="icmp_type") Integer icmpType; - @Column(name="type") - @Enumerated(value=EnumType.STRING) - NetworkACLType type; - @Column(name="traffic_type") @Enumerated(value=EnumType.STRING) TrafficType trafficType; - - // This is a delayed load value. If the value is null, - // then this field has not been loaded yet. - // Call firewallrules dao to load it. - @Transient - List sourceCidrs; + @Column(name="cidr") + String sourceCidrs; @Column(name="uuid") String uuid; + @Column(name="number") + int number; + + @Column(name="action") + @Enumerated(value=EnumType.STRING) + Action action; + public void setSourceCidrList(List sourceCidrs) { - this.sourceCidrs=sourceCidrs; + if(sourceCidrs == null){ + this.sourceCidrs = null; + } else { + StringBuilder sb = new StringBuilder(); + for(String cidr : sourceCidrs){ + if(sb.length() != 0){ + sb.append(","); + } + sb.append(cidr); + } + this.sourceCidrs=sb.toString(); + } } @Override public List getSourceCidrList() { - return sourceCidrs; + if(sourceCidrs == null || sourceCidrs.isEmpty()){ + return null; + } else { + List cidrList = new ArrayList(); + String[] cidrs = sourceCidrs.split(","); + for(String cidr : cidrs){ + cidrList.add(cidr); + } + return cidrList; + } } @Override @@ -120,10 +137,6 @@ public long getACLId() { return ACLId; } - @Override - public NetworkACLType getType() { - return type; - } public Date getCreated() { return created; } @@ -134,7 +147,7 @@ protected NetworkACLItemVO() { public NetworkACLItemVO(Integer portStart, Integer portEnd, String protocol, long aclId, List sourceCidrs, Integer icmpCode, - Integer icmpType, TrafficType trafficType) { + Integer icmpType, TrafficType trafficType, Action action, int number) { this.sourcePortStart = portStart; this.sourcePortEnd = portEnd; this.protocol = protocol; @@ -142,15 +155,16 @@ public NetworkACLItemVO(Integer portStart, Integer portEnd, String protocol, this.state = State.Staged; this.icmpCode = icmpCode; this.icmpType = icmpType; - this.sourceCidrs = sourceCidrs; + setSourceCidrList(sourceCidrs); this.uuid = UUID.randomUUID().toString(); - this.type = NetworkACLType.User; this.trafficType = trafficType; + this.action = action; + this.number = number; } - public NetworkACLItemVO(int port, String protocol, long aclId, List sourceCidrs, Integer icmpCode, Integer icmpType) { - this(port, port, protocol, aclId, sourceCidrs, icmpCode, icmpType, null); + public NetworkACLItemVO(int port, String protocol, long aclId, List sourceCidrs, Integer icmpCode, Integer icmpType, Action action, int number) { + this(port, port, protocol, aclId, sourceCidrs, icmpCode, icmpType, null, action, number); } @Override @@ -175,22 +189,18 @@ public String getUuid() { @Override public Action getAction() { - return null; //To change body of implemented methods use File | Settings | File Templates. + return action; } @Override public int getNumber() { - return 0; //To change body of implemented methods use File | Settings | File Templates. + return number; } public void setUuid(String uuid) { this.uuid = uuid; } - public void setType(NetworkACLType type) { - this.type = type; - } - @Override public TrafficType getTrafficType() { return trafficType; diff --git a/server/src/com/cloud/network/vpc/NetworkACLManager.java b/server/src/com/cloud/network/vpc/NetworkACLManager.java index dba91b2f254d..3be15fadbe94 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLManager.java +++ b/server/src/com/cloud/network/vpc/NetworkACLManager.java @@ -39,8 +39,9 @@ public interface NetworkACLManager extends NetworkACLService{ List listNetworkACLItems(long guestNtwkId); - boolean applyNetworkACL(long networkId, Account caller) throws ResourceUnavailableException; + boolean applyNetworkACL(long aclId, Account caller) throws ResourceUnavailableException; - @DB - void revokeRule(NetworkACLItemVO rule, Account caller, long userId, boolean needUsageEvent); + void removeRule(NetworkACLItem rule); + + boolean applyACLToNetwork(long networkId, Account caller) throws ResourceUnavailableException; } diff --git a/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java b/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java index a345cc680f0e..8c6cf35f341c 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java +++ b/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java @@ -111,13 +111,16 @@ public boolean revokeACLItemsForNetwork(long networkId, long userId, Account cal for (NetworkACLItemVO aclItem : aclItems) { // Mark all Network ACLs rules as Revoke, but don't revoke them yet - we have to revoke all rules for ip, no // need to send them one by one - revokeNetworkACLItem(aclItem.getId(), false, caller, Account.ACCOUNT_ID_SYSTEM); + //revokeNetworkACLItem(aclItem.getId(), false, caller, Account.ACCOUNT_ID_SYSTEM); + if (aclItem.getState() == State.Add || aclItem.getState() == State.Active) { + aclItem.setState(State.Revoke); + } } //List ACLsToRevoke = _networkACLItemDao.listByNetwork(networkId); // now send everything to the backend - boolean success = applyNetworkACL(network.getNetworkACLId(), caller); + boolean success = applyACLItemsToNetwork(network.getId(), aclItems, caller); if (s_logger.isDebugEnabled()) { s_logger.debug("Successfully released Network ACLs for network id=" + networkId + " and # of rules now = " @@ -139,22 +142,45 @@ public NetworkACLItem getNetworkACLItem(long ruleId) { } @Override - public boolean applyNetworkACLtoNetworks(long aclId, Account caller) throws ResourceUnavailableException { + public boolean applyNetworkACL(long aclId, Account caller) throws ResourceUnavailableException { boolean handled = false; List rules = _networkACLItemDao.listByACL(aclId); //Find all networks using this ACL List networks = _networkDao.listByAclId(aclId); for(NetworkVO network : networks){ - applyNetworkACL(network.getId(), caller); + //Failure case?? + handled = applyACLItemsToNetwork(network.getId(), rules, caller); + } + if(handled){ + for (NetworkACLItem rule : rules) { + if (rule.getState() == NetworkACLItem.State.Revoke) { + removeRule(rule); + } else if (rule.getState() == NetworkACLItem.State.Add) { + NetworkACLItemVO ruleVO = _networkACLItemDao.findById(rule.getId()); + ruleVO.setState(NetworkACLItem.State.Active); + _networkACLItemDao.update(ruleVO.getId(), ruleVO); + } + } } return handled; } @Override - public boolean applyNetworkACL(long networkId, Account caller) throws ResourceUnavailableException { + public void removeRule(NetworkACLItem rule) { + //remove the rule + _networkACLItemDao.remove(rule.getId()); + } + + @Override + public boolean applyACLToNetwork(long networkId, Account caller) throws ResourceUnavailableException { Network network = _networkDao.findById(networkId); - boolean handled = false; List rules = _networkACLItemDao.listByACL(network.getNetworkACLId()); + return applyACLItemsToNetwork(networkId, rules, caller); + } + + public boolean applyACLItemsToNetwork(long networkId, List rules, Account caller) throws ResourceUnavailableException { + Network network = _networkDao.findById(networkId); + boolean handled = false; for (NetworkACLServiceProvider element: _networkAclElements) { Network.Provider provider = element.getProvider(); boolean isAclProvider = _networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.NetworkACL, provider); @@ -170,19 +196,16 @@ public boolean applyNetworkACL(long networkId, Account caller) throws ResourceUn @Override public NetworkACLItem createNetworkACLItem(CreateNetworkACLCmd aclItemCmd) throws NetworkRuleConflictException { - if (aclItemCmd.getSourceCidrList() == null) { - //_networkACLItemDao.loadSourceCidrs(aclItemCmd); - } return createNetworkACLItem(UserContext.current().getCaller(), aclItemCmd.getSourcePortStart(), aclItemCmd.getSourcePortEnd(), aclItemCmd.getProtocol(), aclItemCmd.getSourceCidrList(), aclItemCmd.getIcmpCode(), - aclItemCmd.getIcmpType(), null, aclItemCmd.getType(), aclItemCmd.getNetworkId(), aclItemCmd.getTrafficType(), aclItemCmd.getACLId()); + aclItemCmd.getIcmpType(), aclItemCmd.getNetworkId(), aclItemCmd.getTrafficType(), aclItemCmd.getACLId(), aclItemCmd.getAction(), aclItemCmd.getNumber()); } @DB @ActionEvent(eventType = EventTypes.EVENT_NETWORK_ACL_ITEM_CREATE, eventDescription = "creating network ACL Item", create = true) protected NetworkACLItem createNetworkACLItem(Account caller, Integer portStart, Integer portEnd, String protocol, List sourceCidrList, - Integer icmpCode, Integer icmpType, Long relatedRuleId, NetworkACLItem.NetworkACLType type, - Long networkId, NetworkACLItem.TrafficType trafficType, Long aclId) throws NetworkRuleConflictException { + Integer icmpCode, Integer icmpType, Long networkId, NetworkACLItem.TrafficType trafficType, Long aclId, + String action, Integer number) throws NetworkRuleConflictException { if(aclId == null){ Network network = _networkMgr.getNetwork(networkId); @@ -229,19 +252,22 @@ protected NetworkACLItem createNetworkACLItem(Account caller, Integer portStart, } } + NetworkACLItem.Action ruleAction = NetworkACLItem.Action.Allow; + if("deny".equals(action)){ + ruleAction = NetworkACLItem.Action.Deny; + } + // If number is null, set it to currentMax + 1 validateNetworkACLItem(caller, portStart, portEnd, protocol); Transaction txn = Transaction.currentTxn(); txn.start(); - NetworkACLItemVO newRule = new NetworkACLItemVO(portStart, portEnd, protocol.toLowerCase(), aclId, sourceCidrList, icmpCode, icmpType, trafficType); - newRule.setType(type); + + NetworkACLItemVO newRule = new NetworkACLItemVO(portStart, portEnd, protocol.toLowerCase(), aclId, sourceCidrList, icmpCode, icmpType, trafficType, ruleAction, number); newRule = _networkACLItemDao.persist(newRule); - if (type == NetworkACLItem.NetworkACLType.User) { //ToDo: Is this required now with?? //detectNetworkACLConflict(newRule); - } if (!_networkACLItemDao.setStateToAdd(newRule)) { throw new CloudRuntimeException("Unable to update the state to add for " + newRule); @@ -292,7 +318,8 @@ protected boolean revokeNetworkACLItem(long ruleId, boolean apply, Account calle if (apply) { try { - success = applyNetworkACL(rule.getACLId(), caller); + applyNetworkACL(rule.getACLId(), caller); + success = true; } catch (ResourceUnavailableException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } @@ -327,7 +354,7 @@ public Pair, Integer> listNetworkACLItems(ListNet // _accountMgr.buildACLSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); sb.and("id", sb.entity().getId(), Op.EQ); - //sb.and("networkId", sb.entity().getNetworkId(), Op.EQ); + sb.and("aclId", sb.entity().getACLId(), Op.EQ); sb.and("trafficType", sb.entity().getTrafficType(), Op.EQ); if (tags != null && !tags.isEmpty()) { @@ -350,7 +377,8 @@ public Pair, Integer> listNetworkACLItems(ListNet } if (networkId != null) { - sc.setParameters("networkId", networkId); + Network network = _networkDao.findById(networkId); + sc.setParameters("aclId", network.getNetworkACLId()); } if (trafficType != null) { @@ -400,13 +428,25 @@ public Pair, Integer> listNetworkACLs(ListNetworkACLL @Override public boolean replaceNetworkACL(long aclId, long networkId) { NetworkVO network = _networkDao.findById(networkId); + if(network == null){ + throw new InvalidParameterValueException("Unable to find Network: " +networkId); + } + NetworkACL acl = _networkACLDao.findById(aclId); + if(acl == null){ + throw new InvalidParameterValueException("Unable to find NetworkACL: " +aclId); + } + if(network.getVpcId() == null){ + throw new InvalidParameterValueException("Network does not belong to VPC: " +networkId); + } + if(network.getVpcId() != acl.getVpcId()){ + throw new InvalidParameterValueException("Network: "+networkId+" and ACL: "+aclId+" do not belong to the same VPC"); + } network.setNetworkACLId(aclId); return _networkDao.update(networkId, network); } - @Override @DB - public void revokeRule(NetworkACLItemVO rule, Account caller, long userId, boolean needUsageEvent) { + private void revokeRule(NetworkACLItemVO rule, Account caller, long userId, boolean needUsageEvent) { if (caller != null) { //_accountMgr.checkAccess(caller, null, true, rule); } diff --git a/server/src/com/cloud/network/vpc/dao/NetworkACLItemDaoImpl.java b/server/src/com/cloud/network/vpc/dao/NetworkACLItemDaoImpl.java index 69810e021f05..98f5d6f8527c 100644 --- a/server/src/com/cloud/network/vpc/dao/NetworkACLItemDaoImpl.java +++ b/server/src/com/cloud/network/vpc/dao/NetworkACLItemDaoImpl.java @@ -16,28 +16,18 @@ // under the License. package com.cloud.network.vpc.dao; -import com.cloud.network.dao.FirewallRulesCidrsDao; -import com.cloud.network.dao.IPAddressDao; -import com.cloud.network.dao.IPAddressVO; import com.cloud.network.vpc.NetworkACLItem; import com.cloud.network.vpc.NetworkACLItem.State; import com.cloud.network.vpc.NetworkACLItemDao; import com.cloud.network.vpc.NetworkACLItemVO; -import com.cloud.server.ResourceTag.TaggedResourceType; -import com.cloud.tags.dao.ResourceTagDao; import com.cloud.utils.db.DB; import com.cloud.utils.db.GenericDaoBase; -import com.cloud.utils.db.GenericSearchBuilder; -import com.cloud.utils.db.JoinBuilder; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; -import com.cloud.utils.db.SearchCriteria.Func; import com.cloud.utils.db.SearchCriteria.Op; -import com.cloud.utils.db.Transaction; import org.springframework.stereotype.Component; import javax.ejb.Local; -import javax.inject.Inject; import java.util.List; @Component @@ -48,13 +38,6 @@ public class NetworkACLItemDaoImpl extends GenericDaoBase AllFieldsSearch; protected final SearchBuilder NotRevokedSearch; protected final SearchBuilder ReleaseSearch; - protected SearchBuilder VmSearch; - protected final SearchBuilder SystemRuleSearch; - protected final GenericSearchBuilder RulesByIpCount; - - @Inject protected FirewallRulesCidrsDao _firewallRulesCidrsDao; - @Inject ResourceTagDao _tagsDao; - @Inject IPAddressDao _ipDao; protected NetworkACLItemDaoImpl() { super(); @@ -81,13 +64,6 @@ protected NetworkACLItemDaoImpl() { ReleaseSearch.and("ports", ReleaseSearch.entity().getSourcePortStart(), Op.IN); ReleaseSearch.done(); - SystemRuleSearch = createSearchBuilder(); - SystemRuleSearch.and("type", SystemRuleSearch.entity().getType(), Op.EQ); - SystemRuleSearch.done(); - - RulesByIpCount = createSearchBuilder(Long.class); - RulesByIpCount.select(null, Func.COUNT, RulesByIpCount.entity().getId()); - RulesByIpCount.done(); } @@ -109,12 +85,8 @@ public boolean setStateToAdd(NetworkACLItemVO rule) { @Override public boolean revoke(NetworkACLItemVO rule) { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - public boolean releasePorts(long ipAddressId, String protocol, int[] ports) { - return false; //To change body of implemented methods use File | Settings | File Templates. + rule.setState(State.Revoke); + return update(rule.getId(), rule); } @Override @@ -125,11 +97,6 @@ public List listByACL(long aclId) { return listBy(sc); } - @Override - public List listSystemRules() { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - @Override public List listByACLTrafficTypeAndNotRevoked(long aclId, NetworkACLItem.TrafficType trafficType) { return null; //To change body of implemented methods use File | Settings | File Templates. @@ -140,8 +107,4 @@ public List listByACLTrafficType(long aclId, NetworkACLItem.Tr return null; //To change body of implemented methods use File | Settings | File Templates. } - @Override - public void loadSourceCidrs(NetworkACLItemVO rule) { - //To change body of implemented methods use File | Settings | File Templates. - } } diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index 49f32b183562..ea8d05eb1774 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -1164,8 +1164,10 @@ CREATE TABLE `cloud`.`network_acl_item` ( `created` datetime COMMENT 'Date created', `icmp_code` int(10) COMMENT 'The ICMP code (if protocol=ICMP). A value of -1 means all codes for the given ICMP type.', `icmp_type` int(10) COMMENT 'The ICMP type (if protocol=ICMP). A value of -1 means all types.', - `type` varchar(10) NOT NULL DEFAULT 'USER', `traffic_type` char(32) COMMENT 'the traffic type of the rule, can be Ingress or Egress', + `cidr` varchar(255) COMMENT 'comma seperated cidr list', + `number` int(10) NOT NULL COMMENT 'priority number of the acl item', + `action` varchar(10) NOT NULL COMMENT 'rule action, allow or deny', PRIMARY KEY (`id`), CONSTRAINT `fk_network_acl_item__acl_id` FOREIGN KEY(`acl_id`) REFERENCES `network_acl`(`id`) ON DELETE CASCADE, CONSTRAINT `uc_network_acl_item__uuid` UNIQUE (`uuid`) From 5d711be0d71173f1f6fb69259a60ef341acf3802 Mon Sep 17 00:00:00 2001 From: Kishan Kavala Date: Thu, 25 Apr 2013 18:59:13 +0530 Subject: [PATCH 05/14] CLOUDSTACK-763: Added filters to list APIs. Seperated service interface implementation to NetworkACLServiceImpl. Added default ACL to upgrade schema --- .../com/cloud/agent/api/to/NetworkACLTO.java | 14 +- .../network/firewall/NetworkACLService.java | 74 ++- .../com/cloud/network/vpc/NetworkACLItem.java | 2 +- .../user/network/CreateNetworkACLCmd.java | 146 ++---- .../user/network/CreateNetworkACLListCmd.java | 11 +- .../user/network/DeleteNetworkACLCmd.java | 26 +- .../user/network/DeleteNetworkACLListCmd.java | 17 +- .../user/network/ListNetworkACLListsCmd.java | 24 +- .../user/network/ListNetworkACLsCmd.java | 33 +- .../network/ReplaceNetworkACLListCmd.java | 15 +- .../api/response/NetworkACLItemResponse.java | 14 + client/tomcatconf/applicationContext.xml.in | 1 + .../src/com/cloud/api/ApiResponseHelper.java | 31 +- .../com/cloud/network/NetworkManagerImpl.java | 34 +- .../cloud/network/vpc/NetworkACLItemDao.java | 7 +- .../cloud/network/vpc/NetworkACLItemVO.java | 51 +-- .../cloud/network/vpc/NetworkACLManager.java | 82 +++- .../network/vpc/NetworkACLManagerImpl.java | 420 +++++------------- .../network/vpc/NetworkACLServiceImpl.java | 372 ++++++++++++++++ .../vpc/dao/NetworkACLItemDaoImpl.java | 32 +- .../cloud/tags/TaggedResourceManagerImpl.java | 5 +- setup/db/db/schema-410to420.sql | 3 + 22 files changed, 819 insertions(+), 595 deletions(-) create mode 100644 server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java diff --git a/api/src/com/cloud/agent/api/to/NetworkACLTO.java b/api/src/com/cloud/agent/api/to/NetworkACLTO.java index bd91f7782786..398591b120db 100644 --- a/api/src/com/cloud/agent/api/to/NetworkACLTO.java +++ b/api/src/com/cloud/agent/api/to/NetworkACLTO.java @@ -92,7 +92,7 @@ public long getId() { } public String getSrcVlanTag() { - return vlanTag; + return vlanTag; } public String getProtocol() { @@ -104,18 +104,18 @@ public int[] getSrcPortRange() { } public Integer getIcmpType(){ - return icmpType; + return icmpType; } public Integer getIcmpCode(){ - return icmpCode; + return icmpCode; } public String getStringPortRange() { - if (portRange == null || portRange.length < 2) - return "0:0"; - else - return NetUtils.portRangeToString(portRange); + if (portRange == null || portRange.length < 2) + return "0:0"; + else + return NetUtils.portRangeToString(portRange); } public boolean revoked() { diff --git a/api/src/com/cloud/network/firewall/NetworkACLService.java b/api/src/com/cloud/network/firewall/NetworkACLService.java index 779e54ebd0bc..5f068a3828bc 100644 --- a/api/src/com/cloud/network/firewall/NetworkACLService.java +++ b/api/src/com/cloud/network/firewall/NetworkACLService.java @@ -32,33 +32,85 @@ import com.cloud.utils.Pair; public interface NetworkACLService { - NetworkACLItem getNetworkACLItem(long ruleId); - boolean applyNetworkACL(long aclId, Account caller) throws ResourceUnavailableException; + /** + * Creates Network ACL for the specified VPC + * @param name + * @param description + * @param vpcId + * @return + */ + NetworkACL createNetworkACL(String name, String description, long vpcId); + + /** + * Get Network ACL with specified Id + * @param id + * @return + */ + NetworkACL getNetworkACL(long id); + + /** + * List NeetworkACLs by Id/Name/Network or Vpc it belongs to + * @param id + * @param name + * @param networkId + * @param vpcId + * @return + */ + Pair,Integer> listNetworkACLs(Long id, String name, Long networkId, Long vpcId); + + /** + * Delete specified network ACL. Deletion fails if the list is not empty + * @param id + * @return + */ + boolean deleteNetworkACL(long id); + + /** + * Associates ACL with specified Network + * @param aclId + * @param networkId + * @return + * @throws ResourceUnavailableException + */ + boolean replaceNetworkACL(long aclId, long networkId) throws ResourceUnavailableException; + + /** + * Applied ACL to associated networks + * @param aclId + * @return + * @throws ResourceUnavailableException + */ + boolean applyNetworkACL(long aclId) throws ResourceUnavailableException; /** + * Creates a Network ACL Item within an ACL and applies the ACL to associated networks * @param createNetworkACLCmd * @return */ - NetworkACLItem createNetworkACLItem(CreateNetworkACLCmd aclItemCmd) throws NetworkRuleConflictException; + NetworkACLItem createNetworkACLItem(CreateNetworkACLCmd aclItemCmd); + /** + * Return ACL item with specified Id * @param ruleId - * @param apply * @return */ - boolean revokeNetworkACLItem(long ruleId, boolean apply); + NetworkACLItem getNetworkACLItem(long ruleId); + /** + * Lists Network ACL Items by Id, Network, ACLId, Traffic Type, protocol * @param listNetworkACLsCmd * @return */ Pair, Integer> listNetworkACLItems(ListNetworkACLsCmd cmd); - NetworkACL createNetworkACL(CreateNetworkACLListCmd cmd); - - NetworkACL getNetworkACL(long id); + /** + * Revoked ACL Item with specified Id + * @param ruleId + * @param apply + * @return + */ + boolean revokeNetworkACLItem(long ruleId); - boolean deleteNetworkACL(long id); - Pair,Integer> listNetworkACLs(ListNetworkACLListsCmd listNetworkACLListsCmd); - boolean replaceNetworkACL(long aclId, long networkId); } diff --git a/api/src/com/cloud/network/vpc/NetworkACLItem.java b/api/src/com/cloud/network/vpc/NetworkACLItem.java index 308696c50240..312fa7390b27 100644 --- a/api/src/com/cloud/network/vpc/NetworkACLItem.java +++ b/api/src/com/cloud/network/vpc/NetworkACLItem.java @@ -64,7 +64,7 @@ enum Action { State getState(); - long getACLId(); + long getAclId(); Integer getIcmpCode(); diff --git a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java index b806a598cb97..984ed5751563 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java @@ -111,30 +111,6 @@ public List getSourceCidrList() { } } - public long getVpcId() { - Long vpcId = null; - - if(getACLId() != null){ - NetworkACL acl = _networkACLService.getNetworkACL(getACLId()); - if(acl == null){ - throw new InvalidParameterValueException("Invalid aclId is given"); - } - vpcId = acl.getVpcId(); - } else if(getNetworkId() != null){ - Network network = _networkService.getNetwork(getNetworkId()); - if (network == null) { - throw new InvalidParameterValueException("Invalid networkId is given"); - } - vpcId = network.getVpcId(); - } - - if (vpcId == null) { - throw new InvalidParameterValueException("Can create network ACL only for the ACL belonging to the VPC"); - } - - return vpcId; - } - public NetworkACLItem.TrafficType getTrafficType() { if (trafficType == null) { return NetworkACLItem.TrafficType.Ingress; @@ -164,44 +140,17 @@ public Integer getNumber() { return number; } - @Override - public void execute() throws ResourceUnavailableException { - UserContext callerContext = UserContext.current(); - boolean success = false; - NetworkACLItem rule = _networkACLService.getNetworkACLItem(getEntityId()); - try { - UserContext.current().setEventDetails("Rule Id: " + getEntityId()); - success = _networkACLService.applyNetworkACL(rule.getACLId(), callerContext.getCaller()); - - // State is different after the rule is applied, so get new object here - NetworkACLItemResponse aclResponse = new NetworkACLItemResponse(); - if (rule != null) { - aclResponse = _responseGenerator.createNetworkACLItemResponse(rule); - setResponseObject(aclResponse); - } - aclResponse.setResponseName(getCommandName()); - } finally { - if (!success || rule == null) { - _networkACLService.revokeNetworkACLItem(getEntityId(), true); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create network ACL"); - } - } - } - public Integer getSourcePortStart() { - if (publicStartPort != null) { - return publicStartPort.intValue(); - } - return null; + return publicStartPort; } public Integer getSourcePortEnd() { if (publicEndPort == null) { if (publicStartPort != null) { - return publicStartPort.intValue(); + return publicStartPort; } } else { - return publicEndPort.intValue(); + return publicEndPort; } return null; @@ -213,39 +162,8 @@ public Long getNetworkId() { @Override public long getEntityOwnerId() { - Vpc vpc = _vpcService.getVpc(getVpcId()); - if (vpc == null) { - throw new InvalidParameterValueException("Invalid vpcId is given"); - } - - Account account = _accountService.getAccount(vpc.getAccountId()); - return account.getId(); - } - - public long getDomainId() { - Vpc vpc = _vpcService.getVpc(getVpcId()); - return vpc.getDomainId(); - } - - @Override - public void create() { - if (getSourceCidrList() != null) { - for (String cidr: getSourceCidrList()){ - if (!NetUtils.isValidCIDR(cidr)){ - throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Source cidrs formatting error " + cidr); - } - } - } - - try { - NetworkACLItem result = _networkACLService.createNetworkACLItem(this); - setEntityId(result.getId()); - setEntityUuid(result.getUuid()); - } catch (NetworkRuleConflictException ex) { - s_logger.info("Network rule conflict: " + ex.getMessage()); - s_logger.trace("Network Rule Conflict: ", ex); - throw new ServerApiException(ApiErrorCode.NETWORK_RULE_CONFLICT_ERROR, ex.getMessage()); - } + Account caller = UserContext.current().getCaller(); + return caller.getAccountId(); } @Override @@ -255,23 +173,7 @@ public String getEventType() { @Override public String getEventDescription() { - //Network network = _networkService.getNetwork(networkId); - return ("Creating Network ACL Item for protocol:" + this.getProtocol()); - } - - public long getAccountId() { - Vpc vpc = _vpcService.getVpc(getVpcId()); - return vpc.getAccountId(); - } - - @Override - public String getSyncObjType() { - return BaseAsyncCmd.networkSyncObject; - } - - @Override - public Long getSyncObjId() { - return getNetworkId(); + return "Creating Network ACL Item"; } public Integer getIcmpCode() { @@ -293,12 +195,40 @@ public Integer getIcmpType() { return null; } + public Long getACLId() { + return aclId; + } + @Override - public AsyncJob.Type getInstanceType() { - return AsyncJob.Type.FirewallRule; + public void create() { + NetworkACLItem result = _networkACLService.createNetworkACLItem(this); + setEntityId(result.getId()); + setEntityUuid(result.getUuid()); } - public Long getACLId() { - return aclId; + @Override + public void execute() throws ResourceUnavailableException { + boolean success = false; + NetworkACLItem rule = _networkACLService.getNetworkACLItem(getEntityId()); + try { + UserContext.current().setEventDetails("Rule Id: " + getEntityId()); + success = _networkACLService.applyNetworkACL(rule.getAclId()); + + // State is different after the rule is applied, so get new object here + rule = _networkACLService.getNetworkACLItem(getEntityId()); + NetworkACLItemResponse aclResponse = new NetworkACLItemResponse(); + if (rule != null) { + aclResponse = _responseGenerator.createNetworkACLItemResponse(rule); + setResponseObject(aclResponse); + } + aclResponse.setResponseName(getCommandName()); + } finally { + if (!success || rule == null) { + _networkACLService.revokeNetworkACLItem(getEntityId()); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create network ACL Item"); + } + } } + } + diff --git a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLListCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLListCmd.java index 0cc460d2b788..591a3541a53b 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLListCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLListCmd.java @@ -23,7 +23,12 @@ import com.cloud.network.vpc.Vpc; import com.cloud.user.Account; import com.cloud.user.UserContext; -import org.apache.cloudstack.api.*; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCreateCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.NetworkACLResponse; import org.apache.cloudstack.api.response.VpcResponse; import org.apache.log4j.Logger; @@ -75,15 +80,13 @@ public String getCommandName() { @Override public void create() { - NetworkACL result = _networkACLService.createNetworkACL(this); + NetworkACL result = _networkACLService.createNetworkACL(getName(), getDescription(), getVpcId()); setEntityId(result.getId()); setEntityUuid(result.getUuid()); } @Override public void execute() throws ResourceUnavailableException { - UserContext callerContext = UserContext.current(); - boolean success = false; NetworkACL acl = _networkACLService.getNetworkACL(getEntityId()); if(acl != null){ NetworkACLResponse aclResponse = _responseGenerator.createNetworkACLResponse(acl); diff --git a/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLCmd.java index faf46308d92e..d35b22c532a1 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLCmd.java @@ -17,6 +17,7 @@ package org.apache.cloudstack.api.command.user.network; import com.cloud.network.vpc.NetworkACLItem; +import com.cloud.user.Account; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -49,10 +50,6 @@ public class DeleteNetworkACLCmd extends BaseAsyncCmd { required=true, description="the ID of the network ACL") private Long id; - // unexposed parameter needed for events logging - @Parameter(name=ApiConstants.ACCOUNT_ID, type=CommandType.UUID, entityType = AccountResponse.class, - expose=false) - private Long ownerId; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -81,31 +78,20 @@ public String getEventDescription() { @Override public long getEntityOwnerId() { - return 2L; -/* if (ownerId == null) { - NetworkACLItem rule = _networkACLService.getNetworkACLItem(id); - if (rule == null) { - throw new InvalidParameterValueException("Unable to find network ACL by id=" + id); - } else { - - NetworkACL acl = _networkACLService - rule.getACLId(); - - } - } - return ownerId;*/ + Account caller = UserContext.current().getCaller(); + return caller.getAccountId(); } @Override public void execute() throws ResourceUnavailableException { - UserContext.current().setEventDetails("Network ACL Id: " + id); - boolean result = _networkACLService.revokeNetworkACLItem(id, true); + UserContext.current().setEventDetails("Network ACL Item Id: " + id); + boolean result = _networkACLService.revokeNetworkACLItem(id); if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); this.setResponseObject(response); } else { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete network ACL"); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete network ACL Item"); } } diff --git a/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLListCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLListCmd.java index 42ecd8d155d5..379b44a0d50c 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLListCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLListCmd.java @@ -23,6 +23,7 @@ import com.cloud.network.rules.FirewallRule; import com.cloud.network.vpc.NetworkACL; import com.cloud.network.vpc.Vpc; +import com.cloud.user.Account; import com.cloud.user.UserContext; import org.apache.cloudstack.api.*; import org.apache.cloudstack.api.response.AccountResponse; @@ -48,7 +49,7 @@ public class DeleteNetworkACLListCmd extends BaseAsyncCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// - public Long getId() { + public long getId() { return id; } @@ -72,18 +73,8 @@ public String getEventDescription() { @Override public long getEntityOwnerId() { - NetworkACL acl = _networkACLService.getNetworkACL(id); - if (acl == null) { - throw new InvalidParameterValueException("Unable to find network ACL by id=" + id); - } else { - long vpcId = acl.getVpcId(); - Vpc vpc = _vpcService.getVpc(vpcId); - if(vpc != null){ - return vpc.getAccountId(); - } else { - throw new InvalidParameterValueException("Unable to find VPC associated with network ACL by id=" + id); - } - } + Account caller = UserContext.current().getCaller(); + return caller.getAccountId(); } @Override diff --git a/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkACLListsCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkACLListsCmd.java index 55d61477ece7..bb825d9f9f97 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkACLListsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkACLListsCmd.java @@ -16,23 +16,23 @@ // under the License. package org.apache.cloudstack.api.command.user.network; -import com.cloud.network.rules.FirewallRule; import com.cloud.network.vpc.NetworkACL; import com.cloud.utils.Pair; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; -import org.apache.cloudstack.api.BaseListTaggedResourcesCmd; +import org.apache.cloudstack.api.BaseListCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.NetworkACLResponse; import org.apache.cloudstack.api.response.NetworkResponse; +import org.apache.cloudstack.api.response.VpcResponse; import org.apache.log4j.Logger; import java.util.ArrayList; import java.util.List; @APICommand(name = "listNetworkACLLists", description="Lists all network ACLs", responseObject=NetworkACLResponse.class) -public class ListNetworkACLListsCmd extends BaseListTaggedResourcesCmd { +public class ListNetworkACLListsCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(ListNetworkACLListsCmd.class.getName()); private static final String s_name = "listnetworkacllistsresponse"; @@ -48,6 +48,14 @@ public class ListNetworkACLListsCmd extends BaseListTaggedResourcesCmd { description="list network ACLs by network Id") private Long networkId; + @Parameter(name=ApiConstants.VPC_ID, type=CommandType.UUID, entityType = VpcResponse.class, + description="list network ACLs by Vpc Id") + private Long vpcId; + + @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, description="list network ACLs by specified name") + private String name; + + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -60,6 +68,14 @@ public Long getId() { return id; } + public Long getVpcId() { + return vpcId; + } + + public String getName(){ + return name; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -71,7 +87,7 @@ public String getCommandName() { @Override public void execute(){ - Pair,Integer> result = _networkACLService.listNetworkACLs(this); + Pair,Integer> result = _networkACLService.listNetworkACLs(getId(), getName(), getNetworkId(), getVpcId()); ListResponse response = new ListResponse(); List aclResponses = new ArrayList(); diff --git a/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkACLsCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkACLsCmd.java index 53e19d72f71b..df21a722408c 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkACLsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkACLsCmd.java @@ -24,10 +24,7 @@ import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListTaggedResourcesCmd; import org.apache.cloudstack.api.Parameter; -import org.apache.cloudstack.api.response.FirewallRuleResponse; -import org.apache.cloudstack.api.response.ListResponse; -import org.apache.cloudstack.api.response.NetworkACLItemResponse; -import org.apache.cloudstack.api.response.NetworkResponse; +import org.apache.cloudstack.api.response.*; import org.apache.log4j.Logger; import com.cloud.network.rules.FirewallRule; @@ -43,16 +40,26 @@ public class ListNetworkACLsCmd extends BaseListTaggedResourcesCmd { //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = FirewallRuleResponse.class, - description="Lists network ACL with the specified ID.") + description="Lists network ACL Item with the specified ID") private Long id; @Parameter(name=ApiConstants.NETWORK_ID, type=CommandType.UUID, entityType = NetworkResponse.class, - description="list network ACLs by network Id") + description="list network ACL Items by network Id") private Long networkId; - @Parameter(name=ApiConstants.TRAFFIC_TYPE, type=CommandType.STRING, description="list network ACLs by traffic type - Ingress or Egress") + @Parameter(name=ApiConstants.TRAFFIC_TYPE, type=CommandType.STRING, description="list network ACL Items by traffic type - Ingress or Egress") private String trafficType; + @Parameter(name=ApiConstants.ACL_ID, type=CommandType.UUID, entityType = NetworkACLResponse.class, + description="list network ACL Items by ACL Id") + private Long aclId; + + @Parameter(name=ApiConstants.PROTOCOL, type=CommandType.STRING, description="list network ACL Items by Protocol") + private String protocol; + + @Parameter(name=ApiConstants.ACTION, type=CommandType.STRING, description="list network ACL Items by Action") + private String action; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -69,6 +76,18 @@ public String getTrafficType() { return trafficType; } + public Long getAclId(){ + return aclId; + } + + public String getProtocol() { + return protocol; + } + + public String getAction() { + return action; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/org/apache/cloudstack/api/command/user/network/ReplaceNetworkACLListCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/ReplaceNetworkACLListCmd.java index 78e0b1a61f31..b8abc788b8b0 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/ReplaceNetworkACLListCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/ReplaceNetworkACLListCmd.java @@ -21,6 +21,7 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.vpc.NetworkACL; import com.cloud.network.vpc.Vpc; +import com.cloud.user.Account; import com.cloud.user.UserContext; import org.apache.cloudstack.api.*; import org.apache.cloudstack.api.response.NetworkACLResponse; @@ -77,18 +78,8 @@ public String getEventDescription() { @Override public long getEntityOwnerId() { - NetworkACL acl = _networkACLService.getNetworkACL(aclId); - if (acl == null) { - throw new InvalidParameterValueException("Unable to find network ACL by id=" + aclId); - } else { - long vpcId = acl.getVpcId(); - Vpc vpc = _vpcService.getVpc(vpcId); - if(vpc != null){ - return vpc.getAccountId(); - } else { - throw new InvalidParameterValueException("Unable to find VPC associated with network ACL by id=" + aclId); - } - } + Account caller = UserContext.current().getCaller(); + return caller.getAccountId(); } @Override diff --git a/api/src/org/apache/cloudstack/api/response/NetworkACLItemResponse.java b/api/src/org/apache/cloudstack/api/response/NetworkACLItemResponse.java index 177c42b04128..400a4db76312 100644 --- a/api/src/org/apache/cloudstack/api/response/NetworkACLItemResponse.java +++ b/api/src/org/apache/cloudstack/api/response/NetworkACLItemResponse.java @@ -62,6 +62,12 @@ public class NetworkACLItemResponse extends BaseResponse { @SerializedName(ApiConstants.ACL_ID) @Param(description="the ID of the ACL this item belongs to") private String aclId; + @SerializedName(ApiConstants.NUMBER) @Param(description= "Number of the ACL Item") + private Integer number; + + @SerializedName(ApiConstants.ACTION) @Param(description="Action of ACL Item. Allow/Deny") + private String action; + public void setId(String id) { this.id = id; } @@ -105,4 +111,12 @@ public void setTags(List tags) { public void setAclId(String aclId) { this.aclId = aclId; } + + public void setNumber(Integer number) { + this.number = number; + } + + public void setAction(String action) { + this.action = action; + } } diff --git a/client/tomcatconf/applicationContext.xml.in b/client/tomcatconf/applicationContext.xml.in index 997b944553ed..ff95ec99d7e6 100644 --- a/client/tomcatconf/applicationContext.xml.in +++ b/client/tomcatconf/applicationContext.xml.in @@ -685,6 +685,7 @@ + diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index f966ea0ee6ab..95480627adaa 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -2539,42 +2539,43 @@ public FirewallResponse createFirewallResponse(FirewallRule fwRule) { } @Override - public NetworkACLItemResponse createNetworkACLItemResponse(NetworkACLItem networkACL) { + public NetworkACLItemResponse createNetworkACLItemResponse(NetworkACLItem aclItem) { NetworkACLItemResponse response = new NetworkACLItemResponse(); - response.setId(networkACL.getUuid()); - response.setProtocol(networkACL.getProtocol()); - if (networkACL.getSourcePortStart() != null) { - response.setStartPort(Integer.toString(networkACL.getSourcePortStart())); + response.setId(aclItem.getUuid()); + response.setProtocol(aclItem.getProtocol()); + if (aclItem.getSourcePortStart() != null) { + response.setStartPort(Integer.toString(aclItem.getSourcePortStart())); } - if (networkACL.getSourcePortEnd() != null) { - response.setEndPort(Integer.toString(networkACL.getSourcePortEnd())); + if (aclItem.getSourcePortEnd() != null) { + response.setEndPort(Integer.toString(aclItem.getSourcePortEnd())); } - List cidrs = ApiDBUtils.findFirewallSourceCidrs(networkACL.getId()); - response.setCidrList(StringUtils.join(cidrs, ",")); + response.setCidrList(StringUtils.join(aclItem.getSourceCidrList(), ",")); - response.setTrafficType(networkACL.getTrafficType().toString()); + response.setTrafficType(aclItem.getTrafficType().toString()); - NetworkACLItem.State state = networkACL.getState(); + NetworkACLItem.State state = aclItem.getState(); String stateToSet = state.toString(); if (state.equals(NetworkACLItem.State.Revoke)) { stateToSet = "Deleting"; } - response.setIcmpCode(networkACL.getIcmpCode()); - response.setIcmpType(networkACL.getIcmpType()); + response.setIcmpCode(aclItem.getIcmpCode()); + response.setIcmpType(aclItem.getIcmpType()); response.setState(stateToSet); + response.setNumber(aclItem.getNumber()); + response.setAction(aclItem.getAction().toString()); - NetworkACL acl = ApiDBUtils.findByNetworkACLId(networkACL.getACLId()); + NetworkACL acl = ApiDBUtils.findByNetworkACLId(aclItem.getAclId()); if(acl != null){ response.setAclId(acl.getUuid()); } //set tag information - List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.NetworkACL, networkACL.getId()); + List tags = ApiDBUtils.listByResourceTypeAndId(TaggedResourceType.NetworkACL, aclItem.getId()); List tagResponses = new ArrayList(); for (ResourceTag tag : tags) { ResourceTagResponse tagResponse = createResourceTagResponse(tag, true); diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index d1d929ca1342..7d349fd38456 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -2665,7 +2665,7 @@ protected boolean reprogramNetworkRules(long networkId, Account caller, NetworkV } //apply network ACLs - if (!_networkACLMgr.applyACLToNetwork(networkId, caller)) { + if (!_networkACLMgr.applyACLToNetwork(networkId)) { s_logger.warn("Failed to reapply network ACLs as a part of of network id=" + networkId + " restart"); success = false; } @@ -3279,28 +3279,26 @@ private boolean shutdownNetworkResources(long networkId, Account caller, long ca success = false; } - //revoke all Network ACLs for the network w/o applying them in the DB - List networkACLs = _firewallDao.listByNetworkAndPurpose(networkId, Purpose.NetworkACL); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Releasing " + networkACLs.size() + " Network ACLs for network id=" + networkId + - " as a part of shutdownNetworkRules"); - } - - for (FirewallRuleVO networkACL : networkACLs) { - s_logger.trace("Marking network ACL " + networkACL + " with Revoke state"); - networkACL.setState(FirewallRule.State.Revoke); - } + if(network.getVpcId() != null){ + if (s_logger.isDebugEnabled()) { + s_logger.debug("Releasing Network ACL Items for network id=" + networkId + + " as a part of shutdownNetworkRules"); + } - try { - if (!_firewallMgr.applyRules(networkACLs, true, false)) { - s_logger.warn("Failed to cleanup network ACLs as a part of shutdownNetworkRules"); + try { + //revoke all Network ACLs for the network w/o applying them in the DB + if (!_networkACLMgr.revokeACLItemsForNetwork(networkId, callerUserId, caller)) { + s_logger.warn("Failed to cleanup network ACLs as a part of shutdownNetworkRules"); + success = false; + } + } catch (ResourceUnavailableException ex) { + s_logger.warn("Failed to cleanup network ACLs as a part of shutdownNetworkRules due to ", ex); success = false; } - } catch (ResourceUnavailableException ex) { - s_logger.warn("Failed to cleanup network ACLs as a part of shutdownNetworkRules due to ", ex); - success = false; + } + //release all static nats for the network if (!_rulesMgr.applyStaticNatForNetwork(networkId, false, caller, true)) { s_logger.warn("Failed to disable static nats as part of shutdownNetworkRules for network id " + networkId); diff --git a/server/src/com/cloud/network/vpc/NetworkACLItemDao.java b/server/src/com/cloud/network/vpc/NetworkACLItemDao.java index d24f082b5bee..8f70ac768c92 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLItemDao.java +++ b/server/src/com/cloud/network/vpc/NetworkACLItemDao.java @@ -25,15 +25,12 @@ */ public interface NetworkACLItemDao extends GenericDao { - List listByACLAndNotRevoked(long aclId); - boolean setStateToAdd(NetworkACLItemVO rule); boolean revoke(NetworkACLItemVO rule); List listByACL(long aclId); - List listByACLTrafficTypeAndNotRevoked(long aclId, NetworkACLItemVO.TrafficType trafficType); - List listByACLTrafficType(long aclId, NetworkACLItemVO.TrafficType trafficType); - + int getMaxNumberByACL(long aclId); + } diff --git a/server/src/com/cloud/network/vpc/NetworkACLItemVO.java b/server/src/com/cloud/network/vpc/NetworkACLItemVO.java index 5df97a960982..71ccebf07969 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLItemVO.java +++ b/server/src/com/cloud/network/vpc/NetworkACLItemVO.java @@ -49,7 +49,7 @@ public class NetworkACLItemVO implements NetworkACLItem { Date created; @Column(name="acl_id") - Long ACLId; + long aclId; @Column(name="icmp_code") Integer icmpCode; @@ -74,6 +74,27 @@ public class NetworkACLItemVO implements NetworkACLItem { @Enumerated(value=EnumType.STRING) Action action; + protected NetworkACLItemVO() { + this.uuid = UUID.randomUUID().toString(); + } + + public NetworkACLItemVO(Integer portStart, Integer portEnd, String protocol, + long aclId, List sourceCidrs, Integer icmpCode, + Integer icmpType, TrafficType trafficType, Action action, int number) { + this.sourcePortStart = portStart; + this.sourcePortEnd = portEnd; + this.protocol = protocol; + this.aclId = aclId; + this.state = State.Staged; + this.icmpCode = icmpCode; + this.icmpType = icmpType; + setSourceCidrList(sourceCidrs); + this.uuid = UUID.randomUUID().toString(); + this.trafficType = trafficType; + this.action = action; + this.number = number; + } + public void setSourceCidrList(List sourceCidrs) { if(sourceCidrs == null){ this.sourceCidrs = null; @@ -133,40 +154,16 @@ public State getState() { } @Override - public long getACLId() { - return ACLId; + public long getAclId() { + return aclId; } public Date getCreated() { return created; } - protected NetworkACLItemVO() { - this.uuid = UUID.randomUUID().toString(); - } - - public NetworkACLItemVO(Integer portStart, Integer portEnd, String protocol, - long aclId, List sourceCidrs, Integer icmpCode, - Integer icmpType, TrafficType trafficType, Action action, int number) { - this.sourcePortStart = portStart; - this.sourcePortEnd = portEnd; - this.protocol = protocol; - this.ACLId = aclId; - this.state = State.Staged; - this.icmpCode = icmpCode; - this.icmpType = icmpType; - setSourceCidrList(sourceCidrs); - this.uuid = UUID.randomUUID().toString(); - this.trafficType = trafficType; - this.action = action; - this.number = number; - } - public NetworkACLItemVO(int port, String protocol, long aclId, List sourceCidrs, Integer icmpCode, Integer icmpType, Action action, int number) { - this(port, port, protocol, aclId, sourceCidrs, icmpCode, icmpType, null, action, number); - } - @Override public String toString() { return new StringBuilder("Rule[").append(id).append("-").append("NetworkACL").append("-").append(state).append("]").toString(); diff --git a/server/src/com/cloud/network/vpc/NetworkACLManager.java b/server/src/com/cloud/network/vpc/NetworkACLManager.java index 3be15fadbe94..1b1e958231ee 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLManager.java +++ b/server/src/com/cloud/network/vpc/NetworkACLManager.java @@ -19,6 +19,7 @@ import java.util.List; import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.dao.NetworkVO; import com.cloud.network.firewall.NetworkACLService; import com.cloud.network.rules.FirewallRule; import com.cloud.user.Account; @@ -26,9 +27,81 @@ import org.apache.cloudstack.api.command.user.network.CreateNetworkACLListCmd; -public interface NetworkACLManager extends NetworkACLService{ - +public interface NetworkACLManager{ + + /** + * Creates Network ACL for the specified VPC + * @param name + * @param description + * @param vpcId + * @return + */ + NetworkACL createNetworkACL(String name, String description, long vpcId); + + /** + * Fetches Network ACL with specified Id + * @param id + * @return + */ + NetworkACL getNetworkACL(long id); + + /** + * Applies the items in the ACL to all associated networks + * @param aclId + * @return + * @throws ResourceUnavailableException + */ + boolean applyNetworkACL(long aclId) throws ResourceUnavailableException; + + /** + * Deletes the specified Network ACL + * @param id + * @return + */ + boolean deleteNetworkACL(NetworkACL acl); + + /** + * Associates acl with a network and applies the ACLItems + * @param acl + * @param network + * @return + */ + boolean replaceNetworkACL(NetworkACL acl, NetworkVO network) throws ResourceUnavailableException; + + /** + * Creates a Network ACL Item within an ACL and applies it to associated networks + * @param sourcePortStart + * @param sourcePortEnd + * @param protocol + * @param sourceCidrList + * @param icmpCode + * @param icmpType + * @param trafficType + * @param aclId + * @param action + * @param number + * @return + */ + NetworkACLItem createNetworkACLItem(Integer sourcePortStart, Integer sourcePortEnd, String protocol, + List sourceCidrList, Integer icmpCode, Integer icmpType, + NetworkACLItem.TrafficType trafficType, Long aclId, String action, Integer number); + /** + * Returns Network ACL Item with specified Id + * @param ruleId + * @return + */ + NetworkACLItem getNetworkACLItem(long ruleId); + + /** + * Revoke ACL Item and apply changes + * @param ruleId + * @return + */ + boolean revokeNetworkACLItem(long ruleId); + + /** + * Revoke ACL Items for network and remove them in back-end. Db is not updated * @param networkId * @param userId * @param caller @@ -39,9 +112,6 @@ public interface NetworkACLManager extends NetworkACLService{ List listNetworkACLItems(long guestNtwkId); - boolean applyNetworkACL(long aclId, Account caller) throws ResourceUnavailableException; - - void removeRule(NetworkACLItem rule); + boolean applyACLToNetwork(long networkId) throws ResourceUnavailableException; - boolean applyACLToNetwork(long networkId, Account caller) throws ResourceUnavailableException; } diff --git a/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java b/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java index 8c6cf35f341c..20fd58665247 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java +++ b/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java @@ -16,62 +16,36 @@ // under the License. package com.cloud.network.vpc; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import javax.ejb.Local; -import javax.inject.Inject; -import javax.naming.ConfigurationException; - -import com.cloud.network.dao.NetworkDao; -import com.cloud.network.dao.NetworkVO; -import com.cloud.network.element.NetworkACLServiceProvider; -import com.cloud.network.vpc.dao.NetworkACLDao; -import com.cloud.network.vpc.NetworkACLItem.State; -import org.apache.cloudstack.api.command.user.network.CreateNetworkACLCmd; -import org.apache.cloudstack.api.command.user.network.CreateNetworkACLListCmd; -import org.apache.cloudstack.api.command.user.network.ListNetworkACLListsCmd; -import org.apache.cloudstack.api.command.user.network.ListNetworkACLsCmd; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - -import org.apache.cloudstack.acl.SecurityChecker.AccessType; import com.cloud.event.ActionEvent; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.NetworkRuleConflictException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Network; -import com.cloud.network.Network.Capability; import com.cloud.network.Network.Service; import com.cloud.network.NetworkModel; -import com.cloud.network.Networks; -import com.cloud.network.firewall.NetworkACLService; -import com.cloud.projects.Project.ListProjectResourcesCriteria; -import com.cloud.server.ResourceTag.TaggedResourceType; -import com.cloud.tags.ResourceTagVO; +import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.NetworkVO; +import com.cloud.network.element.NetworkACLServiceProvider; +import com.cloud.network.vpc.NetworkACLItem.State; +import com.cloud.network.vpc.dao.NetworkACLDao; import com.cloud.tags.dao.ResourceTagDao; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.UserContext; -import com.cloud.utils.Pair; -import com.cloud.utils.Ternary; -import com.cloud.utils.component.Manager; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.db.DB; -import com.cloud.utils.db.Filter; -import com.cloud.utils.db.JoinBuilder; -import com.cloud.utils.db.SearchBuilder; -import com.cloud.utils.db.SearchCriteria; -import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.net.NetUtils; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import javax.ejb.Local; +import javax.inject.Inject; +import java.util.List; @Component -@Local(value = { NetworkACLService.class, NetworkACLManager.class}) +@Local(value = { NetworkACLManager.class}) public class NetworkACLManagerImpl extends ManagerBase implements NetworkACLManager{ private static final Logger s_logger = Logger.getLogger(NetworkACLManagerImpl.class); @@ -94,62 +68,22 @@ public class NetworkACLManagerImpl extends ManagerBase implements NetworkACLMana @Inject NetworkDao _networkDao; - - @Override - public boolean revokeACLItemsForNetwork(long networkId, long userId, Account caller) throws ResourceUnavailableException { - Network network = _networkDao.findById(networkId); - List aclItems = _networkACLItemDao.listByACL(network.getNetworkACLId()); - if (aclItems.isEmpty()) { - s_logger.debug("Found no network ACL Items for network id=" + networkId); - return true; - } - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Releasing " + aclItems.size() + " Network ACL Items for network id=" + networkId); - } - - for (NetworkACLItemVO aclItem : aclItems) { - // Mark all Network ACLs rules as Revoke, but don't revoke them yet - we have to revoke all rules for ip, no - // need to send them one by one - //revokeNetworkACLItem(aclItem.getId(), false, caller, Account.ACCOUNT_ID_SYSTEM); - if (aclItem.getState() == State.Add || aclItem.getState() == State.Active) { - aclItem.setState(State.Revoke); - } - } - - //List ACLsToRevoke = _networkACLItemDao.listByNetwork(networkId); - - // now send everything to the backend - boolean success = applyACLItemsToNetwork(network.getId(), aclItems, caller); - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Successfully released Network ACLs for network id=" + networkId + " and # of rules now = " - + aclItems.size()); - } - - return success; - } - @Override - public List listNetworkACLItems(long guestNtwkId) { - Network network = _networkMgr.getNetwork(guestNtwkId); - return _networkACLItemDao.listByACL(network.getNetworkACLId()); - } - - @Override - public NetworkACLItem getNetworkACLItem(long ruleId) { - return _networkACLItemDao.findById(ruleId); + public NetworkACL createNetworkACL(String name, String description, long vpcId) { + NetworkACLVO acl = new NetworkACLVO(name, description, vpcId); + _networkACLDao.persist(acl); + return acl; } @Override - public boolean applyNetworkACL(long aclId, Account caller) throws ResourceUnavailableException { + public boolean applyNetworkACL(long aclId) throws ResourceUnavailableException { boolean handled = false; List rules = _networkACLItemDao.listByACL(aclId); //Find all networks using this ACL List networks = _networkDao.listByAclId(aclId); for(NetworkVO network : networks){ //Failure case?? - handled = applyACLItemsToNetwork(network.getId(), rules, caller); + handled = applyACLItemsToNetwork(network.getId(), rules); } if(handled){ for (NetworkACLItem rule : rules) { @@ -166,108 +100,54 @@ public boolean applyNetworkACL(long aclId, Account caller) throws ResourceUnavai } @Override - public void removeRule(NetworkACLItem rule) { - //remove the rule - _networkACLItemDao.remove(rule.getId()); + public NetworkACL getNetworkACL(long id) { + return _networkACLDao.findById(id); } @Override - public boolean applyACLToNetwork(long networkId, Account caller) throws ResourceUnavailableException { - Network network = _networkDao.findById(networkId); - List rules = _networkACLItemDao.listByACL(network.getNetworkACLId()); - return applyACLItemsToNetwork(networkId, rules, caller); - } - - public boolean applyACLItemsToNetwork(long networkId, List rules, Account caller) throws ResourceUnavailableException { - Network network = _networkDao.findById(networkId); - boolean handled = false; - for (NetworkACLServiceProvider element: _networkAclElements) { - Network.Provider provider = element.getProvider(); - boolean isAclProvider = _networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.NetworkACL, provider); - if (!isAclProvider) { - continue; - } - handled = element.applyNetworkACLs(network, rules); - if (handled) - break; + public boolean deleteNetworkACL(NetworkACL acl) { + List aclItems = _networkACLItemDao.listByACL(acl.getId()); + if(aclItems.size() > 0){ + throw new CloudRuntimeException("ACL is not empty. Cannot delete network ACL: "+acl.getUuid()); } - return handled; + return _networkACLDao.remove(acl.getId()); } @Override - public NetworkACLItem createNetworkACLItem(CreateNetworkACLCmd aclItemCmd) throws NetworkRuleConflictException { - return createNetworkACLItem(UserContext.current().getCaller(), aclItemCmd.getSourcePortStart(), - aclItemCmd.getSourcePortEnd(), aclItemCmd.getProtocol(), aclItemCmd.getSourceCidrList(), aclItemCmd.getIcmpCode(), - aclItemCmd.getIcmpType(), aclItemCmd.getNetworkId(), aclItemCmd.getTrafficType(), aclItemCmd.getACLId(), aclItemCmd.getAction(), aclItemCmd.getNumber()); + public boolean replaceNetworkACL(NetworkACL acl, NetworkVO network) throws ResourceUnavailableException { + if(network.getVpcId() != acl.getVpcId()){ + throw new InvalidParameterValueException("Network: "+network.getUuid()+" and ACL: "+acl.getUuid()+" do not belong to the same VPC"); + } + network.setNetworkACLId(acl.getId()); + if(_networkDao.update(network.getId(), network)){ + return applyACLToNetwork(network.getId()); + } + return false; } + @Override @DB @ActionEvent(eventType = EventTypes.EVENT_NETWORK_ACL_ITEM_CREATE, eventDescription = "creating network ACL Item", create = true) - protected NetworkACLItem createNetworkACLItem(Account caller, Integer portStart, Integer portEnd, String protocol, List sourceCidrList, - Integer icmpCode, Integer icmpType, Long networkId, NetworkACLItem.TrafficType trafficType, Long aclId, - String action, Integer number) throws NetworkRuleConflictException { - - if(aclId == null){ - Network network = _networkMgr.getNetwork(networkId); - if (network == null) { - throw new InvalidParameterValueException("Can't find network by id"); - } - aclId = network.getNetworkACLId(); - - if (aclId == null) { - throw new InvalidParameterValueException("Network is not associated with any ACL"); - } - } - - NetworkACL networkACL = _networkACLDao.findById(aclId); - - Vpc vpc = _vpcMgr.getVpc(networkACL.getVpcId()); - Account aclOwner = _accountMgr.getAccount(vpc.getAccountId()); - - //check if the caller can access vpc - _accountMgr.checkAccess(caller, null, false, vpc); - - //check if the acl can be created for this network - _accountMgr.checkAccess(aclOwner, AccessType.ModifyEntry, false, networkACL); - - // icmp code and icmp type can't be passed in for any other protocol rather than icmp - if (!protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO) && (icmpCode != null || icmpType != null)) { - throw new InvalidParameterValueException("Can specify icmpCode and icmpType for ICMP protocol only"); - } - - if (protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO) && (portStart != null || portEnd != null)) { - throw new InvalidParameterValueException("Can't specify start/end port when protocol is ICMP"); - } - - //validate icmp code and type - if (icmpType != null) { - if (icmpType.longValue() != -1 && !NetUtils.validateIcmpType(icmpType.longValue())) { - throw new InvalidParameterValueException("Invalid icmp type; should belong to [0-255] range"); - } - if (icmpCode != null) { - if (icmpCode.longValue() != -1 && !NetUtils.validateIcmpCode(icmpCode.longValue())) { - throw new InvalidParameterValueException("Invalid icmp code; should belong to [0-15] range and can" + - " be defined when icmpType belongs to [0-40] range"); - } - } - } - + public NetworkACLItem createNetworkACLItem(Integer portStart, Integer portEnd, String protocol, List sourceCidrList, + Integer icmpCode, Integer icmpType, NetworkACLItem.TrafficType trafficType, Long aclId, + String action, Integer number) { NetworkACLItem.Action ruleAction = NetworkACLItem.Action.Allow; if("deny".equals(action)){ ruleAction = NetworkACLItem.Action.Deny; } // If number is null, set it to currentMax + 1 - validateNetworkACLItem(caller, portStart, portEnd, protocol); + if(number == null){ + number = _networkACLItemDao.getMaxNumberByACL(aclId) + 1; + } Transaction txn = Transaction.currentTxn(); txn.start(); - NetworkACLItemVO newRule = new NetworkACLItemVO(portStart, portEnd, protocol.toLowerCase(), aclId, sourceCidrList, icmpCode, icmpType, trafficType, ruleAction, number); newRule = _networkACLItemDao.persist(newRule); - //ToDo: Is this required now with?? - //detectNetworkACLConflict(newRule); + //ToDo: Is this required now with number?? + //detectNetworkACLConflict(newRule); if (!_networkACLItemDao.setStateToAdd(newRule)) { throw new CloudRuntimeException("Unable to update the state to add for " + newRule); @@ -279,199 +159,105 @@ protected NetworkACLItem createNetworkACLItem(Account caller, Integer portStart, return getNetworkACLItem(newRule.getId()); } - protected void validateNetworkACLItem(Account caller, Integer portStart, Integer portEnd, - String proto) { - - if (portStart != null && !NetUtils.isValidPort(portStart)) { - throw new InvalidParameterValueException("publicPort is an invalid value: " + portStart); - } - if (portEnd != null && !NetUtils.isValidPort(portEnd)) { - throw new InvalidParameterValueException("Public port range is an invalid value: " + portEnd); - } - - // start port can't be bigger than end port - if (portStart != null && portEnd != null && portStart > portEnd) { - throw new InvalidParameterValueException("Start port can't be bigger than end port"); - } - } - @Override - public boolean revokeNetworkACLItem(long ruleId, boolean apply) { - Account caller = UserContext.current().getCaller(); - long userId = UserContext.current().getCallerUserId(); - return revokeNetworkACLItem(ruleId, apply, caller, userId); + public NetworkACLItem getNetworkACLItem(long ruleId) { + return _networkACLItemDao.findById(ruleId); } @ActionEvent(eventType = EventTypes.EVENT_NETWORK_ACL_DELETE, eventDescription = "revoking network acl", async = true) - protected boolean revokeNetworkACLItem(long ruleId, boolean apply, Account caller, long userId) { + public boolean revokeNetworkACLItem(long ruleId) { NetworkACLItemVO rule = _networkACLItemDao.findById(ruleId); - if (rule == null) { - throw new InvalidParameterValueException("Unable to find network ACL Item" + ruleId); - } - - // _accountMgr.checkAccess(caller, null, true, rule); - revokeRule(rule, caller, userId, false); + revokeRule(rule); boolean success = false; - if (apply) { - try { - applyNetworkACL(rule.getACLId(), caller); - success = true; - } catch (ResourceUnavailableException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } - } else { + try { + applyNetworkACL(rule.getAclId()); success = true; + } catch (ResourceUnavailableException e) { + return false; } return success; } - - @Override - public Pair, Integer> listNetworkACLItems(ListNetworkACLsCmd cmd) { - Long networkId = cmd.getNetworkId(); - Long id = cmd.getId(); - String trafficType = cmd.getTrafficType(); - Map tags = cmd.getTags(); - - Account caller = UserContext.current().getCaller(); - List permittedAccounts = new ArrayList(); - - Ternary domainIdRecursiveListProject = - new Ternary(cmd.getDomainId(), cmd.isRecursive(), null); - _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, - domainIdRecursiveListProject, cmd.listAll(), false); - Long domainId = domainIdRecursiveListProject.first(); - Boolean isRecursive = domainIdRecursiveListProject.second(); - ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); - - Filter filter = new Filter(NetworkACLItemVO.class, "id", false, cmd.getStartIndex(), cmd.getPageSizeVal()); - SearchBuilder sb = _networkACLItemDao.createSearchBuilder(); - // _accountMgr.buildACLSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); - - sb.and("id", sb.entity().getId(), Op.EQ); - sb.and("aclId", sb.entity().getACLId(), Op.EQ); - sb.and("trafficType", sb.entity().getTrafficType(), Op.EQ); - - if (tags != null && !tags.isEmpty()) { - SearchBuilder tagSearch = _resourceTagDao.createSearchBuilder(); - for (int count=0; count < tags.size(); count++) { - tagSearch.or().op("key" + String.valueOf(count), tagSearch.entity().getKey(), SearchCriteria.Op.EQ); - tagSearch.and("value" + String.valueOf(count), tagSearch.entity().getValue(), SearchCriteria.Op.EQ); - tagSearch.cp(); + @DB + private void revokeRule(NetworkACLItemVO rule) { + if (rule.getState() == State.Staged) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Found a rule that is still in stage state so just removing it: " + rule); } - tagSearch.and("resourceType", tagSearch.entity().getResourceType(), SearchCriteria.Op.EQ); - sb.groupBy(sb.entity().getId()); - sb.join("tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER); - } - - SearchCriteria sc = sb.create(); - // _accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); - - if (id != null) { - sc.setParameters("id", id); + _networkACLItemDao.remove(rule.getId()); + } else if (rule.getState() == State.Add || rule.getState() == State.Active) { + rule.setState(State.Revoke); + _networkACLItemDao.update(rule.getId(), rule); } + } - if (networkId != null) { - Network network = _networkDao.findById(networkId); - sc.setParameters("aclId", network.getNetworkACLId()); + @Override + public boolean revokeACLItemsForNetwork(long networkId, long userId, Account caller) throws ResourceUnavailableException { + Network network = _networkDao.findById(networkId); + List aclItems = _networkACLItemDao.listByACL(network.getNetworkACLId()); + if (aclItems.isEmpty()) { + s_logger.debug("Found no network ACL Items for network id=" + networkId); + return true; } - if (trafficType != null) { - sc.setParameters("trafficType", trafficType); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Releasing " + aclItems.size() + " Network ACL Items for network id=" + networkId); } - if (tags != null && !tags.isEmpty()) { - int count = 0; - sc.setJoinParameters("tagSearch", "resourceType", TaggedResourceType.NetworkACL.toString()); - for (String key : tags.keySet()) { - sc.setJoinParameters("tagSearch", "key" + String.valueOf(count), key); - sc.setJoinParameters("tagSearch", "value" + String.valueOf(count), tags.get(key)); - count++; + for (NetworkACLItemVO aclItem : aclItems) { + // Mark all Network ACLs rules as Revoke, but don't update in DB + if (aclItem.getState() == State.Add || aclItem.getState() == State.Active) { + aclItem.setState(State.Revoke); } } - Pair, Integer> result = _networkACLItemDao.searchAndCount(sc, filter); - return new Pair, Integer>(result.first(), result.second()); - } + boolean success = applyACLItemsToNetwork(network.getId(), aclItems); - @Override - public NetworkACL createNetworkACL(CreateNetworkACLListCmd cmd) { - NetworkACLVO acl = new NetworkACLVO(cmd.getName(), cmd.getDescription(), cmd.getVpcId()); - _networkACLDao.persist(acl); - return acl; - } + if (s_logger.isDebugEnabled() && success) { + s_logger.debug("Successfully released Network ACLs for network id=" + networkId + " and # of rules now = " + + aclItems.size()); + } - @Override - public NetworkACL getNetworkACL(long id) { - return _networkACLDao.findById(id); + return success; } @Override - public boolean deleteNetworkACL(long id) { - return _networkACLDao.remove(id); + public List listNetworkACLItems(long guestNtwkId) { + Network network = _networkMgr.getNetwork(guestNtwkId); + return _networkACLItemDao.listByACL(network.getNetworkACLId()); } - @Override - public Pair, Integer> listNetworkACLs(ListNetworkACLListsCmd listNetworkACLListsCmd) { - SearchBuilder sb = _networkACLDao.createSearchBuilder(); - SearchCriteria sc = sb.create(); - Filter filter = new Filter(NetworkACLVO.class, "id", false, null, null); - Pair, Integer> acls = _networkACLDao.searchAndCount(sc, filter); - return new Pair, Integer>(acls.first(), acls.second()); + private void removeRule(NetworkACLItem rule) { + //remove the rule + _networkACLItemDao.remove(rule.getId()); } @Override - public boolean replaceNetworkACL(long aclId, long networkId) { - NetworkVO network = _networkDao.findById(networkId); - if(network == null){ - throw new InvalidParameterValueException("Unable to find Network: " +networkId); - } - NetworkACL acl = _networkACLDao.findById(aclId); - if(acl == null){ - throw new InvalidParameterValueException("Unable to find NetworkACL: " +aclId); - } - if(network.getVpcId() == null){ - throw new InvalidParameterValueException("Network does not belong to VPC: " +networkId); - } - if(network.getVpcId() != acl.getVpcId()){ - throw new InvalidParameterValueException("Network: "+networkId+" and ACL: "+aclId+" do not belong to the same VPC"); - } - network.setNetworkACLId(aclId); - return _networkDao.update(networkId, network); + public boolean applyACLToNetwork(long networkId) throws ResourceUnavailableException { + Network network = _networkDao.findById(networkId); + List rules = _networkACLItemDao.listByACL(network.getNetworkACLId()); + return applyACLItemsToNetwork(networkId, rules); } - @DB - private void revokeRule(NetworkACLItemVO rule, Account caller, long userId, boolean needUsageEvent) { - if (caller != null) { - //_accountMgr.checkAccess(caller, null, true, rule); - } - - Transaction txn = Transaction.currentTxn(); - boolean generateUsageEvent = false; - - txn.start(); - if (rule.getState() == State.Staged) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Found a rule that is still in stage state so just removing it: " + rule); + public boolean applyACLItemsToNetwork(long networkId, List rules) throws ResourceUnavailableException { + Network network = _networkDao.findById(networkId); + boolean handled = false; + for (NetworkACLServiceProvider element: _networkAclElements) { + Network.Provider provider = element.getProvider(); + boolean isAclProvider = _networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.NetworkACL, provider); + if (!isAclProvider) { + continue; } - _networkACLItemDao.remove(rule.getId()); - generateUsageEvent = true; - } else if (rule.getState() == State.Add || rule.getState() == State.Active) { - rule.setState(State.Revoke); - _networkACLItemDao.update(rule.getId(), rule); - generateUsageEvent = true; + handled = element.applyNetworkACLs(network, rules); + if (handled) + break; } - -/* if (generateUsageEvent && needUsageEvent) { - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NET_RULE_DELETE, rule.getAccountId(), 0, rule.getId(), - null, rule.getClass().getName(), rule.getUuid()); - }*/ - - txn.commit(); + return handled; } + } diff --git a/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java b/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java new file mode 100644 index 000000000000..381bc6a35d13 --- /dev/null +++ b/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java @@ -0,0 +1,372 @@ +// 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.network.vpc; + +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.Network; +import com.cloud.network.NetworkModel; +import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.NetworkVO; +import com.cloud.network.element.NetworkACLServiceProvider; +import com.cloud.network.firewall.NetworkACLService; +import com.cloud.network.vpc.dao.NetworkACLDao; +import com.cloud.projects.Project.ListProjectResourcesCriteria; +import com.cloud.server.ResourceTag.TaggedResourceType; +import com.cloud.tags.ResourceTagVO; +import com.cloud.tags.dao.ResourceTagDao; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; +import com.cloud.user.UserContext; +import com.cloud.utils.Pair; +import com.cloud.utils.Ternary; +import com.cloud.utils.component.ManagerBase; +import com.cloud.utils.db.Filter; +import com.cloud.utils.db.JoinBuilder; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.net.NetUtils; +import org.apache.cloudstack.acl.SecurityChecker; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.command.user.network.CreateNetworkACLCmd; +import org.apache.cloudstack.api.command.user.network.ListNetworkACLsCmd; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import javax.ejb.Local; +import javax.inject.Inject; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + + +@Component +@Local(value = { NetworkACLService.class}) +public class NetworkACLServiceImpl extends ManagerBase implements NetworkACLService{ + private static final Logger s_logger = Logger.getLogger(NetworkACLServiceImpl.class); + + @Inject + AccountManager _accountMgr; + @Inject + NetworkModel _networkMgr; + @Inject + VpcManager _vpcMgr; + @Inject + ResourceTagDao _resourceTagDao; + @Inject + NetworkACLDao _networkACLDao; + @Inject + NetworkACLItemDao _networkACLItemDao; + @Inject + List _networkAclElements; + @Inject + NetworkModel _networkModel; + @Inject + NetworkDao _networkDao; + @Inject + NetworkACLManager _networkAclMgr; + + @Override + public NetworkACL createNetworkACL(String name, String description, long vpcId) { + Account caller = UserContext.current().getCaller(); + Vpc vpc = _vpcMgr.getVpc(vpcId); + if(vpc == null){ + throw new InvalidParameterValueException("Unable to find VPC"); + } + _accountMgr.checkAccess(caller, null, true, vpc); + return _networkAclMgr.createNetworkACL(name, description, vpcId); + } + + @Override + public NetworkACL getNetworkACL(long id) { + return _networkAclMgr.getNetworkACL(id); + } + + @Override + public Pair, Integer> listNetworkACLs(Long id, String name, Long networkId, Long vpcId) { + SearchBuilder sb = _networkACLDao.createSearchBuilder(); + sb.and("id", sb.entity().getId(), Op.EQ); + sb.and("name", sb.entity().getName(), Op.EQ); + sb.and("vpcId", sb.entity().getVpcId(), Op.EQ); + + if(networkId != null){ + SearchBuilder network = _networkDao.createSearchBuilder(); + network.and("networkId", network.entity().getId(), Op.EQ); + sb.join("networkJoin", network, sb.entity().getId(), network.entity().getNetworkACLId(), JoinBuilder.JoinType.INNER); + } + + SearchCriteria sc = sb.create(); + if(id != null){ + sc.setParameters("id", id); + } + + if(name != null){ + sc.setParameters("name", name); + } + + if(vpcId != null){ + sc.setParameters("vpcId", name); + } + + if(networkId != null){ + sc.setJoinParameters("networkJoin", "networkId", networkId); + } + + Filter filter = new Filter(NetworkACLVO.class, "id", false, null, null); + Pair, Integer> acls = _networkACLDao.searchAndCount(sc, filter); + return new Pair, Integer>(acls.first(), acls.second()); + } + + @Override + public boolean deleteNetworkACL(long id) { + Account caller = UserContext.current().getCaller(); + NetworkACL acl = _networkACLDao.findById(id); + if(acl == null) { + throw new InvalidParameterValueException("Unable to find specified ACL"); + } + Vpc vpc = _vpcMgr.getVpc(acl.getVpcId()); + if(vpc == null){ + throw new InvalidParameterValueException("Unable to find specified VPC associated with the ACL"); + } + _accountMgr.checkAccess(caller, null, true, vpc); + return _networkAclMgr.deleteNetworkACL(acl); + } + + @Override + public boolean replaceNetworkACL(long aclId, long networkId) throws ResourceUnavailableException { + Account caller = UserContext.current().getCaller(); + + NetworkVO network = _networkDao.findById(networkId); + if(network == null){ + throw new InvalidParameterValueException("Unable to find specified Network"); + } + + NetworkACL acl = _networkACLDao.findById(aclId); + if(acl == null){ + throw new InvalidParameterValueException("Unable to find specified NetworkACL"); + } + + if(network.getVpcId() == null){ + throw new InvalidParameterValueException("Network is not part of a VPC: "+ network.getUuid()); + } + + Vpc vpc = _vpcMgr.getVpc(acl.getVpcId()); + if(vpc == null){ + throw new InvalidParameterValueException("Unable to find Vpc associated with the NetworkACL"); + } + _accountMgr.checkAccess(caller, null, true, vpc); + if(network.getVpcId() != acl.getVpcId()){ + throw new InvalidParameterValueException("Network: "+networkId+" and ACL: "+aclId+" do not belong to the same VPC"); + } + return _networkAclMgr.replaceNetworkACL(acl, network); + } + + @Override + public NetworkACLItem createNetworkACLItem(CreateNetworkACLCmd aclItemCmd){ + Account caller = UserContext.current().getCaller(); + Long aclId = aclItemCmd.getACLId(); + if(aclId == null){ + //ACL id is not specified. Get the ACL details from network + if(aclItemCmd.getNetworkId() == null){ + throw new InvalidParameterValueException("Cannot create Network ACL Item. ACL Id or network Id is required"); + } + Network network = _networkMgr.getNetwork(aclItemCmd.getNetworkId()); + if(network.getVpcId() == null){ + throw new InvalidParameterValueException("Network: "+network.getUuid()+" does not belong to VPC"); + } + aclId = network.getNetworkACLId(); + } + + NetworkACL acl = _networkAclMgr.getNetworkACL(aclId); + if(acl == null){ + throw new InvalidParameterValueException("Unable to find specified ACL"); + } + + Vpc vpc = _vpcMgr.getVpc(acl.getVpcId()); + if(vpc == null){ + throw new InvalidParameterValueException("Unable to find Vpc associated with the NetworkACL"); + } + _accountMgr.checkAccess(caller, null, true, vpc); + + Account aclOwner = _accountMgr.getAccount(vpc.getAccountId()); + _accountMgr.checkAccess(aclOwner, SecurityChecker.AccessType.ModifyEntry, false, acl); + + validateNetworkACLItem(aclItemCmd.getSourcePortStart(), aclItemCmd.getSourcePortEnd(), aclItemCmd.getSourceCidrList(), + aclItemCmd.getProtocol(), aclItemCmd.getIcmpCode(), aclItemCmd.getIcmpType(), aclItemCmd.getAction()); + + return _networkAclMgr.createNetworkACLItem(aclItemCmd.getSourcePortStart(), + aclItemCmd.getSourcePortEnd(), aclItemCmd.getProtocol(), aclItemCmd.getSourceCidrList(), aclItemCmd.getIcmpCode(), + aclItemCmd.getIcmpType(), aclItemCmd.getTrafficType(), aclId, aclItemCmd.getAction(), aclItemCmd.getNumber()); + } + + private void validateNetworkACLItem(Integer portStart, Integer portEnd, List sourceCidrList, String protocol, Integer icmpCode, + Integer icmpType, String action) { + + if (portStart != null && !NetUtils.isValidPort(portStart)) { + throw new InvalidParameterValueException("publicPort is an invalid value: " + portStart); + } + if (portEnd != null && !NetUtils.isValidPort(portEnd)) { + throw new InvalidParameterValueException("Public port range is an invalid value: " + portEnd); + } + + // start port can't be bigger than end port + if (portStart != null && portEnd != null && portStart > portEnd) { + throw new InvalidParameterValueException("Start port can't be bigger than end port"); + } + + if (sourceCidrList != null) { + for (String cidr: sourceCidrList){ + if (!NetUtils.isValidCIDR(cidr)){ + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Source cidrs formatting error " + cidr); + } + } + } + + // icmp code and icmp type can't be passed in for any other protocol rather than icmp + if (!protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO) && (icmpCode != null || icmpType != null)) { + throw new InvalidParameterValueException("Can specify icmpCode and icmpType for ICMP protocol only"); + } + + if (protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO) && (portStart != null || portEnd != null)) { + throw new InvalidParameterValueException("Can't specify start/end port when protocol is ICMP"); + } + + //validate icmp code and type + if (icmpType != null) { + if (icmpType.longValue() != -1 && !NetUtils.validateIcmpType(icmpType.longValue())) { + throw new InvalidParameterValueException("Invalid icmp type; should belong to [0-255] range"); + } + if (icmpCode != null) { + if (icmpCode.longValue() != -1 && !NetUtils.validateIcmpCode(icmpCode.longValue())) { + throw new InvalidParameterValueException("Invalid icmp code; should belong to [0-15] range and can" + + " be defined when icmpType belongs to [0-40] range"); + } + } + } + + if(action != null){ + try { + NetworkACLItem.Action.valueOf(action); + } catch (IllegalArgumentException ex) { + throw new InvalidParameterValueException("Invalid action. Allowed actions are Aloow and Deny"); + } + } + } + + @Override + public NetworkACLItem getNetworkACLItem(long ruleId) { + return _networkAclMgr.getNetworkACLItem(ruleId); + } + + @Override + public boolean applyNetworkACL(long aclId) throws ResourceUnavailableException { + return _networkAclMgr.applyNetworkACL(aclId); + } + + @Override + public Pair, Integer> listNetworkACLItems(ListNetworkACLsCmd cmd) { + Long networkId = cmd.getNetworkId(); + Long id = cmd.getId(); + Long aclId = cmd.getAclId(); + String trafficType = cmd.getTrafficType(); + String protocol = cmd.getProtocol(); + String action = cmd.getAction(); + Map tags = cmd.getTags(); + + Account caller = UserContext.current().getCaller(); + List permittedAccounts = new ArrayList(); + + Ternary domainIdRecursiveListProject = + new Ternary(cmd.getDomainId(), cmd.isRecursive(), null); + _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, + domainIdRecursiveListProject, cmd.listAll(), false); + Long domainId = domainIdRecursiveListProject.first(); + Boolean isRecursive = domainIdRecursiveListProject.second(); + ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); + + Filter filter = new Filter(NetworkACLItemVO.class, "id", false, cmd.getStartIndex(), cmd.getPageSizeVal()); + SearchBuilder sb = _networkACLItemDao.createSearchBuilder(); + //_accountMgr.buildACLSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); + + sb.and("id", sb.entity().getId(), Op.EQ); + sb.and("aclId", sb.entity().getAclId(), Op.EQ); + sb.and("trafficType", sb.entity().getTrafficType(), Op.EQ); + sb.and("protocol", sb.entity().getProtocol(), Op.EQ); + sb.and("action", sb.entity().getAction(), Op.EQ); + + if (tags != null && !tags.isEmpty()) { + SearchBuilder tagSearch = _resourceTagDao.createSearchBuilder(); + for (int count=0; count < tags.size(); count++) { + tagSearch.or().op("key" + String.valueOf(count), tagSearch.entity().getKey(), Op.EQ); + tagSearch.and("value" + String.valueOf(count), tagSearch.entity().getValue(), Op.EQ); + tagSearch.cp(); + } + tagSearch.and("resourceType", tagSearch.entity().getResourceType(), Op.EQ); + sb.groupBy(sb.entity().getId()); + sb.join("tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER); + } + + SearchCriteria sc = sb.create(); + // _accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); + + if (id != null) { + sc.setParameters("id", id); + } + + if (networkId != null) { + Network network = _networkDao.findById(networkId); + aclId = network.getNetworkACLId(); + } + + if (trafficType != null) { + sc.setParameters("trafficType", trafficType); + } + + if(aclId != null){ + sc.setParameters("aclId", aclId); + } + + if(protocol != null){ + sc.setParameters("protocol", protocol); + } + + if(action != null){ + sc.setParameters("action", action); + } + + if (tags != null && !tags.isEmpty()) { + int count = 0; + sc.setJoinParameters("tagSearch", "resourceType", TaggedResourceType.NetworkACL.toString()); + for (String key : tags.keySet()) { + sc.setJoinParameters("tagSearch", "key" + String.valueOf(count), key); + sc.setJoinParameters("tagSearch", "value" + String.valueOf(count), tags.get(key)); + count++; + } + } + + Pair, Integer> result = _networkACLItemDao.searchAndCount(sc, filter); + return new Pair, Integer>(result.first(), result.second()); + } + + @Override + public boolean revokeNetworkACLItem(long ruleId) { + return _networkAclMgr.revokeNetworkACLItem(ruleId); + } + +} \ No newline at end of file diff --git a/server/src/com/cloud/network/vpc/dao/NetworkACLItemDaoImpl.java b/server/src/com/cloud/network/vpc/dao/NetworkACLItemDaoImpl.java index 98f5d6f8527c..a433e0cd8ecb 100644 --- a/server/src/com/cloud/network/vpc/dao/NetworkACLItemDaoImpl.java +++ b/server/src/com/cloud/network/vpc/dao/NetworkACLItemDaoImpl.java @@ -16,14 +16,10 @@ // under the License. package com.cloud.network.vpc.dao; -import com.cloud.network.vpc.NetworkACLItem; import com.cloud.network.vpc.NetworkACLItem.State; import com.cloud.network.vpc.NetworkACLItemDao; import com.cloud.network.vpc.NetworkACLItemVO; -import com.cloud.utils.db.DB; -import com.cloud.utils.db.GenericDaoBase; -import com.cloud.utils.db.SearchBuilder; -import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.*; import com.cloud.utils.db.SearchCriteria.Op; import org.springframework.stereotype.Component; @@ -38,6 +34,7 @@ public class NetworkACLItemDaoImpl extends GenericDaoBase AllFieldsSearch; protected final SearchBuilder NotRevokedSearch; protected final SearchBuilder ReleaseSearch; + protected final GenericSearchBuilder MaxNumberSearch; protected NetworkACLItemDaoImpl() { super(); @@ -46,7 +43,7 @@ protected NetworkACLItemDaoImpl() { AllFieldsSearch.and("protocol", AllFieldsSearch.entity().getProtocol(), Op.EQ); AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), Op.EQ); AllFieldsSearch.and("id", AllFieldsSearch.entity().getId(), Op.EQ); - AllFieldsSearch.and("aclId", AllFieldsSearch.entity().getACLId(), Op.EQ); + AllFieldsSearch.and("aclId", AllFieldsSearch.entity().getAclId(), Op.EQ); AllFieldsSearch.and("trafficType", AllFieldsSearch.entity().getTrafficType(), Op.EQ); AllFieldsSearch.done(); @@ -55,7 +52,7 @@ protected NetworkACLItemDaoImpl() { NotRevokedSearch.and("protocol", NotRevokedSearch.entity().getProtocol(), Op.EQ); NotRevokedSearch.and("sourcePortStart", NotRevokedSearch.entity().getSourcePortStart(), Op.EQ); NotRevokedSearch.and("sourcePortEnd", NotRevokedSearch.entity().getSourcePortEnd(), Op.EQ); - NotRevokedSearch.and("aclId", NotRevokedSearch.entity().getACLId(), Op.EQ); + NotRevokedSearch.and("aclId", NotRevokedSearch.entity().getAclId(), Op.EQ); NotRevokedSearch.and("trafficType", NotRevokedSearch.entity().getTrafficType(), Op.EQ); NotRevokedSearch.done(); @@ -64,14 +61,13 @@ protected NetworkACLItemDaoImpl() { ReleaseSearch.and("ports", ReleaseSearch.entity().getSourcePortStart(), Op.IN); ReleaseSearch.done(); + MaxNumberSearch = createSearchBuilder(Integer.class); + MaxNumberSearch.select(null, SearchCriteria.Func.MAX, MaxNumberSearch.entity().getNumber()); + MaxNumberSearch.and("aclId", MaxNumberSearch.entity().getAclId(), Op.EQ); + MaxNumberSearch.done(); } - @Override - public List listByACLAndNotRevoked(long aclId) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - @Override public boolean setStateToAdd(NetworkACLItemVO rule) { SearchCriteria sc = AllFieldsSearch.create(); @@ -98,13 +94,11 @@ public List listByACL(long aclId) { } @Override - public List listByACLTrafficTypeAndNotRevoked(long aclId, NetworkACLItem.TrafficType trafficType) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - public List listByACLTrafficType(long aclId, NetworkACLItem.TrafficType trafficType) { - return null; //To change body of implemented methods use File | Settings | File Templates. + public int getMaxNumberByACL(long aclId) { + SearchCriteria sc = MaxNumberSearch.create(); + sc.setParameters("aclId", aclId); + Integer max = customSearch(sc, null).get(0); + return (max == null) ? 0 : max; } } diff --git a/server/src/com/cloud/tags/TaggedResourceManagerImpl.java b/server/src/com/cloud/tags/TaggedResourceManagerImpl.java index 20fccee2cc0c..daffe93c851a 100644 --- a/server/src/com/cloud/tags/TaggedResourceManagerImpl.java +++ b/server/src/com/cloud/tags/TaggedResourceManagerImpl.java @@ -25,6 +25,7 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.network.vpc.NetworkACLItemDao; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -117,6 +118,8 @@ public class TaggedResourceManagerImpl extends ManagerBase implements TaggedReso StaticRouteDao _staticRouteDao; @Inject VMSnapshotDao _vmSnapshotDao; + @Inject + NetworkACLItemDao _networkACLItemDao; @Override public boolean configure(String name, Map params) throws ConfigurationException { @@ -133,7 +136,7 @@ public boolean configure(String name, Map params) throws Configu _daoMap.put(TaggedResourceType.PublicIpAddress, _publicIpDao); _daoMap.put(TaggedResourceType.Project, _projectDao); _daoMap.put(TaggedResourceType.Vpc, _vpcDao); - _daoMap.put(TaggedResourceType.NetworkACL, _firewallDao); + _daoMap.put(TaggedResourceType.NetworkACL, _networkACLItemDao); _daoMap.put(TaggedResourceType.StaticRoute, _staticRouteDao); _daoMap.put(TaggedResourceType.VMSnapshot, _vmSnapshotDao); _daoMap.put(TaggedResourceType.RemoteAccessVpn, _vpnDao); diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index ea8d05eb1774..02a44997d3dd 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -1174,3 +1174,6 @@ CREATE TABLE `cloud`.`network_acl_item` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8; ALTER TABLE `cloud`.`networks` add column `network_acl_id` bigint unsigned COMMENT 'network acl id'; +INSERT INTO `cloud`.`network_acl` values (1, UUID(), 0, "Default Network ACL", "default"); +INSERT INTO `cloud`.`network_acl_item` (id, uuid, acl_id, state, protocol, created, traffic_type, cidr, number, action) values (1, UUID(), 1, "Active", "tcp", now(), "Ingress", "0.0.0.0/0", 1, "Deny"); +INSERT INTO `cloud`.`network_acl_item` (id, uuid, acl_id, state, protocol, created, traffic_type, cidr, number, action) values (2, UUID(), 1, "Active", "tcp", now(), "Egress", "0.0.0.0/0", 2, "Deny"); From 0de6a80f50b5a4f3b9b47a3e30baf239109115b0 Mon Sep 17 00:00:00 2001 From: Kishan Kavala Date: Thu, 2 May 2013 17:53:56 +0530 Subject: [PATCH 06/14] CLOUDSTACK-763: Added acl_id param to createNetwork API. Backend changes for acl_deny. Support for all protocol and protocol number --- api/src/com/cloud/network/Network.java | 2 + api/src/com/cloud/network/NetworkProfile.java | 5 ++ api/src/com/cloud/network/vpc/NetworkACL.java | 3 ++ .../user/network/CreateNetworkACLCmd.java | 2 +- .../user/network/CreateNetworkCmd.java | 15 +++--- .../src/com/cloud/network/dao/NetworkVO.java | 1 + .../debian/config/opt/cloud/bin/vpc_acl.sh | 11 +++-- .../com/cloud/network/NetworkServiceImpl.java | 30 +++++++++++- .../cloud/network/vpc/NetworkACLItemDao.java | 1 + .../network/vpc/NetworkACLManagerImpl.java | 14 ++---- .../network/vpc/NetworkACLServiceImpl.java | 46 ++++++++++++++++--- .../src/com/cloud/network/vpc/VpcManager.java | 2 +- .../com/cloud/network/vpc/VpcManagerImpl.java | 7 ++- .../vpc/dao/NetworkACLItemDaoImpl.java | 9 ++++ .../com/cloud/vpc/MockVpcManagerImpl.java | 2 +- setup/db/create-schema.sql | 1 - setup/db/db/schema-410to420.sql | 12 +++-- 17 files changed, 125 insertions(+), 38 deletions(-) diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java index 0b20122f0598..793fa5649d67 100644 --- a/api/src/com/cloud/network/Network.java +++ b/api/src/com/cloud/network/Network.java @@ -325,4 +325,6 @@ public void setIp6Address(String ip6Address) { Long getVpcId(); Long getNetworkACLId(); + + void setNetworkACLId(Long networkACLId); } diff --git a/api/src/com/cloud/network/NetworkProfile.java b/api/src/com/cloud/network/NetworkProfile.java index 568edf7c9ec9..1807021fa8d9 100644 --- a/api/src/com/cloud/network/NetworkProfile.java +++ b/api/src/com/cloud/network/NetworkProfile.java @@ -243,6 +243,11 @@ public Long getNetworkACLId() { return networkAclId; } + @Override + public void setNetworkACLId(Long networkACLId) { + this.networkAclId = networkACLId; + } + @Override public void setTrafficType(TrafficType type) { this.trafficType = type; diff --git a/api/src/com/cloud/network/vpc/NetworkACL.java b/api/src/com/cloud/network/vpc/NetworkACL.java index 1b171e31de6e..c5a0d6db1dac 100644 --- a/api/src/com/cloud/network/vpc/NetworkACL.java +++ b/api/src/com/cloud/network/vpc/NetworkACL.java @@ -21,6 +21,9 @@ import org.apache.cloudstack.api.InternalIdentity; public interface NetworkACL extends InternalIdentity, ControlledEntity{ + public static final long DEFAULT_DENY = 1; + public static final long DEFAULT_ALLOW = 2; + String getDescription(); String getUuid(); diff --git a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java index 984ed5751563..e78fe44ff0fc 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java @@ -56,7 +56,7 @@ public class CreateNetworkACLCmd extends BaseAsyncCreateCmd { // /////////////////////////////////////////////////// @Parameter(name = ApiConstants.PROTOCOL, type = CommandType.STRING, required = true, description = - "the protocol for the ACL rule. Valid values are TCP/UDP/ICMP.") + "the protocol for the ACL rule. Valid values are TCP/UDP/ICMP/ALL or valid protocol number") private String protocol; @Parameter(name = ApiConstants.START_PORT, type = CommandType.INTEGER, description = "the starting port of ACL") diff --git a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java index fc7bd9fdd3f1..e88aca73b773 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java @@ -22,13 +22,7 @@ import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; -import org.apache.cloudstack.api.response.DomainResponse; -import org.apache.cloudstack.api.response.NetworkOfferingResponse; -import org.apache.cloudstack.api.response.NetworkResponse; -import org.apache.cloudstack.api.response.PhysicalNetworkResponse; -import org.apache.cloudstack.api.response.ProjectResponse; -import org.apache.cloudstack.api.response.VpcResponse; -import org.apache.cloudstack.api.response.ZoneResponse; +import org.apache.cloudstack.api.response.*; import org.apache.log4j.Logger; import com.cloud.exception.ConcurrentOperationException; @@ -126,6 +120,9 @@ public class CreateNetworkCmd extends BaseCmd { @Parameter(name=ApiConstants.IP6_CIDR, type=CommandType.STRING, description="the CIDR of IPv6 network, must be at least /64") private String ip6Cidr; + @Parameter(name=ApiConstants.ACL_ID, type=CommandType.UUID, entityType = NetworkACLResponse.class, + description="Network ACL Id associated for the network") + private Long aclId; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -247,6 +244,10 @@ public String getIp6Cidr() { return ip6Cidr.toLowerCase(); } + public Long getAclId() { + return aclId; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/engine/schema/src/com/cloud/network/dao/NetworkVO.java b/engine/schema/src/com/cloud/network/dao/NetworkVO.java index 664bc7759972..bf338d529060 100644 --- a/engine/schema/src/com/cloud/network/dao/NetworkVO.java +++ b/engine/schema/src/com/cloud/network/dao/NetworkVO.java @@ -544,6 +544,7 @@ public void setIp6Gateway(String ip6Gateway) { this.ip6Gateway = ip6Gateway; } + @Override public void setNetworkACLId(Long networkACLId) { this.networkACLId = networkACLId; } diff --git a/patches/systemvm/debian/config/opt/cloud/bin/vpc_acl.sh b/patches/systemvm/debian/config/opt/cloud/bin/vpc_acl.sh index 8a207e880be0..903d6d6127aa 100755 --- a/patches/systemvm/debian/config/opt/cloud/bin/vpc_acl.sh +++ b/patches/systemvm/debian/config/opt/cloud/bin/vpc_acl.sh @@ -102,6 +102,7 @@ acl_entry_for_guest_network() { local sport=$(echo $rule | cut -d: -f3) local eport=$(echo $rule | cut -d: -f4) local cidrs=$(echo $rule | cut -d: -f5 | sed 's/-/ /g') + local action=$(echo $rule | cut -d: -f6) if [ "$sport" == "0" -a "$eport" == "0" ] then DPORT="" @@ -123,21 +124,21 @@ acl_entry_for_guest_network() { if [ "$ttype" == "Ingress" ] then sudo iptables -I ACL_INBOUND_$dev -p $prot -s $lcidr \ - --icmp-type $typecode -j ACCEPT + --icmp-type $typecode -j $action else let egress++ sudo iptables -t mangle -I ACL_OUTBOUND_$dev -p $prot -d $lcidr \ - --icmp-type $typecode -j ACCEPT + --icmp-type $typecode -j $action fi else if [ "$ttype" == "Ingress" ] then sudo iptables -I ACL_INBOUND_$dev -p $prot -s $lcidr \ - $DPORT -j ACCEPT + $DPORT -j $action else let egress++ sudo iptables -t mangle -I ACL_OUTBOUND_$dev -p $prot -d $lcidr \ - $DPORT -j ACCEPT + $DPORT -j $action fi fi result=$? @@ -195,7 +196,7 @@ fi # protocal:sport:eport:cidr #-a tcp:80:80:0.0.0.0/0::tcp:220:220:0.0.0.0/0:,172.16.92.44:tcp:222:222:192.168.10.0/24-75.57.23.0/22-88.100.33.1/32 # if any entry is reverted , entry will be in the format :reverted:0:0:0 -# example : 172.16.92.44:tcp:80:80:0.0.0.0/0:,172.16.92.44:tcp:220:220:0.0.0.0/0:,200.1.1.2:reverted:0:0:0 +# example : 172.16.92.44:tcp:80:80:0.0.0.0/0:ACCEPT:,172.16.92.44:tcp:220:220:0.0.0.0/0:DROP,200.1.1.2:reverted:0:0:0 success=0 diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java index 5e8be92fdb55..72ecd520fad2 100755 --- a/server/src/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/com/cloud/network/NetworkServiceImpl.java @@ -18,6 +18,8 @@ import java.net.Inet6Address; import java.net.InetAddress; +import java.net.InetAddress; +import java.net.Inet6Address; import java.net.UnknownHostException; import java.security.InvalidParameterException; import java.sql.PreparedStatement; @@ -42,6 +44,10 @@ import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd; import org.apache.cloudstack.api.command.admin.network.ListDedicatedGuestVlanRangesCmd; +import com.cloud.network.vpc.NetworkACL; +import com.cloud.network.vpc.dao.NetworkACLDao; +import org.apache.cloudstack.acl.ControlledEntity.ACLType; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd; import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd; import org.apache.cloudstack.api.command.user.network.ListNetworksCmd; @@ -49,6 +55,10 @@ import org.apache.cloudstack.api.command.user.vm.ListNicsCmd; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; +import org.apache.cloudstack.api.command.user.vm.ListNicsCmd; +import org.bouncycastle.util.IPAddress; import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; @@ -271,6 +281,8 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { DataCenterVnetDao _datacneter_vnet; @Inject AccountGuestVlanMapDao _accountGuestVlanMapDao; + @Inject + NetworkACLDao _networkACLDao; int _cidrLimit; boolean _allowSubdomainNetworkAccess; @@ -900,6 +912,7 @@ public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapac String endIPv6 = cmd.getEndIpv6(); String ip6Gateway = cmd.getIp6Gateway(); String ip6Cidr = cmd.getIp6Cidr(); + Long aclId = cmd.getAclId(); // Validate network offering NetworkOfferingVO ntwkOff = _networkOfferingDao.findById(networkOfferingId); @@ -1177,8 +1190,21 @@ && areServicesSupportedByNetworkOffering(ntwkOff.getId(), Service.SourceNat))) { if (!_configMgr.isOfferingForVpc(ntwkOff)){ throw new InvalidParameterValueException("Network offering can't be used for VPC networks"); } - network = _vpcMgr.createVpcGuestNetwork(networkOfferingId, name, displayText, gateway, cidr, vlanId, - networkDomain, owner, sharedDomainId, pNtwk, zoneId, aclType, subdomainAccess, vpcId, caller); + if(aclId == null){ + //Use default deny all ACL, when aclId is not specified + aclId = NetworkACL.DEFAULT_DENY; + } else { + NetworkACL acl = _networkACLDao.findById(aclId); + if(acl == null){ + throw new InvalidParameterValueException("Unable to find specified NetworkACL"); + } + + if(vpcId != acl.getVpcId()){ + throw new InvalidParameterValueException("ACL: "+aclId+" do not belong to the VPC"); + } + } + network = _vpcMgr.createVpcGuestNetwork(networkOfferingId, name, displayText, gateway, cidr, vlanId, + networkDomain, owner, sharedDomainId, pNtwk, zoneId, aclType, subdomainAccess, vpcId, aclId, caller); } else { if (_configMgr.isOfferingForVpc(ntwkOff)){ throw new InvalidParameterValueException("Network offering can be used for VPC networks only"); diff --git a/server/src/com/cloud/network/vpc/NetworkACLItemDao.java b/server/src/com/cloud/network/vpc/NetworkACLItemDao.java index 8f70ac768c92..e4b187184ff3 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLItemDao.java +++ b/server/src/com/cloud/network/vpc/NetworkACLItemDao.java @@ -33,4 +33,5 @@ public interface NetworkACLItemDao extends GenericDao { int getMaxNumberByACL(long aclId); + NetworkACLItemVO findByAclAndNumber(long aclId, int number); } diff --git a/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java b/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java index 20fd58665247..67547c602f9b 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java +++ b/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java @@ -77,13 +77,15 @@ public NetworkACL createNetworkACL(String name, String description, long vpcId) @Override public boolean applyNetworkACL(long aclId) throws ResourceUnavailableException { - boolean handled = false; + boolean handled = true; List rules = _networkACLItemDao.listByACL(aclId); //Find all networks using this ACL List networks = _networkDao.listByAclId(aclId); for(NetworkVO network : networks){ - //Failure case?? - handled = applyACLItemsToNetwork(network.getId(), rules); + if(!applyACLItemsToNetwork(network.getId(), rules)) { + handled = false; + break; + } } if(handled){ for (NetworkACLItem rule : rules) { @@ -115,9 +117,6 @@ public boolean deleteNetworkACL(NetworkACL acl) { @Override public boolean replaceNetworkACL(NetworkACL acl, NetworkVO network) throws ResourceUnavailableException { - if(network.getVpcId() != acl.getVpcId()){ - throw new InvalidParameterValueException("Network: "+network.getUuid()+" and ACL: "+acl.getUuid()+" do not belong to the same VPC"); - } network.setNetworkACLId(acl.getId()); if(_networkDao.update(network.getId(), network)){ return applyACLToNetwork(network.getId()); @@ -146,9 +145,6 @@ public NetworkACLItem createNetworkACLItem(Integer portStart, Integer portEnd, S NetworkACLItemVO newRule = new NetworkACLItemVO(portStart, portEnd, protocol.toLowerCase(), aclId, sourceCidrList, icmpCode, icmpType, trafficType, ruleAction, number); newRule = _networkACLItemDao.persist(newRule); - //ToDo: Is this required now with number?? - //detectNetworkACLConflict(newRule); - if (!_networkACLItemDao.setStateToAdd(newRule)) { throw new CloudRuntimeException("Unable to update the state to add for " + newRule); } diff --git a/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java b/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java index 381bc6a35d13..2844dcbaaa0a 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java +++ b/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java @@ -20,6 +20,7 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Network; import com.cloud.network.NetworkModel; +import com.cloud.network.Networks; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkVO; import com.cloud.network.element.NetworkACLServiceProvider; @@ -46,6 +47,7 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.command.user.network.CreateNetworkACLCmd; import org.apache.cloudstack.api.command.user.network.ListNetworkACLsCmd; +import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -166,14 +168,24 @@ public boolean replaceNetworkACL(long aclId, long networkId) throws ResourceUnav throw new InvalidParameterValueException("Network is not part of a VPC: "+ network.getUuid()); } - Vpc vpc = _vpcMgr.getVpc(acl.getVpcId()); - if(vpc == null){ - throw new InvalidParameterValueException("Unable to find Vpc associated with the NetworkACL"); + if (network.getTrafficType() != Networks.TrafficType.Guest) { + throw new InvalidParameterValueException("Network ACL can be created just for networks of type " + Networks.TrafficType.Guest); } - _accountMgr.checkAccess(caller, null, true, vpc); - if(network.getVpcId() != acl.getVpcId()){ - throw new InvalidParameterValueException("Network: "+networkId+" and ACL: "+aclId+" do not belong to the same VPC"); + + if(aclId != NetworkACL.DEFAULT_DENY) { + //ACL is not default DENY + // ACL should be associated with a VPC + Vpc vpc = _vpcMgr.getVpc(acl.getVpcId()); + if(vpc == null){ + throw new InvalidParameterValueException("Unable to find Vpc associated with the NetworkACL"); + } + + _accountMgr.checkAccess(caller, null, true, vpc); + if(network.getVpcId() != acl.getVpcId()){ + throw new InvalidParameterValueException("Network: "+networkId+" and ACL: "+aclId+" do not belong to the same VPC"); + } } + return _networkAclMgr.replaceNetworkACL(acl, network); } @@ -207,6 +219,12 @@ public NetworkACLItem createNetworkACLItem(CreateNetworkACLCmd aclItemCmd){ Account aclOwner = _accountMgr.getAccount(vpc.getAccountId()); _accountMgr.checkAccess(aclOwner, SecurityChecker.AccessType.ModifyEntry, false, acl); + if(aclItemCmd.getNumber() != null){ + if(_networkACLItemDao.findByAclAndNumber(aclId, aclItemCmd.getNumber()) != null){ + throw new InvalidParameterValueException("ACL item with number "+aclItemCmd.getNumber()+" already exists in ACL: "+acl.getUuid()); + } + } + validateNetworkACLItem(aclItemCmd.getSourcePortStart(), aclItemCmd.getSourcePortEnd(), aclItemCmd.getSourceCidrList(), aclItemCmd.getProtocol(), aclItemCmd.getIcmpCode(), aclItemCmd.getIcmpType(), aclItemCmd.getAction()); @@ -238,6 +256,22 @@ private void validateNetworkACLItem(Integer portStart, Integer portEnd, List 255){ + throw new InvalidParameterValueException("Invalid protocol number: " + protoNumber); + } + } else { + //Protocol is not number + //Check for valid protocol strings + String supportedProtocols = "tcp,udp,icmp,all"; + if(!supportedProtocols.contains(protocol.toLowerCase())){ + throw new InvalidParameterValueException("Invalid protocol: " + protocol); + } + } + // icmp code and icmp type can't be passed in for any other protocol rather than icmp if (!protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO) && (icmpCode != null || icmpType != null)) { throw new InvalidParameterValueException("Can specify icmpCode and icmpType for ICMP protocol only"); diff --git a/server/src/com/cloud/network/vpc/VpcManager.java b/server/src/com/cloud/network/vpc/VpcManager.java index 84ab8ef5dd7c..07b9494547f1 100644 --- a/server/src/com/cloud/network/vpc/VpcManager.java +++ b/server/src/com/cloud/network/vpc/VpcManager.java @@ -104,7 +104,7 @@ public interface VpcManager extends VpcService{ */ Network createVpcGuestNetwork(long ntwkOffId, String name, String displayText, String gateway, String cidr, String vlanId, String networkDomain, Account owner, Long domainId, PhysicalNetwork pNtwk, long zoneId, - ACLType aclType, Boolean subdomainAccess, long vpcId, Account caller) + ACLType aclType, Boolean subdomainAccess, long vpcId, long aclId, Account caller) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException; diff --git a/server/src/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/com/cloud/network/vpc/VpcManagerImpl.java index a7f06e988dd6..4af9278b30fa 100644 --- a/server/src/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/com/cloud/network/vpc/VpcManagerImpl.java @@ -1940,7 +1940,7 @@ public boolean isIpAllocatedToVpc(IpAddress ip) { @Override public Network createVpcGuestNetwork(long ntwkOffId, String name, String displayText, String gateway, String cidr, String vlanId, String networkDomain, Account owner, Long domainId, - PhysicalNetwork pNtwk, long zoneId, ACLType aclType, Boolean subdomainAccess, long vpcId, Account caller) + PhysicalNetwork pNtwk, long zoneId, ACLType aclType, Boolean subdomainAccess, long vpcId, long aclId, Account caller) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException { Vpc vpc = getActiveVpc(vpcId); @@ -1966,7 +1966,10 @@ public Network createVpcGuestNetwork(long ntwkOffId, String name, String display //2) Create network Network guestNetwork = _ntwkMgr.createGuestNetwork(ntwkOffId, name, displayText, gateway, cidr, vlanId, networkDomain, owner, domainId, pNtwk, zoneId, aclType, subdomainAccess, vpcId, null, null); - + if(guestNetwork != null){ + guestNetwork.setNetworkACLId(aclId); + _ntwkDao.update(guestNetwork.getId(), (NetworkVO)guestNetwork); + } return guestNetwork; } diff --git a/server/src/com/cloud/network/vpc/dao/NetworkACLItemDaoImpl.java b/server/src/com/cloud/network/vpc/dao/NetworkACLItemDaoImpl.java index a433e0cd8ecb..8162ce85ca1e 100644 --- a/server/src/com/cloud/network/vpc/dao/NetworkACLItemDaoImpl.java +++ b/server/src/com/cloud/network/vpc/dao/NetworkACLItemDaoImpl.java @@ -45,6 +45,8 @@ protected NetworkACLItemDaoImpl() { AllFieldsSearch.and("id", AllFieldsSearch.entity().getId(), Op.EQ); AllFieldsSearch.and("aclId", AllFieldsSearch.entity().getAclId(), Op.EQ); AllFieldsSearch.and("trafficType", AllFieldsSearch.entity().getTrafficType(), Op.EQ); + AllFieldsSearch.and("number", AllFieldsSearch.entity().getNumber(), Op.EQ); + AllFieldsSearch.and("action", AllFieldsSearch.entity().getAction(), Op.EQ); AllFieldsSearch.done(); NotRevokedSearch = createSearchBuilder(); @@ -101,4 +103,11 @@ public int getMaxNumberByACL(long aclId) { return (max == null) ? 0 : max; } + @Override + public NetworkACLItemVO findByAclAndNumber(long aclId, int number) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("aclId", aclId); + sc.setParameters("number", number); + return findOneBy(sc); + } } diff --git a/server/test/com/cloud/vpc/MockVpcManagerImpl.java b/server/test/com/cloud/vpc/MockVpcManagerImpl.java index baccbd045d29..b4851d64355d 100644 --- a/server/test/com/cloud/vpc/MockVpcManagerImpl.java +++ b/server/test/com/cloud/vpc/MockVpcManagerImpl.java @@ -303,7 +303,7 @@ public void unassignIPFromVpcNetwork(long ipId, long networkId) { */ @Override public Network createVpcGuestNetwork(long ntwkOffId, String name, String displayText, String gateway, String cidr, String vlanId, String networkDomain, Account owner, Long domainId, PhysicalNetwork pNtwk, - long zoneId, ACLType aclType, Boolean subdomainAccess, long vpcId, Account caller) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException { + long zoneId, ACLType aclType, Boolean subdomainAccess, long vpcId, long aclId, Account caller) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException { // TODO Auto-generated method stub return null; } diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 37c2352c7ecd..b1feb0228363 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -268,7 +268,6 @@ CREATE TABLE `cloud`.`networks` ( `removed` datetime COMMENT 'date removed if not null', `specify_ip_ranges` int(1) unsigned NOT NULL DEFAULT 0 COMMENT 'true if the network provides an ability to define ip ranges', `vpc_id` bigint unsigned COMMENT 'vpc this network belongs to', - `network_acl_id` bigint unsigned COMMENT 'network acl id', PRIMARY KEY (`id`), CONSTRAINT `fk_networks__network_offering_id` FOREIGN KEY (`network_offering_id`) REFERENCES `network_offerings`(`id`), CONSTRAINT `fk_networks__data_center_id` FOREIGN KEY (`data_center_id`) REFERENCES `data_center`(`id`) ON DELETE CASCADE, diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index 02a44997d3dd..85d17e77e7d5 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -1169,11 +1169,17 @@ CREATE TABLE `cloud`.`network_acl_item` ( `number` int(10) NOT NULL COMMENT 'priority number of the acl item', `action` varchar(10) NOT NULL COMMENT 'rule action, allow or deny', PRIMARY KEY (`id`), + UNIQUE KEY (`acl_id`, `number`), CONSTRAINT `fk_network_acl_item__acl_id` FOREIGN KEY(`acl_id`) REFERENCES `network_acl`(`id`) ON DELETE CASCADE, CONSTRAINT `uc_network_acl_item__uuid` UNIQUE (`uuid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; ALTER TABLE `cloud`.`networks` add column `network_acl_id` bigint unsigned COMMENT 'network acl id'; -INSERT INTO `cloud`.`network_acl` values (1, UUID(), 0, "Default Network ACL", "default"); -INSERT INTO `cloud`.`network_acl_item` (id, uuid, acl_id, state, protocol, created, traffic_type, cidr, number, action) values (1, UUID(), 1, "Active", "tcp", now(), "Ingress", "0.0.0.0/0", 1, "Deny"); -INSERT INTO `cloud`.`network_acl_item` (id, uuid, acl_id, state, protocol, created, traffic_type, cidr, number, action) values (2, UUID(), 1, "Active", "tcp", now(), "Egress", "0.0.0.0/0", 2, "Deny"); + +INSERT INTO `cloud`.`network_acl` (id, uuid, vpc_id, description, name) values (1, UUID(), 0, "Default Network ACL Deny All", "default_deny"); +INSERT INTO `cloud`.`network_acl_item` (id, uuid, acl_id, state, protocol, created, traffic_type, cidr, number, action) values (1, UUID(), 1, "Active", "all", now(), "Ingress", "0.0.0.0/0", 1, "Deny"); +INSERT INTO `cloud`.`network_acl_item` (id, uuid, acl_id, state, protocol, created, traffic_type, cidr, number, action) values (2, UUID(), 1, "Active", "all", now(), "Egress", "0.0.0.0/0", 2, "Deny"); + +INSERT INTO `cloud`.`network_acl` (id, uuid, vpc_id, description, name) values (2, UUID(), 0, "Default Network ACL Allow All", "default_allow"); +INSERT INTO `cloud`.`network_acl_item` (id, uuid, acl_id, state, protocol, created, traffic_type, cidr, number, action) values (3, UUID(), 2, "Active", "all", now(), "Ingress", "0.0.0.0/0", 1, "Allow"); +INSERT INTO `cloud`.`network_acl_item` (id, uuid, acl_id, state, protocol, created, traffic_type, cidr, number, action) values (4, UUID(), 2, "Active", "all", now(), "Egress", "0.0.0.0/0", 2, "Allow"); From f9a9e1be970b853657d5bfb71a058fbaa3aff322 Mon Sep 17 00:00:00 2001 From: Kishan Kavala Date: Fri, 3 May 2013 18:06:57 +0530 Subject: [PATCH 07/14] CLOUDSTACK-763: Upgrade networkAcls from firewall_rules to network_acl_item table --- .../cloud/upgrade/dao/Upgrade410to420.java | 158 ++++++++++++++++++ 1 file changed, 158 insertions(+) diff --git a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java index 05e2b49ffe45..180c7492a11f 100644 --- a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java +++ b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java @@ -23,11 +23,19 @@ import java.io.File; import java.sql.Connection; +import java.sql.Date; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Types; import java.util.UUID; +import com.cloud.network.vpc.NetworkACL; +import org.apache.log4j.Logger; + +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; + public class Upgrade410to420 implements DbUpgrade { final static Logger s_logger = Logger.getLogger(Upgrade410to420.class); @@ -66,6 +74,7 @@ public void performDataMigration(Connection conn) { updatePrimaryStore(conn); addEgressFwRulesForSRXGuestNw(conn); upgradeEIPNetworkOfferings(conn); + updateNetworkACLs(conn); } private void updateSystemVmTemplates(Connection conn) { @@ -306,6 +315,7 @@ private void updateRemoteAccessVpn(Connection conn) { } } } + private void addEgressFwRulesForSRXGuestNw(Connection conn) { PreparedStatement pstmt = null; ResultSet rs = null; @@ -387,11 +397,159 @@ private void upgradeEIPNetworkOfferings(Connection conn) { } } catch (SQLException e) { throw new CloudRuntimeException("Unable to set elastic_ip_service for network offerings with EIP service enabled.", e); + } + } + + private void updateNetworkACLs(Connection conn) { + //Fetch all VPC Tiers + //For each tier create a network ACL and move all the acl_items to network_acl_item table + // If there are no acl_items for a tier, associate it with default ACL + s_logger.debug("Updating network ACLs"); + PreparedStatement pstmt = null; + PreparedStatement pstmtDelete = null; + ResultSet rs = null; + ResultSet rsAcls = null; + ResultSet rsCidr = null; + //1,2 are default acl Ids, start Ids from 3 + long nextAclId = 3; + try { + pstmt = conn.prepareStatement("SELECT id, vpc_id, uuid FROM `cloud`.`networks` where vpc_id is not null and removed is null"); + rs = pstmt.executeQuery(); + while (rs.next()) { + Long networkId = rs.getLong(1); + s_logger.debug("Updating network ACLs for network: "+networkId); + Long vpcId = rs.getLong(2); + String tierUuid = rs.getString(3); + pstmt = conn.prepareStatement("SELECT id, uuid, start_port, end_port, state, protocol, icmp_code, icmp_type, created, traffic_type FROM `cloud`.`firewall_rules` where network_id = ? and purpose = 'NetworkACL'"); + pstmt.setLong(1, networkId); + rsAcls = pstmt.executeQuery(); + boolean hasAcls = false; + Long aclId = null; + int number = 1; + while(rsAcls.next()){ + if(!hasAcls){ + hasAcls = true; + aclId = nextAclId++; + //create ACL + s_logger.debug("Creating network ACL for tier: "+tierUuid); + pstmt = conn.prepareStatement("INSERT INTO `cloud`.`network_acl` (id, uuid, vpc_id, description, name) values (?, UUID(), ? , ?, ?)"); + pstmt.setLong(1, aclId); + pstmt.setLong(2, vpcId); + pstmt.setString(3, "ACL for tier " + tierUuid); + pstmt.setString(4, "tier_" + tierUuid); + pstmt.executeUpdate(); + } + + Long fwRuleId = rsAcls.getLong(1); + String cidr = null; + //get cidr + pstmt = conn.prepareStatement("SELECT id, source_cidr FROM `cloud`.`firewall_rules_cidrs` where firewall_rule_id = ?"); + pstmt.setLong(1, fwRuleId); + rsCidr = pstmt.executeQuery(); + while(rsCidr.next()){ + Long cidrId = rsCidr.getLong(1); + String sourceCidr = rsCidr.getString(2); + if(cidr == null){ + cidr = sourceCidr; + } else { + cidr += ","+sourceCidr; + } + //Delete cidr entry + pstmtDelete = conn.prepareStatement("DELETE FROM `cloud`.`firewall_rules_cidrs` where id = ?"); + pstmtDelete.setLong(1, cidrId); + pstmtDelete.executeUpdate(); + } + + + String aclItemUuid = rsAcls.getString(2); + //Move acl to network_acl_item table + s_logger.debug("Moving firewall rule: "+aclItemUuid); + pstmt = conn.prepareStatement("INSERT INTO `cloud`.`network_acl_item` (uuid, acl_id, start_port, end_port, state, protocol, icmp_code, icmp_type, created, traffic_type, cidr, number, action) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )"); + //uuid + pstmt.setString(1, aclItemUuid); + //aclId + pstmt.setLong(2, aclId); + //Start port + Integer startPort = rsAcls.getInt(3); + if(rsAcls.wasNull()){ + pstmt.setNull(3, Types.INTEGER); + } else { + pstmt.setLong(3, startPort); + } + //End port + Integer endPort = rsAcls.getInt(4); + if(rsAcls.wasNull()){ + pstmt.setNull(4, Types.INTEGER); + } else { + pstmt.setLong(4, endPort); + } + //State + String state = rsAcls.getString(5); + pstmt.setString(5, state); + //protocol + String protocol = rsAcls.getString(6); + pstmt.setString(6, protocol); + //icmp_code + Integer icmpCode = rsAcls.getInt(7); + if(rsAcls.wasNull()){ + pstmt.setNull(7, Types.INTEGER); + } else { + pstmt.setLong(7, icmpCode); + } + + //icmp_type + Integer icmpType = rsAcls.getInt(8); + if(rsAcls.wasNull()){ + pstmt.setNull(8, Types.INTEGER); + } else { + pstmt.setLong(8, icmpType); + } + + //created + Date created = rsAcls.getDate(9); + pstmt.setDate(9, created); + //traffic type + String trafficType = rsAcls.getString(10); + pstmt.setString(10, trafficType); + + //cidr + pstmt.setString(11, cidr); + //number + pstmt.setInt(12, number++); + //action + pstmt.setString(13, "Allow"); + pstmt.executeUpdate(); + + //Delete firewall rule + pstmtDelete = conn.prepareStatement("DELETE FROM `cloud`.`firewall_rules` where id = ?"); + pstmtDelete.setLong(1, fwRuleId); + pstmtDelete.executeUpdate(); + } + if(!hasAcls){ + //no network ACls for this network. + // Assign default Deny ACL + aclId = NetworkACL.DEFAULT_DENY; + } + //Assign acl to network + pstmt = conn.prepareStatement("UPDATE `cloud`.`networks` set network_acl_id=? where id=?"); + pstmt.setLong(1, aclId); + pstmt.setLong(2, networkId); + pstmt.executeUpdate(); + } + s_logger.debug("Done updating network ACLs "); + } catch (SQLException e) { + throw new CloudRuntimeException("Unable to move network acls from firewall rules table to network_acl_item table", e); } finally { try { if (rs != null) { rs.close(); } + if (rsAcls != null) { + rsAcls.close(); + } + if (rsCidr != null) { + rsCidr.close(); + } if (pstmt != null) { pstmt.close(); } From cf50eec00d90ad307da7b339ba8507a95f9c24bd Mon Sep 17 00:00:00 2001 From: Kishan Kavala Date: Tue, 7 May 2013 00:14:09 +0530 Subject: [PATCH 08/14] CLOUDSTACK-763: Added API updateNetworkACLItem to update an existing ACL Item --- api/src/com/cloud/event/EventTypes.java | 2 +- .../network/firewall/NetworkACLService.java | 4 +- .../user/network/CreateNetworkACLCmd.java | 2 +- client/tomcatconf/commands.properties.in | 1 + .../cloud/network/vpc/NetworkACLItemVO.java | 40 +++++++++++-- .../cloud/network/vpc/NetworkACLManager.java | 3 + .../network/vpc/NetworkACLManagerImpl.java | 59 ++++++++++++++++++- .../network/vpc/NetworkACLServiceImpl.java | 52 +++++++++++++++- .../cloud/server/ManagementServerImpl.java | 2 +- ...MockVpcVirtualNetworkApplianceManager.java | 10 +--- .../com/cloud/vpc/dao/MockNetworkDaoImpl.java | 5 ++ 11 files changed, 163 insertions(+), 17 deletions(-) diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java index 63611edce8e3..51f5003834f9 100755 --- a/api/src/com/cloud/event/EventTypes.java +++ b/api/src/com/cloud/event/EventTypes.java @@ -336,10 +336,10 @@ public class EventTypes { // Network ACL public static final String EVENT_NETWORK_ACL_CREATE = "NETWORK.ACL.CREATE"; - public static final String EVENT_NETWORK_ACL_UPDATE = "NETWORK.ACL.UPDATE"; public static final String EVENT_NETWORK_ACL_DELETE = "NETWORK.ACL.DELETE"; public static final String EVENT_NETWORK_ACL_REPLACE = "NETWORK.ACL.REPLACE"; public static final String EVENT_NETWORK_ACL_ITEM_CREATE = "NETWORK.ACL.ITEM.CREATE"; + public static final String EVENT_NETWORK_ACL_ITEM_UPDATE = "NETWORK.ACL.ITEM.UPDATE"; public static final String EVENT_NETWORK_ACL_ITEM_DELETE = "NETWORK.ACL.ITEM.DELETE"; // VPC offerings diff --git a/api/src/com/cloud/network/firewall/NetworkACLService.java b/api/src/com/cloud/network/firewall/NetworkACLService.java index 5f068a3828bc..cd25da345f68 100644 --- a/api/src/com/cloud/network/firewall/NetworkACLService.java +++ b/api/src/com/cloud/network/firewall/NetworkACLService.java @@ -112,5 +112,7 @@ public interface NetworkACLService { boolean revokeNetworkACLItem(long ruleId); - + NetworkACLItem updateNetworkACLItem(Long id, String protocol, List sourceCidrList, NetworkACLItem.TrafficType trafficType, + String action, Integer number, Integer sourcePortStart, Integer sourcePortEnd, + Integer icmpCode, Integer icmpType) throws ResourceUnavailableException; } diff --git a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java index e78fe44ff0fc..1ed6445e5962 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java @@ -44,7 +44,7 @@ import com.cloud.user.UserContext; import com.cloud.utils.net.NetUtils; -@APICommand(name = "createNetworkACL", description = "Creates a ACL rule the given network (the network has to belong to VPC)", +@APICommand(name = "createNetworkACL", description = "Creates a ACL rule in the given network (the network has to belong to VPC)", responseObject = NetworkACLItemResponse.class) public class CreateNetworkACLCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreateNetworkACLCmd.class.getName()); diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index 4e10527cd748..fb443e0b17a4 100644 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -433,6 +433,7 @@ deletePrivateGateway=1 #### Network ACL commands createNetworkACL=15 +updateNetworkACLItem=15 deleteNetworkACL=15 listNetworkACLs=15 createNetworkACLList=15 diff --git a/server/src/com/cloud/network/vpc/NetworkACLItemVO.java b/server/src/com/cloud/network/vpc/NetworkACLItemVO.java index 71ccebf07969..74d0445755a6 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLItemVO.java +++ b/server/src/com/cloud/network/vpc/NetworkACLItemVO.java @@ -194,12 +194,44 @@ public int getNumber() { return number; } - public void setUuid(String uuid) { - this.uuid = uuid; - } - @Override public TrafficType getTrafficType() { return trafficType; } + + public void setSourcePortStart(Integer sourcePortStart) { + this.sourcePortStart = sourcePortStart; + } + + public void setSourcePortEnd(Integer sourcePortEnd) { + this.sourcePortEnd = sourcePortEnd; + } + + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + public void setIcmpCode(Integer icmpCode) { + this.icmpCode = icmpCode; + } + + public void setIcmpType(Integer icmpType) { + this.icmpType = icmpType; + } + + public void setTrafficType(TrafficType trafficType) { + this.trafficType = trafficType; + } + + public void setSourceCidrs(String sourceCidrs) { + this.sourceCidrs = sourceCidrs; + } + + public void setNumber(int number) { + this.number = number; + } + + public void setAction(Action action) { + this.action = action; + } } diff --git a/server/src/com/cloud/network/vpc/NetworkACLManager.java b/server/src/com/cloud/network/vpc/NetworkACLManager.java index 1b1e958231ee..fc2b1a88591d 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLManager.java +++ b/server/src/com/cloud/network/vpc/NetworkACLManager.java @@ -114,4 +114,7 @@ NetworkACLItem createNetworkACLItem(Integer sourcePortStart, Integer sourcePortE boolean applyACLToNetwork(long networkId) throws ResourceUnavailableException; + NetworkACLItem updateNetworkACLItem(Long id, String protocol, List sourceCidrList, NetworkACLItem.TrafficType trafficType, + String action, Integer number, Integer sourcePortStart, Integer sourcePortEnd, + Integer icmpCode, Integer icmpType) throws ResourceUnavailableException; } diff --git a/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java b/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java index 67547c602f9b..28f5af27bb8c 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java +++ b/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java @@ -131,7 +131,7 @@ public NetworkACLItem createNetworkACLItem(Integer portStart, Integer portEnd, S Integer icmpCode, Integer icmpType, NetworkACLItem.TrafficType trafficType, Long aclId, String action, Integer number) { NetworkACLItem.Action ruleAction = NetworkACLItem.Action.Allow; - if("deny".equals(action)){ + if("deny".equalsIgnoreCase(action)){ ruleAction = NetworkACLItem.Action.Deny; } // If number is null, set it to currentMax + 1 @@ -240,6 +240,63 @@ public boolean applyACLToNetwork(long networkId) throws ResourceUnavailableExcep return applyACLItemsToNetwork(networkId, rules); } + @Override + public NetworkACLItem updateNetworkACLItem(Long id, String protocol, List sourceCidrList, NetworkACLItem.TrafficType trafficType, + String action, Integer number, Integer sourcePortStart, Integer sourcePortEnd, Integer icmpCode, + Integer icmpType) throws ResourceUnavailableException { + NetworkACLItemVO aclItem = _networkACLItemDao.findById(id); + aclItem.setState(State.Add); + + if(protocol != null){ + aclItem.setProtocol(protocol); + } + + if(sourceCidrList != null){ + aclItem.setSourceCidrList(sourceCidrList); + } + + if(trafficType != null){ + aclItem.setTrafficType(trafficType); + } + + if(action != null){ + NetworkACLItem.Action ruleAction = NetworkACLItem.Action.Allow; + if("deny".equalsIgnoreCase(action)){ + ruleAction = NetworkACLItem.Action.Deny; + } + aclItem.setAction(ruleAction); + } + + if(number != null){ + aclItem.setNumber(number); + } + + if(sourcePortStart != null){ + aclItem.setSourcePortStart(sourcePortStart); + } + + if(sourcePortEnd != null){ + aclItem.setSourcePortEnd(sourcePortEnd); + } + + if(icmpCode != null){ + aclItem.setIcmpCode(icmpCode); + } + + if(icmpType != null){ + aclItem.setIcmpType(icmpType); + } + + if(_networkACLItemDao.update(id, aclItem)){ + if(applyNetworkACL(aclItem.getAclId())){ + return aclItem; + } else { + throw new CloudRuntimeException("Failed to apply Network ACL Item: "+aclItem.getUuid()); + } + } + return null; + } + public boolean applyACLItemsToNetwork(long networkId, List rules) throws ResourceUnavailableException { Network network = _networkDao.findById(networkId); boolean handled = false; diff --git a/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java b/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java index 2844dcbaaa0a..ae9b8f985ec9 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java +++ b/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java @@ -142,6 +142,11 @@ public boolean deleteNetworkACL(long id) { if(acl == null) { throw new InvalidParameterValueException("Unable to find specified ACL"); } + + if(acl.getId() == NetworkACL.DEFAULT_ALLOW || acl.getId() == NetworkACL.DEFAULT_DENY){ + throw new InvalidParameterValueException("Default ACL cannot be removed"); + } + Vpc vpc = _vpcMgr.getVpc(acl.getVpcId()); if(vpc == null){ throw new InvalidParameterValueException("Unable to find specified VPC associated with the ACL"); @@ -298,7 +303,7 @@ private void validateNetworkACLItem(Integer portStart, Integer portEnd, List, Integer> listNetworkACLItems(ListNet @Override public boolean revokeNetworkACLItem(long ruleId) { + NetworkACLItemVO aclItem = _networkACLItemDao.findById(ruleId); + if(aclItem != null){ + if((aclItem.getAclId() == NetworkACL.DEFAULT_ALLOW) || (aclItem.getAclId() == NetworkACL.DEFAULT_DENY)){ + throw new InvalidParameterValueException("ACL Items in default ACL cannot be deleted"); + } + } return _networkAclMgr.revokeNetworkACLItem(ruleId); } + @Override + public NetworkACLItem updateNetworkACLItem(Long id, String protocol, List sourceCidrList, NetworkACLItem.TrafficType trafficType, + String action, Integer number, Integer sourcePortStart, Integer sourcePortEnd, Integer icmpCode, + Integer icmpType) throws ResourceUnavailableException { + NetworkACLItemVO aclItem = _networkACLItemDao.findById(id); + if(aclItem == null){ + throw new InvalidParameterValueException("Unable to find ACL Item cannot be found"); + } + + if(aclItem.getAclId() == NetworkACL.DEFAULT_ALLOW || aclItem.getAclId() == NetworkACL.DEFAULT_DENY){ + throw new InvalidParameterValueException("Default ACL Items cannot be updated"); + } + + NetworkACL acl = _networkAclMgr.getNetworkACL(aclItem.getAclId()); + + Vpc vpc = _vpcMgr.getVpc(acl.getVpcId()); + + Account caller = UserContext.current().getCaller(); + + _accountMgr.checkAccess(caller, null, true, vpc); + + Account aclOwner = _accountMgr.getAccount(vpc.getAccountId()); + _accountMgr.checkAccess(aclOwner, SecurityChecker.AccessType.ModifyEntry, false, acl); + + if(number != null){ + //Check if ACL Item with specified number already exists + NetworkACLItemVO aclNumber = _networkACLItemDao.findByAclAndNumber(acl.getId(), number); + if((aclNumber != null) && (aclNumber.getId() != id)){ + throw new InvalidParameterValueException("ACL item with number "+number+" already exists in ACL: "+acl.getUuid()); + } + } + + validateNetworkACLItem((sourcePortStart == null) ? aclItem.getSourcePortStart() : sourcePortStart, (sourcePortEnd == null) ? aclItem.getSourcePortEnd() : sourcePortEnd, + sourceCidrList, protocol, icmpCode, (icmpType == null) ? aclItem.getIcmpType() : icmpType, action); + + return _networkAclMgr.updateNetworkACLItem(id, protocol, sourceCidrList, trafficType, action, number, sourcePortStart, + sourcePortEnd, icmpCode, icmpType); + } + } \ No newline at end of file diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index b98b53f16a03..04a537bc437f 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -2548,11 +2548,11 @@ public List> getCommands() { cmdList.add(UpdateVMAffinityGroupCmd.class); cmdList.add(ListAffinityGroupTypesCmd.class); cmdList.add(ListNetworkIsolationMethodsCmd.class); - cmdList.add(CreateNetworkACLListCmd.class); cmdList.add(DeleteNetworkACLListCmd.class); cmdList.add(ListNetworkACLListsCmd.class); cmdList.add(ReplaceNetworkACLListCmd.class); + cmdList.add(UpdateNetworkACLItemCmd.class); return cmdList; } diff --git a/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java b/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java index ef5478bb1f86..cd1373c68938 100644 --- a/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java +++ b/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java @@ -23,6 +23,7 @@ import javax.ejb.Local; import javax.naming.ConfigurationException; +import com.cloud.network.vpc.NetworkACLItem; import org.apache.cloudstack.api.command.admin.router.UpgradeRouterCmd; import org.springframework.stereotype.Component; @@ -336,14 +337,9 @@ public List deployVirtualRouterInVpc(Vpc vpc, DeployDestination return null; } - /* (non-Javadoc) - * @see com.cloud.network.router.VpcVirtualNetworkApplianceManager#applyNetworkACLs(com.cloud.network.Network, java.util.List, java.util.List) - */ @Override - public boolean applyNetworkACLs(Network network, List rules, - List routers) throws ResourceUnavailableException { - // TODO Auto-generated method stub - return false; + public boolean applyNetworkACLs(Network network, List rules, List routers) throws ResourceUnavailableException { + return false; //To change body of implemented methods use File | Settings | File Templates. } /* (non-Javadoc) diff --git a/server/test/com/cloud/vpc/dao/MockNetworkDaoImpl.java b/server/test/com/cloud/vpc/dao/MockNetworkDaoImpl.java index a4832915f510..4747e702e659 100644 --- a/server/test/com/cloud/vpc/dao/MockNetworkDaoImpl.java +++ b/server/test/com/cloud/vpc/dao/MockNetworkDaoImpl.java @@ -362,4 +362,9 @@ public List listRedundantNetworks() { return null; } + @Override + public List listByAclId(long aclId) { + return null; + } + } From 463edd1a738f441f1bbe76331763a24437d310d7 Mon Sep 17 00:00:00 2001 From: Kishan Kavala Date: Tue, 7 May 2013 11:43:56 +0530 Subject: [PATCH 09/14] CLOUDSTACK-763: Removed unused methods --- api/src/com/cloud/network/vpc/NetworkACL.java | 2 +- .../com/cloud/network/vpc/NetworkACLServiceImpl.java | 8 -------- server/src/com/cloud/network/vpc/NetworkACLVO.java | 11 +---------- 3 files changed, 2 insertions(+), 19 deletions(-) diff --git a/api/src/com/cloud/network/vpc/NetworkACL.java b/api/src/com/cloud/network/vpc/NetworkACL.java index c5a0d6db1dac..8bde7c2142fb 100644 --- a/api/src/com/cloud/network/vpc/NetworkACL.java +++ b/api/src/com/cloud/network/vpc/NetworkACL.java @@ -20,7 +20,7 @@ import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.api.InternalIdentity; -public interface NetworkACL extends InternalIdentity, ControlledEntity{ +public interface NetworkACL extends InternalIdentity{ public static final long DEFAULT_DENY = 1; public static final long DEFAULT_ALLOW = 2; diff --git a/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java b/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java index ae9b8f985ec9..570ba2bc2889 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java +++ b/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java @@ -76,8 +76,6 @@ public class NetworkACLServiceImpl extends ManagerBase implements NetworkACLServ @Inject NetworkACLItemDao _networkACLItemDao; @Inject - List _networkAclElements; - @Inject NetworkModel _networkModel; @Inject NetworkDao _networkDao; @@ -221,9 +219,6 @@ public NetworkACLItem createNetworkACLItem(CreateNetworkACLCmd aclItemCmd){ } _accountMgr.checkAccess(caller, null, true, vpc); - Account aclOwner = _accountMgr.getAccount(vpc.getAccountId()); - _accountMgr.checkAccess(aclOwner, SecurityChecker.AccessType.ModifyEntry, false, acl); - if(aclItemCmd.getNumber() != null){ if(_networkACLItemDao.findByAclAndNumber(aclId, aclItemCmd.getNumber()) != null){ throw new InvalidParameterValueException("ACL item with number "+aclItemCmd.getNumber()+" already exists in ACL: "+acl.getUuid()); @@ -435,9 +430,6 @@ public NetworkACLItem updateNetworkACLItem(Long id, String protocol, List Date: Tue, 7 May 2013 11:45:45 +0530 Subject: [PATCH 10/14] CLOUDSTACK-763: Added API updateNetworkACLItem to update an existing ACL Item --- .../user/network/UpdateNetworkACLItemCmd.java | 173 ++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 api/src/org/apache/cloudstack/api/command/user/network/UpdateNetworkACLItemCmd.java diff --git a/api/src/org/apache/cloudstack/api/command/user/network/UpdateNetworkACLItemCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/UpdateNetworkACLItemCmd.java new file mode 100644 index 000000000000..1ea815ab1fb1 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/network/UpdateNetworkACLItemCmd.java @@ -0,0 +1,173 @@ +// 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 org.apache.cloudstack.api.command.user.network; + +import com.cloud.event.EventTypes; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.vpc.NetworkACLItem; +import com.cloud.user.Account; +import com.cloud.user.UserContext; +import com.cloud.utils.net.NetUtils; +import org.apache.cloudstack.api.*; +import org.apache.cloudstack.api.response.NetworkACLItemResponse; +import org.apache.cloudstack.api.response.NetworkACLResponse; +import org.apache.cloudstack.api.response.NetworkResponse; +import org.apache.log4j.Logger; + +import java.util.ArrayList; +import java.util.List; + +@APICommand(name = "updateNetworkACLItem", description = "Updates ACL Item with specified Id", +responseObject = NetworkACLItemResponse.class) +public class UpdateNetworkACLItemCmd extends BaseAsyncCmd { + public static final Logger s_logger = Logger.getLogger(UpdateNetworkACLItemCmd.class.getName()); + + private static final String s_name = "createnetworkaclresponse"; + + // /////////////////////////////////////////////////// + // ////////////// API parameters ///////////////////// + // /////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = NetworkACLItemResponse.class, + required=true, description="the ID of the network ACL Item") + private Long id; + + @Parameter(name = ApiConstants.PROTOCOL, type = CommandType.STRING, description = + "the protocol for the ACL rule. Valid values are TCP/UDP/ICMP/ALL or valid protocol number") + private String protocol; + + @Parameter(name = ApiConstants.START_PORT, type = CommandType.INTEGER, description = "the starting port of ACL") + private Integer publicStartPort; + + @Parameter(name = ApiConstants.END_PORT, type = CommandType.INTEGER, description = "the ending port of ACL") + private Integer publicEndPort; + + @Parameter(name = ApiConstants.CIDR_LIST, type = CommandType.LIST, collectionType = CommandType.STRING, + description = "the cidr list to allow traffic from/to") + private List cidrlist; + + @Parameter(name = ApiConstants.ICMP_TYPE, type = CommandType.INTEGER, description = "type of the icmp message being sent") + private Integer icmpType; + + @Parameter(name = ApiConstants.ICMP_CODE, type = CommandType.INTEGER, description = "error code for this icmp message") + private Integer icmpCode; + + @Parameter(name=ApiConstants.TRAFFIC_TYPE, type=CommandType.STRING, description="the traffic type for the ACL," + + "can be Ingress or Egress, defaulted to Ingress if not specified") + private String trafficType; + + @Parameter(name=ApiConstants.NUMBER, type=CommandType.INTEGER, description="The network of the vm the ACL will be created for") + private Integer number; + + @Parameter(name=ApiConstants.ACTION, type=CommandType.STRING, description="scl entry action, allow or deny") + private String action; + + // /////////////////////////////////////////////////// + // ///////////////// Accessors /////////////////////// + // /////////////////////////////////////////////////// + + public Long getId() { + return id; + } + + public String getProtocol() { + if(protocol != null){ + return protocol.trim(); + } else + return null; + } + + public List getSourceCidrList() { + return cidrlist; + } + + public NetworkACLItem.TrafficType getTrafficType() { + if (trafficType != null) { + for (NetworkACLItem.TrafficType type : NetworkACLItem.TrafficType.values()) { + if (type.toString().equalsIgnoreCase(trafficType)) { + return type; + } + } + } + return null; + } + + // /////////////////////////////////////////////////// + // ///////////// API Implementation/////////////////// + // /////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + public String getAction() { + return action; + } + + public Integer getNumber() { + return number; + } + + public Integer getSourcePortStart() { + return publicStartPort; + } + + public Integer getSourcePortEnd() { + return publicEndPort; + } + + @Override + public long getEntityOwnerId() { + Account caller = UserContext.current().getCaller(); + return caller.getAccountId(); + } + + @Override + public String getEventType() { + return EventTypes.EVENT_NETWORK_ACL_ITEM_UPDATE; + } + + @Override + public String getEventDescription() { + return "Updating Network ACL Item"; + } + + public Integer getIcmpCode() { + return icmpCode; + } + + public Integer getIcmpType() { + return icmpType; + } + + @Override + public void execute() throws ResourceUnavailableException { + UserContext.current().setEventDetails("Rule Id: " + getId()); + NetworkACLItem aclItem = _networkACLService.updateNetworkACLItem(getId(), getProtocol(), getSourceCidrList(), getTrafficType(), + getAction(), getNumber(), getSourcePortStart(), getSourcePortEnd(), getIcmpCode(), getIcmpType()); + if (aclItem == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update network ACL Item"); + } + NetworkACLItemResponse aclResponse = _responseGenerator.createNetworkACLItemResponse(aclItem); + setResponseObject(aclResponse); + aclResponse.setResponseName(getCommandName()); + } + +} + From e335d8b5b505a34096dc85feb46306a8e9e96135 Mon Sep 17 00:00:00 2001 From: Kishan Kavala Date: Tue, 7 May 2013 19:43:28 +0530 Subject: [PATCH 11/14] CLOUDSTACK-763: Added unit tests and integration test --- .../{firewall => vpc}/NetworkACLService.java | 2 +- .../org/apache/cloudstack/api/BaseCmd.java | 2 +- .../user/network/CreateNetworkACLCmd.java | 4 +- .../cloud/network/vpc/NetworkACLItemVO.java | 2 +- .../cloud/network/vpc/NetworkACLManager.java | 1 - .../network/vpc/NetworkACLManagerImpl.java | 9 +- .../network/vpc/NetworkACLServiceImpl.java | 1 - .../com/cloud/vpc/NetworkACLManagerTest.java | 195 ++++++++++++++++ .../com/cloud/vpc/NetworkACLServiceTest.java | 219 ++++++++++++++++++ 9 files changed, 426 insertions(+), 9 deletions(-) rename api/src/com/cloud/network/{firewall => vpc}/NetworkACLService.java (99%) create mode 100644 server/test/com/cloud/vpc/NetworkACLManagerTest.java create mode 100644 server/test/com/cloud/vpc/NetworkACLServiceTest.java diff --git a/api/src/com/cloud/network/firewall/NetworkACLService.java b/api/src/com/cloud/network/vpc/NetworkACLService.java similarity index 99% rename from api/src/com/cloud/network/firewall/NetworkACLService.java rename to api/src/com/cloud/network/vpc/NetworkACLService.java index cd25da345f68..9fc476f0f4b5 100644 --- a/api/src/com/cloud/network/firewall/NetworkACLService.java +++ b/api/src/com/cloud/network/vpc/NetworkACLService.java @@ -14,7 +14,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package com.cloud.network.firewall; +package com.cloud.network.vpc; import java.util.List; diff --git a/api/src/org/apache/cloudstack/api/BaseCmd.java b/api/src/org/apache/cloudstack/api/BaseCmd.java index 48d18d029fb9..98e5a648ef79 100644 --- a/api/src/org/apache/cloudstack/api/BaseCmd.java +++ b/api/src/org/apache/cloudstack/api/BaseCmd.java @@ -49,7 +49,7 @@ import com.cloud.network.VpcVirtualNetworkApplianceService; import com.cloud.network.as.AutoScaleService; import com.cloud.network.firewall.FirewallService; -import com.cloud.network.firewall.NetworkACLService; +import com.cloud.network.vpc.NetworkACLService; import com.cloud.network.lb.LoadBalancingRulesService; import com.cloud.network.rules.RulesService; import com.cloud.network.security.SecurityGroupService; diff --git a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java index 1ed6445e5962..275fa1866b69 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java @@ -179,7 +179,7 @@ public String getEventDescription() { public Integer getIcmpCode() { if (icmpCode != null) { return icmpCode; - } else if (protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO)) { + } else if (getProtocol().equalsIgnoreCase(NetUtils.ICMP_PROTO)) { return -1; } return null; @@ -188,7 +188,7 @@ public Integer getIcmpCode() { public Integer getIcmpType() { if (icmpType != null) { return icmpType; - } else if (protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO)) { + } else if (getProtocol().equalsIgnoreCase(NetUtils.ICMP_PROTO)) { return -1; } diff --git a/server/src/com/cloud/network/vpc/NetworkACLItemVO.java b/server/src/com/cloud/network/vpc/NetworkACLItemVO.java index 74d0445755a6..46f84c9f617a 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLItemVO.java +++ b/server/src/com/cloud/network/vpc/NetworkACLItemVO.java @@ -74,7 +74,7 @@ public class NetworkACLItemVO implements NetworkACLItem { @Enumerated(value=EnumType.STRING) Action action; - protected NetworkACLItemVO() { + public NetworkACLItemVO() { this.uuid = UUID.randomUUID().toString(); } diff --git a/server/src/com/cloud/network/vpc/NetworkACLManager.java b/server/src/com/cloud/network/vpc/NetworkACLManager.java index fc2b1a88591d..58c26e3c607c 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLManager.java +++ b/server/src/com/cloud/network/vpc/NetworkACLManager.java @@ -20,7 +20,6 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.dao.NetworkVO; -import com.cloud.network.firewall.NetworkACLService; import com.cloud.network.rules.FirewallRule; import com.cloud.user.Account; import com.cloud.utils.db.DB; diff --git a/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java b/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java index 28f5af27bb8c..430e55d04f58 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java +++ b/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java @@ -71,8 +71,7 @@ public class NetworkACLManagerImpl extends ManagerBase implements NetworkACLMana @Override public NetworkACL createNetworkACL(String name, String description, long vpcId) { NetworkACLVO acl = new NetworkACLVO(name, description, vpcId); - _networkACLDao.persist(acl); - return acl; + return _networkACLDao.persist(acl); } @Override @@ -195,6 +194,9 @@ private void revokeRule(NetworkACLItemVO rule) { @Override public boolean revokeACLItemsForNetwork(long networkId, long userId, Account caller) throws ResourceUnavailableException { Network network = _networkDao.findById(networkId); + if(network.getNetworkACLId() == null){ + return true; + } List aclItems = _networkACLItemDao.listByACL(network.getNetworkACLId()); if (aclItems.isEmpty()) { s_logger.debug("Found no network ACL Items for network id=" + networkId); @@ -236,6 +238,9 @@ private void removeRule(NetworkACLItem rule) { @Override public boolean applyACLToNetwork(long networkId) throws ResourceUnavailableException { Network network = _networkDao.findById(networkId); + if(network.getNetworkACLId() == null){ + return true; + } List rules = _networkACLItemDao.listByACL(network.getNetworkACLId()); return applyACLItemsToNetwork(networkId, rules); } diff --git a/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java b/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java index 570ba2bc2889..94be0c702a01 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java +++ b/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java @@ -24,7 +24,6 @@ import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkVO; import com.cloud.network.element.NetworkACLServiceProvider; -import com.cloud.network.firewall.NetworkACLService; import com.cloud.network.vpc.dao.NetworkACLDao; import com.cloud.projects.Project.ListProjectResourcesCriteria; import com.cloud.server.ResourceTag.TaggedResourceType; diff --git a/server/test/com/cloud/vpc/NetworkACLManagerTest.java b/server/test/com/cloud/vpc/NetworkACLManagerTest.java new file mode 100644 index 000000000000..dc53b2b6372b --- /dev/null +++ b/server/test/com/cloud/vpc/NetworkACLManagerTest.java @@ -0,0 +1,195 @@ +// 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.vpc; + +import com.cloud.network.Network; +import com.cloud.network.NetworkManager; +import com.cloud.network.NetworkModel; +import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.NetworkVO; +import com.cloud.network.element.NetworkACLServiceProvider; +import com.cloud.network.vpc.NetworkACLItem; +import com.cloud.network.vpc.NetworkACLItemDao; +import com.cloud.network.vpc.NetworkACLItemVO; +import com.cloud.network.vpc.NetworkACLManager; +import com.cloud.network.vpc.NetworkACLManagerImpl; +import com.cloud.network.vpc.NetworkACLVO; +import com.cloud.network.vpc.VpcManager; +import com.cloud.network.vpc.dao.NetworkACLDao; +import com.cloud.tags.dao.ResourceTagDao; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; +import com.cloud.user.AccountVO; +import com.cloud.user.UserContext; +import com.cloud.utils.component.ComponentContext; +import com.cloud.utils.exception.CloudRuntimeException; +import junit.framework.TestCase; +import org.apache.cloudstack.test.utils.SpringUtils; +import org.apache.log4j.Logger; +import org.junit.Before; +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.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 javax.inject.Inject; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(loader = AnnotationConfigContextLoader.class) +public class NetworkACLManagerTest extends TestCase{ + @Inject + NetworkACLManager _aclMgr; + + @Inject + AccountManager _accountMgr; + @Inject + VpcManager _vpcMgr; + @Inject + NetworkACLDao _networkACLDao; + @Inject + NetworkACLItemDao _networkACLItemDao; + @Inject + NetworkDao _networkDao; + @Inject + NetworkModel _networkModel; + @Inject + List _networkAclElements; + + private NetworkACLVO acl; + private NetworkACLItemVO aclItem; + + private static final Logger s_logger = Logger.getLogger( NetworkACLManagerTest.class); + + @Before + public void setUp() { + ComponentContext.initComponentsLifeCycle(); + Account account = new AccountVO("testaccount", 1, "testdomain", (short) 0, UUID.randomUUID().toString()); + UserContext.registerContext(1, account, null, true); + acl = Mockito.mock(NetworkACLVO.class); + aclItem = Mockito.mock(NetworkACLItemVO.class); + } + + @Test + public void testCreateACL() throws Exception { + Mockito.when(_networkACLDao.persist(Mockito.any(NetworkACLVO.class))).thenReturn(acl); + assertNotNull(_aclMgr.createNetworkACL("acl_new", "acl desc", 1L)); + } + + @Test + public void testApplyACL() throws Exception { + NetworkVO network = Mockito.mock(NetworkVO.class); + Mockito.when(_networkDao.findById(Mockito.anyLong())).thenReturn(network); + Mockito.when(_networkModel.isProviderSupportServiceInNetwork(Mockito.anyLong(), Mockito.any(Network.Service.class), Mockito.any(Network.Provider.class))).thenReturn(true); + Mockito.when(_networkAclElements.get(0).applyNetworkACLs(Mockito.any(Network.class), Mockito.anyList())).thenReturn(true); + assertTrue(_aclMgr.applyACLToNetwork(1L)); + } + + @Test + public void testRevokeACLItem() throws Exception { + Mockito.when(_networkACLItemDao.findById(Mockito.anyLong())).thenReturn(aclItem); + assertTrue(_aclMgr.revokeNetworkACLItem(1L)); + } + + @Test + public void testUpdateACLItem() throws Exception { + Mockito.when(_networkACLItemDao.findById(Mockito.anyLong())).thenReturn(aclItem); + Mockito.when(_networkACLItemDao.update(Mockito.anyLong(), Mockito.any(NetworkACLItemVO.class))).thenReturn(true); + assertNotNull(_aclMgr.updateNetworkACLItem(1L, "UDP", null, NetworkACLItem.TrafficType.Ingress, "Deny", 10, 22, 32, null, null)); + } + + @Test(expected = CloudRuntimeException.class) + public void deleteNonEmptyACL() throws Exception { + List aclItems = new ArrayList(); + aclItems.add(aclItem); + Mockito.when(_networkACLItemDao.listByACL(Mockito.anyLong())).thenReturn(aclItems); + _aclMgr.deleteNetworkACL(acl); + } + + @Configuration + @ComponentScan(basePackageClasses={NetworkACLManagerImpl.class}, + includeFilters={@ComponentScan.Filter(value=NetworkACLTestConfiguration.Library.class, type= FilterType.CUSTOM)}, + useDefaultFilters=false) + public static class NetworkACLTestConfiguration extends SpringUtils.CloudStackTestConfiguration{ + + @Bean + public AccountManager accountManager() { + return Mockito.mock(AccountManager.class); + } + + @Bean + public NetworkManager networkManager() { + return Mockito.mock(NetworkManager.class); + } + + @Bean + public NetworkModel networkModel() { + return Mockito.mock(NetworkModel.class); + } + + @Bean + public VpcManager vpcManager() { + return Mockito.mock(VpcManager.class); + } + + @Bean + public ResourceTagDao resourceTagDao() { + return Mockito.mock(ResourceTagDao.class); + } + + @Bean + public NetworkACLDao networkACLDao() { + return Mockito.mock(NetworkACLDao.class); + } + + @Bean + public NetworkACLItemDao networkACLItemDao() { + return Mockito.mock(NetworkACLItemDao.class); + } + + @Bean + public NetworkDao networkDao() { + return Mockito.mock(NetworkDao.class); + } + + @Bean + public NetworkACLServiceProvider networkElements() { + return Mockito.mock(NetworkACLServiceProvider.class); + } + + public static class Library implements TypeFilter { + @Override + public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException { + mdr.getClassMetadata().getClassName(); + ComponentScan cs = NetworkACLTestConfiguration.class.getAnnotation(ComponentScan.class); + return SpringUtils.includedInBasePackageClasses(mdr.getClassMetadata().getClassName(), cs); + } + } + } + +} diff --git a/server/test/com/cloud/vpc/NetworkACLServiceTest.java b/server/test/com/cloud/vpc/NetworkACLServiceTest.java new file mode 100644 index 000000000000..145efb47275d --- /dev/null +++ b/server/test/com/cloud/vpc/NetworkACLServiceTest.java @@ -0,0 +1,219 @@ +// 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.vpc; + +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.network.NetworkManager; +import com.cloud.network.NetworkModel; +import com.cloud.network.dao.NetworkDao; +import com.cloud.network.vpc.*; +import com.cloud.network.vpc.dao.NetworkACLDao; +import com.cloud.tags.dao.ResourceTagDao; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; +import com.cloud.user.AccountVO; +import com.cloud.user.UserContext; +import com.cloud.utils.component.ComponentContext; +import junit.framework.TestCase; +import org.apache.cloudstack.api.command.user.network.CreateNetworkACLCmd; +import org.apache.cloudstack.test.utils.SpringUtils; +import org.apache.log4j.Logger; +import org.junit.Before; +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.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 javax.inject.Inject; +import java.io.IOException; +import java.util.UUID; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(loader = AnnotationConfigContextLoader.class) +public class NetworkACLServiceTest extends TestCase{ + @Inject + NetworkACLService _aclService; + + @Inject + AccountManager _accountMgr; + @Inject + VpcManager _vpcMgr; + @Inject + NetworkACLManager _networkAclMgr; + @Inject + NetworkACLDao _networkACLDao; + @Inject + NetworkACLItemDao _networkACLItemDao; + + private CreateNetworkACLCmd createACLItemCmd; + private NetworkACLVO acl; + private NetworkACLItemVO aclItem; + + private static final Logger s_logger = Logger.getLogger( NetworkACLServiceTest.class); + + @Before + public void setUp() { + ComponentContext.initComponentsLifeCycle(); + Account account = new AccountVO("testaccount", 1, "testdomain", (short) 0, UUID.randomUUID().toString()); + UserContext.registerContext(1, account, null, true); + + createACLItemCmd = new CreateNetworkACLCmd(){ + @Override + public Long getACLId(){ + return 1L; + } + + @Override + public Integer getNumber(){ + return 1; + } + + @Override + public String getProtocol(){ + return "TCP"; + } + }; + + acl = new NetworkACLVO(){ + @Override + public Long getVpcId(){ + return 1L; + } + + @Override + public long getId(){ + return 1L; + } + + }; + + aclItem = new NetworkACLItemVO(){ + @Override + public long getAclId(){ + return 4L; + } + }; + } + + @Test + public void testCreateACL() throws Exception { + Mockito.when(_vpcMgr.getVpc(Mockito.anyLong())).thenReturn(new VpcVO()); + Mockito.when(_networkAclMgr.createNetworkACL("acl_new", "acl desc", 1L)).thenReturn(acl); + assertNotNull(_aclService.createNetworkACL("acl_new", "acl desc", 1L)); + } + + @Test(expected = InvalidParameterValueException.class) + public void testDeleteDefaultACL() throws Exception { + Mockito.when(_networkACLDao.findById(Mockito.anyLong())).thenReturn(acl); + Mockito.when(_networkAclMgr.deleteNetworkACL(acl)).thenReturn(true); + _aclService.deleteNetworkACL(1L); + } + + @Test + public void testCreateACLItem() throws Exception { + Mockito.when(_vpcMgr.getVpc(Mockito.anyLong())).thenReturn(new VpcVO()); + Mockito.when(_networkAclMgr.getNetworkACL(Mockito.anyLong())).thenReturn(acl); + Mockito.when(_networkAclMgr.createNetworkACLItem(Mockito.anyInt(), Mockito.anyInt(), Mockito.anyString(), Mockito.anyList(), Mockito.anyInt(), Mockito.anyInt(), + Mockito.any(NetworkACLItem.TrafficType.class), Mockito.anyLong(), Mockito.anyString(), Mockito.anyInt())).thenReturn(new NetworkACLItemVO()); + assertNotNull(_aclService.createNetworkACLItem(createACLItemCmd)); + } + + @Test(expected = InvalidParameterValueException.class) + public void testCreateACLItemDuplicateNumber() throws Exception { + Mockito.when(_vpcMgr.getVpc(Mockito.anyLong())).thenReturn(new VpcVO()); + Mockito.when(_networkAclMgr.getNetworkACL(Mockito.anyLong())).thenReturn(acl); + Mockito.when(_networkACLItemDao.findByAclAndNumber(Mockito.anyLong(), Mockito.anyInt())).thenReturn(new NetworkACLItemVO()); + _aclService.createNetworkACLItem(createACLItemCmd); + } + + @Test + public void testDeleteACLItem() throws Exception { + Mockito.when(_networkACLItemDao.findById(Mockito.anyLong())).thenReturn(aclItem); + Mockito.when(_networkAclMgr.revokeNetworkACLItem(Mockito.anyLong())).thenReturn(true); + assertTrue(_aclService.revokeNetworkACLItem(1L)); + } + + @Configuration + @ComponentScan(basePackageClasses={NetworkACLServiceImpl.class}, + includeFilters={@ComponentScan.Filter(value=NetworkACLTestConfiguration.Library.class, type= FilterType.CUSTOM)}, + useDefaultFilters=false) + public static class NetworkACLTestConfiguration extends SpringUtils.CloudStackTestConfiguration{ + + @Bean + public AccountManager accountManager() { + return Mockito.mock(AccountManager.class); + } + + @Bean + public NetworkManager networkManager() { + return Mockito.mock(NetworkManager.class); + } + + @Bean + public NetworkModel networkModel() { + return Mockito.mock(NetworkModel.class); + } + + @Bean + public VpcManager vpcManager() { + return Mockito.mock(VpcManager.class); + } + + @Bean + public ResourceTagDao resourceTagDao() { + return Mockito.mock(ResourceTagDao.class); + } + + @Bean + public NetworkACLDao networkACLDao() { + return Mockito.mock(NetworkACLDao.class); + } + + @Bean + public NetworkACLItemDao networkACLItemDao() { + return Mockito.mock(NetworkACLItemDao.class); + } + + @Bean + public NetworkDao networkDao() { + return Mockito.mock(NetworkDao.class); + } + + @Bean + public NetworkACLManager networkACLManager() { + return Mockito.mock(NetworkACLManager.class); + } + + public static class Library implements TypeFilter { + @Override + public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException { + mdr.getClassMetadata().getClassName(); + ComponentScan cs = NetworkACLTestConfiguration.class.getAnnotation(ComponentScan.class); + return SpringUtils.includedInBasePackageClasses(mdr.getClassMetadata().getClassName(), cs); + } + } + } + +} From fa2a2d9052ad1f1d7cf9fcc3cdc8abed760224c6 Mon Sep 17 00:00:00 2001 From: Kishan Kavala Date: Tue, 7 May 2013 19:44:02 +0530 Subject: [PATCH 12/14] CLOUDSTACK-763: Added unit tests and integration test --- test/integration/smoke/test_network_acl.py | 119 +++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 test/integration/smoke/test_network_acl.py diff --git a/test/integration/smoke/test_network_acl.py b/test/integration/smoke/test_network_acl.py new file mode 100644 index 000000000000..300fff92f30b --- /dev/null +++ b/test/integration/smoke/test_network_acl.py @@ -0,0 +1,119 @@ +# 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. +""" Tests for Network ACLs in VPC +""" +#Import Local Modules +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * + + +class TestNetworkACL(cloudstackTestCase): + networkOfferingId = 11 + networkId = None + vmId = None + vpcId = None + aclId = None + + zoneId = 1 + serviceOfferingId = 1 + templateId = 5 + + def setUp(self): + self.apiClient = self.testClient.getApiClient() + + + + def test_networkAcl(self): + + # 1) Create VPC + self.createVPC() + + # 2) Create ACl + self.createACL() + + # 3) Create ACl Item + self.createACLItem() + + # 4) Create network with ACL + self.createNetwork() + + # 5) Deploy a vm + self.deployVm() + + def createACL(self): + createAclCmd = createNetworkACLList.createNetworkACLListCmd() + createAclCmd.name = "acl1" + createAclCmd.description = "new acl" + createAclCmd.vpcId = TestNetworkACL.vpcId + createAclResponse = self.apiClient.createNetworkACLList(createAclCmd) + TestNetworkACL.aclId = createAclResponse.id + + def createACLItem(self): + createAclItemCmd = createNetworkACL.createNetworkACLCmd() + createAclItemCmd.cidr = "0.0.0.0/0" + createAclItemCmd.protocol = "TCP" + createAclItemCmd.number = "10" + createAclItemCmd.action = "Deny" + createAclItemCmd.aclId = TestNetworkACL.aclId + createAclItemResponse = self.apiClient.createNetworkACL(createAclItemCmd) + self.assertIsNotNone(createAclItemResponse.id, "Network failed to aclItem") + + def createVPC(self): + createVPCCmd = createVPC.createVPCCmd() + createVPCCmd.name = "new vpc" + createVPCCmd.cidr = "10.1.1.0/24" + createVPCCmd.displaytext = "new vpc" + createVPCCmd.vpcofferingid = 1 + createVPCCmd.zoneid = self.zoneId + createVPCResponse = self.apiClient.createVPC(createVPCCmd) + TestNetworkACL.vpcId = createVPCResponse.id + + + def createNetwork(self): + createNetworkCmd = createNetwork.createNetworkCmd() + createNetworkCmd.name = "vpc network" + createNetworkCmd.displaytext = "vpc network" + createNetworkCmd.netmask = "255.255.255.0" + createNetworkCmd.gateway = "10.1.1.1" + createNetworkCmd.zoneid = self.zoneId + createNetworkCmd.vpcid = TestNetworkACL.vpcId + createNetworkCmd.networkofferingid = TestNetworkACL.networkOfferingId + createNetworkCmd.aclId = TestNetworkACL.aclId + createNetworkResponse = self.apiClient.createNetwork(createNetworkCmd) + TestNetworkACL.networkId = createNetworkResponse.id + + self.assertIsNotNone(createNetworkResponse.id, "Network failed to create") + + def deployVm(self): + deployVirtualMachineCmd = deployVirtualMachine.deployVirtualMachineCmd() + deployVirtualMachineCmd.networkids = TestNetworkACL.networkId + deployVirtualMachineCmd.serviceofferingid = TestNetworkACL.serviceOfferingId + deployVirtualMachineCmd.zoneid = TestNetworkACL.zoneId + deployVirtualMachineCmd.templateid = TestNetworkACL.templateId + deployVirtualMachineCmd.hypervisor = "XenServer" + deployVMResponse = self.apiClient.deployVirtualMachine(deployVirtualMachineCmd) + TestNetworkACL.vmId = deployVMResponse.id + + def tearDown(self): + #destroy the vm + if TestNetworkACL.vmId is not None: + destroyVirtualMachineCmd = destroyVirtualMachine.destroyVirtualMachineCmd() + destroyVirtualMachineCmd.id = TestNetworkACL.vmId + destroyVirtualMachineResponse = self.apiClient.destroyVirtualMachine(destroyVirtualMachineCmd) From 0396ef9c235031e09a661dcfe7cf075945a1362e Mon Sep 17 00:00:00 2001 From: Kishan Kavala Date: Tue, 7 May 2013 20:10:28 +0530 Subject: [PATCH 13/14] CLOUDSTACK-763: Added comments and removed unused imports --- .../cloud/network/vpc/NetworkACLService.java | 31 +++++++++------- .../cloud/upgrade/dao/Upgrade410to420.java | 11 ++++-- .../cloud/network/vpc/NetworkACLManager.java | 35 +++++++++++++++---- .../network/vpc/NetworkACLManagerImpl.java | 7 ++-- .../network/vpc/NetworkACLServiceImpl.java | 5 +-- setup/db/db/schema-410to420.sql | 2 ++ 6 files changed, 65 insertions(+), 26 deletions(-) diff --git a/api/src/com/cloud/network/vpc/NetworkACLService.java b/api/src/com/cloud/network/vpc/NetworkACLService.java index 9fc476f0f4b5..0258333f1fe8 100644 --- a/api/src/com/cloud/network/vpc/NetworkACLService.java +++ b/api/src/com/cloud/network/vpc/NetworkACLService.java @@ -17,19 +17,12 @@ package com.cloud.network.vpc; -import java.util.List; - -import com.cloud.network.vpc.NetworkACL; -import com.cloud.network.vpc.NetworkACLItem; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.utils.Pair; import org.apache.cloudstack.api.command.user.network.CreateNetworkACLCmd; -import org.apache.cloudstack.api.command.user.network.CreateNetworkACLListCmd; -import org.apache.cloudstack.api.command.user.network.ListNetworkACLListsCmd; import org.apache.cloudstack.api.command.user.network.ListNetworkACLsCmd; -import com.cloud.exception.NetworkRuleConflictException; -import com.cloud.exception.ResourceUnavailableException; -import com.cloud.user.Account; -import com.cloud.utils.Pair; +import java.util.List; public interface NetworkACLService { /** @@ -49,7 +42,7 @@ public interface NetworkACLService { NetworkACL getNetworkACL(long id); /** - * List NeetworkACLs by Id/Name/Network or Vpc it belongs to + * List NetworkACLs by Id/Name/Network or Vpc it belongs to * @param id * @param name * @param networkId @@ -111,7 +104,21 @@ public interface NetworkACLService { */ boolean revokeNetworkACLItem(long ruleId); - + /** + * Updates existing aclItem applies to associated networks + * @param id + * @param protocol + * @param sourceCidrList + * @param trafficType + * @param action + * @param number + * @param sourcePortStart + * @param sourcePortEnd + * @param icmpCode + * @param icmpType + * @return + * @throws ResourceUnavailableException + */ NetworkACLItem updateNetworkACLItem(Long id, String protocol, List sourceCidrList, NetworkACLItem.TrafficType trafficType, String action, Integer number, Integer sourcePortStart, Integer sourcePortEnd, Integer icmpCode, Integer icmpType) throws ResourceUnavailableException; diff --git a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java index 180c7492a11f..ac681ced1664 100644 --- a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java +++ b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java @@ -404,15 +404,20 @@ private void updateNetworkACLs(Connection conn) { //Fetch all VPC Tiers //For each tier create a network ACL and move all the acl_items to network_acl_item table // If there are no acl_items for a tier, associate it with default ACL + s_logger.debug("Updating network ACLs"); + PreparedStatement pstmt = null; PreparedStatement pstmtDelete = null; ResultSet rs = null; ResultSet rsAcls = null; ResultSet rsCidr = null; - //1,2 are default acl Ids, start Ids from 3 + + //1,2 are default acl Ids, start acl Ids from 3 long nextAclId = 3; + try { + //Get all VPC tiers pstmt = conn.prepareStatement("SELECT id, vpc_id, uuid FROM `cloud`.`networks` where vpc_id is not null and removed is null"); rs = pstmt.executeQuery(); while (rs.next()) { @@ -430,7 +435,7 @@ private void updateNetworkACLs(Connection conn) { if(!hasAcls){ hasAcls = true; aclId = nextAclId++; - //create ACL + //create ACL for the tier s_logger.debug("Creating network ACL for tier: "+tierUuid); pstmt = conn.prepareStatement("INSERT INTO `cloud`.`network_acl` (id, uuid, vpc_id, description, name) values (?, UUID(), ? , ?, ?)"); pstmt.setLong(1, aclId); @@ -442,7 +447,7 @@ private void updateNetworkACLs(Connection conn) { Long fwRuleId = rsAcls.getLong(1); String cidr = null; - //get cidr + //get cidr from firewall_rules_cidrs pstmt = conn.prepareStatement("SELECT id, source_cidr FROM `cloud`.`firewall_rules_cidrs` where firewall_rule_id = ?"); pstmt.setLong(1, fwRuleId); rsCidr = pstmt.executeQuery(); diff --git a/server/src/com/cloud/network/vpc/NetworkACLManager.java b/server/src/com/cloud/network/vpc/NetworkACLManager.java index 58c26e3c607c..0ff3e8807552 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLManager.java +++ b/server/src/com/cloud/network/vpc/NetworkACLManager.java @@ -16,14 +16,11 @@ // under the License. package com.cloud.network.vpc; -import java.util.List; - import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.dao.NetworkVO; -import com.cloud.network.rules.FirewallRule; import com.cloud.user.Account; -import com.cloud.utils.db.DB; -import org.apache.cloudstack.api.command.user.network.CreateNetworkACLListCmd; + +import java.util.List; public interface NetworkACLManager{ @@ -108,11 +105,37 @@ NetworkACLItem createNetworkACLItem(Integer sourcePortStart, Integer sourcePortE * @throws ResourceUnavailableException */ boolean revokeACLItemsForNetwork(long networkId, long userId, Account caller) throws ResourceUnavailableException; - + + /** + * List network ACL items by network + * @param guestNtwkId + * @return + */ List listNetworkACLItems(long guestNtwkId); + /** + * Applies asscociated ACL to specified network + * @param networkId + * @return + * @throws ResourceUnavailableException + */ boolean applyACLToNetwork(long networkId) throws ResourceUnavailableException; + /** + * Updates and existing network ACL Item + * @param id + * @param protocol + * @param sourceCidrList + * @param trafficType + * @param action + * @param number + * @param sourcePortStart + * @param sourcePortEnd + * @param icmpCode + * @param icmpType + * @return + * @throws ResourceUnavailableException + */ NetworkACLItem updateNetworkACLItem(Long id, String protocol, List sourceCidrList, NetworkACLItem.TrafficType trafficType, String action, Integer number, Integer sourcePortStart, Integer sourcePortEnd, Integer icmpCode, Integer icmpType) throws ResourceUnavailableException; diff --git a/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java b/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java index 430e55d04f58..71d6da4c148d 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java +++ b/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java @@ -18,7 +18,6 @@ import com.cloud.event.ActionEvent; import com.cloud.event.EventTypes; -import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Network; import com.cloud.network.Network.Service; @@ -78,7 +77,7 @@ public NetworkACL createNetworkACL(String name, String description, long vpcId) public boolean applyNetworkACL(long aclId) throws ResourceUnavailableException { boolean handled = true; List rules = _networkACLItemDao.listByACL(aclId); - //Find all networks using this ACL + //Find all networks using this ACL and apply the ACL List networks = _networkDao.listByAclId(aclId); for(NetworkVO network : networks){ if(!applyACLItemsToNetwork(network.getId(), rules)) { @@ -117,7 +116,9 @@ public boolean deleteNetworkACL(NetworkACL acl) { @Override public boolean replaceNetworkACL(NetworkACL acl, NetworkVO network) throws ResourceUnavailableException { network.setNetworkACLId(acl.getId()); + //Update Network ACL if(_networkDao.update(network.getId(), network)){ + //Apply ACL to network return applyACLToNetwork(network.getId()); } return false; @@ -133,7 +134,7 @@ public NetworkACLItem createNetworkACLItem(Integer portStart, Integer portEnd, S if("deny".equalsIgnoreCase(action)){ ruleAction = NetworkACLItem.Action.Deny; } - // If number is null, set it to currentMax + 1 + // If number is null, set it to currentMax + 1 (for backward compatibility) if(number == null){ number = _networkACLItemDao.getMaxNumberByACL(aclId) + 1; } diff --git a/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java b/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java index 94be0c702a01..7c50d907b17e 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java +++ b/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java @@ -23,7 +23,6 @@ import com.cloud.network.Networks; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkVO; -import com.cloud.network.element.NetworkACLServiceProvider; import com.cloud.network.vpc.dao.NetworkACLDao; import com.cloud.projects.Project.ListProjectResourcesCriteria; import com.cloud.server.ResourceTag.TaggedResourceType; @@ -41,7 +40,6 @@ import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.net.NetUtils; -import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.command.user.network.CreateNetworkACLCmd; @@ -140,6 +138,7 @@ public boolean deleteNetworkACL(long id) { throw new InvalidParameterValueException("Unable to find specified ACL"); } + //Do not allow deletion of default ACLs if(acl.getId() == NetworkACL.DEFAULT_ALLOW || acl.getId() == NetworkACL.DEFAULT_DENY){ throw new InvalidParameterValueException("Default ACL cannot be removed"); } @@ -218,6 +217,7 @@ public NetworkACLItem createNetworkACLItem(CreateNetworkACLCmd aclItemCmd){ } _accountMgr.checkAccess(caller, null, true, vpc); + //Ensure that number is unique within the ACL if(aclItemCmd.getNumber() != null){ if(_networkACLItemDao.findByAclAndNumber(aclId, aclItemCmd.getNumber()) != null){ throw new InvalidParameterValueException("ACL item with number "+aclItemCmd.getNumber()+" already exists in ACL: "+acl.getUuid()); @@ -293,6 +293,7 @@ private void validateNetworkACLItem(Integer portStart, Integer portEnd, List Date: Tue, 7 May 2013 13:02:29 -0700 Subject: [PATCH 14/14] CLOUDSTACK-2364: fixed private gateway creation in VPC - the vnet for the private gateway network is not stored in data_center_vnet table --- .../com/cloud/network/NetworkManagerImpl.java | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 7d349fd38456..73ec16016c31 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -2005,23 +2005,28 @@ public Network createGuestNetwork(long networkOfferingId, String name, String di if (_networksDao.countByZoneAndUri(zoneId, uri) > 0) { throw new InvalidParameterValueException("Network with vlan " + vlanId + " already exists in zone " + zoneId); } else { - DataCenterVnetVO dcVnet = _datacenterVnetDao.findVnet(zoneId, vlanId.toString()).get(0); - // Fail network creation if specified vlan is dedicated to a different account - if (dcVnet.getAccountGuestVlanMapId() != null) { - Long accountGuestVlanMapId = dcVnet.getAccountGuestVlanMapId(); - AccountGuestVlanMapVO map = _accountGuestVlanMapDao.findById(accountGuestVlanMapId); - if (map.getAccountId() != owner.getAccountId()) { - throw new InvalidParameterValueException("Vlan " + vlanId + " is dedicated to a different account"); - } - // Fail network creation if owner has a dedicated range of vlans but the specified vlan belongs to the system pool - } else { - List maps = _accountGuestVlanMapDao.listAccountGuestVlanMapsByAccount(owner.getAccountId()); - if (maps != null && !maps.isEmpty()) { - int vnetsAllocatedToAccount = _datacenterVnetDao.countVnetsAllocatedToAccount(zoneId, owner.getAccountId()); - int vnetsDedicatedToAccount = _datacenterVnetDao.countVnetsDedicatedToAccount(zoneId, owner.getAccountId()); - if (vnetsAllocatedToAccount < vnetsDedicatedToAccount) { - throw new InvalidParameterValueException("Specified vlan " + vlanId + " doesn't belong" + - " to the vlan range dedicated to the owner "+ owner.getAccountName()); + List dcVnets = _datacenterVnetDao.findVnet(zoneId, vlanId.toString()); + //for the network that is created as part of private gateway, + //the vnet is not coming from the data center vnet table, so the list can be empty + if (!dcVnets.isEmpty()) { + DataCenterVnetVO dcVnet = dcVnets.get(0); + // Fail network creation if specified vlan is dedicated to a different account + if (dcVnet.getAccountGuestVlanMapId() != null) { + Long accountGuestVlanMapId = dcVnet.getAccountGuestVlanMapId(); + AccountGuestVlanMapVO map = _accountGuestVlanMapDao.findById(accountGuestVlanMapId); + if (map.getAccountId() != owner.getAccountId()) { + throw new InvalidParameterValueException("Vlan " + vlanId + " is dedicated to a different account"); + } + // Fail network creation if owner has a dedicated range of vlans but the specified vlan belongs to the system pool + } else { + List maps = _accountGuestVlanMapDao.listAccountGuestVlanMapsByAccount(owner.getAccountId()); + if (maps != null && !maps.isEmpty()) { + int vnetsAllocatedToAccount = _datacenterVnetDao.countVnetsAllocatedToAccount(zoneId, owner.getAccountId()); + int vnetsDedicatedToAccount = _datacenterVnetDao.countVnetsDedicatedToAccount(zoneId, owner.getAccountId()); + if (vnetsAllocatedToAccount < vnetsDedicatedToAccount) { + throw new InvalidParameterValueException("Specified vlan " + vlanId + " doesn't belong" + + " to the vlan range dedicated to the owner "+ owner.getAccountName()); + } } } }