| // 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.firewall; | |
| import java.util.ArrayList; | |
| import java.util.Arrays; | |
| import java.util.Collection; | |
| import java.util.Collections; | |
| import java.util.HashSet; | |
| import java.util.List; | |
| import java.util.Locale; | |
| import java.util.Map; | |
| import java.util.Objects; | |
| import java.util.Set; | |
| import javax.inject.Inject; | |
| import javax.naming.ConfigurationException; | |
| import com.cloud.network.vpc.Vpc; | |
| import com.cloud.network.vpc.dao.VpcOfferingDao; | |
| import org.apache.commons.lang3.ObjectUtils; | |
| import org.springframework.stereotype.Component; | |
| import com.cloud.dc.DataCenter; | |
| import com.cloud.network.dao.NsxProviderDao; | |
| import com.cloud.network.element.NsxProviderVO; | |
| import com.cloud.utils.db.EntityManager; | |
| import org.apache.cloudstack.api.command.user.firewall.IListFirewallRulesCmd; | |
| import org.apache.cloudstack.api.command.user.ipv6.ListIpv6FirewallRulesCmd; | |
| import org.apache.cloudstack.context.CallContext; | |
| import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; | |
| import org.apache.cloudstack.framework.config.dao.ConfigurationDao; | |
| import org.apache.cloudstack.network.RoutedIpv4Manager; | |
| import com.cloud.configuration.Config; | |
| import com.cloud.domain.dao.DomainDao; | |
| import com.cloud.event.ActionEvent; | |
| import com.cloud.event.EventTypes; | |
| import com.cloud.event.UsageEventUtils; | |
| import com.cloud.event.dao.EventDao; | |
| import com.cloud.event.dao.UsageEventDao; | |
| import com.cloud.exception.InvalidParameterValueException; | |
| import com.cloud.exception.NetworkRuleConflictException; | |
| import com.cloud.exception.ResourceUnavailableException; | |
| import com.cloud.network.IpAddress; | |
| import com.cloud.network.IpAddressManager; | |
| 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.NetworkRuleApplier; | |
| import com.cloud.network.dao.FirewallRulesCidrsDao; | |
| import com.cloud.network.dao.FirewallRulesDao; | |
| import com.cloud.network.dao.FirewallRulesDcidrsDao; | |
| import com.cloud.network.dao.IPAddressDao; | |
| import com.cloud.network.dao.IPAddressVO; | |
| import com.cloud.network.dao.NetworkDao; | |
| import com.cloud.network.dao.NetworkServiceMapDao; | |
| import com.cloud.network.dao.NetworkVO; | |
| import com.cloud.network.element.FirewallServiceProvider; | |
| import com.cloud.network.element.NetworkACLServiceProvider; | |
| import com.cloud.network.element.NetworkElement; | |
| import com.cloud.network.element.PortForwardingServiceProvider; | |
| import com.cloud.network.element.StaticNatServiceProvider; | |
| import com.cloud.network.rules.FirewallManager; | |
| import com.cloud.network.rules.FirewallRule; | |
| import com.cloud.network.rules.FirewallRule.FirewallRuleType; | |
| import com.cloud.network.rules.FirewallRule.Purpose; | |
| import com.cloud.network.rules.FirewallRule.State; | |
| import com.cloud.network.rules.FirewallRuleVO; | |
| import com.cloud.network.rules.PortForwardingRule; | |
| import com.cloud.network.rules.PortForwardingRuleVO; | |
| import com.cloud.network.rules.dao.PortForwardingRulesDao; | |
| import com.cloud.network.vpc.VpcManager; | |
| 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.user.DomainManager; | |
| import com.cloud.utils.Pair; | |
| import com.cloud.utils.Ternary; | |
| 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.db.TransactionCallbackNoReturn; | |
| import com.cloud.utils.db.TransactionCallbackWithException; | |
| import com.cloud.utils.db.TransactionStatus; | |
| import com.cloud.utils.exception.CloudRuntimeException; | |
| import com.cloud.utils.net.NetUtils; | |
| import com.cloud.vm.UserVmVO; | |
| import com.cloud.vm.dao.UserVmDao; | |
| @Component | |
| public class FirewallManagerImpl extends ManagerBase implements FirewallService, FirewallManager, NetworkRuleApplier { | |
| @Inject | |
| FirewallRulesDao _firewallDao; | |
| @Inject | |
| IPAddressDao _ipAddressDao; | |
| @Inject | |
| EventDao _eventDao; | |
| @Inject | |
| DomainDao _domainDao; | |
| @Inject | |
| FirewallRulesCidrsDao _firewallCidrsDao; | |
| @Inject | |
| FirewallRulesDcidrsDao _firewallDcidrsDao; | |
| @Inject | |
| AccountManager _accountMgr; | |
| @Inject | |
| NetworkOrchestrationService _networkMgr; | |
| @Inject | |
| NetworkModel _networkModel; | |
| @Inject | |
| UsageEventDao _usageEventDao; | |
| @Inject | |
| ConfigurationDao _configDao; | |
| @Inject | |
| DomainManager _domainMgr; | |
| @Inject | |
| PortForwardingRulesDao _pfRulesDao; | |
| @Inject | |
| UserVmDao _vmDao; | |
| @Inject | |
| ResourceTagDao _resourceTagDao; | |
| @Inject | |
| NetworkDao _networkDao; | |
| @Inject | |
| VpcManager _vpcMgr; | |
| @Inject | |
| EntityManager entityManager; | |
| @Inject | |
| NsxProviderDao nsxProviderDao; | |
| @Inject | |
| NetworkServiceMapDao networkServiceMapDao; | |
| List<FirewallServiceProvider> _firewallElements; | |
| List<PortForwardingServiceProvider> _pfElements; | |
| List<StaticNatServiceProvider> _staticNatElements; | |
| List<NetworkACLServiceProvider> _networkAclElements; | |
| @Inject | |
| IpAddressManager _ipAddrMgr; | |
| @Inject | |
| RoutedIpv4Manager routedIpv4Manager; | |
| @Inject | |
| VpcOfferingDao vpcOfferingDao; | |
| private boolean _elbEnabled = false; | |
| static Boolean rulesContinueOnErrFlag = true; | |
| @Override | |
| public boolean configure(String name, Map<String, Object> params) throws ConfigurationException { | |
| _name = name; | |
| String elbEnabledString = _configDao.getValue(Config.ElasticLoadBalancerEnabled.key()); | |
| _elbEnabled = Boolean.parseBoolean(elbEnabledString); | |
| if (_ipAddrMgr.RulesContinueOnError.value() != null) { | |
| rulesContinueOnErrFlag = _ipAddrMgr.RulesContinueOnError.value(); | |
| } | |
| return true; | |
| } | |
| @Override | |
| public boolean start() { | |
| logger.info("Firewall provider list is " + _firewallElements.iterator().next()); | |
| return super.start(); | |
| } | |
| @Override | |
| @ActionEvent(eventType = EventTypes.EVENT_FIREWALL_EGRESS_OPEN, eventDescription = "creating egress firewall rule for network", create = true) | |
| public FirewallRule createEgressFirewallRule(FirewallRule rule) throws NetworkRuleConflictException { | |
| Account caller = CallContext.current().getCallingAccount(); | |
| Network network = _networkDao.findById(rule.getNetworkId()); | |
| if (network.getGuestType() == Network.GuestType.Shared) { | |
| throw new InvalidParameterValueException("Egress firewall rules are not supported for " + network.getGuestType() + " networks"); | |
| } | |
| List<String> sourceCidrs = rule.getSourceCidrList(); | |
| if (sourceCidrs != null && !sourceCidrs.isEmpty()) | |
| Collections.replaceAll(sourceCidrs, "0.0.0.0/0", network.getCidr()); | |
| return createFirewallRuleForNonVPC(null, caller, rule.getXid(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getProtocol(), sourceCidrs, | |
| rule.getDestinationCidrList(), rule.getIcmpCode(), rule.getIcmpType(), null, rule.getType(), rule.getNetworkId(), rule.getTrafficType(), rule.isDisplay()); | |
| } | |
| @Override | |
| @ActionEvent(eventType = EventTypes.EVENT_FIREWALL_OPEN, eventDescription = "creating firewall rule", create = true) | |
| public FirewallRule createIngressFirewallRule(FirewallRule rule) throws NetworkRuleConflictException { | |
| Account caller = CallContext.current().getCallingAccount(); | |
| Long sourceIpAddressId = rule.getSourceIpAddressId(); | |
| IPAddressVO sourceIp = getSourceIpForIngressRule(sourceIpAddressId); | |
| if (sourceIp.getVpcId() != null) { | |
| return createIngressFirewallRuleForVpcIp(rule, caller, sourceIp); | |
| } | |
| return createIngressFirewallRuleForIsolatedIp(rule, caller, sourceIp); | |
| } | |
| protected IPAddressVO getSourceIpForIngressRule(Long sourceIpAddressId) { | |
| if (sourceIpAddressId == null) { | |
| return null; | |
| } | |
| IPAddressVO sourceIp = _ipAddressDao.findById(sourceIpAddressId); | |
| if (sourceIp == null) { | |
| throw new CloudRuntimeException("Unable to find IP address by id=" + sourceIpAddressId); | |
| } | |
| return sourceIp; | |
| } | |
| protected FirewallRule createIngressFirewallRuleForIsolatedIp(FirewallRule rule, Account caller, IPAddressVO sourceIp) | |
| throws NetworkRuleConflictException { | |
| return createFirewallRuleForNonVPC(rule.getSourceIpAddressId(), caller, rule.getXid(), rule.getSourcePortStart(), rule.getSourcePortEnd(), | |
| rule.getProtocol(), rule.getSourceCidrList(), null, rule.getIcmpCode(), rule.getIcmpType(), null, rule.getType(), | |
| rule.getNetworkId(), rule.getTrafficType(), rule.isDisplay()); | |
| } | |
| protected FirewallRule createIngressFirewallRuleForVpcIp(FirewallRule rule, Account caller, IPAddressVO sourceIp) | |
| throws NetworkRuleConflictException { | |
| Long vpcId = sourceIp != null ? sourceIp.getVpcId() : null; | |
| return createFirewallRuleForVpc(rule.getSourceIpAddressId(), caller, rule.getXid(), rule.getSourcePortStart(), rule.getSourcePortEnd(), | |
| rule.getProtocol(), rule.getSourceCidrList(), null, rule.getIcmpCode(), rule.getIcmpType(), null, rule.getType(), | |
| vpcId, rule.getTrafficType(), rule.isDisplay()); | |
| } | |
| //Destination CIDR capability is currently implemented for egress rules only. For others, the field is passed as null. | |
| @DB | |
| protected FirewallRule createFirewallRule(final Long ipAddrId, Account caller, final String xId, final Integer portStart, final Integer portEnd, final String protocol, | |
| final List<String> sourceCidrList, final List<String> destCidrList, final Integer icmpCode, final Integer icmpType, final Long relatedRuleId, | |
| final FirewallRule.FirewallRuleType type, final Long networkId, final Long vpcId, final FirewallRule.TrafficType trafficType, final Boolean forDisplay) throws NetworkRuleConflictException { | |
| if (vpcId != null) { | |
| return createFirewallRuleForVpc(ipAddrId, caller, xId, portStart, portEnd, protocol, sourceCidrList, destCidrList, icmpCode, icmpType, relatedRuleId, | |
| type, vpcId, trafficType, forDisplay); | |
| } | |
| return createFirewallRuleForNonVPC(ipAddrId, caller, xId, portStart, portEnd, protocol, sourceCidrList, destCidrList, icmpCode, icmpType, relatedRuleId, | |
| type, networkId, trafficType, forDisplay); | |
| } | |
| @DB | |
| protected FirewallRule createFirewallRuleForNonVPC(final Long ipAddrId, Account caller, final String xId, final Integer portStart, final Integer portEnd, final String protocol, | |
| final List<String> sourceCidrList, final List<String> destCidrList, final Integer icmpCode, final Integer icmpType, final Long relatedRuleId, | |
| final FirewallRule.FirewallRuleType type, final Long networkId, final FirewallRule.TrafficType trafficType, final Boolean forDisplay) throws NetworkRuleConflictException { | |
| IPAddressVO ipAddress = null; | |
| try { | |
| // Validate ip address | |
| if (ipAddrId != null) { | |
| // this for ingress firewall rule, for egress id is null | |
| ipAddress = _ipAddressDao.acquireInLockTable(ipAddrId); | |
| if (ipAddress == null) { | |
| throw new InvalidParameterValueException("Unable to create firewall rule; " + "couldn't locate IP address by id in the system"); | |
| } | |
| _networkModel.checkIpForService(ipAddress, Service.Firewall, null); | |
| } | |
| validateFirewallRule(caller, ipAddress, portStart, portEnd, protocol, Purpose.Firewall, type, networkId, trafficType); | |
| // 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"); | |
| } | |
| Long accountId = null; | |
| Long domainId = null; | |
| if (ipAddress != null) { | |
| //Ingress firewall rule | |
| accountId = ipAddress.getAllocatedToAccountId(); | |
| domainId = ipAddress.getAllocatedInDomainId(); | |
| } else if (networkId != null) { | |
| //egress firewall rule | |
| Network network = _networkModel.getNetwork(networkId); | |
| accountId = network.getAccountId(); | |
| domainId = network.getDomainId(); | |
| } | |
| final Long accountIdFinal = accountId; | |
| final Long domainIdFinal = domainId; | |
| return Transaction.execute((TransactionCallbackWithException<FirewallRuleVO, NetworkRuleConflictException>) status -> { | |
| FirewallRuleVO newRule = new FirewallRuleVO(xId, ipAddrId, portStart, portEnd, protocol.toLowerCase(), networkId, accountIdFinal, domainIdFinal, Purpose.Firewall, | |
| sourceCidrList, destCidrList, icmpCode, icmpType, relatedRuleId, trafficType); | |
| newRule.setType(type); | |
| if (forDisplay != null) { | |
| newRule.setDisplay(forDisplay); | |
| } | |
| newRule = _firewallDao.persist(newRule); | |
| if (type == FirewallRuleType.User) | |
| detectRulesConflict(newRule); | |
| if (!_firewallDao.setStateToAdd(newRule)) { | |
| throw new CloudRuntimeException("Unable to update the state to add for " + newRule); | |
| } | |
| CallContext.current().setEventDetails("Rule ID: " + newRule.getUuid()); | |
| CallContext.current().putContextParameter(FirewallRule.class, newRule.getId()); | |
| return newRule; | |
| }); | |
| } finally { | |
| if (ipAddrId != null) { | |
| _ipAddressDao.releaseFromLockTable(ipAddrId); | |
| } | |
| } | |
| } | |
| @DB | |
| protected FirewallRule createFirewallRuleForVpc(final Long ipAddrId, Account caller, final String xId, final Integer portStart, final Integer portEnd, final String protocol, | |
| final List<String> sourceCidrList, final List<String> destCidrList, final Integer icmpCode, final Integer icmpType, | |
| final Long relatedRuleId, final FirewallRuleType type, final Long vpcId, | |
| final FirewallRule.TrafficType trafficType, final Boolean forDisplay) throws NetworkRuleConflictException { | |
| IPAddressVO ipAddress = null; | |
| try { | |
| Long resolvedVpcId = vpcId; | |
| if (ipAddrId != null) { | |
| ipAddress = _ipAddressDao.acquireInLockTable(ipAddrId); | |
| if (ipAddress == null) { | |
| throw new InvalidParameterValueException("Unable to create firewall rule; " + "couldn't locate IP address by id in the system"); | |
| } | |
| resolvedVpcId = resolvedVpcId != null ? resolvedVpcId : ipAddress.getVpcId(); | |
| } | |
| if (resolvedVpcId == null) { | |
| throw new InvalidParameterValueException("Unable to create VPC firewall rule; couldn't locate VPC id"); | |
| } | |
| validateFirewallRuleForVpc(caller, ipAddress, portStart, portEnd, protocol, Purpose.Firewall, type, resolvedVpcId, trafficType); | |
| 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"); | |
| } | |
| Long accountId = null; | |
| Long domainId = null; | |
| if (ipAddress != null) { | |
| accountId = ipAddress.getAllocatedToAccountId(); | |
| domainId = ipAddress.getAllocatedInDomainId(); | |
| } else { | |
| Vpc vpc = _vpcMgr.getActiveVpc(resolvedVpcId); | |
| if (vpc == null) { | |
| throw new InvalidParameterValueException("Unable to create VPC firewall rule; couldn't locate VPC by id=" + resolvedVpcId); | |
| } | |
| accountId = vpc.getAccountId(); | |
| domainId = vpc.getDomainId(); | |
| } | |
| final Long accountIdFinal = accountId; | |
| final Long domainIdFinal = domainId; | |
| final Long resolvedNetworkIdFinal = null; | |
| final Long resolvedVpcIdFinal = resolvedVpcId; | |
| return Transaction.execute((TransactionCallbackWithException<FirewallRuleVO, NetworkRuleConflictException>) status -> { | |
| FirewallRuleVO newRule = new FirewallRuleVO(xId, ipAddrId, portStart, portEnd, protocol.toLowerCase(), resolvedNetworkIdFinal, accountIdFinal, domainIdFinal, Purpose.Firewall, | |
| sourceCidrList, destCidrList, icmpCode, icmpType, relatedRuleId, trafficType); | |
| newRule.setVpcId(resolvedVpcIdFinal); | |
| newRule.setType(type); | |
| if (forDisplay != null) { | |
| newRule.setDisplay(forDisplay); | |
| } | |
| newRule = _firewallDao.persist(newRule); | |
| if (type == FirewallRuleType.User) | |
| detectRulesConflict(newRule); | |
| if (!_firewallDao.setStateToAdd(newRule)) { | |
| throw new CloudRuntimeException("Unable to update the state to add for " + newRule); | |
| } | |
| CallContext.current().setEventDetails("Rule ID: " + newRule.getUuid()); | |
| CallContext.current().putContextParameter(FirewallRule.class, newRule.getId()); | |
| return newRule; | |
| }); | |
| } finally { | |
| if (ipAddrId != null) { | |
| _ipAddressDao.releaseFromLockTable(ipAddrId); | |
| } | |
| } | |
| } | |
| protected void validateFirewallRuleForVpc(Account caller, IPAddressVO ipAddress, Integer portStart, Integer portEnd, String proto, Purpose purpose, | |
| FirewallRuleType type, Long vpcId, FirewallRule.TrafficType trafficType) { | |
| 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); | |
| } | |
| if (portStart != null && portEnd != null && portStart > portEnd) { | |
| throw new InvalidParameterValueException("Start port can't be bigger than end port"); | |
| } | |
| if (ipAddress == null && type == FirewallRuleType.System) { | |
| return; | |
| } | |
| if (vpcId == null) { | |
| throw new InvalidParameterValueException("Unable to retrieve VPC id to validate the rule"); | |
| } | |
| if (ipAddress != null) { | |
| _accountMgr.checkAccess(caller, null, true, ipAddress); | |
| } | |
| Vpc vpc = _vpcMgr.getActiveVpc(vpcId); | |
| if (vpc == null) { | |
| throw new InvalidParameterValueException("Unable to retrieve VPC to validate the rule by id=" + vpcId); | |
| } | |
| Map<Network.Capability, String> caps = null; | |
| if (purpose == Purpose.Firewall) { | |
| caps = getFirewallServiceCapabilitiesForVpc(vpcId); | |
| if (caps == null) { | |
| throw new InvalidParameterValueException("Firewall service is not supported in VPC " + vpc); | |
| } | |
| } | |
| if (caps != null) { | |
| String supportedTrafficTypes = null; | |
| if (purpose == FirewallRule.Purpose.Firewall) { | |
| supportedTrafficTypes = caps.get(Capability.SupportedTrafficDirection).toLowerCase(); | |
| } | |
| String supportedProtocols; | |
| if (purpose == FirewallRule.Purpose.Firewall && trafficType == FirewallRule.TrafficType.Egress) { | |
| supportedProtocols = caps.get(Capability.SupportedEgressProtocols).toLowerCase(); | |
| } else { | |
| supportedProtocols = caps.get(Capability.SupportedProtocols).toLowerCase(); | |
| } | |
| if (!supportedProtocols.contains(proto.toLowerCase())) { | |
| throw new InvalidParameterValueException("Protocol " + proto + " is not supported in VPC " + vpcId); | |
| } else if (proto.equalsIgnoreCase(NetUtils.ICMP_PROTO) && purpose != Purpose.Firewall) { | |
| throw new InvalidParameterValueException("Protocol " + proto + " is currently supported only for rules with purpose " + Purpose.Firewall); | |
| } else if (purpose == Purpose.Firewall && !supportedTrafficTypes.contains(trafficType.toString().toLowerCase())) { | |
| throw new InvalidParameterValueException(String.format("Traffic Type %s is currently supported by Firewall in VPC %s", trafficType, vpc.getUuid())); | |
| } | |
| } | |
| } | |
| protected Map<Network.Capability, String> getFirewallServiceCapabilitiesForVpc(Long vpcId) { | |
| for (FirewallServiceProvider fwElement : _firewallElements) { | |
| Network.Provider provider = fwElement.getProvider(); | |
| if (_vpcMgr.isProviderSupportServiceInVpc(vpcId, Service.Firewall, provider)) { | |
| Map<Service, Map<Capability, String>> capabilities = fwElement.getCapabilities(); | |
| if (capabilities != null && capabilities.get(Service.Firewall) != null) { | |
| return capabilities.get(Service.Firewall); | |
| } | |
| } | |
| } | |
| return null; | |
| } | |
| protected Long resolveIsolatedFirewallRuleNetworkId(IPAddressVO ipAddress, Long networkId) { | |
| _networkModel.checkIpForService(ipAddress, Service.Firewall, networkId); | |
| return ipAddress.getAssociatedWithNetworkId(); | |
| } | |
| @Override | |
| public Pair<List<? extends FirewallRule>, Integer> listFirewallRules(IListFirewallRulesCmd cmd) { | |
| Long ipId = cmd.getIpAddressId(); | |
| Long id = cmd.getId(); | |
| Long networkId = cmd.getNetworkId(); | |
| Map<String, String> tags = cmd.getTags(); | |
| FirewallRule.TrafficType trafficType = cmd.getTrafficType(); | |
| Boolean display = cmd.getDisplay(); | |
| Account caller = CallContext.current().getCallingAccount(); | |
| List<Long> permittedAccounts = new ArrayList<Long>(); | |
| if (ipId != null) { | |
| IPAddressVO ipAddressVO = _ipAddressDao.findById(ipId); | |
| if (ipAddressVO == null || !ipAddressVO.readyToUse()) { | |
| throw new InvalidParameterValueException("Ip address id=" + ipId + " not ready for firewall rules yet"); | |
| } | |
| _accountMgr.checkAccess(caller, null, true, ipAddressVO); | |
| } | |
| Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>(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(FirewallRuleVO.class, "id", false, cmd.getStartIndex(), cmd.getPageSizeVal()); | |
| SearchBuilder<FirewallRuleVO> sb = _firewallDao.createSearchBuilder(); | |
| _accountMgr.buildACLSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); | |
| sb.and("id", sb.entity().getId(), Op.EQ); | |
| sb.and("trafficType", sb.entity().getTrafficType(), Op.EQ); | |
| sb.and("networkId", sb.entity().getNetworkId(), Op.EQ); | |
| sb.and("ip", sb.entity().getSourceIpAddressId(), Op.EQ); | |
| sb.and("purpose", sb.entity().getPurpose(), Op.EQ); | |
| sb.and("display", sb.entity().isDisplay(), Op.EQ); | |
| if (tags != null && !tags.isEmpty()) { | |
| SearchBuilder<ResourceTagVO> 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(); | |
| } | |
| 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<FirewallRuleVO> sc = sb.create(); | |
| _accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); | |
| if (id != null) { | |
| sc.setParameters("id", id); | |
| } | |
| if (tags != null && !tags.isEmpty()) { | |
| int count = 0; | |
| sc.setJoinParameters("tagSearch", "resourceType", ResourceObjectType.FirewallRule.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++; | |
| } | |
| } | |
| if (display != null) { | |
| sc.setParameters("display", display); | |
| } | |
| if (ipId != null) { | |
| sc.setParameters("ip", ipId); | |
| } | |
| if (networkId != null) { | |
| sc.setParameters("networkId", networkId); | |
| } | |
| if (cmd instanceof ListIpv6FirewallRulesCmd) { | |
| sc.setParameters("purpose", Purpose.Ipv6Firewall); | |
| } else { | |
| sc.setParameters("purpose", Purpose.Firewall); | |
| } | |
| if (trafficType != null) { | |
| sc.setParameters("trafficType", trafficType); | |
| } | |
| Pair<List<FirewallRuleVO>, Integer> result = _firewallDao.searchAndCount(sc, filter); | |
| return new Pair<List<? extends FirewallRule>, Integer>(result.first(), result.second()); | |
| } | |
| //Intermediate function used in detectRulesConflict to check for the conflicting cidrs in the rules already applied and the newRule being applied. | |
| boolean detectConflictingCidrs(List<String> cidrList1, List<String> cidrList2){ | |
| if(cidrList1.isEmpty() && cidrList2.isEmpty()){ | |
| return true; | |
| } | |
| Collection<String> similar = new HashSet<String>(cidrList1); | |
| similar.retainAll(cidrList2); | |
| return (similar.size()>0); | |
| } | |
| @Override | |
| public void detectRulesConflict(FirewallRule newRule) throws NetworkRuleConflictException { | |
| List<FirewallRuleVO> rules; | |
| if (newRule.getSourceIpAddressId() != null) { | |
| rules = _firewallDao.listByIpAndPurposeAndNotRevoked(newRule.getSourceIpAddressId(), null); | |
| assert (rules.size() >= 1) : "For network rules, we now always first persist the rule and then check for " | |
| + "network conflicts so we should at least have one rule at this point."; | |
| } else { | |
| // fetches only firewall egress rules. | |
| rules = _firewallDao.listByNetworkPurposeTrafficTypeAndNotRevoked(newRule.getNetworkId(), Purpose.Firewall, newRule.getTrafficType()); | |
| assert (rules.size() >= 1); | |
| } | |
| Long newRuleVpcId = newRule.getVpcId(); | |
| boolean newRuleIsVpc = newRuleVpcId != null; | |
| NetworkVO newRuleNetwork = null; | |
| boolean newRuleIsOnVpcNetwork = false; | |
| boolean vpcConserveModeEnabled = false; | |
| if (!newRuleIsVpc) { | |
| newRuleNetwork = getNewRuleNetwork(newRule); | |
| newRuleIsOnVpcNetwork = newRuleNetwork.getVpcId() != null; | |
| vpcConserveModeEnabled = newRuleIsOnVpcNetwork && _vpcMgr.isNetworkOnVpcEnabledConserveMode(newRuleNetwork); | |
| } | |
| for (FirewallRuleVO rule : rules) { | |
| if (rule.getId() == newRule.getId()) { | |
| continue; // Skips my own rule. | |
| } | |
| boolean oneOfRulesIsFirewall = | |
| ((rule.getPurpose() == Purpose.Firewall || newRule.getPurpose() == Purpose.Firewall) && ((newRule.getPurpose() != rule.getPurpose()) || (!newRule.getProtocol() | |
| .equalsIgnoreCase(rule.getProtocol())))); | |
| // if both rules are firewall/port forwarding and their cidrs are different, we can skip port ranges verification | |
| boolean duplicatedCidrs = false; | |
| boolean bothRulesFirewall = (rule.getPurpose() == newRule.getPurpose() && rule.getPurpose() == Purpose.Firewall); | |
| if (bothRulesFirewall) { | |
| _firewallDao.loadSourceCidrs(rule); | |
| _firewallDao.loadSourceCidrs((FirewallRuleVO)newRule); | |
| if (ObjectUtils.anyNull(rule.getSourceCidrList(), newRule.getSourceCidrList())) { | |
| continue; | |
| } | |
| _firewallDao.loadDestinationCidrs(rule); | |
| _firewallDao.loadDestinationCidrs((FirewallRuleVO) newRule); | |
| duplicatedCidrs = detectConflictingCidrs(rule.getSourceCidrList(), newRule.getSourceCidrList()) && detectConflictingCidrs(rule.getDestinationCidrList(), newRule.getDestinationCidrList()); | |
| } | |
| boolean bothRulesPortForwarding = rule.getPurpose() == newRule.getPurpose() && rule.getPurpose() == Purpose.PortForwarding; | |
| if (bothRulesPortForwarding) { | |
| _firewallDao.loadSourceCidrs(rule); | |
| _firewallDao.loadSourceCidrs((FirewallRuleVO) newRule); | |
| if (ObjectUtils.anyNull(rule.getSourceCidrList(), newRule.getSourceCidrList())) { | |
| continue; | |
| } | |
| duplicatedCidrs = detectConflictingCidrs(rule.getSourceCidrList(), newRule.getSourceCidrList()); | |
| } | |
| if (!oneOfRulesIsFirewall) { | |
| if (rule.getPurpose() == Purpose.StaticNat && newRule.getPurpose() != Purpose.StaticNat) { | |
| throw new NetworkRuleConflictException("There is 1 to 1 Nat rule specified for the ip address id=" + newRule.getSourceIpAddressId()); | |
| } else if (rule.getPurpose() != Purpose.StaticNat && newRule.getPurpose() == Purpose.StaticNat) { | |
| throw new NetworkRuleConflictException("There is already firewall rule specified for the ip address id=" + newRule.getSourceIpAddressId()); | |
| } | |
| } | |
| // Checking if the rule applied is to the same network that is passed in the rule. | |
| // (except for VPCs with conserve mode = true) | |
| if (!newRuleIsVpc && (!newRuleIsOnVpcNetwork || !vpcConserveModeEnabled) | |
| && !Objects.equals(rule.getNetworkId(), newRule.getNetworkId()) && rule.getState() != State.Revoke) { | |
| String errMsg = String.format("New rule is for a different network than what's specified in rule %s", rule.getXid()); | |
| if (newRuleIsOnVpcNetwork) { | |
| Vpc vpc = _vpcMgr.getActiveVpc(newRuleNetwork.getVpcId()); | |
| errMsg += String.format(" - VPC id=%s is not using conserve mode", vpc.getUuid()); | |
| } | |
| throw new NetworkRuleConflictException(errMsg); | |
| } | |
| //Check for the ICMP protocol. This has to be done separately from other protocols as we need to check the ICMP codes and ICMP type also. | |
| if (newRule.getProtocol().equalsIgnoreCase(NetUtils.ICMP_PROTO) && newRule.getProtocol().equalsIgnoreCase(rule.getProtocol())) { | |
| if (newRule.getIcmpCode().longValue() == rule.getIcmpCode().longValue() && newRule.getIcmpType().longValue() == rule.getIcmpType().longValue() && | |
| newRule.getProtocol().equalsIgnoreCase(rule.getProtocol()) && duplicatedCidrs) { | |
| throw new InvalidParameterValueException(String.format("New rule conflicts with existing rule: %s", rule)); | |
| } | |
| } | |
| boolean notNullPorts = | |
| (newRule.getSourcePortStart() != null && newRule.getSourcePortEnd() != null && rule.getSourcePortStart() != null && rule.getSourcePortEnd() != null); | |
| boolean nullPorts = | |
| (newRule.getSourcePortStart() == null && newRule.getSourcePortEnd() == null && rule.getSourcePortStart() == null && rule.getSourcePortEnd() == null); | |
| // If ports are not specified and cidrs are same and protocol is also same(NOT ICMP as it is separately checked above) | |
| if(nullPorts && duplicatedCidrs && (rule.getProtocol().equalsIgnoreCase(newRule.getProtocol())) && !newRule.getProtocol().equalsIgnoreCase(NetUtils.ICMP_PROTO)) { | |
| throw new NetworkRuleConflictException("There is already a firewall rule specified with protocol = " +newRule.getProtocol()+ " and no ports"); | |
| } | |
| if (!notNullPorts) { | |
| continue; | |
| } else if (checkIfRulesHaveConflictingPortRanges(newRule, rule, oneOfRulesIsFirewall, bothRulesFirewall, bothRulesPortForwarding, duplicatedCidrs)) { | |
| // we allow port forwarding rules with the same parameters but different protocols | |
| boolean allowPf = | |
| (rule.getPurpose() == Purpose.PortForwarding && newRule.getPurpose() == Purpose.PortForwarding && !newRule.getProtocol().equalsIgnoreCase( | |
| rule.getProtocol())) || (rule.getPurpose() == Purpose.Vpn && newRule.getPurpose() == Purpose.PortForwarding && !newRule.getProtocol().equalsIgnoreCase( | |
| rule.getProtocol())); | |
| boolean allowStaticNat = | |
| (rule.getPurpose() == Purpose.StaticNat && newRule.getPurpose() == Purpose.StaticNat && !newRule.getProtocol().equalsIgnoreCase(rule.getProtocol())); | |
| boolean allowVpnPf = | |
| (rule.getPurpose() == Purpose.PortForwarding && newRule.getPurpose() == Purpose.Vpn && !newRule.getProtocol().equalsIgnoreCase(rule.getProtocol())); | |
| boolean allowVpnLb = | |
| (rule.getPurpose() == Purpose.LoadBalancing && newRule.getPurpose() == Purpose.Vpn && !newRule.getProtocol().equalsIgnoreCase(rule.getProtocol())); | |
| if (!(allowPf || allowStaticNat || oneOfRulesIsFirewall || allowVpnPf || allowVpnLb)) { | |
| throw new NetworkRuleConflictException(String.format("The range specified, %d-%d, conflicts with rule %s which has %d-%d", newRule.getSourcePortStart(), newRule.getSourcePortEnd(), rule, rule.getSourcePortStart(), rule.getSourcePortEnd())); | |
| } | |
| } | |
| } | |
| if (logger.isDebugEnabled()) { | |
| logger.debug("No network rule conflicts detected for " + newRule + " against " + (rules.size() - 1) + " existing rules"); | |
| } | |
| } | |
| protected NetworkVO getNewRuleNetwork(FirewallRule newRule) { | |
| NetworkVO newRuleNetwork = _networkDao.findById(newRule.getNetworkId()); | |
| if (newRuleNetwork == null) { | |
| throw new InvalidParameterValueException("Unable to create firewall rule as cannot find network by id=" + newRule.getNetworkId()); | |
| } | |
| return newRuleNetwork; | |
| } | |
| protected boolean checkIfRulesHaveConflictingPortRanges(FirewallRule newRule, FirewallRule rule, boolean oneOfRulesIsFirewall, boolean bothRulesFirewall, boolean bothRulesPortForwarding, boolean duplicatedCidrs) { | |
| String rulesAsString = String.format("[%s] and [%s]", rule, newRule); | |
| if (oneOfRulesIsFirewall) { | |
| logger.debug(String.format("Only one of the rules (%s) is firewall; therefore, their port ranges will not conflict.", | |
| rulesAsString)); | |
| return false; | |
| } | |
| if ((bothRulesFirewall || bothRulesPortForwarding) && !duplicatedCidrs) { | |
| logger.debug(String.format("Both rules (%s) are firewall/port forwarding, but they do not have duplicated CIDRs; therefore, their port ranges will not conflict.", | |
| rulesAsString)); | |
| return false; | |
| } | |
| if (rule.getSourcePortStart() <= newRule.getSourcePortStart() && rule.getSourcePortEnd() >= newRule.getSourcePortStart()) { | |
| logger.debug(String.format("Rules (%s) have conflicting port ranges.", rulesAsString)); | |
| return true; | |
| } | |
| if (rule.getSourcePortStart() <= newRule.getSourcePortEnd() && rule.getSourcePortEnd() >= newRule.getSourcePortEnd()) { | |
| logger.debug(String.format("Rules (%s) have conflicting port ranges.", rulesAsString)); | |
| return true; | |
| } | |
| if (newRule.getSourcePortStart() <= rule.getSourcePortStart() && newRule.getSourcePortEnd() >= rule.getSourcePortStart()) { | |
| logger.debug(String.format("Rules (%s) have conflicting port ranges.", rulesAsString)); | |
| return true; | |
| } | |
| if (newRule.getSourcePortStart() <= rule.getSourcePortEnd() && newRule.getSourcePortEnd() >= rule.getSourcePortEnd()) { | |
| logger.debug(String.format("Rules (%s) have conflicting port ranges.", rulesAsString)); | |
| return true; | |
| } | |
| logger.debug(String.format("Rules (%s) do not have conflicting port ranges.", rulesAsString)); | |
| return false; | |
| } | |
| @Override | |
| public void validateFirewallRule(Account caller, IPAddressVO ipAddress, Integer portStart, Integer portEnd, String proto, Purpose purpose, FirewallRuleType type, | |
| Long networkId, FirewallRule.TrafficType trafficType) { | |
| 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 (ipAddress == null && type == FirewallRuleType.System) { | |
| return; | |
| } | |
| if (ipAddress != null) { | |
| networkId = isVpcIpAddress(ipAddress) | |
| ? validateFirewallRuleForVpcIp(ipAddress, networkId) | |
| : validateFirewallRuleForIsolatedIp(ipAddress); | |
| // Validate ip address | |
| _accountMgr.checkAccess(caller, null, true, ipAddress); | |
| } | |
| //network id either has to be passed explicitly, or implicitly as a part of ipAddress object | |
| if (networkId == null) { | |
| throw new InvalidParameterValueException("Unable to retrieve network id to validate the rule"); | |
| } | |
| Network network = _networkModel.getNetwork(networkId); | |
| assert network != null : "Can't create rule as network associated with public ip address is null?"; | |
| if (trafficType == FirewallRule.TrafficType.Egress) { | |
| _accountMgr.checkAccess(caller, null, true, network); | |
| } | |
| // Verify that the network guru supports the protocol specified | |
| Map<Network.Capability, String> caps = null; | |
| if (purpose == Purpose.LoadBalancing) { | |
| if (!_elbEnabled) { | |
| caps = _networkModel.getNetworkServiceCapabilities(network.getId(), Service.Lb); | |
| } | |
| } else if (purpose == Purpose.PortForwarding) { | |
| caps = _networkModel.getNetworkServiceCapabilities(network.getId(), Service.PortForwarding); | |
| } else if (purpose == Purpose.Firewall) { | |
| if (routedIpv4Manager.isVirtualRouterGateway(network)) { | |
| throw new CloudRuntimeException("Unable to create routing firewall rule. Please use routing firewall API instead."); | |
| } | |
| caps = getFirewallServiceCapabilities(network); | |
| } | |
| if (caps != null) { | |
| String supportedProtocols; | |
| String supportedTrafficTypes = null; | |
| if (purpose == FirewallRule.Purpose.Firewall) { | |
| String supportedTrafficTypesStr = caps.get(Capability.SupportedTrafficDirection); | |
| if (supportedTrafficTypesStr == null) { | |
| throw new CloudRuntimeException("Supported traffic direction capability is not defined for Firewall service"); | |
| } | |
| supportedTrafficTypes = supportedTrafficTypesStr.toLowerCase(); | |
| } | |
| if (purpose == FirewallRule.Purpose.Firewall && trafficType == FirewallRule.TrafficType.Egress) { | |
| // throw an exception if cap is not found | |
| String supportedProtocolsStr = caps.get(Capability.SupportedEgressProtocols); | |
| if (supportedProtocolsStr == null) { | |
| throw new CloudRuntimeException("Supported egress protocols capability is not defined for Firewall service"); | |
| } | |
| supportedProtocols = supportedProtocolsStr.toLowerCase(); | |
| } else { | |
| String supportedProtocolsStr = caps.get(Capability.SupportedProtocols); | |
| if (supportedProtocolsStr == null) { | |
| throw new CloudRuntimeException("Supported protocols capability is not defined for " + purpose + " service"); | |
| } | |
| supportedProtocols = supportedProtocolsStr.toLowerCase(); | |
| } | |
| if (!supportedProtocols.contains(proto.toLowerCase())) { | |
| throw new InvalidParameterValueException("Protocol " + proto + " is not supported in zone " + network.getDataCenterId()); | |
| } else if (proto.equalsIgnoreCase(NetUtils.ICMP_PROTO) && purpose != Purpose.Firewall) { | |
| throw new InvalidParameterValueException("Protocol " + proto + " is currently supported only for rules with purpose " + Purpose.Firewall); | |
| } else if (purpose == Purpose.Firewall && !supportedTrafficTypes.contains(trafficType.toString().toLowerCase())) { | |
| throw new InvalidParameterValueException(String.format("Traffic Type %s is currently supported by Firewall in network %s", trafficType, network)); | |
| } | |
| } | |
| } | |
| protected boolean isVpcIpAddress(IPAddressVO ipAddress) { | |
| return ipAddress.getVpcId() != null; | |
| } | |
| protected Long validateFirewallRuleForIsolatedIp(IPAddressVO ipAddress) { | |
| if (ipAddress.getAssociatedWithNetworkId() == null) { | |
| throw new InvalidParameterValueException("Unable to create firewall rule ; ip with specified id is not associated with any network"); | |
| } | |
| return ipAddress.getAssociatedWithNetworkId(); | |
| } | |
| protected Long validateFirewallRuleForVpcIp(IPAddressVO ipAddress, Long networkId) { | |
| if (networkId == null) { | |
| throw new InvalidParameterValueException("Unable to retrieve network id to validate the rule"); | |
| } | |
| return networkId; | |
| } | |
| protected Map<Network.Capability, String> getFirewallServiceCapabilities(Network network) { | |
| if (network.getVpcId() == null) { | |
| return _networkModel.getNetworkServiceCapabilities(network.getId(), Service.Firewall); | |
| } | |
| for (FirewallServiceProvider fwElement : _firewallElements) { | |
| Network.Provider provider = fwElement.getProvider(); | |
| if (_vpcMgr.isProviderSupportServiceInVpc(network.getVpcId(), Service.Firewall, provider)) { | |
| Map<Service, Map<Capability, String>> capabilities = fwElement.getCapabilities(); | |
| if (capabilities != null && capabilities.get(Service.Firewall) != null) { | |
| return capabilities.get(Service.Firewall); | |
| } | |
| } | |
| } | |
| return _networkModel.getNetworkServiceCapabilities(network.getId(), Service.Firewall); | |
| } | |
| @Override | |
| public boolean applyRules(List<? extends FirewallRule> rules, boolean continueOnError, boolean updateRulesInDB) throws ResourceUnavailableException { | |
| boolean success = true; | |
| if (rules == null || rules.size() == 0) { | |
| logger.debug("There are no rules to forward to the network elements"); | |
| return true; | |
| } | |
| Purpose purpose = rules.get(0).getPurpose(); | |
| boolean applied; | |
| if (purpose.equals(Purpose.Ipv6Firewall)) { | |
| Network network = _networkDao.findById(rules.get(0).getNetworkId()); | |
| applied = applyRules(network, purpose, rules); | |
| } else { | |
| applied = _ipAddrMgr.applyRules(rules, purpose, this, continueOnError); | |
| } | |
| if (!applied) { | |
| logger.warn("Rules are not completely applied"); | |
| return false; | |
| } else { | |
| if (updateRulesInDB) { | |
| for (FirewallRule rule : rules) { | |
| if (rule.getState() == FirewallRule.State.Revoke) { | |
| FirewallRuleVO relatedRule = _firewallDao.findByRelatedId(rule.getId()); | |
| if (relatedRule != null) { | |
| logger.warn(String.format("Can't remove the firewall rule [%s] as it has related firewall rule [%s]; leaving it in Revoke state", rule, relatedRule)); | |
| success = false; | |
| } else { | |
| removeRule(rule); | |
| if (rule.getSourceIpAddressId() != null && rule.getVpcId() == null) { | |
| //if the rule is the last one for the ip address assigned to VPC, unassign it from the network | |
| _vpcMgr.unassignIPFromVpcNetwork(rule.getSourceIpAddressId(), rule.getNetworkId()); | |
| } | |
| } | |
| } else if (rule.getState() == FirewallRule.State.Add) { | |
| FirewallRuleVO ruleVO = _firewallDao.findById(rule.getId()); | |
| ruleVO.setState(FirewallRule.State.Active); | |
| _firewallDao.update(ruleVO.getId(), ruleVO); | |
| } | |
| } | |
| } | |
| } | |
| return success; | |
| } | |
| @Override | |
| public boolean applyRules(Network network, Vpc vpc, Purpose purpose, List<? extends FirewallRule> rules) throws ResourceUnavailableException { | |
| boolean handled = false; | |
| switch (purpose) { | |
| /* StaticNatRule would be applied by Firewall provider, since the incompatible of two object */ | |
| case StaticNat: | |
| case Firewall: | |
| case Ipv6Firewall: | |
| for (FirewallServiceProvider fwElement : _firewallElements) { | |
| Network.Provider provider = fwElement.getProvider(); | |
| boolean isFwProvider; | |
| Long effectiveVpcId = null; | |
| if (vpc != null) { | |
| effectiveVpcId = vpc.getId(); | |
| } else if (network != null) { | |
| effectiveVpcId = network.getVpcId(); | |
| } | |
| if (effectiveVpcId != null) { | |
| isFwProvider = _vpcMgr.isProviderSupportServiceInVpc(effectiveVpcId, Service.Firewall, provider); | |
| } else { | |
| isFwProvider = _networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.Firewall, provider); | |
| } | |
| if (!isFwProvider) { | |
| continue; | |
| } | |
| if (vpc != null) { | |
| handled = fwElement.applyFWRulesInVPC(vpc, rules); | |
| } else { | |
| handled = fwElement.applyFWRules(network, rules); | |
| } | |
| if (handled) | |
| break; | |
| } | |
| if (!handled) { | |
| // Get provider name and get the element by provider name (it could be an external provider) | |
| String fwProviderName = networkServiceMapDao.getProviderForServiceInNetwork(network.getId(), Service.Firewall); | |
| if (fwProviderName != null) { | |
| NetworkElement element = _networkModel.getElementImplementingProvider(fwProviderName); | |
| if (element instanceof FirewallServiceProvider) { | |
| handled = ((FirewallServiceProvider) element).applyFWRules(network, rules); | |
| } | |
| } | |
| } | |
| break; | |
| case PortForwarding: | |
| for (PortForwardingServiceProvider element : _pfElements) { | |
| Network.Provider provider = element.getProvider(); | |
| boolean isPfProvider = _networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.PortForwarding, provider); | |
| if (!isPfProvider) { | |
| continue; | |
| } | |
| handled = element.applyPFRules(network, (List<PortForwardingRule>)rules); | |
| if (handled) | |
| break; | |
| } | |
| if (!handled) { | |
| // Get provider name and get the element by provider name (it could be an external provider) | |
| String pfProviderName = networkServiceMapDao.getProviderForServiceInNetwork(network.getId(), Service.PortForwarding); | |
| if (pfProviderName != null) { | |
| NetworkElement element = _networkModel.getElementImplementingProvider(pfProviderName); | |
| if (element instanceof PortForwardingServiceProvider) { | |
| handled = ((PortForwardingServiceProvider) element).applyPFRules(network, (List<PortForwardingRule>) rules); | |
| } | |
| } | |
| } | |
| break; | |
| /* case NetworkACL: | |
| 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; | |
| } | |
| break;*/ | |
| default: | |
| assert (false) : "Unexpected fall through in applying rules to the network elements"; | |
| logger.error("FirewallManager cannot process rules of type " + purpose); | |
| throw new CloudRuntimeException("FirewallManager cannot process rules of type " + purpose); | |
| } | |
| return handled; | |
| } | |
| @Override | |
| public boolean applyRules(Network network, Purpose purpose, List<? extends FirewallRule> rules) throws ResourceUnavailableException { | |
| return applyRules(network, null, purpose, rules); | |
| } | |
| @Override | |
| public void removeRule(FirewallRule rule) { | |
| //remove the rule | |
| _firewallDao.remove(rule.getId()); | |
| } | |
| @Override | |
| @ActionEvent(eventType = EventTypes.EVENT_FIREWALL_OPEN, eventDescription = "creating firewall rule", async = true) | |
| public boolean applyIngressFwRules(long ipId, Account caller) throws ResourceUnavailableException { | |
| return applyIngressFirewallRules(ipId, caller); | |
| } | |
| @Override | |
| @DB | |
| public boolean applyIngressFirewallRules(long ipId, Account caller) throws ResourceUnavailableException { | |
| try { | |
| IPAddressVO ipAddress = _ipAddressDao.acquireInLockTable(ipId); | |
| if (ipAddress == null) { | |
| logger.error(String.format("Unable to acquire lock for public IP [%s].", ipId)); | |
| throw new CloudRuntimeException("Unable to acquire lock for public IP."); | |
| } | |
| List<FirewallRuleVO> rules = _firewallDao.listByIpAndPurpose(ipId, Purpose.Firewall); | |
| return applyFirewallRules(rules, false, caller); | |
| } finally { | |
| _ipAddressDao.releaseFromLockTable(ipId); | |
| } | |
| } | |
| @Override | |
| @ActionEvent(eventType = EventTypes.EVENT_FIREWALL_EGRESS_OPEN, eventDescription = "creating egress firewall rule", async = true) | |
| public boolean applyEgressFirewallRules(FirewallRule rule, Account caller) throws ResourceUnavailableException { | |
| List<FirewallRuleVO> rules = _firewallDao.listByNetworkPurposeTrafficType(rule.getNetworkId(), Purpose.Firewall, FirewallRule.TrafficType.Egress); | |
| return applyFirewallRules(rules, false, caller); | |
| } | |
| @Override | |
| public boolean applyFirewallRules(List<FirewallRuleVO> rules, boolean continueOnError, Account caller) { | |
| if (rules.size() == 0) { | |
| logger.debug("There are no firewall rules to apply"); | |
| return true; | |
| } | |
| for (FirewallRuleVO rule : rules) { | |
| // validate rule - for NSX | |
| Long networkId = rule.getNetworkId(); | |
| if (networkId != null) { | |
| validateNsxConstraints(networkId, rule); | |
| } | |
| // load cidrs if any | |
| rule.setSourceCidrList(_firewallCidrsDao.getSourceCidrs(rule.getId())); | |
| rule.setDestinationCidrsList(_firewallDcidrsDao.getDestCidrs(rule.getId())); | |
| } | |
| if (caller != null) { | |
| _accountMgr.checkAccess(caller, null, true, rules.toArray(new FirewallRuleVO[rules.size()])); | |
| } | |
| try { | |
| if (!applyRules(rules, continueOnError, true)) { | |
| return false; | |
| } | |
| } catch (ResourceUnavailableException ex) { | |
| logger.warn("Failed to apply firewall rules due to : "+ ex.getMessage()); | |
| return false; | |
| } | |
| return true; | |
| } | |
| private void validateNsxConstraints(long networkId, FirewallRuleVO rule) { | |
| String protocol = rule.getProtocol(); | |
| final Network network = entityManager.findById(Network.class, networkId); | |
| final DataCenter dc = entityManager.findById(DataCenter.class, network.getDataCenterId()); | |
| final NsxProviderVO nsxProvider = nsxProviderDao.findByZoneId(dc.getId()); | |
| if (Objects.isNull(nsxProvider)) { | |
| return; | |
| } | |
| if (NetUtils.ICMP_PROTO.equals(protocol.toLowerCase(Locale.ROOT)) && (rule.getIcmpType() == -1 || rule.getIcmpCode() == -1) | |
| && State.Add.equals(rule.getState())) { | |
| String errorMsg = "Passing -1 for ICMP type is not supported for NSX enabled zones"; | |
| logger.error(errorMsg); | |
| throw new InvalidParameterValueException(errorMsg); | |
| } | |
| if (List.of(NetUtils.TCP_PROTO, NetUtils.UDP_PROTO).contains(protocol.toLowerCase(Locale.ROOT)) && | |
| (Objects.isNull(rule.getSourcePortStart()) || Objects.isNull(rule.getSourcePortEnd())) && | |
| State.Add.equals(rule.getState())) { | |
| String errorMsg = "Source start and end ports are required to be passed"; | |
| logger.error(errorMsg); | |
| throw new InvalidParameterValueException(errorMsg); | |
| } | |
| } | |
| @Override | |
| public boolean applyDefaultEgressFirewallRule(Long networkId, boolean defaultPolicy, boolean add) throws ResourceUnavailableException { | |
| logger.debug("applying default firewall egress rules "); | |
| NetworkVO network = _networkDao.findById(networkId); | |
| List<String> sourceCidr = new ArrayList<String>(); | |
| List<String> destCidr = new ArrayList<String>(); | |
| sourceCidr.add(network.getCidr()); | |
| destCidr.add(NetUtils.ALL_IP4_CIDRS); | |
| FirewallRuleVO ruleVO = | |
| new FirewallRuleVO(null, null, null, null, "all", networkId, network.getAccountId(), network.getDomainId(), Purpose.Firewall, sourceCidr, destCidr, null, null, null, | |
| FirewallRule.TrafficType.Egress, FirewallRuleType.System); | |
| ruleVO.setState(add ? State.Add : State.Revoke); | |
| List<FirewallRuleVO> rules = new ArrayList<FirewallRuleVO>(); | |
| rules.add(ruleVO); | |
| try { | |
| //this is not required to store in db because we don't to add this rule along with the normal rules | |
| if (!applyRules(rules, false, false)) { | |
| return false; | |
| } | |
| } catch (ResourceUnavailableException ex) { | |
| logger.warn("Failed to apply default egress rules for guest network due to ", ex); | |
| return false; | |
| } | |
| return true; | |
| } | |
| protected boolean revokeFirewallRule(long ruleId, boolean apply, Account caller, long userId) { | |
| FirewallRuleVO rule = _firewallDao.findById(ruleId); | |
| if (rule == null || !Arrays.asList(Purpose.Firewall, Purpose.Ipv6Firewall).contains(rule.getPurpose())) { | |
| throw new InvalidParameterValueException("Unable to find " + ruleId + " having purpose " + Arrays.asList(Purpose.Firewall, Purpose.Ipv6Firewall)); | |
| } | |
| if (rule.getType() == FirewallRuleType.System && !_accountMgr.isRootAdmin(caller.getId())) { | |
| throw new InvalidParameterValueException("Only root admin can delete the system wide firewall rule"); | |
| } | |
| _accountMgr.checkAccess(caller, null, true, rule); | |
| revokeRule(rule, caller, userId, false); | |
| boolean success = false; | |
| Long networkId = rule.getNetworkId(); | |
| if (apply) { | |
| // ingress firewall rule | |
| if (rule.getSourceIpAddressId() != null) { | |
| //fetches ingress firewall, ingress firewall rules associated with the ip | |
| List<FirewallRuleVO> rules = _firewallDao.listByIpAndPurpose(rule.getSourceIpAddressId(), Purpose.Firewall); | |
| return applyFirewallRules(rules, false, caller); | |
| } else if (networkId != null) { | |
| //egress firewall rule, or ipv4/ipv6 routing firewall rule | |
| List<FirewallRuleVO> rules = _firewallDao.listByNetworkPurposeTrafficType(rule.getNetworkId(), rule.getPurpose(), rule.getTrafficType()); | |
| return applyFirewallRules(rules, false, caller); | |
| } | |
| } else { | |
| success = true; | |
| } | |
| return success; | |
| } | |
| @Override | |
| @ActionEvent(eventType = EventTypes.EVENT_FIREWALL_CLOSE, eventDescription = "revoking firewall rule", async = true) | |
| public boolean revokeIngressFwRule(long ruleId, boolean apply) { | |
| return revokeIngressFirewallRule(ruleId, apply); | |
| } | |
| @Override | |
| public boolean revokeIngressFirewallRule(long ruleId, boolean apply) { | |
| Account caller = CallContext.current().getCallingAccount(); | |
| long userId = CallContext.current().getCallingUserId(); | |
| return revokeFirewallRule(ruleId, apply, caller, userId); | |
| } | |
| @Override | |
| @ActionEvent(eventType = EventTypes.EVENT_FIREWALL_EGRESS_CLOSE, eventDescription = "revoking egress firewall rule", async = true) | |
| public boolean revokeEgressFirewallRule(long ruleId, boolean apply) { | |
| Account caller = CallContext.current().getCallingAccount(); | |
| long userId = CallContext.current().getCallingUserId(); | |
| return revokeFirewallRule(ruleId, apply, caller, userId); | |
| } | |
| @Override | |
| @ActionEvent(eventType = EventTypes.EVENT_FIREWALL_UPDATE, eventDescription = "updating firewall rule", async = true) | |
| public FirewallRule updateIngressFirewallRule(long ruleId, String customId, Boolean forDisplay) { | |
| Account caller = CallContext.current().getCallingAccount(); | |
| return updateFirewallRule(ruleId, customId, caller, forDisplay); | |
| } | |
| @Override | |
| @ActionEvent(eventType = EventTypes.EVENT_FIREWALL_EGRESS_UPDATE, eventDescription = "updating egress firewall rule", async = true) | |
| public FirewallRule updateEgressFirewallRule(long ruleId, String customId, Boolean forDisplay) { | |
| Account caller = CallContext.current().getCallingAccount(); | |
| return updateFirewallRule(ruleId, customId, caller, forDisplay); | |
| } | |
| protected FirewallRule updateFirewallRule(long ruleId, String customId, Account caller, Boolean forDisplay) { | |
| FirewallRuleVO rule = _firewallDao.findById(ruleId); | |
| if (rule == null || rule.getPurpose() != Purpose.Firewall) { | |
| throw new InvalidParameterValueException("Unable to find " + ruleId + " having purpose " + Purpose.Firewall); | |
| } | |
| if (rule.getType() == FirewallRuleType.System && caller.getType() != Account.Type.ADMIN) { | |
| throw new InvalidParameterValueException("Only root admin can update the system wide firewall rule"); | |
| } | |
| _accountMgr.checkAccess(caller, null, true, rule); | |
| if (customId != null) { | |
| rule.setUuid(customId); | |
| } | |
| if (forDisplay != null) { | |
| rule.setDisplay(forDisplay); | |
| } | |
| _firewallDao.update(ruleId, rule); | |
| return _firewallDao.findById(ruleId); | |
| } | |
| @Override | |
| @DB | |
| public void revokeRule(final FirewallRuleVO rule, Account caller, long userId, final boolean needUsageEvent) { | |
| if (caller != null) { | |
| _accountMgr.checkAccess(caller, null, true, rule); | |
| } | |
| Transaction.execute(new TransactionCallbackNoReturn() { | |
| @Override | |
| public void doInTransactionWithoutResult(TransactionStatus status) { | |
| boolean generateUsageEvent = false; | |
| if (rule.getState() == State.Staged) { | |
| if (logger.isDebugEnabled()) { | |
| logger.debug("Found a rule that is still in stage state so just removing it: " + rule); | |
| } | |
| removeRule(rule); | |
| generateUsageEvent = true; | |
| } else if (rule.getState() == State.Add || rule.getState() == State.Active) { | |
| rule.setState(State.Revoke); | |
| _firewallDao.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()); | |
| } | |
| } | |
| }); | |
| } | |
| @Override | |
| public FirewallRule getFirewallRule(long ruleId) { | |
| return _firewallDao.findById(ruleId); | |
| } | |
| @Override | |
| @ActionEvent(eventType = EventTypes.EVENT_FIREWALL_CLOSE, eventDescription = "revoking firewall rule", async = true) | |
| public boolean revokeFirewallRulesForIp(IpAddress ip, long userId, Account caller) throws ResourceUnavailableException { | |
| List<FirewallRule> rules = new ArrayList<FirewallRule>(); | |
| List<FirewallRuleVO> fwRules = _firewallDao.listByIpAndPurposeAndNotRevoked(ip.getId(), Purpose.Firewall); | |
| if (logger.isDebugEnabled()) { | |
| logger.debug("Releasing {} firewall rules for ip {}", fwRules.size(), ip); | |
| } | |
| for (FirewallRuleVO rule : fwRules) { | |
| // Mark all Firewall 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 | |
| revokeFirewallRule(rule.getId(), false, caller, Account.ACCOUNT_ID_SYSTEM); | |
| } | |
| // now send everything to the backend | |
| List<FirewallRuleVO> rulesToApply = _firewallDao.listByIpAndPurpose(ip.getId(), Purpose.Firewall); | |
| //apply rules | |
| if (!applyFirewallRules(rulesToApply, rulesContinueOnErrFlag, caller)) { | |
| if (!rulesContinueOnErrFlag) { | |
| return false; | |
| } | |
| } | |
| // Now we check again in case more rules have been inserted. | |
| rules.addAll(_firewallDao.listByIpAndPurposeAndNotRevoked(ip.getId(), Purpose.Firewall)); | |
| if (logger.isDebugEnabled()) { | |
| logger.debug("Successfully released firewall rules for ip {} and # of rules now = {}", ip, rules.size()); | |
| } | |
| return rules.size() == 0; | |
| } | |
| @Override | |
| @ActionEvent(eventType = EventTypes.EVENT_FIREWALL_OPEN, eventDescription = "creating firewall rule", create = true) | |
| public FirewallRule createRuleForAllCidrs(long ipAddrId, Account caller, Integer startPort, Integer endPort, String protocol, Integer icmpCode, Integer icmpType, | |
| Long relatedRuleId, long networkId) throws NetworkRuleConflictException { | |
| // If firwallRule for this port range already exists, return it | |
| List<FirewallRuleVO> rules = _firewallDao.listByIpPurposePortsProtocolAndNotRevoked(ipAddrId, startPort, endPort, protocol, Purpose.Firewall); | |
| if (!rules.isEmpty()) { | |
| return rules.get(0); | |
| } | |
| List<String> oneCidr = new ArrayList<String>(); | |
| oneCidr.add(NetUtils.ALL_IP4_CIDRS); | |
| return createFirewallRule(ipAddrId, caller, null, startPort, endPort, protocol, oneCidr, null, icmpCode, icmpType, relatedRuleId, FirewallRule.FirewallRuleType.User, | |
| networkId, null, FirewallRule.TrafficType.Ingress, true); | |
| } | |
| @Override | |
| @ActionEvent(eventType = EventTypes.EVENT_FIREWALL_CLOSE, eventDescription = "revoking firewall rule", async = true) | |
| public boolean revokeAllFirewallRulesForNetwork(Network network, long userId, Account caller) throws ResourceUnavailableException { | |
| List<FirewallRule> rules = new ArrayList<FirewallRule>(); | |
| List<FirewallRuleVO> fwRules = _firewallDao.listByNetworkAndPurposeAndNotRevoked(network.getId(), Purpose.Firewall); | |
| if (logger.isDebugEnabled()) { | |
| logger.debug("Releasing {} firewall rules for network {}", fwRules.size(), network); | |
| } | |
| for (FirewallRuleVO rule : fwRules) { | |
| // Mark all Firewall 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 | |
| revokeFirewallRule(rule.getId(), false, caller, Account.ACCOUNT_ID_SYSTEM); | |
| } | |
| // now send everything to the backend | |
| List<FirewallRuleVO> rulesToApply = _firewallDao.listByNetworkAndPurpose(network.getId(), Purpose.Firewall); | |
| boolean success = applyFirewallRules(rulesToApply, true, caller); | |
| // Now we check again in case more rules have been inserted. | |
| rules.addAll(_firewallDao.listByNetworkAndPurposeAndNotRevoked(network.getId(), Purpose.Firewall)); | |
| if (logger.isDebugEnabled()) { | |
| logger.debug("Successfully released firewall rules for network {} and # of rules now = {}", network, rules.size()); | |
| } | |
| return success && rules.size() == 0; | |
| } | |
| @Override | |
| public boolean revokeRelatedFirewallRule(long ruleId, boolean apply) { | |
| FirewallRule fwRule = _firewallDao.findByRelatedId(ruleId); | |
| if (fwRule == null) { | |
| logger.trace("No related firewall rule exists for rule id=" + ruleId + " so returning true here"); | |
| return true; | |
| } | |
| logger.debug("Revoking Firewall rule [{}] as a part of rule delete id={} with apply={}", fwRule, ruleId, apply); | |
| return revokeIngressFirewallRule(fwRule.getId(), apply); | |
| } | |
| @Override | |
| @ActionEvent(eventType = EventTypes.EVENT_FIREWALL_CLOSE, eventDescription = "revoking firewall rule", async = true) | |
| public boolean revokeFirewallRulesForVm(long vmId) { | |
| boolean success = true; | |
| UserVmVO vm = _vmDao.findByIdIncludingRemoved(vmId); | |
| if (vm == null) { | |
| return false; | |
| } | |
| List<PortForwardingRuleVO> pfRules = _pfRulesDao.listByVm(vmId); | |
| List<FirewallRuleVO> staticNatRules = _firewallDao.listStaticNatByVmId(vm.getId()); | |
| List<FirewallRuleVO> firewallRules = new ArrayList<FirewallRuleVO>(); | |
| // Make a list of firewall rules to reprogram | |
| for (PortForwardingRuleVO pfRule : pfRules) { | |
| FirewallRuleVO relatedRule = _firewallDao.findByRelatedId(pfRule.getId()); | |
| if (relatedRule != null) { | |
| firewallRules.add(relatedRule); | |
| } | |
| } | |
| for (FirewallRuleVO staticNatRule : staticNatRules) { | |
| FirewallRuleVO relatedRule = _firewallDao.findByRelatedId(staticNatRule.getId()); | |
| if (relatedRule != null) { | |
| firewallRules.add(relatedRule); | |
| } | |
| } | |
| Set<Long> ipsToReprogram = new HashSet<Long>(); | |
| if (firewallRules.isEmpty()) { | |
| logger.debug("No firewall rules are found for vm: {}", vm); | |
| return true; | |
| } else { | |
| logger.debug("Found {} to cleanup for vm: {}", firewallRules.size(), vm); | |
| } | |
| for (FirewallRuleVO rule : firewallRules) { | |
| // Mark firewall rules as Revoked, but don't revoke it yet (apply=false) | |
| revokeFirewallRule(rule.getId(), false, _accountMgr.getSystemAccount(), Account.ACCOUNT_ID_SYSTEM); | |
| ipsToReprogram.add(rule.getSourceIpAddressId()); | |
| } | |
| // apply rules for all ip addresses | |
| for (Long ipId : ipsToReprogram) { | |
| IPAddressVO ip = _ipAddressDao.findById(ipId); | |
| logger.debug("Applying firewall rules for ip address {} with id={} as a part of vm expunge", ip, ipId); | |
| try { | |
| success = success && applyIngressFirewallRules(ipId, _accountMgr.getSystemAccount()); | |
| } catch (ResourceUnavailableException ex) { | |
| logger.warn("Failed to apply firewall rules for ip {}", ip); | |
| success = false; | |
| } | |
| } | |
| return success; | |
| } | |
| @Override | |
| @ActionEvent(eventType = EventTypes.EVENT_FIREWALL_OPEN, eventDescription = "creating firewall rule", create = true) | |
| public boolean addSystemFirewallRules(IPAddressVO ip, Account acct) { | |
| List<FirewallRuleVO> systemRules = _firewallDao.listSystemRules(); | |
| for (FirewallRuleVO rule : systemRules) { | |
| try { | |
| if (rule.getSourceCidrList() == null && (rule.getPurpose() == Purpose.Firewall || rule.getPurpose() == Purpose.NetworkACL)) { | |
| _firewallDao.loadSourceCidrs(rule); | |
| } | |
| createFirewallRule(ip.getId(), acct, rule.getXid(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getProtocol(), rule.getSourceCidrList(),null, | |
| rule.getIcmpCode(), rule.getIcmpType(), rule.getRelated(), FirewallRuleType.System, rule.getNetworkId(), rule.getVpcId(), rule.getTrafficType(), true); | |
| } catch (Exception e) { | |
| logger.debug("Failed to add system wide firewall rule, due to:" + e.toString()); | |
| } | |
| } | |
| return true; | |
| } | |
| public List<FirewallServiceProvider> getFirewallElements() { | |
| return _firewallElements; | |
| } | |
| @Inject | |
| public void setFirewallElements(List<FirewallServiceProvider> firewallElements) { | |
| _firewallElements = firewallElements; | |
| } | |
| public List<PortForwardingServiceProvider> getPfElements() { | |
| return _pfElements; | |
| } | |
| @Inject | |
| public void setPfElements(List<PortForwardingServiceProvider> pfElements) { | |
| _pfElements = pfElements; | |
| } | |
| public List<StaticNatServiceProvider> getStaticNatElements() { | |
| return _staticNatElements; | |
| } | |
| @Inject | |
| public void setStaticNatElements(List<StaticNatServiceProvider> staticNatElements) { | |
| _staticNatElements = staticNatElements; | |
| } | |
| public List<NetworkACLServiceProvider> getNetworkAclElements() { | |
| return _networkAclElements; | |
| } | |
| @Inject | |
| public void setNetworkAclElements(List<NetworkACLServiceProvider> networkAclElements) { | |
| _networkAclElements = networkAclElements; | |
| } | |
| } |