diff --git a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/DeletedNsxDistributedFirewallRulesCommand.java b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/DeletedNsxDistributedFirewallRulesCommand.java new file mode 100644 index 00000000000..7fe585a5cb7 --- /dev/null +++ b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/agent/api/DeletedNsxDistributedFirewallRulesCommand.java @@ -0,0 +1,11 @@ +package org.apache.cloudstack.agent.api; + +import org.apache.cloudstack.resource.NsxNetworkRule; + +import java.util.List; + +public class DeletedNsxDistributedFirewallRulesCommand extends CreateNsxDistributedFirewallRulesCommand { + public DeletedNsxDistributedFirewallRulesCommand(long domainId, long accountId, long zoneId, Long vpcId, long networkId, List rules) { + super(domainId, accountId, zoneId, vpcId, networkId, rules); + } +} diff --git a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxResource.java b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxResource.java index 1754387fdf0..ce0d1fb2960 100644 --- a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxResource.java +++ b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/resource/NsxResource.java @@ -47,6 +47,7 @@ import org.apache.cloudstack.agent.api.DeleteNsxLoadBalancerRuleCommand; import org.apache.cloudstack.agent.api.DeleteNsxSegmentCommand; import org.apache.cloudstack.agent.api.DeleteNsxNatRuleCommand; import org.apache.cloudstack.agent.api.DeleteNsxTier1GatewayCommand; +import org.apache.cloudstack.agent.api.DeletedNsxDistributedFirewallRulesCommand; import org.apache.cloudstack.service.NsxApiClient; import org.apache.cloudstack.utils.NsxControllerUtils; import org.apache.commons.collections.CollectionUtils; @@ -124,6 +125,8 @@ public class NsxResource implements ServerResource { return executeRequest((CreateNsxLoadBalancerRuleCommand) cmd); } else if (cmd instanceof DeleteNsxLoadBalancerRuleCommand) { return executeRequest((DeleteNsxLoadBalancerRuleCommand) cmd); + } else if (cmd instanceof DeletedNsxDistributedFirewallRulesCommand) { + return executeRequest((DeletedNsxDistributedFirewallRulesCommand) cmd); } else if (cmd instanceof CreateNsxDistributedFirewallRulesCommand) { return executeRequest((CreateNsxDistributedFirewallRulesCommand) cmd); } else { @@ -471,6 +474,20 @@ public class NsxResource implements ServerResource { return new NsxAnswer(cmd, true, null); } + private NsxAnswer executeRequest(DeletedNsxDistributedFirewallRulesCommand cmd) { + String segmentName = NsxControllerUtils.getNsxSegmentId(cmd.getDomainId(), cmd.getAccountId(), + cmd.getZoneId(), cmd.getVpcId(), cmd.getNetworkId()); + List rules = cmd.getRules(); + try { + nsxApiClient.deleteDistributedFirewallRules(segmentName, rules); + } catch (Exception e) { + LOGGER.error(String.format("Failed to create NSX distributed firewall %s: %s", segmentName, e.getMessage()), e); + return new NsxAnswer(cmd, new CloudRuntimeException(e.getMessage())); + } + return new NsxAnswer(cmd, true, null); + } + + @Override public boolean start() { return true; diff --git a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxApiClient.java b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxApiClient.java index e6640f10593..d7290ba95a3 100644 --- a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxApiClient.java +++ b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxApiClient.java @@ -31,6 +31,7 @@ import com.vmware.nsx_policy.infra.Sites; import com.vmware.nsx_policy.infra.Tier1s; import com.vmware.nsx_policy.infra.domains.Groups; import com.vmware.nsx_policy.infra.domains.SecurityPolicies; +import com.vmware.nsx_policy.infra.domains.security_policies.Rules; import com.vmware.nsx_policy.infra.sites.EnforcementPoints; import com.vmware.nsx_policy.infra.tier_0s.LocaleServices; import com.vmware.nsx_policy.infra.tier_1s.nat.NatRules; @@ -818,6 +819,19 @@ public class NsxApiClient { } } + public void deleteDistributedFirewallRules(String segmentName, List nsxRules) { + for(NsxNetworkRule rule : nsxRules) { + String ruleId = NsxControllerUtils.getNsxDistributedFirewallPolicyRuleId(segmentName, rule.getRuleId()); + String svcName = getServiceName(ruleId, rule.getPrivatePort(), rule.getProtocol()); + // delete rules + Rules rules = (Rules) nsxService.apply(Rules.class); + rules.delete(DEFAULT_DOMAIN, segmentName, ruleId); + // delete service - if any + Services services = (Services) nsxService.apply(Services.class); + services.delete(svcName); + } + } + private List getRulesForDistributedFirewall(String segmentName, List nsxRules) { List rules = new ArrayList<>(); for (NsxNetworkRule rule: nsxRules) { diff --git a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxElement.java b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxElement.java index 79f4d4e34b7..0872515ec8e 100644 --- a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxElement.java +++ b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxElement.java @@ -666,7 +666,7 @@ public class NsxElement extends AdapterBase implements DhcpServiceProvider, Dns for (NetworkACLItem rule : rules) { NsxNetworkRule networkRule = new NsxNetworkRule.Builder() .setRuleId(rule.getId()) - .setSourceCidrList(transformCidrListValues(rule.getSourceCidrList())) + .setSourceCidrList(Objects.nonNull(rule.getSourceCidrList()) ? transformCidrListValues(rule.getSourceCidrList()) : List.of("ANY")) .setAclAction(rule.getAction().toString()) .setTrafficType(rule.getTrafficType().toString()) .setService(Network.Service.NetworkACL) @@ -682,7 +682,7 @@ public class NsxElement extends AdapterBase implements DhcpServiceProvider, Dns private List transformCidrListValues(List sourceCidrList) { List list = new ArrayList<>(); for (String cidr : sourceCidrList) { - if (cidr.equals("0.0.0.0/0")) { + if (cidr == null || cidr.equals("0.0.0.0/0")) { list.add("ANY"); } else { list.add(cidr); @@ -697,12 +697,15 @@ public class NsxElement extends AdapterBase implements DhcpServiceProvider, Dns if (!canHandle(network, Network.Service.Firewall)) { return false; } - List nsxNetworkRules = new ArrayList<>(); + List nsxAddNetworkRules = new ArrayList<>(); + List nsxDelNetworkRules = new ArrayList<>(); for (FirewallRule rule : rules) { NsxNetworkRule networkRule = new NsxNetworkRule.Builder() .setRuleId(rule.getId()) - .setSourceCidrList(transformCidrListValues(rule.getSourceCidrList())) - .setDestinationCidrList(transformCidrListValues(rule.getDestinationCidrList())) + .setSourceCidrList(Objects.nonNull(rule.getSourceCidrList()) ? + transformCidrListValues(rule.getSourceCidrList()) : List.of("ANY")) + .setDestinationCidrList(Objects.nonNull(rule.getDestinationCidrList()) ? + transformCidrListValues(rule.getDestinationCidrList()) : List.of("ANY")) .setIcmpCode(rule.getIcmpCode()) .setIcmpType(rule.getIcmpType()) .setPrivatePort(getPrivatePortRange(rule)) @@ -710,8 +713,19 @@ public class NsxElement extends AdapterBase implements DhcpServiceProvider, Dns .setService(Network.Service.Firewall) .setProtocol(rule.getProtocol().toUpperCase(Locale.ROOT)) .build(); - nsxNetworkRules.add(networkRule); + if (rule.getState() == FirewallRule.State.Add) { + nsxAddNetworkRules.add(networkRule); + } else if (rule.getState() == FirewallRule.State.Revoke) { + nsxDelNetworkRules.add(networkRule); + } } - return nsxService.addFirewallRules(network, nsxNetworkRules); + boolean success = true; + if (!nsxDelNetworkRules.isEmpty()) { + success = nsxService.deleteFirewallRules(network, nsxDelNetworkRules); + if (!success) { + LOGGER.warn("Not all firewall rules were successfully deleted"); + } + } + return success && nsxService.addFirewallRules(network, nsxAddNetworkRules); } } diff --git a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxServiceImpl.java b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxServiceImpl.java index a506c83cfdd..233f7b9e7bc 100644 --- a/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxServiceImpl.java +++ b/plugins/network-elements/nsx/src/main/java/org/apache/cloudstack/service/NsxServiceImpl.java @@ -36,6 +36,7 @@ import org.apache.cloudstack.agent.api.DeleteNsxLoadBalancerRuleCommand; import org.apache.cloudstack.agent.api.DeleteNsxSegmentCommand; import org.apache.cloudstack.agent.api.DeleteNsxNatRuleCommand; import org.apache.cloudstack.agent.api.DeleteNsxTier1GatewayCommand; +import org.apache.cloudstack.agent.api.DeletedNsxDistributedFirewallRulesCommand; import org.apache.cloudstack.resource.NsxNetworkRule; import org.apache.cloudstack.utils.NsxControllerUtils; import org.apache.cloudstack.utils.NsxHelper; @@ -181,4 +182,11 @@ public class NsxServiceImpl implements NsxService { NsxAnswer result = nsxControllerUtils.sendNsxCommand(command, network.getDataCenterId()); return result.getResult(); } + + public boolean deleteFirewallRules(Network network, List netRules) { + DeletedNsxDistributedFirewallRulesCommand command = new DeletedNsxDistributedFirewallRulesCommand(network.getDomainId(), + network.getAccountId(), network.getDataCenterId(), network.getVpcId(), network.getId(), netRules); + NsxAnswer result = nsxControllerUtils.sendNsxCommand(command, network.getDataCenterId()); + return result.getResult(); + } }