Skip to content

Commit 8ad3a1b

Browse files
committed
Refactor giant if & add unit tests
1 parent c7568f1 commit 8ad3a1b

File tree

2 files changed

+141
-19
lines changed

2 files changed

+141
-19
lines changed

server/src/main/java/com/cloud/network/firewall/FirewallManagerImpl.java

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
4141
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
4242
import org.apache.cloudstack.network.RoutedIpv4Manager;
43+
import org.apache.commons.lang3.ObjectUtils;
4344
import org.springframework.stereotype.Component;
4445

4546
import com.cloud.configuration.Config;
@@ -410,12 +411,13 @@ public void detectRulesConflict(FirewallRule newRule) throws NetworkRuleConflict
410411
_firewallDao.loadSourceCidrs(rule);
411412
_firewallDao.loadSourceCidrs((FirewallRuleVO)newRule);
412413

414+
if (ObjectUtils.anyNull(rule.getSourceCidrList(), newRule.getSourceCidrList())) {
415+
continue;
416+
}
417+
413418
_firewallDao.loadDestinationCidrs(rule);
414419
_firewallDao.loadDestinationCidrs((FirewallRuleVO) newRule);
415420

416-
if (rule.getSourceCidrList() == null || newRule.getSourceCidrList() == null) {
417-
continue;
418-
}
419421
duplicatedCidrs = (detectConflictingCidrs(rule.getSourceCidrList(), newRule.getSourceCidrList()) && detectConflictingCidrs(rule.getDestinationCidrList(), newRule.getDestinationCidrList()));
420422
}
421423

@@ -424,7 +426,7 @@ public void detectRulesConflict(FirewallRule newRule) throws NetworkRuleConflict
424426
_firewallDao.loadSourceCidrs(rule);
425427
_firewallDao.loadSourceCidrs((FirewallRuleVO) newRule);
426428

