Search in sources :

Example 51 with NetworkRuleConflictException

use of com.cloud.exception.NetworkRuleConflictException in project cosmic by MissionCriticalCloud.

the class FirewallManagerImpl method createFirewallRule.

@DB
protected FirewallRule createFirewallRule(final Long ipAddrId, final Account caller, final String xId, final Integer portStart, final Integer portEnd, final String protocol, final List<String> sourceCidrList, 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;
    if (ipAddrId != null) {
        // this for ingress firewall rule, for egress id is null
        ipAddress = _ipAddressDao.findById(ipAddrId);
        // Validate ip address
        if (ipAddress == null && type == FirewallRule.FirewallRuleType.User) {
            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
        final Network network = _networkModel.getNetwork(networkId);
        accountId = network.getAccountId();
        domainId = network.getDomainId();
    }
    final Long accountIdFinal = accountId;
    final Long domainIdFinal = domainId;
    return Transaction.execute(new TransactionCallbackWithException<FirewallRuleVO, NetworkRuleConflictException>() {

        @Override
        public FirewallRuleVO doInTransaction(final TransactionStatus status) throws NetworkRuleConflictException {
            FirewallRuleVO newRule = new FirewallRuleVO(xId, ipAddrId, portStart, portEnd, protocol.toLowerCase(), networkId, accountIdFinal, domainIdFinal, Purpose.Firewall, sourceCidrList, 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.getId());
            return newRule;
        }
    });
}
Also used : InvalidParameterValueException(com.cloud.utils.exception.InvalidParameterValueException) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) Network(com.cloud.network.Network) TransactionStatus(com.cloud.utils.db.TransactionStatus) IPAddressVO(com.cloud.network.dao.IPAddressVO) NetworkRuleConflictException(com.cloud.exception.NetworkRuleConflictException) FirewallRuleVO(com.cloud.network.rules.FirewallRuleVO) DB(com.cloud.utils.db.DB)

Example 52 with NetworkRuleConflictException

use of com.cloud.exception.NetworkRuleConflictException in project cosmic by MissionCriticalCloud.

the class FirewallManagerImpl method detectRulesConflict.

