| // 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 java.util.ArrayList; |
| import java.util.List; |
| import java.util.Map; |
| |
| import javax.inject.Inject; |
| |
| 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.ListNetworkACLListsCmd; |
| import org.apache.cloudstack.api.command.user.network.ListNetworkACLsCmd; |
| import org.apache.cloudstack.context.CallContext; |
| import org.apache.commons.lang.StringUtils; |
| import org.apache.log4j.Logger; |
| import org.springframework.stereotype.Component; |
| |
| 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.NetworkModel; |
| import com.cloud.network.Networks; |
| import com.cloud.network.dao.NetworkDao; |
| import com.cloud.network.dao.NetworkVO; |
| import com.cloud.network.vpc.dao.NetworkACLDao; |
| import com.cloud.network.vpc.dao.VpcDao; |
| import com.cloud.network.vpc.dao.VpcGatewayDao; |
| import com.cloud.projects.Project.ListProjectResourcesCriteria; |
| import com.cloud.server.ResourceTag.ResourceObjectType; |
| import com.cloud.tags.ResourceTagVO; |
| import com.cloud.tags.dao.ResourceTagDao; |
| import com.cloud.user.Account; |
| import com.cloud.user.AccountManager; |
| import com.cloud.utils.Pair; |
| import com.cloud.utils.Ternary; |
| import com.cloud.utils.component.ManagerBase; |
| import com.cloud.utils.db.EntityManager; |
| 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.exception.CloudRuntimeException; |
| import com.cloud.utils.net.NetUtils; |
| |
| @Component |
| public class NetworkACLServiceImpl extends ManagerBase implements NetworkACLService { |
| private static final Logger s_logger = Logger.getLogger(NetworkACLServiceImpl.class); |
| |
| @Inject |
| AccountManager _accountMgr; |
| @Inject |
| NetworkModel _networkMgr; |
| @Inject |
| ResourceTagDao _resourceTagDao; |
| @Inject |
| NetworkACLDao _networkACLDao; |
| @Inject |
| NetworkACLItemDao _networkACLItemDao; |
| @Inject |
| NetworkModel _networkModel; |
| @Inject |
| NetworkDao _networkDao; |
| @Inject |
| NetworkACLManager _networkAclMgr; |
| @Inject |
| VpcGatewayDao _vpcGatewayDao; |
| @Inject |
| VpcManager _vpcMgr; |
| @Inject |
| EntityManager _entityMgr; |
| @Inject |
| VpcDao _vpcDao; |
| @Inject |
| VpcService _vpcSvc; |
| |
| @Override |
| public NetworkACL createNetworkACL(final String name, final String description, final long vpcId, final Boolean forDisplay) { |
| final Account caller = CallContext.current().getCallingAccount(); |
| final Vpc vpc = _entityMgr.findById(Vpc.class, vpcId); |
| if (vpc == null) { |
| throw new InvalidParameterValueException("Unable to find VPC"); |
| } |
| _accountMgr.checkAccess(caller, null, true, vpc); |
| return _networkAclMgr.createNetworkACL(name, description, vpcId, forDisplay); |
| } |
| |
| @Override |
| @ActionEvent(eventType = EventTypes.EVENT_NETWORK_ACL_CREATE, eventDescription = "creating network acl list", async = true) |
| public NetworkACL getNetworkACL(final long id) { |
| return _networkAclMgr.getNetworkACL(id); |
| } |
| |
| @Override |
| public Pair<List<? extends NetworkACL>, Integer> listNetworkACLs(final ListNetworkACLListsCmd cmd) { |
| final Long id = cmd.getId(); |
| final String name = cmd.getName(); |
| final Long networkId = cmd.getNetworkId(); |
| final Long vpcId = cmd.getVpcId(); |
| final String keyword = cmd.getKeyword(); |
| final Boolean display = cmd.getDisplay(); |
| |
| final SearchBuilder<NetworkACLVO> 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.IN); |
| sb.and("display", sb.entity().isDisplay(), Op.EQ); |
| |
| final Account caller = CallContext.current().getCallingAccount(); |
| |
| if (networkId != null) { |
| final SearchBuilder<NetworkVO> network = _networkDao.createSearchBuilder(); |
| network.and("networkId", network.entity().getId(), Op.EQ); |
| sb.join("networkJoin", network, sb.entity().getId(), network.entity().getNetworkACLId(), JoinBuilder.JoinType.INNER); |
| } |
| |
| final SearchCriteria<NetworkACLVO> sc = sb.create(); |
| |
| if (keyword != null) { |
| final SearchCriteria<NetworkACLVO> ssc = _networkACLDao.createSearchCriteria(); |
| ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%"); |
| ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%"); |
| sc.addAnd("name", SearchCriteria.Op.SC, ssc); |
| } |
| |
| if (display != null) { |
| sc.setParameters("display", display); |
| } |
| |
| if(id != null){ |
| sc.setParameters("id", id); |
| } |
| |
| if (name != null) { |
| sc.setParameters("name", name); |
| } |
| |
| if (vpcId != null) { |
| final Vpc vpc = _entityMgr.findById(Vpc.class, vpcId); |
| if (vpc == null) { |
| throw new InvalidParameterValueException("Unable to find VPC"); |
| } |
| _accountMgr.checkAccess(caller, null, true, vpc); |
| //Include vpcId 0 to list default ACLs |
| sc.setParameters("vpcId", vpcId, 0); |
| } else { |
| //ToDo: Add accountId to network_acl table for permission check |
| |
| // VpcId is not specified. Find permitted VPCs for the caller |
| // and list ACLs belonging to the permitted VPCs |
| final List<Long> permittedAccounts = new ArrayList<Long>(); |
| Long domainId = cmd.getDomainId(); |
| boolean isRecursive = cmd.isRecursive(); |
| final String accountName = cmd.getAccountName(); |
| final Long projectId = cmd.getProjectId(); |
| final boolean listAll = cmd.listAll(); |
| final Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, |
| ListProjectResourcesCriteria>(domainId, isRecursive, null); |
| _accountMgr.buildACLSearchParameters(caller, id, accountName, projectId, permittedAccounts, domainIdRecursiveListProject, |
| listAll, false); |
| domainId = domainIdRecursiveListProject.first(); |
| isRecursive = domainIdRecursiveListProject.second(); |
| final ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); |
| final SearchBuilder<VpcVO> sbVpc = _vpcDao.createSearchBuilder(); |
| _accountMgr.buildACLSearchBuilder(sbVpc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); |
| final SearchCriteria<VpcVO> scVpc = sbVpc.create(); |
| _accountMgr.buildACLSearchCriteria(scVpc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); |
| final List<VpcVO> vpcs = _vpcDao.search(scVpc, null); |
| final List<Long> vpcIds = new ArrayList<Long>(); |
| for (final VpcVO vpc : vpcs) { |
| vpcIds.add(vpc.getId()); |
| } |
| //Add vpc_id 0 to list default ACLs |
| vpcIds.add(0L); |
| sc.setParameters("vpcId", vpcIds.toArray()); |
| } |
| |
| if (networkId != null) { |
| sc.setJoinParameters("networkJoin", "networkId", networkId); |
| } |
| |
| final Filter filter = new Filter(NetworkACLVO.class, "id", false, null, null); |
| final Pair<List<NetworkACLVO>, Integer> acls = _networkACLDao.searchAndCount(sc, filter); |
| return new Pair<List<? extends NetworkACL>, Integer>(acls.first(), acls.second()); |
| } |
| |
| @Override |
| @ActionEvent(eventType = EventTypes.EVENT_NETWORK_ACL_DELETE, eventDescription = "Deleting Network ACL List", async = true) |
| public boolean deleteNetworkACL(final long id) { |
| final Account caller = CallContext.current().getCallingAccount(); |
| final NetworkACL acl = _networkACLDao.findById(id); |
| if (acl == null) { |
| 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"); |
| } |
| |
| final Vpc vpc = _entityMgr.findById(Vpc.class, 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 replaceNetworkACLonPrivateGw(final long aclId, final long privateGatewayId) throws ResourceUnavailableException { |
| final Account caller = CallContext.current().getCallingAccount(); |
| final VpcGateway gateway = _vpcGatewayDao.findById(privateGatewayId); |
| if (gateway == null) { |
| throw new InvalidParameterValueException("Unable to find specified private gateway"); |
| } |
| |
| final VpcGatewayVO vo = _vpcGatewayDao.findById(privateGatewayId); |
| if (vo.getState() != VpcGateway.State.Ready) { |
| throw new InvalidParameterValueException("Gateway is not in Ready state"); |
| } |
| |
| final NetworkACL acl = _networkACLDao.findById(aclId); |
| if (acl == null) { |
| throw new InvalidParameterValueException("Unable to find specified NetworkACL"); |
| } |
| |
| if (gateway.getVpcId() == null) { |
| throw new InvalidParameterValueException("Unable to find specified vpc id"); |
| } |
| |
| if (aclId != NetworkACL.DEFAULT_DENY && aclId != NetworkACL.DEFAULT_ALLOW) { |
| final Vpc vpc = _entityMgr.findById(Vpc.class, acl.getVpcId()); |
| if (vpc == null) { |
| throw new InvalidParameterValueException("Unable to find Vpc associated with the NetworkACL"); |
| } |
| _accountMgr.checkAccess(caller, null, true, vpc); |
| if (!gateway.getVpcId().equals(acl.getVpcId())) { |
| throw new InvalidParameterValueException("private gateway: " + privateGatewayId + " and ACL: " + aclId + " do not belong to the same VPC"); |
| } |
| } |
| |
| final PrivateGateway privateGateway = _vpcSvc.getVpcPrivateGateway(gateway.getId()); |
| _accountMgr.checkAccess(caller, null, true, privateGateway); |
| |
| return _networkAclMgr.replaceNetworkACLForPrivateGw(acl, privateGateway); |
| |
| } |
| |
| @Override |
| public boolean replaceNetworkACL(final long aclId, final long networkId) throws ResourceUnavailableException { |
| final Account caller = CallContext.current().getCallingAccount(); |
| |
| final NetworkVO network = _networkDao.findById(networkId); |
| if (network == null) { |
| throw new InvalidParameterValueException("Unable to find specified Network"); |
| } |
| |
| final 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()); |
| } |
| |
| if (network.getTrafficType() != Networks.TrafficType.Guest) { |
| throw new InvalidParameterValueException("Network ACL can be created just for networks of type " + Networks.TrafficType.Guest); |
| } |
| |
| if (aclId != NetworkACL.DEFAULT_DENY && aclId != NetworkACL.DEFAULT_ALLOW) { |
| //ACL is not default DENY/ALLOW |
| // ACL should be associated with a VPC |
| final Vpc vpc = _entityMgr.findById(Vpc.class, 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().equals(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(final CreateNetworkACLCmd aclItemCmd) { |
| final Account caller = CallContext.current().getCallingAccount(); |
| 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"); |
| } |
| final Network network = _networkMgr.getNetwork(aclItemCmd.getNetworkId()); |
| if (network.getVpcId() == null) { |
| throw new InvalidParameterValueException("Network: " + network.getUuid() + " does not belong to VPC"); |
| } |
| aclId = network.getNetworkACLId(); |
| |
| if (aclId == null) { |
| //Network is not associated with any ACL. Create a new ACL and add aclItem in it for backward compatibility |
| s_logger.debug("Network " + network.getId() + " is not associated with any ACL. Creating an ACL before adding acl item"); |
| |
| //verify that ACLProvider is supported by network offering |
| if (!_networkModel.areServicesSupportedByNetworkOffering(network.getNetworkOfferingId(), Network.Service.NetworkACL)) { |
| throw new InvalidParameterValueException("Network Offering does not support NetworkACL service"); |
| } |
| |
| final Vpc vpc = _entityMgr.findById(Vpc.class, network.getVpcId()); |
| if (vpc == null) { |
| throw new InvalidParameterValueException("Unable to find Vpc associated with the Network"); |
| } |
| |
| //Create new ACL |
| final String aclName = "VPC_" + vpc.getName() + "_Tier_" + network.getName() + "_ACL_" + network.getUuid(); |
| final String description = "ACL for " + aclName; |
| final NetworkACL acl = _networkAclMgr.createNetworkACL(aclName, description, network.getVpcId(), aclItemCmd.getDisplay()); |
| if (acl == null) { |
| throw new CloudRuntimeException("Error while create ACL before adding ACL Item for network " + network.getId()); |
| } |
| s_logger.debug("Created ACL: " + aclName + " for network " + network.getId()); |
| aclId = acl.getId(); |
| //Apply acl to network |
| try { |
| if (!_networkAclMgr.replaceNetworkACL(acl, (NetworkVO)network)) { |
| throw new CloudRuntimeException("Unable to apply auto created ACL to network " + network.getId()); |
| } |
| s_logger.debug("Created ACL is applied to network " + network.getId()); |
| } catch (final ResourceUnavailableException e) { |
| throw new CloudRuntimeException("Unable to apply auto created ACL to network " + network.getId(), e); |
| } |
| } |
| } |
| |
| final NetworkACL acl = _networkAclMgr.getNetworkACL(aclId); |
| if (acl == null) { |
| throw new InvalidParameterValueException("Unable to find specified ACL"); |
| } |
| |
| if (aclId == NetworkACL.DEFAULT_DENY || aclId == NetworkACL.DEFAULT_ALLOW) { |
| throw new InvalidParameterValueException("Default ACL cannot be modified"); |
| } |
| |
| final Vpc vpc = _entityMgr.findById(Vpc.class, acl.getVpcId()); |
| if (vpc == null) { |
| throw new InvalidParameterValueException("Unable to find Vpc associated with the NetworkACL"); |
| } |
| _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()); |
| } |
| } |
| |
| validateNetworkACLItem(aclItemCmd.getSourcePortStart(), aclItemCmd.getSourcePortEnd(), aclItemCmd.getSourceCidrList(), aclItemCmd.getProtocol(), |
| aclItemCmd.getIcmpCode(), aclItemCmd.getIcmpType(), aclItemCmd.getAction(), aclItemCmd.getNumber()); |
| |
| return _networkAclMgr.createNetworkACLItem(aclItemCmd.getSourcePortStart(), aclItemCmd.getSourcePortEnd(), aclItemCmd.getProtocol(), |
| aclItemCmd.getSourceCidrList(), aclItemCmd.getIcmpCode(), aclItemCmd.getIcmpType(), aclItemCmd.getTrafficType(), aclId, aclItemCmd.getAction(), |
| aclItemCmd.getNumber(), aclItemCmd.getDisplay()); |
| } |
| |
| private void validateNetworkACLItem(final Integer portStart, final Integer portEnd, final List<String> sourceCidrList, final String protocol, final Integer icmpCode, final Integer icmpType, |
| final String action, final Integer number) { |
| |
| 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"); |
| } |
| |
| // start port and end port must be null for protocol = 'all' |
| if ((portStart != null || portEnd != null) && protocol != null && protocol.equalsIgnoreCase("all")) { |
| throw new InvalidParameterValueException("start port and end port must be null if protocol = 'all'"); |
| } |
| |
| if (sourceCidrList != null) { |
| for (final String cidr : sourceCidrList) { |
| if (!NetUtils.isValidIp4Cidr(cidr)) { |
| throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Source cidrs formatting error " + cidr); |
| } |
| } |
| } |
| |
| //Validate Protocol |
| if (protocol != null) { |
| //Check if protocol is a number |
| if (StringUtils.isNumeric(protocol)) { |
| final int protoNumber = Integer.parseInt(protocol); |
| if (protoNumber < 0 || protoNumber > 255) { |
| throw new InvalidParameterValueException("Invalid protocol number: " + protoNumber); |
| } |
| } else { |
| //Protocol is not number |
| //Check for valid protocol strings |
| final 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"); |
| } |
| |
| 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"); |
| } |
| } |
| } |
| |
| //Check ofr valid action Allow/Deny |
| if (action != null) { |
| if (!("Allow".equalsIgnoreCase(action) || "Deny".equalsIgnoreCase(action))) { |
| throw new InvalidParameterValueException("Invalid action. Allowed actions are Allow and Deny"); |
| } |
| } |
| |
| //Check for valid number |
| if (number != null && number < 1) { |
| throw new InvalidParameterValueException("Invalid number. Number cannot be < 1"); |
| } |
| } |
| |
| @Override |
| public NetworkACLItem getNetworkACLItem(final long ruleId) { |
| return _networkAclMgr.getNetworkACLItem(ruleId); |
| } |
| |
| @Override |
| @ActionEvent(eventType = EventTypes.EVENT_NETWORK_ACL_ITEM_CREATE, eventDescription = "Applying Network ACL Item", async = true) |
| public boolean applyNetworkACL(final long aclId) throws ResourceUnavailableException { |
| return _networkAclMgr.applyNetworkACL(aclId); |
| } |
| |
| @Override |
| public Pair<List<? extends NetworkACLItem>, Integer> listNetworkACLItems(final ListNetworkACLsCmd cmd) { |
| final Long networkId = cmd.getNetworkId(); |
| final Long id = cmd.getId(); |
| Long aclId = cmd.getAclId(); |
| final String trafficType = cmd.getTrafficType(); |
| final String protocol = cmd.getProtocol(); |
| final String action = cmd.getAction(); |
| final Map<String, String> tags = cmd.getTags(); |
| final Account caller = CallContext.current().getCallingAccount(); |
| |
| final Filter filter = new Filter(NetworkACLItemVO.class, "id", false, cmd.getStartIndex(), cmd.getPageSizeVal()); |
| final SearchBuilder<NetworkACLItemVO> sb = _networkACLItemDao.createSearchBuilder(); |
| |
| 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()) { |
| final SearchBuilder<ResourceTagVO> 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); |
| } |
| |
| if (aclId == null) { |
| //Join with network_acl table when aclId is not specified to list acl_items within permitted VPCs |
| final SearchBuilder<NetworkACLVO> vpcSearch = _networkACLDao.createSearchBuilder(); |
| vpcSearch.and("vpcId", vpcSearch.entity().getVpcId(), Op.IN); |
| sb.join("vpcSearch", vpcSearch, sb.entity().getAclId(), vpcSearch.entity().getId(), JoinBuilder.JoinType.INNER); |
| } |
| |
| final SearchCriteria<NetworkACLItemVO> sc = sb.create(); |
| |
| if (id != null) { |
| sc.setParameters("id", id); |
| } |
| |
| if (networkId != null) { |
| final Network network = _networkDao.findById(networkId); |
| aclId = network.getNetworkACLId(); |
| if( aclId == null){ |
| // No aclId associated with the network. |
| //Return empty list |
| return new Pair(new ArrayList<NetworkACLItem>(), 0); |
| } |
| } |
| |
| if (trafficType != null) { |
| sc.setParameters("trafficType", trafficType); |
| } |
| |
| if (aclId != null) { |
| // Get VPC and check access |
| final NetworkACL acl = _networkACLDao.findById(aclId); |
| if (acl.getVpcId() != 0) { |
| final Vpc vpc = _vpcDao.findById(acl.getVpcId()); |
| if (vpc == null) { |
| throw new InvalidParameterValueException("Unable to find VPC associated with acl"); |
| } |
| _accountMgr.checkAccess(caller, null, true, vpc); |
| } |
| sc.setParameters("aclId", aclId); |
| } else { |
| //ToDo: Add accountId to network_acl_item table for permission check |
| |
| |
| // aclId is not specified |
| // List permitted VPCs and filter aclItems |
| final List<Long> permittedAccounts = new ArrayList<Long>(); |
| Long domainId = cmd.getDomainId(); |
| boolean isRecursive = cmd.isRecursive(); |
| final String accountName = cmd.getAccountName(); |
| final Long projectId = cmd.getProjectId(); |
| final boolean listAll = cmd.listAll(); |
| final Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, |
| ListProjectResourcesCriteria>(domainId, isRecursive, null); |
| _accountMgr.buildACLSearchParameters(caller, id, accountName, projectId, permittedAccounts, domainIdRecursiveListProject, |
| listAll, false); |
| domainId = domainIdRecursiveListProject.first(); |
| isRecursive = domainIdRecursiveListProject.second(); |
| final ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); |
| final SearchBuilder<VpcVO> sbVpc = _vpcDao.createSearchBuilder(); |
| _accountMgr.buildACLSearchBuilder(sbVpc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); |
| final SearchCriteria<VpcVO> scVpc = sbVpc.create(); |
| _accountMgr.buildACLSearchCriteria(scVpc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); |
| final List<VpcVO> vpcs = _vpcDao.search(scVpc, null); |
| final List<Long> vpcIds = new ArrayList<Long>(); |
| for (final VpcVO vpc : vpcs) { |
| vpcIds.add(vpc.getId()); |
| } |
| //Add vpc_id 0 to list acl_items in default ACL |
| vpcIds.add(0L); |
| sc.setJoinParameters("vpcSearch", "vpcId", vpcIds.toArray()); |
| } |
| |
| 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", ResourceObjectType.NetworkACL.toString()); |
| for (final String key : tags.keySet()) { |
| sc.setJoinParameters("tagSearch", "key" + String.valueOf(count), key); |
| sc.setJoinParameters("tagSearch", "value" + String.valueOf(count), tags.get(key)); |
| count++; |
| } |
| } |
| |
| final Pair<List<NetworkACLItemVO>, Integer> result = _networkACLItemDao.searchAndCount(sc, filter); |
| final List<NetworkACLItemVO> aclItemVOs = result.first(); |
| for (final NetworkACLItemVO item: aclItemVOs) { |
| _networkACLItemDao.loadCidrs(item); |
| } |
| return new Pair<List<? extends NetworkACLItem>, Integer>(aclItemVOs, result.second()); |
| } |
| |
| @Override |
| @ActionEvent(eventType = EventTypes.EVENT_NETWORK_ACL_ITEM_DELETE, eventDescription = "Deleting Network ACL Item", async = true) |
| public boolean revokeNetworkACLItem(final long ruleId) { |
| final NetworkACLItemVO aclItem = _networkACLItemDao.findById(ruleId); |
| if(aclItem != null){ |
| final NetworkACL acl = _networkAclMgr.getNetworkACL(aclItem.getAclId()); |
| |
| final Vpc vpc = _entityMgr.findById(Vpc.class, acl.getVpcId()); |
| |
| if(aclItem.getAclId() == NetworkACL.DEFAULT_ALLOW || aclItem.getAclId() == NetworkACL.DEFAULT_DENY){ |
| throw new InvalidParameterValueException("ACL Items in default ACL cannot be deleted"); |
| } |
| |
| final Account caller = CallContext.current().getCallingAccount(); |
| |
| _accountMgr.checkAccess(caller, null, true, vpc); |
| |
| } |
| return _networkAclMgr.revokeNetworkACLItem(ruleId); |
| } |
| |
| @Override |
| public NetworkACLItem updateNetworkACLItem(final Long id, final String protocol, final List<String> sourceCidrList, final NetworkACLItem.TrafficType trafficType, final String action, |
| final Integer number, final Integer sourcePortStart, final Integer sourcePortEnd, final Integer icmpCode, final Integer icmpType, final String newUUID, final Boolean forDisplay) throws ResourceUnavailableException { |
| final 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"); |
| } |
| |
| final NetworkACL acl = _networkAclMgr.getNetworkACL(aclItem.getAclId()); |
| |
| final Vpc vpc = _entityMgr.findById(Vpc.class, acl.getVpcId()); |
| |
| final Account caller = CallContext.current().getCallingAccount(); |
| |
| _accountMgr.checkAccess(caller, null, true, vpc); |
| |
| if (number != null) { |
| //Check if ACL Item with specified number already exists |
| final 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, number); |
| |
| return _networkAclMgr.updateNetworkACLItem(id, protocol, sourceCidrList, trafficType, action, number, sourcePortStart, sourcePortEnd, icmpCode, icmpType, newUUID, forDisplay); |
| } |
| |
| @Override |
| @ActionEvent(eventType = EventTypes.EVENT_NETWORK_ACL_UPDATE, eventDescription = "updating network acl", async = true) |
| public NetworkACL updateNetworkACL(final Long id, final String customId, final Boolean forDisplay) { |
| final NetworkACLVO acl = _networkACLDao.findById(id); |
| final Vpc vpc = _entityMgr.findById(Vpc.class, acl.getVpcId()); |
| final Account caller = CallContext.current().getCallingAccount(); |
| _accountMgr.checkAccess(caller, null, true, vpc); |
| |
| if (customId != null) { |
| acl.setUuid(customId); |
| } |
| |
| if (forDisplay != null) { |
| acl.setDisplay(forDisplay); |
| } |
| |
| _networkACLDao.update(id, acl); |
| return _networkACLDao.findById(id); |
| } |
| |
| } |