427-
if (rule.getSourceCidrList() == null || newRule.getSourceCidrList() == null) {
429+
if (ObjectUtils.anyNull(rule.getSourceCidrList(), newRule.getSourceCidrList())) {
428430
continue;
429431
}
430432

@@ -464,18 +466,7 @@ public void detectRulesConflict(FirewallRule newRule) throws NetworkRuleConflict
464466

465467
if (!notNullPorts) {
466468
continue;
467-
} else if (!oneOfRulesIsFirewall &&
468-
!((bothRulesFirewall || bothRulesPortForwarding) && !duplicatedCidrs) &&
469-
((rule.getSourcePortStart().intValue() <= newRule.getSourcePortStart().intValue() &&
470-
rule.getSourcePortEnd().intValue() >= newRule.getSourcePortStart().intValue()) ||
471-
(rule.getSourcePortStart().intValue() <= newRule.getSourcePortEnd().intValue() &&
472-
rule.getSourcePortEnd().intValue() >= newRule.getSourcePortEnd().intValue()) ||
473-
(newRule.getSourcePortStart().intValue() <= rule.getSourcePortStart().intValue() &&
474-
newRule.getSourcePortEnd().intValue() >= rule.getSourcePortStart().intValue()) ||
475-
(newRule.getSourcePortStart().intValue() <= rule.getSourcePortEnd().intValue() &&
476-
newRule.getSourcePortEnd().intValue() >= rule.getSourcePortEnd().intValue()))) {
477-
//Above else if conditions checks for the conflicting port ranges.
478-
469+
} else if (checkIfRulesHaveConflictingPortRanges(newRule, rule, oneOfRulesIsFirewall, bothRulesFirewall, bothRulesPortForwarding, duplicatedCidrs)) {
479470
// we allow port forwarding rules with the same parameters but different protocols
480471
boolean allowPf =
481472
(rule.getPurpose() == Purpose.PortForwarding && newRule.getPurpose() == Purpose.PortForwarding && !newRule.getProtocol().equalsIgnoreCase(
@@ -502,6 +493,45 @@ public void detectRulesConflict(FirewallRule newRule) throws NetworkRuleConflict
502493
}
503494
}
504495

496+
protected boolean checkIfRulesHaveConflictingPortRanges(FirewallRule newRule, FirewallRule rule, boolean oneOfRulesIsFirewall, boolean bothRulesFirewall, boolean bothRulesPortForwarding, boolean duplicatedCidrs) {
497+
String rulesAsString = String.format("[%s] and [%s]", rule, newRule);
498+
499+
if (oneOfRulesIsFirewall) {
500+
logger.debug("Only one of the rules (%s) is firewall; therefore, their port ranges will not conflict.",
501+
rulesAsString);
502+
return false;
503+
}
504+
505+
if ((bothRulesFirewall || bothRulesPortForwarding) && !duplicatedCidrs) {
506+
logger.debug("Both rules (%s) are firewall/port forwarding, but they do not have duplicated CIDRs; therefore, their port ranges will not conflict.",
507+
rulesAsString);
508+
return false;
509+
}
510+
511+
if (rule.getSourcePortStart() <= newRule.getSourcePortStart() && rule.getSourcePortEnd() >= newRule.getSourcePortStart()) {
512+
logger.debug("Rules (%s) have conflicting port ranges.", rulesAsString);
513+
return true;
514+
}
515+
516+
if (rule.getSourcePortStart() <= newRule.getSourcePortEnd() && rule.getSourcePortEnd() >= newRule.getSourcePortEnd()) {
517+
logger.debug("Rules (%s) have conflicting port ranges.", rulesAsString);
518+
return true;
519+
}
520+
521+
if (newRule.getSourcePortStart() <= rule.getSourcePortStart() && newRule.getSourcePortEnd() >= rule.getSourcePortStart()) {
522+
logger.debug("Rules (%s) have conflicting port ranges.", rulesAsString);
523+
return true;
524+
}
525+
526+
if (newRule.getSourcePortStart() <= rule.getSourcePortEnd() && newRule.getSourcePortEnd() >= rule.getSourcePortEnd()) {
527+
logger.debug("Rules (%s) have conflicting port ranges.", rulesAsString);
528+
return true;
529+
}
530+
531+
logger.debug("Rules (%s) do not have conflicting port ranges.", rulesAsString);
532+
return false;
533+
}
534+
505535
@Override
506536
public void validateFirewallRule(Account caller, IPAddressVO ipAddress, Integer portStart, Integer portEnd, String proto, Purpose purpose, FirewallRuleType type,
507537
Long networkId, FirewallRule.TrafficType trafficType) {

server/src/test/java/com/cloud/network/firewall/FirewallManagerTest.java

Lines changed: 95 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,26 +27,26 @@
2727
import com.cloud.network.element.FirewallServiceProvider;
2828
import com.cloud.network.element.VirtualRouterElement;
2929
import com.cloud.network.element.VpcVirtualRouterElement;
30-
import com.cloud.network.rules.FirewallManager;
3130
import com.cloud.network.rules.FirewallRule;
3231
import com.cloud.network.rules.FirewallRule.Purpose;
3332
import com.cloud.network.rules.FirewallRuleVO;
3433
import com.cloud.network.vpc.VpcManager;
3534
import com.cloud.user.AccountManager;
3635
import com.cloud.user.DomainManager;
3736
import com.cloud.utils.component.ComponentContext;
38-
import junit.framework.Assert;
3937
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
4038
import org.apache.logging.log4j.Logger;
4139
import org.apache.logging.log4j.LogManager;
4240
import org.junit.After;
41+
import org.junit.Assert;
4342
import org.junit.Before;
4443
import org.junit.Ignore;
4544
import org.junit.Test;
4645
import org.junit.runner.RunWith;
4746
import org.mockito.InjectMocks;
4847
import org.mockito.Mock;
4948
import org.mockito.MockitoAnnotations;
49+
import org.mockito.Spy;
5050
import org.mockito.junit.MockitoJUnitRunner;
5151

5252
import java.util.ArrayList;
@@ -111,19 +111,42 @@ public void testInjected() {
111111
@Mock
112112
FirewallRulesDao _firewallDao;
113113

114+
@Spy
114115
@InjectMocks
115-
FirewallManager _firewallMgr = new FirewallManagerImpl();
116+
FirewallManagerImpl _firewallMgr;
117+
118+
FirewallRule fwRule50to150;
119+
FirewallRule fwRule100to200;
120+
FirewallRule fwRule151to200;
121+
122+
FirewallRule pfRule50to150;
123+
FirewallRule pfRule100to200;
124+
FirewallRule pfRule151to200;
125+
116126

117127
@Before
118128
public void initMocks() {
119129
closeable = MockitoAnnotations.openMocks(this);
130+
131+
fwRule50to150 = createFirewallRule(50, 150, Purpose.Firewall);
132+
fwRule100to200 = createFirewallRule(100, 150, Purpose.Firewall);
133+
fwRule151to200 = createFirewallRule(151, 200, Purpose.Firewall);
134+
135+
pfRule50to150 = createFirewallRule(50, 150, Purpose.PortForwarding);
136+
pfRule100to200 = createFirewallRule(100, 150, Purpose.PortForwarding);
137+
pfRule151to200 = createFirewallRule(151, 200, Purpose.PortForwarding);
120138
}
121139

122140
@After
123141
public void tearDown() throws Exception {
124142
closeable.close();
125143
}
126144

145+
private FirewallRule createFirewallRule(int startPort, int endPort, Purpose purpose) {
146+
return new FirewallRuleVO("xid", 1L, startPort, endPort, "TCP", 2, 3, 4, purpose, new ArrayList<>(),
147+
new ArrayList<>(), 5, 6, null, FirewallRule.TrafficType.Ingress);
148+
}
149+
127150
@Ignore("Requires database to be set up")
128151
@Test
129152
public void testApplyRules() {
@@ -218,6 +241,75 @@ public void testDetectRulesConflict() {
218241
}
219242
}
220243

244+
@Test
245+
public void checkIfRulesHaveConflictingPortRangesTestOnlyOneRuleIsFirewallReturnsFalse()
246+
{
247+
boolean result = _firewallMgr.checkIfRulesHaveConflictingPortRanges(fwRule50to150, pfRule50to150, true, false, false, true);
248+
249+
Assert.assertFalse(result);
250+
}
251+
252+
@Test
253+
public void checkIfRulesHaveConflictingPortRangesTestBothRulesAreFirewallButNoDuplicateCidrsReturnsFalse()
254+
{
255+
boolean result = _firewallMgr.checkIfRulesHaveConflictingPortRanges(fwRule50to150, fwRule50to150, false, true, false, false);
256+
257+
Assert.assertFalse(result);
258+
}
259+
260+
@Test
261+
public void checkIfRulesHaveConflictingPortRangesTestBothRulesArePortForwardingButNoDuplicateCidrsReturnsFalse()
262+
{
263+
boolean result = _firewallMgr.checkIfRulesHaveConflictingPortRanges(pfRule50to150, pfRule50to150, false, false, true, false);
264+
265+
Assert.assertFalse(result);
266+
}
267+
268+
@Test
269+
public void checkIfRulesHaveConflictingPortRangesTestBothRulesAreFirewallAndDuplicatedCidrsAndNewRuleSourceStartPortIsInsideExistingRangeReturnsTrue()
270+
{
271+
boolean result = _firewallMgr.checkIfRulesHaveConflictingPortRanges(fwRule100to200, fwRule50to150, false, true, false, true);
272+
273+
Assert.assertTrue(result);
274+
}
275+
276+
@Test
277+
public void checkIfRulesHaveConflictingPortRangesTestBothRulesAreFirewallAndDuplicatedCidrsAndNewRuleSourceEndPortIsInsideExistingRangeReturnsTrue()
278+
{
279+
boolean result = _firewallMgr.checkIfRulesHaveConflictingPortRanges(fwRule50to150, fwRule100to200, false, true, false, true);
280+
281+
Assert.assertTrue(result);
282+
}
283+
284+
@Test
285+
public void checkIfRulesHaveConflictingPortRangesTestBothRulesArePortForwardingAndDuplicatedCidrsAndNewRuleSourceStartPortIsInsideExistingRangeReturnsTrue()
286+
{
287+
boolean result = _firewallMgr.checkIfRulesHaveConflictingPortRanges(pfRule50to150, pfRule100to200, false, false, true, true);
288+
289+
Assert.assertTrue(result);
290+
}
291+
292+
@Test
293+
public void checkIfRulesHaveConflictingPortRangesTestBothRulesArePortForwardingAndDuplicatedCidrsAndNewRuleSourceEndPortIsInsideExistingRangeReturnsTrue()
294+
{
295+
boolean result = _firewallMgr.checkIfRulesHaveConflictingPortRanges(pfRule50to150, pfRule100to200, false, false, true, true);
296+
297+
Assert.assertTrue(result);
298+
}
299+
300+
@Test
301+
public void checkIfRulesHaveConflictingPortRangesTestBothRulesAreFirewallAndDuplicatedCidrsAndNoRangeConflictReturnsFalse()
302+
{
303+
boolean result = _firewallMgr.checkIfRulesHaveConflictingPortRanges(fwRule50to150, fwRule151to200, false, true, false, true);
221304

305+
Assert.assertFalse(result);
306+
}
222307

308+
@Test
309+
public void checkIfRulesHaveConflictingPortRangesTestBothRulesArePortForwardingAndDuplicatedCidrsAndNoRangeConflictReturnsFalse()
310+
{
311+
boolean result = _firewallMgr.checkIfRulesHaveConflictingPortRanges(pfRule50to150, pfRule151to200, false, false, true, true);
312+
313+
Assert.assertFalse(result);
314+
}
223315
}

0 commit comments

Comments
 (0)