@Override
public void detectRulesConflict(final FirewallRule newRule) throws NetworkRuleConflictException {
    final 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);
    }
    for (final FirewallRuleVO rule : rules) {
        if (rule.getId() == newRule.getId()) {
            // Skips my own rule.
            continue;
        }
        final boolean oneOfRulesIsFirewall = ((rule.getPurpose() == Purpose.Firewall || newRule.getPurpose() == Purpose.Firewall) && ((newRule.getPurpose() != rule.getPurpose()) || (!newRule.getProtocol().equalsIgnoreCase(rule.getProtocol()))));
        // if both rules are firewall and their cidrs are different, we can skip port ranges verification
        final boolean bothRulesFirewall = (rule.getPurpose() == newRule.getPurpose() && rule.getPurpose() == Purpose.Firewall);
        boolean duplicatedCidrs = false;
        if (bothRulesFirewall) {
            // Verify that the rules have different cidrs
            _firewallDao.loadSourceCidrs(rule);
            _firewallDao.loadSourceCidrs((FirewallRuleVO) newRule);
            final List<String> ruleCidrList = rule.getSourceCidrList();
            final List<String> newRuleCidrList = newRule.getSourceCidrList();
            if (ruleCidrList == null || newRuleCidrList == null) {
                continue;
            }
            final Collection<String> similar = new HashSet<>(ruleCidrList);
            similar.retainAll(newRuleCidrList);
            if (similar.size() > 0) {
                duplicatedCidrs = true;
            }
        }
        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());
            }
        }
        if (rule.getNetworkId() != newRule.getNetworkId() && rule.getState() != State.Revoke) {
            throw new NetworkRuleConflictException("New rule is for a different network than what's specified in rule " + rule.getXid());
        }
        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("New rule conflicts with existing rule id=" + rule.getId());
            }
        }
        final boolean notNullPorts = (newRule.getSourcePortStart() != null && newRule.getSourcePortEnd() != null && rule.getSourcePortStart() != null && rule.getSourcePortEnd() != null);
        final boolean nullPorts = (newRule.getSourcePortStart() == null && newRule.getSourcePortEnd() == null && rule.getSourcePortStart() == null && rule.getSourcePortEnd() == null);
        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 (!oneOfRulesIsFirewall && !(bothRulesFirewall && !duplicatedCidrs) && ((rule.getSourcePortStart().intValue() <= newRule.getSourcePortStart().intValue() && rule.getSourcePortEnd().intValue() >= newRule.getSourcePortStart().intValue()) || (rule.getSourcePortStart().intValue() <= newRule.getSourcePortEnd().intValue() && rule.getSourcePortEnd().intValue() >= newRule.getSourcePortEnd().intValue()) || (newRule.getSourcePortStart().intValue() <= rule.getSourcePortStart().intValue() && newRule.getSourcePortEnd().intValue() >= rule.getSourcePortStart().intValue()) || (newRule.getSourcePortStart().intValue() <= rule.getSourcePortEnd().intValue() && newRule.getSourcePortEnd().intValue() >= rule.getSourcePortEnd().intValue()))) {
            // we allow port forwarding rules with the same parameters but different protocols
            final 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()));
            final boolean allowStaticNat = (rule.getPurpose() == Purpose.StaticNat && newRule.getPurpose() == Purpose.StaticNat && !newRule.getProtocol().equalsIgnoreCase(rule.getProtocol()));
            final boolean allowVpnPf = (rule.getPurpose() == Purpose.PortForwarding && newRule.getPurpose() == Purpose.Vpn && !newRule.getProtocol().equalsIgnoreCase(rule.getProtocol()));
            final boolean allowVpnLb = (rule.getPurpose() == Purpose.LoadBalancing && newRule.getPurpose() == Purpose.Vpn && !newRule.getProtocol().equalsIgnoreCase(rule.getProtocol()));
            if (!(allowPf || allowStaticNat || oneOfRulesIsFirewall || allowVpnPf || allowVpnLb)) {
                throw new NetworkRuleConflictException("The range specified, " + newRule.getSourcePortStart() + "-" + newRule.getSourcePortEnd() + ", conflicts with rule " + rule.getId() + " which has " + rule.getSourcePortStart() + "-" + rule.getSourcePortEnd());
            }
        }
    }
    if (s_logger.isDebugEnabled()) {
        s_logger.debug("No network rule conflicts detected for " + newRule + " against " + (rules.size() - 1) + " existing rules");
    }
}
Also used : InvalidParameterValueException(com.cloud.utils.exception.InvalidParameterValueException) NetworkRuleConflictException(com.cloud.exception.NetworkRuleConflictException) FirewallRuleVO(com.cloud.network.rules.FirewallRuleVO) HashSet(java.util.HashSet)

Example 53 with NetworkRuleConflictException

use of com.cloud.exception.NetworkRuleConflictException in project cosmic by MissionCriticalCloud.

the class CreateEgressFirewallRuleCmd method create.

@Override
public void create() {
    if (getSourceCidrList() != null) {
        final String guestCidr = _networkService.getNetwork(getNetworkId()).getCidr();
        for (final String cidr : getSourceCidrList()) {
            if (!NetUtils.isValidIp4Cidr(cidr) && !NetUtils.isValidIp6Cidr(cidr)) {
                throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Source cidrs formatting error " + cidr);
            }
            if (cidr.equals(NetUtils.ALL_IP4_CIDRS)) {
                continue;
            }
            if (!NetUtils.isNetworkAWithinNetworkB(cidr, guestCidr)) {
                throw new ServerApiException(ApiErrorCode.PARAM_ERROR, cidr + " is not within the guest cidr " + guestCidr);
            }
        }
    }
    if (getProtocol().equalsIgnoreCase(NetUtils.ALL_PROTO)) {
        if (getSourcePortStart() != null && getSourcePortEnd() != null) {
            throw new InvalidParameterValueException("Do not pass ports to protocol ALL, protocol ALL do not require ports. Unable to create " + "firewall rule for the network id=" + networkId);
        }
    }
    if (getVpcId() != null) {
        throw new InvalidParameterValueException("Unable to create firewall rule for the network id=" + networkId + " as firewall egress rule can be created only for non vpc networks.");
    }
    try {
        final FirewallRule result = _firewallService.createEgressFirewallRule(this);
        if (result != null) {
            setEntityId(result.getId());
            setEntityUuid(result.getUuid());
        }
    } catch (final NetworkRuleConflictException ex) {
        s_logger.info("Network rule conflict: " + ex.getMessage());
        s_logger.trace("Network Rule Conflict: ", ex);
        throw new ServerApiException(ApiErrorCode.NETWORK_RULE_CONFLICT_ERROR, ex.getMessage());
    }
}
Also used : ServerApiException(com.cloud.api.ServerApiException) InvalidParameterValueException(com.cloud.utils.exception.InvalidParameterValueException) FirewallRule(com.cloud.network.rules.FirewallRule) NetworkRuleConflictException(com.cloud.exception.NetworkRuleConflictException)

