Support Firewall for public IPs in VPC

This commit is contained in:
Harikrishna Patnala 2026-02-25 15:32:20 +05:30
parent 1e512ab9c6
commit 332d5ebbbf
10 changed files with 97 additions and 18 deletions

View File

@ -561,6 +561,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
defaultVPCOffProviders.put(Service.StaticNat, defaultProviders);
defaultVPCOffProviders.put(Service.PortForwarding, defaultProviders);
defaultVPCOffProviders.put(Service.Vpn, defaultProviders);
defaultVPCOffProviders.put(Service.Firewall, defaultProviders);
Transaction.execute(new TransactionCallbackNoReturn() {
@Override

View File

@ -17,6 +17,8 @@
package com.cloud.upgrade.dao;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@ -51,6 +53,7 @@ public class Upgrade42210to42300 extends DbUpgradeAbstractImpl implements DbUpgr
@Override
public void performDataMigration(Connection conn) {
unhideJsInterpretationEnabled(conn);
updateVpcDefaultOfferingsWithFirewallService(conn);
}
protected void unhideJsInterpretationEnabled(Connection conn) {
@ -89,4 +92,65 @@ public class Upgrade42210to42300 extends DbUpgradeAbstractImpl implements DbUpgr
logger.warn("Error while decrypting configuration 'js.interpretation.enabled'. The configuration may already be decrypted.");
}
}
private void updateVpcDefaultOfferingsWithFirewallService(Connection conn) {
logger.debug("Updating default VPC offerings to add Firewall service with VpcVirtualRouter provider");
final List<String> defaultVpcOfferingUniqueNames = Arrays.asList(
"DefaultIsolatedNetworkOfferingForVpcNetworks",
"DefaultIsolatedNetworkOfferingForVpcNetworksNoLB",
"DefaultIsolatedNetworkOfferingForVpcNetworksWithInternalLB",
"DefaultNATNSXNetworkOfferingForVpc",
"DefaultRoutedNSXNetworkOfferingForVpc",
"DefaultNATNSXNetworkOfferingForVpcWithInternalLB",
"DefaultRoutedNetrisNetworkOfferingForVpc",
"DefaultNATNetrisNetworkOfferingForVpc",
"DefaultNSXVPCNetworkOfferingforKubernetesService"
);
try {
for (String uniqueName : defaultVpcOfferingUniqueNames) {
PreparedStatement pstmt = conn.prepareStatement("SELECT id FROM `cloud`.`network_offerings` WHERE unique_name = ?");
pstmt.setString(1, uniqueName);
ResultSet rs = pstmt.executeQuery();
if (!rs.next()) {
continue;
}
long offeringId = rs.getLong(1);
rs.close();
pstmt.close();
// Insert into ntwk_offering_service_map (if not exists)
pstmt = conn.prepareStatement("INSERT INTO `cloud`.`ntwk_offering_service_map` " +
"(network_offering_id, service, provider, created) " +
"VALUES (?, 'Firewall', 'VpcVirtualRouter', now())");
pstmt.setLong(1, offeringId);
pstmt.executeUpdate();
pstmt.close();
// Update existing networks (ntwk_service_map)
pstmt = conn.prepareStatement("SELECT id FROM `cloud`.`networks` WHERE network_offering_id = ?");
pstmt.setLong(1, offeringId);
rs = pstmt.executeQuery();
while (rs.next()) {
long networkId = rs.getLong(1);
PreparedStatement insertService = conn.prepareStatement("INSERT INTO `cloud`.`ntwk_service_map` " +
"(network_id, service, provider, created) " +
"VALUES (?, 'Firewall', 'VpcVirtualRouter', now())");
insertService.setLong(1, networkId);
insertService.executeUpdate();
insertService.close();
}
rs.close();
pstmt.close();
}
} catch (SQLException e) {
logger.warn("Exception while updating VPC default offerings with Firewall service: " + e.getMessage(), e);
}
}
}

View File

@ -2986,9 +2986,8 @@ public class KubernetesClusterManagerImpl extends ManagerBase implements Kuberne
defaultKubernetesServiceNetworkOfferingProviders.put(Service.UserData, provider);
if (forVpc) {
defaultKubernetesServiceNetworkOfferingProviders.put(Service.NetworkACL, forNsx ? Network.Provider.Nsx : provider);
} else {
defaultKubernetesServiceNetworkOfferingProviders.put(Service.Firewall, forNsx ? Network.Provider.Nsx : provider);
}
defaultKubernetesServiceNetworkOfferingProviders.put(Service.Firewall, forNsx ? Network.Provider.Nsx : provider);
defaultKubernetesServiceNetworkOfferingProviders.put(Service.Lb, forNsx ? Network.Provider.Nsx : provider);
defaultKubernetesServiceNetworkOfferingProviders.put(Service.SourceNat, forNsx ? Network.Provider.Nsx : provider);
defaultKubernetesServiceNetworkOfferingProviders.put(Service.StaticNat, forNsx ? Network.Provider.Nsx : provider);

