Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
43100da
Support Firewall for public IPs in VPC
harikrishna-patnala Feb 25, 2026
28c32b7
UI changes
harikrishna-patnala Mar 5, 2026
c7559ec
more fixes
harikrishna-patnala Mar 5, 2026
19f6484
UI fix
harikrishna-patnala May 7, 2026
afac190
Firewall tab changes
harikrishna-patnala May 11, 2026
d60bb92
Changes in mapping to the VPC and not the tier network
harikrishna-patnala May 11, 2026
2034b56
Fix vpcid
harikrishna-patnala May 12, 2026
b0e86f5
Fix delete firewall flow
harikrishna-patnala May 12, 2026
8157e68
remove default offering changes
harikrishna-patnala May 12, 2026
82f4f9f
Fix unit test
harikrishna-patnala May 12, 2026
5da3102
Fix whitespace
harikrishna-patnala May 12, 2026
3fbf248
remove Unnecessary Stubbing
harikrishna-patnala May 12, 2026
5a4ba93
more unit test fixes
harikrishna-patnala May 12, 2026
c02463d
Update server/src/main/java/org/apache/cloudstack/network/RoutedIpv4M…
harikrishna-patnala May 13, 2026
9fd1ec7
Update server/src/main/java/org/apache/cloudstack/network/RoutedIpv4M…
harikrishna-patnala May 13, 2026
285eb89
DB and response changes
harikrishna-patnala May 13, 2026
c7afd2e
marvin test
harikrishna-patnala May 13, 2026
6a6481e
more unit tests
harikrishna-patnala May 13, 2026
4476614
Fix UnnecessaryStubbingException
harikrishna-patnala May 13, 2026
307af74
Fix possible NPE
harikrishna-patnala May 13, 2026
7a0bcbc
Fix whitespace
harikrishna-patnala May 13, 2026
d1d3678
Fix vpc uuid in response
harikrishna-patnala May 13, 2026
afcbff6
Add Firewall in clone VPC offering in UI form
harikrishna-patnala May 13, 2026
aba3722
changes for VPC with firewall and without capabilities
harikrishna-patnala Jun 9, 2026
ba28d13
Add VPC firewall check
harikrishna-patnala Jun 9, 2026
bf82f9b
UI fix for VPC no firewall
harikrishna-patnala Jun 11, 2026
431d491
Make the drop rule add by default
harikrishna-patnala Jun 11, 2026
6656cba
Fix restart VPC with cleanup
harikrishna-patnala Jun 16, 2026
a6c04ae
Fix cleanup order
harikrishna-patnala Jun 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion api/src/main/java/com/cloud/network/rules/FirewallRule.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ enum TrafficType {

State getState();

long getNetworkId();
Long getNetworkId();

Long getVpcId();

Long getSourceIpAddressId();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ public State getState() {
}

@Override
public long getNetworkId() {
public Long getNetworkId() {
return networkId;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,13 +223,9 @@ public State getState() {
}

@Override
public long getNetworkId() {
IpAddress ip = _entityMgr.findById(IpAddress.class, getIpAddressId());
Long ntwkId = null;

if (ip.getAssociatedWithNetworkId() != null) {
ntwkId = ip.getAssociatedWithNetworkId();
}
public Long getNetworkId() {
IpAddress ip = getIp();
Long ntwkId = isVpcIp(ip) ? getVpcNetworkIdForFirewallRule(ip) : getIsolatedNetworkIdForFirewallRule(ip);

if (ntwkId == null) {
throw new InvalidParameterValueException("Unable to create firewall rule for the IP address ID=" + ipAddressId +
Expand All @@ -238,6 +234,12 @@ public long getNetworkId() {
return ntwkId;
}

@Override
public Long getVpcId() {
IpAddress ip = getIp();
return isVpcIp(ip) ? ip.getVpcId() : null;
}

@Override
public long getEntityOwnerId() {
Account account = CallContext.current().getCallingAccount();
Expand Down Expand Up @@ -300,7 +302,21 @@ public String getSyncObjType() {

@Override
public Long getSyncObjId() {
return getIp().getAssociatedWithNetworkId();
Long syncObjId = getIp().getAssociatedWithNetworkId();
return syncObjId != null ? syncObjId : getNetworkId();
}

private boolean isVpcIp(IpAddress ip) {
return ip.getVpcId() != null;
}

private Long getIsolatedNetworkIdForFirewallRule(IpAddress ip) {
return ip.getAssociatedWithNetworkId();
}

private Long getVpcNetworkIdForFirewallRule(IpAddress ip) {
// VPC flow is independent from tier association; manager resolves execution network.
return ip.getNetworkId();
}

private IpAddress getIp() {
Expand All @@ -311,6 +327,7 @@ private IpAddress getIp() {
return ip;
}


@Override
public Integer getIcmpCode() {
if (icmpCode != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ public Boolean getOpenFirewall() {
}
}

private Long getVpcId() {
public Long getVpcId() {
if (ipAddressId != null) {
IpAddress ipAddr = _networkService.getIp(ipAddressId);
if (ipAddr == null || !ipAddr.readyToUse()) {
Expand Down Expand Up @@ -275,7 +275,7 @@ public State getState() {
}

@Override
public long getNetworkId() {
public Long getNetworkId() {
IpAddress ip = _entityMgr.findById(IpAddress.class, getIpAddressId());
Long ntwkId = _networkService.getPreferredNetworkIdForPublicIpRuleAssignment(ip, networkId);
if (ntwkId == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,13 @@ public FirewallRule.State getState() {
}

@Override
public long getNetworkId() {
return -1;
public Long getNetworkId() {
return -1L;
}

@Override
public Long getVpcId() {
return null;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ public class FirewallResponse extends BaseResponse {
@Param(description = "The Network ID of the firewall rule")
private String networkId;

@SerializedName(ApiConstants.VPC_ID)
@Param(description = "The VPC ID of the firewall rule")
private String vpcId;

@SerializedName(ApiConstants.IP_ADDRESS)
@Param(description = "The public IP address for the firewall rule")
private String publicIpAddress;
Expand Down Expand Up @@ -115,6 +119,10 @@ public void setNetworkId(String networkId) {
this.networkId = networkId;
}

public void setVpcId(String vpcId) {
this.vpcId = vpcId;
}

public void setState(String state) {
this.state = state;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,15 @@
import java.util.Collections;
import java.util.List;

import com.cloud.network.IpAddress;
import com.cloud.network.NetworkService;
import com.cloud.utils.db.EntityManager;
import org.apache.commons.collections.CollectionUtils;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;

Expand All @@ -33,6 +38,12 @@
@RunWith(MockitoJUnitRunner.class)
public class CreateFirewallRuleCmdTest {

@Mock
private EntityManager entityManager;

@Mock
private NetworkService networkService;

private void validateAllIp4Cidr(final CreateFirewallRuleCmd cmd) {
Assert.assertTrue(CollectionUtils.isNotEmpty(cmd.getSourceCidrList()));
Assert.assertEquals(1, cmd.getSourceCidrList().size());
Expand Down Expand Up @@ -88,4 +99,22 @@ public void testGetSourceCidrList_EmptyFirstElementButMore() {
Assert.assertEquals(2, cmd.getSourceCidrList().size());
Assert.assertEquals(cidr, cmd.getSourceCidrList().get(1));
}

@Test
public void testGetNetworkIdVpcWithoutAssociatedNetworkUsesVpcFallbackAndSyncObjId() {
final CreateFirewallRuleCmd cmd = new CreateFirewallRuleCmd();
final IpAddress ip = Mockito.mock(IpAddress.class);

cmd._entityMgr = entityManager;
cmd._networkService = networkService;
ReflectionTestUtils.setField(cmd, "ipAddressId", 42L);

Mockito.when(networkService.getIp(42L)).thenReturn(ip);
Mockito.when(ip.getAssociatedWithNetworkId()).thenReturn(null);
Mockito.when(ip.getVpcId()).thenReturn(100L);
Mockito.when(ip.getNetworkId()).thenReturn(2L);

Assert.assertEquals(Long.valueOf(2L), cmd.getNetworkId());
Assert.assertEquals(Long.valueOf(2L), cmd.getSyncObjId());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,15 @@ public long getDomainId() {
}

@Override
public long getNetworkId() {
public Long getNetworkId() {
return networkId;
}

@Override
public Long getVpcId() {
return null;
}

@Override
public long getId() {
return id;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,7 @@ public boolean configure(final String name, final Map<String, Object> params) th
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ public interface FirewallRulesDao extends GenericDao<FirewallRuleVO, Long> {

List<FirewallRuleVO> listByNetworkPurposeTrafficType(long networkId, FirewallRule.Purpose purpose, FirewallRule.TrafficType trafficType);

List<FirewallRuleVO> listByVpcPurposeTrafficType(long vpcId, FirewallRule.Purpose purpose, FirewallRule.TrafficType trafficType);

List<FirewallRuleVO> listByIpAndPurposeWithState(Long addressId, FirewallRule.Purpose purpose, FirewallRule.State state);

void loadSourceCidrs(FirewallRuleVO rule);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ protected FirewallRulesDaoImpl() {
AllFieldsSearch.and("domain", AllFieldsSearch.entity().getDomainId(), Op.EQ);
AllFieldsSearch.and("id", AllFieldsSearch.entity().getId(), Op.EQ);
AllFieldsSearch.and("networkId", AllFieldsSearch.entity().getNetworkId(), Op.EQ);
AllFieldsSearch.and("vpcId", AllFieldsSearch.entity().getVpcId(), Op.EQ);
AllFieldsSearch.and("related", AllFieldsSearch.entity().getRelated(), Op.EQ);
AllFieldsSearch.and("trafficType", AllFieldsSearch.entity().getTrafficType(), Op.EQ);
AllFieldsSearch.done();
Expand Down Expand Up @@ -355,6 +356,22 @@ public List<FirewallRuleVO> listByNetworkPurposeTrafficType(long networkId, Purp
return listBy(sc);
}

@Override
public List<FirewallRuleVO> listByVpcPurposeTrafficType(long vpcId, Purpose purpose, TrafficType trafficType) {
SearchCriteria<FirewallRuleVO> sc = AllFieldsSearch.create();
sc.setParameters("vpcId", vpcId);

if (purpose != null) {
sc.setParameters("purpose", purpose);
}

if (trafficType != null) {
sc.setParameters("trafficType", trafficType);
}

return listBy(sc);
}

@Override
@DB
public boolean remove(Long id) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ public class FirewallRuleVO implements FirewallRule {
@Column(name = "network_id")
Long networkId;

@Column(name = "vpc_id")
Long vpcId;

@Column(name = "icmp_code")
Integer icmpCode;

Expand Down Expand Up @@ -190,10 +193,18 @@ public State getState() {
}

@Override
public long getNetworkId() {
public Long getNetworkId() {
return networkId;
}

public Long getVpcId() {
return vpcId;
}

public void setVpcId(Long vpcId) {
this.vpcId = vpcId;
}

@Override
public FirewallRuleType getType() {
return type;
Expand All @@ -207,7 +218,7 @@ protected FirewallRuleVO() {
uuid = UUID.randomUUID().toString();
}

public FirewallRuleVO(String xId, Long ipAddressId, Integer portStart, Integer portEnd, String protocol, long networkId, long accountId, long domainId,
public FirewallRuleVO(String xId, Long ipAddressId, Integer portStart, Integer portEnd, String protocol, Long networkId, long accountId, long domainId,
Purpose purpose, List<String> sourceCidrs, Integer icmpCode, Integer icmpType, Long related, TrafficType trafficType) {
this.xId = xId;
if (xId == null) {
Expand Down Expand Up @@ -251,7 +262,7 @@ public FirewallRuleVO(String xId, long ipAddressId, int port, String protocol, l
}


public FirewallRuleVO(String xId, Long ipAddressId, Integer portStart, Integer portEnd, String protocol, long networkId, long accountId, long domainId,
public FirewallRuleVO(String xId, Long ipAddressId, Integer portStart, Integer portEnd, String protocol, Long networkId, long accountId, long domainId,
Purpose purpose, List<String> sourceCidrs, List<String> destCidrs, Integer icmpCode, Integer icmpType, Long related, TrafficType trafficType) {
this(xId,ipAddressId, portStart, portEnd, protocol, networkId, accountId, domainId, purpose, sourceCidrs, icmpCode, icmpType, related, trafficType);
this.destinationCidrs = destCidrs;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,6 @@ INSERT INTO cloud.role_permissions (uuid, role_id, rule, permission, sort_order)
SELECT uuid(), role_id, 'quotaResourceStatement', permission, sort_order
FROM cloud.role_permissions rp
WHERE rule = 'quotaStatement' AND NOT EXISTS(SELECT 1 FROM cloud.role_permissions rp_ WHERE rp.role_id = rp_.role_id AND rp_.rule = 'quotaResourceStatement');

-- This is part of allowing firewall rules on public IP addresses in VPC network
ALTER TABLE `cloud`.`firewall_rules` MODIFY COLUMN `network_id` BIGINT UNSIGNED NULL;
Original file line number Diff line number Diff line change
Expand Up @@ -2986,9 +2986,8 @@ private void createNetworkOfferingForKubernetes(String offeringName, String offe
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ public void validateIsolatedNetworkIpRulesNoRules() {
}

private FirewallRuleVO createRule(int startPort, int endPort) {
FirewallRuleVO rule = new FirewallRuleVO(null, null, startPort, endPort, "tcp", 1, 1, 1, FirewallRule.Purpose.Firewall, List.of("0.0.0.0/0"), null, null, null, FirewallRule.TrafficType.Ingress);
FirewallRuleVO rule = new FirewallRuleVO(null, null, startPort, endPort, "tcp", 1L, 1, 1, FirewallRule.Purpose.Firewall, List.of("0.0.0.0/0"), null, null, null, FirewallRule.TrafficType.Ingress);
return rule;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ public void addEgressFirewallRule() throws ConfigurationException, Exception {
List<FirewallRuleTO> rules = new ArrayList<FirewallRuleTO>();
List<String> cidrList = new ArrayList<String>();
cidrList.add("0.0.0.0/0");
FirewallRuleVO activeVO = new FirewallRuleVO(null, null, 80, 80, "tcp", 1, 1, 1, Purpose.Firewall, cidrList, null, null, null, FirewallRule.TrafficType.Egress);
FirewallRuleVO activeVO = new FirewallRuleVO(null, null, 80, 80, "tcp", 1L, 1, 1, Purpose.Firewall, cidrList, null, null, null, FirewallRule.TrafficType.Egress);
FirewallRuleTO active = new FirewallRuleTO(activeVO, Long.toString(vlanId), null, Purpose.Firewall, FirewallRule.TrafficType.Egress);
rules.add(active);

Expand Down Expand Up @@ -319,7 +319,7 @@ public void removeEgressFirewallRule() throws ConfigurationException, Exception

long vlanId = 3954;
List<FirewallRuleTO> rules = new ArrayList<FirewallRuleTO>();
FirewallRuleVO revokedVO = new FirewallRuleVO(null, null, 80, 80, "tcp", 1, 1, 1, Purpose.Firewall, null, null, null, null, FirewallRule.TrafficType.Egress);
FirewallRuleVO revokedVO = new FirewallRuleVO(null, null, 80, 80, "tcp", 1L, 1, 1, Purpose.Firewall, null, null, null, null, FirewallRule.TrafficType.Egress);
revokedVO.setState(State.Revoke);
FirewallRuleTO revoked = new FirewallRuleTO(revokedVO, Long.toString(vlanId), null, Purpose.Firewall, FirewallRule.TrafficType.Egress);
rules.add(revoked);
Expand Down
34 changes: 30 additions & 4 deletions server/src/main/java/com/cloud/api/ApiResponseHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -2957,8 +2957,21 @@ public FirewallResponse createFirewallResponse(FirewallRule fwRule) {
}
}

Network network = ApiDBUtils.findNetworkById(fwRule.getNetworkId());
response.setNetworkId(network.getUuid());
Long networkId = fwRule.getNetworkId();
if (networkId != null) {
Comment thread
harikrishna-patnala marked this conversation as resolved.
Network network = ApiDBUtils.findNetworkById(networkId);
if (network != null) {
response.setNetworkId(network.getUuid());
}
}

Long vpcId = fwRule.getVpcId();
if (vpcId != null) {
Vpc vpc = ApiDBUtils.findVpcById(vpcId);
if (vpc != null) {
response.setVpcId(vpc.getUuid());
}
}

FirewallRule.State state = fwRule.getState();
String stateToSet = state.toString();
Expand Down Expand Up @@ -5405,8 +5418,21 @@ public FirewallResponse createIpv6FirewallRuleResponse(FirewallRule fwRule) {
response.setIcmpCode(fwRule.getIcmpCode());
response.setIcmpType(fwRule.getIcmpType());

Network network = ApiDBUtils.findNetworkById(fwRule.getNetworkId());
response.setNetworkId(network.getUuid());
Long networkId = fwRule.getNetworkId();
if (networkId != null) {
Network network = ApiDBUtils.findNetworkById(networkId);
if (network != null) {
response.setNetworkId(network.getUuid());
}
}

Long vpcId = fwRule.getVpcId();
if (vpcId != null) {
Vpc vpc = ApiDBUtils.findVpcById(vpcId);
if (vpc != null) {
response.setVpcId(vpc.getUuid());
}
}

FirewallRule.State state = fwRule.getState();
String stateToSet = state.toString();
Expand Down
Loading
Loading