Example 54 with NetworkRuleConflictException

use of com.cloud.exception.NetworkRuleConflictException in project cosmic by MissionCriticalCloud.

the class ApiDispatcher method dispatch.

public void dispatch(final BaseCmd cmd, final Map<String, String> params, final boolean execute) throws CloudException {
    // Let the chain of responsibility dispatch gradually
    standardDispatchChain.dispatch(new DispatchTask(cmd, params));
    final CallContext ctx = CallContext.current();
    ctx.setEventDisplayEnabled(cmd.isDisplay());
    if (params.get(ApiConstants.PROJECT_ID) != null) {
        final Project project = _entityMgr.findByUuidIncludingRemoved(Project.class, params.get(ApiConstants.PROJECT_ID));
        ctx.setProject(project);
    }
    // TODO This if shouldn't be here. Use polymorphism and move it to validateSpecificParameters
    if (cmd instanceof BaseAsyncCmd) {
        final BaseAsyncCmd asyncCmd = (BaseAsyncCmd) cmd;
        final String startEventId = params.get(ApiConstants.CTX_START_EVENT_ID);
        ctx.setStartEventId(Long.parseLong(startEventId));
        // Synchronise job on the object if needed
        if (asyncCmd.getJob() != null && asyncCmd.getSyncObjId() != null && asyncCmd.getSyncObjType() != null) {
            final Long queueSizeLimit;
            if (asyncCmd.getSyncObjType() != null && asyncCmd.getSyncObjType().equalsIgnoreCase(BaseAsyncCmd.snapshotHostSyncObject)) {
                queueSizeLimit = _createSnapshotQueueSizeLimit;
            } else {
                queueSizeLimit = 1L;
            }
            if (queueSizeLimit != null) {
                if (!execute) {
                    // if we are not within async-execution context, enqueue the command
                    _asyncMgr.syncAsyncJobExecution((AsyncJob) asyncCmd.getJob(), asyncCmd.getSyncObjType(), asyncCmd.getSyncObjId().longValue(), queueSizeLimit);
                    return;
                }
            } else {
                s_logger.trace("The queue size is unlimited, skipping the synchronizing");
            }
        }
    }
    // TODO This if shouldn't be here. Use polymorphism and move it to validateSpecificParameters
    if (cmd instanceof BaseAsyncCustomIdCmd) {
        ((BaseAsyncCustomIdCmd) cmd).checkUuid();
    } else if (cmd instanceof BaseCustomIdCmd) {
        ((BaseCustomIdCmd) cmd).checkUuid();
    }
    try {
        cmd.execute();
    } catch (ResourceUnavailableException | InsufficientCapacityException | ResourceAllocationException | NetworkRuleConflictException e) {
        throw new CloudException("Caught exception while executing command", e);
    }
}
Also used : CloudException(com.cloud.exception.CloudException) CallContext(com.cloud.context.CallContext) NetworkRuleConflictException(com.cloud.exception.NetworkRuleConflictException) Project(com.cloud.projects.Project) ResourceUnavailableException(com.cloud.exception.ResourceUnavailableException) InsufficientCapacityException(com.cloud.exception.InsufficientCapacityException) ResourceAllocationException(com.cloud.exception.ResourceAllocationException) DispatchTask(com.cloud.api.dispatch.DispatchTask)