View File

@ -7223,7 +7223,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
}
if (forVpc == null) {
if (service == Service.SecurityGroup || service == Service.Firewall) {
if (service == Service.SecurityGroup) {
forVpc = false;
} else if (service == Service.NetworkACL) {
forVpc = true;

View File

@ -412,10 +412,6 @@ public class VpcVirtualRouterElement extends VirtualRouterElement implements Vpc
vpnCapabilities.putAll(capabilities.get(Service.Vpn));
vpnCapabilities.put(Capability.VpnTypes, "s2svpn");
capabilities.put(Service.Vpn, vpnCapabilities);
// remove firewall capability
capabilities.remove(Service.Firewall);
// add network ACL capability
final Map<Capability, String> networkACLCapabilities = new HashMap<Capability, String>();
networkACLCapabilities.put(Capability.SupportedProtocols, "tcp,udp,icmp");

View File

@ -989,8 +989,7 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
@Override
public boolean isVirtualRouterGateway(Network network) {
return isRoutedNetwork(network)
&& (networkServiceMapDao.canProviderSupportServiceInNetwork(network.getId(), Service.Gateway, Provider.VirtualRouter))
|| networkServiceMapDao.canProviderSupportServiceInNetwork(network.getId(), Service.Gateway, Provider.VPCVirtualRouter);
&& (networkServiceMapDao.canProviderSupportServiceInNetwork(network.getId(), Service.Gateway, Provider.VirtualRouter));
}
@Override

View File

@ -705,8 +705,8 @@ class CsAcl(CsDataBag):
for item in self.dbag:
if item == "id":
continue
if self.config.is_vpc():
continue
if self.config.is_vpc() and not ("purpose" in self.dbag[item] and self.dbag[item]["purpose"] == "Firewall"):
self.AclDevice(self.dbag[item], self.config).create()
else:
self.AclIP(self.dbag[item], self.config).create()

View File

@ -647,6 +647,18 @@ class CsIP:
(self.address['network'], self.address['network'])])
if self.get_type() in ["public"]:
# Add PREROUTING firewall chain jump for public IP
self.fw.append(["mangle", "front",
"-A PREROUTING " +
"-d %s/32 -j FIREWALL_%s" % (self.address['public_ip'], self.address['public_ip'])])
# Add the firewall chain with default DROP policy
self.fw.append(["mangle", "front",
"-A FIREWALL_%s " % self.address['public_ip'] +
"-m state --state RELATED,ESTABLISHED -j RETURN"])
self.fw.append(["mangle", "",
"-A FIREWALL_%s -j DROP" % self.address['public_ip']])
self.fw.append(
["mangle", "", "-A FORWARD -j VPN_STATS_%s" % self.dev])
self.fw.append(

View File

@ -139,20 +139,22 @@ export default {
// VPC IPs with source nat have only VPN when VPC offering conserve mode = false
if (this.resource.issourcenat && vpc?.vpcofferingconservemode === false) {
this.tabs = this.defaultTabs.concat(this.$route.meta.tabs.filter(tab => tab.name === 'vpn'))
this.tabs = this.defaultTabs.concat(this.$route.meta.tabs.filter(tab => ['vpn', 'firewall'].includes(tab.name)))
return
}
// VPC IPs with static nat have nothing
// VPC IPs with static nat have firewall
if (this.resource.isstaticnat) {
if (this.resource.virtualmachinetype === 'DomainRouter') {
this.tabs = this.defaultTabs.concat(this.$route.meta.tabs.filter(tab => tab.name === 'vpn'))
this.tabs = this.defaultTabs.concat(this.$route.meta.tabs.filter(tab => ['vpn', 'firewall'].includes(tab.name)))
} else {
this.tabs = this.defaultTabs.concat(this.$route.meta.tabs.filter(tab => tab.name === 'firewall'))
}
return
}
// VPC IPs don't have firewall
let tabs = this.$route.meta.tabs.filter(tab => tab.name !== 'firewall')
// VPC IPs now have firewall support
let tabs = this.$route.meta.tabs
const network = await this.fetchNetwork()
if (network && network.networkofferingconservemode) {
@ -168,12 +170,12 @@ export default {
this.portFWRuleCount = await this.fetchPortFWRule()
this.loadBalancerRuleCount = await this.fetchLoadBalancerRule()
// VPC IPs with PF only have PF
// VPC IPs with PF only have PF (and firewall)
if (this.portFWRuleCount > 0) {
tabs = tabs.filter(tab => tab.name !== 'loadbalancing')
}
// VPC IPs with LB rules only have LB
// VPC IPs with LB rules only have LB (and firewall)
if (this.loadBalancerRuleCount > 0) {
tabs = tabs.filter(tab => tab.name !== 'portforwarding')
}

View File

@ -534,6 +534,12 @@ export default {
{ name: 'ConfigDrive' }
]
})
services.push({
name: 'Firewall',
provider: [
{ name: 'VpcVirtualRouter' }
]
})
services.push({
name: 'Lb',
provider: [