From b768d9ac202fd832c4780f1cea5ccd43b06aff84 Mon Sep 17 00:00:00 2001 From: Andrija Panic <45762285+andrijapanicsb@users.noreply.github.com> Date: Fri, 24 Jul 2026 05:15:20 +0200 Subject: [PATCH] network: default egress policy 'allow' for Isolated networks Isolated guest networks created from the built-in default offerings (DefaultIsolatedNetworkOfferingWithSourceNatService and DefaultIsolatedNetworkOffering) previously denied all egress by default, while createNetworkOffering without an explicit egressdefaultpolicy and VPC tiers already allow egress. This aligns the built-in Isolated offerings with allow-by-default and makes the behaviour configurable. - Add global setting network.isolated.default.egress.policy.allow (default true). - Seed the built-in default Isolated network offerings with the egress default policy taken from this setting. - createNetworkOffering without an explicit egressdefaultpolicy now follows the same setting instead of a hard-coded allow. Only affects fresh installations and offerings created without the parameter; existing network offerings and networks are unchanged. --- api/src/main/java/com/cloud/network/NetworkService.java | 9 +++++++++ .../command/admin/network/NetworkOfferingBaseCmd.java | 3 ++- .../main/java/com/cloud/offerings/NetworkOfferingVO.java | 4 ++++ .../main/java/com/cloud/network/NetworkServiceImpl.java | 2 +- .../java/com/cloud/server/ConfigurationServerImpl.java | 9 +++++++++ 5 files changed, 25 insertions(+), 2 deletions(-) diff --git a/api/src/main/java/com/cloud/network/NetworkService.java b/api/src/main/java/com/cloud/network/NetworkService.java index c32bb711c0f2..aaffc3dfea93 100644 --- a/api/src/main/java/com/cloud/network/NetworkService.java +++ b/api/src/main/java/com/cloud/network/NetworkService.java @@ -84,6 +84,15 @@ public interface NetworkService { "allow.end.users.to.specify.vr.mtu", "false", "Allow end Users to specify VR MTU", true, ConfigKey.Scope.Zone); + public static final ConfigKey DefaultEgressPolicyForIsolatedNetworksAllow = new ConfigKey<>("Network", Boolean.class, + "network.isolated.default.egress.policy.allow", "true", + "Default egress policy for Isolated guest networks when no policy is specified. When true (default), egress " + + "traffic is allowed unless explicitly denied by egress firewall rules, matching the behaviour of VPC tiers. When " + + "false, egress is denied unless explicitly allowed. Applies to the built-in default Isolated network offerings " + + "seeded on a fresh installation and to network offerings created via createNetworkOffering without an explicit " + + "egressdefaultpolicy. Existing network offerings and already-created networks are not affected.", + true, ConfigKey.Scope.Global); + List getIsolatedNetworksOwnedByAccountInZone(long zoneId, Account owner); IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId, Boolean displayIp, String ipaddress) throws ResourceAllocationException, InsufficientAddressCapacityException, diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/NetworkOfferingBaseCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/NetworkOfferingBaseCmd.java index 9b42be137314..6dc5b29868f0 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/NetworkOfferingBaseCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/NetworkOfferingBaseCmd.java @@ -18,6 +18,7 @@ import com.cloud.exception.InvalidParameterValueException; import com.cloud.network.Network; +import com.cloud.network.NetworkService; import com.cloud.network.VirtualRouterProvider; import com.cloud.offering.NetworkOffering; import com.cloud.user.Account; @@ -335,7 +336,7 @@ public Boolean getForTungsten() { public Boolean getEgressDefaultPolicy() { if (egressDefaultPolicy == null) { - return true; + return NetworkService.DefaultEgressPolicyForIsolatedNetworksAllow.value(); } return egressDefaultPolicy; } diff --git a/engine/schema/src/main/java/com/cloud/offerings/NetworkOfferingVO.java b/engine/schema/src/main/java/com/cloud/offerings/NetworkOfferingVO.java index 904c8e646eb5..7ac5e154c07f 100644 --- a/engine/schema/src/main/java/com/cloud/offerings/NetworkOfferingVO.java +++ b/engine/schema/src/main/java/com/cloud/offerings/NetworkOfferingVO.java @@ -346,6 +346,10 @@ public boolean isEgressDefaultPolicy() { return egressdefaultpolicy; } + public void setEgressDefaultPolicy(boolean egressdefaultpolicy) { + this.egressdefaultpolicy = egressdefaultpolicy; + } + public NetworkOfferingVO(String name, String displayText, TrafficType trafficType, boolean systemOnly, boolean specifyVlan, Integer rateMbps, Integer multicastRateMbps, boolean isDefault, Availability availability, String tags, Network.GuestType guestType, boolean conserveMode, boolean specifyIpRanges, boolean isPersistent, boolean internalLb, boolean publicLb, boolean isForVpc) { diff --git a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java index 2853fa96330d..b51cee4b7eb1 100644 --- a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java @@ -6313,7 +6313,7 @@ public String getConfigComponentName() { @Override public ConfigKey[] getConfigKeys() { - return new ConfigKey[] {AllowDuplicateNetworkName, AllowEmptyStartEndIpAddress, AllowUsersToMakeNetworksRedundant, VRPrivateInterfaceMtu, VRPublicInterfaceMtu, AllowUsersToSpecifyVRMtu}; + return new ConfigKey[] {AllowDuplicateNetworkName, AllowEmptyStartEndIpAddress, AllowUsersToMakeNetworksRedundant, VRPrivateInterfaceMtu, VRPublicInterfaceMtu, AllowUsersToSpecifyVRMtu, DefaultEgressPolicyForIsolatedNetworksAllow}; } public boolean isDefaultAcl(Long aclId) { diff --git a/server/src/main/java/com/cloud/server/ConfigurationServerImpl.java b/server/src/main/java/com/cloud/server/ConfigurationServerImpl.java index def564dfdc68..5ab0903780db 100644 --- a/server/src/main/java/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/main/java/com/cloud/server/ConfigurationServerImpl.java @@ -71,6 +71,7 @@ import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; import com.cloud.network.Network.State; +import com.cloud.network.NetworkService; import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.Mode; import com.cloud.network.Networks.TrafficType; @@ -1017,6 +1018,12 @@ protected void createDefaultNetworkOfferings() { Transaction.execute(new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { + // Default egress policy for the built-in Isolated network offerings. Allow by default (matching VPC tiers), + // overridable via the global setting network.isolated.default.egress.policy.allow before first initialization. + final boolean isolatedNetworkEgressDefaultPolicyAllow = Boolean.parseBoolean(_configDao.getValueAndInitIfNotExist( + NetworkService.DefaultEgressPolicyForIsolatedNetworksAllow.key(), "Network", + NetworkService.DefaultEgressPolicyForIsolatedNetworksAllow.defaultValue())); + // Offering #1 NetworkOfferingVO defaultSharedSGNetworkOffering = new NetworkOfferingVO(NetworkOffering.DefaultSharedNetworkOfferingWithSGService, "Offering for Shared Security group enabled networks", @@ -1068,6 +1075,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { defaultIsolatedSourceNatEnabledNetworkOffering.setState(NetworkOffering.State.Enabled); defaultIsolatedSourceNatEnabledNetworkOffering.setSupportsVmAutoScaling(true); + defaultIsolatedSourceNatEnabledNetworkOffering.setEgressDefaultPolicy(isolatedNetworkEgressDefaultPolicyAllow); defaultIsolatedSourceNatEnabledNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultIsolatedSourceNatEnabledNetworkOffering); for (Service service : defaultIsolatedSourceNatEnabledNetworkOfferingProviders.keySet()) { @@ -1084,6 +1092,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { false, true, null, null, true, Availability.Optional, null, Network.GuestType.Isolated, true, true, false, false, false, false); defaultIsolatedEnabledNetworkOffering.setState(NetworkOffering.State.Enabled); + defaultIsolatedEnabledNetworkOffering.setEgressDefaultPolicy(isolatedNetworkEgressDefaultPolicyAllow); defaultIsolatedEnabledNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultIsolatedEnabledNetworkOffering); for (Service service : defaultIsolatedNetworkOfferingProviders.keySet()) {