Example 55 with NetworkRuleConflictException

use of com.cloud.exception.NetworkRuleConflictException in project cosmic by MissionCriticalCloud.

the class FirewallManagerTest method testDetectRulesConflict.

@Test
public void testDetectRulesConflict() {
    final List<FirewallRuleVO> ruleList = new ArrayList<>();
    final FirewallRuleVO rule1 = spy(new FirewallRuleVO("rule1", 3, 500, "UDP", 1, 2, 1, Purpose.Vpn, null, null, null, null));
    final FirewallRuleVO rule2 = spy(new FirewallRuleVO("rule2", 3, 1701, "UDP", 1, 2, 1, Purpose.Vpn, null, null, null, null));
    final FirewallRuleVO rule3 = spy(new FirewallRuleVO("rule3", 3, 4500, "UDP", 1, 2, 1, Purpose.Vpn, null, null, null, null));
    ruleList.add(rule1);
    ruleList.add(rule2);
    ruleList.add(rule3);
    final FirewallManagerImpl firewallMgr = (FirewallManagerImpl) _firewallMgr;
    when(firewallMgr._firewallDao.listByIpAndPurposeAndNotRevoked(3, null)).thenReturn(ruleList);
    when(rule1.getId()).thenReturn(1L);
    when(rule2.getId()).thenReturn(2L);
    when(rule3.getId()).thenReturn(3L);
    final FirewallRule newRule1 = new FirewallRuleVO("newRule1", 3, 500, "TCP", 1, 2, 1, Purpose.PortForwarding, null, null, null, null);
    final FirewallRule newRule2 = new FirewallRuleVO("newRule2", 3, 1701, "TCP", 1, 2, 1, Purpose.PortForwarding, null, null, null, null);
    final FirewallRule newRule3 = new FirewallRuleVO("newRule3", 3, 4500, "TCP", 1, 2, 1, Purpose.PortForwarding, null, null, null, null);
    try {
        firewallMgr.detectRulesConflict(newRule1);
        firewallMgr.detectRulesConflict(newRule2);
        firewallMgr.detectRulesConflict(newRule3);
    } catch (final NetworkRuleConflictException ex) {
        Assert.fail();
    }
}
Also used : ArrayList(java.util.ArrayList) FirewallRule(com.cloud.network.rules.FirewallRule) NetworkRuleConflictException(com.cloud.exception.NetworkRuleConflictException) FirewallRuleVO(com.cloud.network.rules.FirewallRuleVO) Test(org.junit.Test)

Aggregations

NetworkRuleConflictException (com.cloud.exception.NetworkRuleConflictException)85 ResourceUnavailableException (com.cloud.exception.ResourceUnavailableException)41 CloudRuntimeException (com.cloud.utils.exception.CloudRuntimeException)28 InsufficientCapacityException (com.cloud.exception.InsufficientCapacityException)26 ResourceAllocationException (com.cloud.exception.ResourceAllocationException)26 ConcurrentOperationException (com.cloud.exception.ConcurrentOperationException)25 ServerApiException (org.apache.cloudstack.api.ServerApiException)25 InvalidParameterValueException (com.cloud.exception.InvalidParameterValueException)19 ServerApiException (com.cloud.api.ServerApiException)18 Network (com.cloud.network.Network)18 IPAddressVO (com.cloud.network.dao.IPAddressVO)17 InsufficientAddressCapacityException (com.cloud.exception.InsufficientAddressCapacityException)16 TransactionStatus (com.cloud.utils.db.TransactionStatus)16 DB (com.cloud.utils.db.DB)15 InvalidParameterValueException (com.cloud.utils.exception.InvalidParameterValueException)14 SuccessResponse (org.apache.cloudstack.api.response.SuccessResponse)13 Account (com.cloud.user.Account)12 TransactionCallbackWithException (com.cloud.utils.db.TransactionCallbackWithException)11 IpAddress (com.cloud.network.IpAddress)10 ActionEvent (com.cloud.event.ActionEvent)8