http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/374a6007/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java index 899faf7..872d1a6 100644 --- a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java @@ -32,8 +32,10 @@ import com.cloud.agent.api.UnPlugNicAnswer; import com.cloud.agent.api.UnPlugNicCommand; import com.cloud.agent.api.routing.IpAssocVpcCommand; import com.cloud.agent.api.routing.NetworkElementCommand; +import com.cloud.agent.api.routing.SetNetworkACLCommand; import com.cloud.agent.api.routing.SetSourceNatCommand; import com.cloud.agent.api.to.IpAddressTO; +import com.cloud.agent.api.to.NetworkACLTO; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.agent.manager.Commands; @@ -68,6 +70,7 @@ import com.cloud.network.VpcVirtualNetworkApplianceService; import com.cloud.network.addr.PublicIp; import com.cloud.network.dao.PhysicalNetworkDao; import com.cloud.network.router.VirtualRouter.Role; +import com.cloud.network.rules.NetworkACL; import com.cloud.network.vpc.Vpc; import com.cloud.network.vpc.Dao.VpcDao; import com.cloud.network.vpc.Dao.VpcOfferingDao; @@ -704,4 +707,55 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian return super.finalizeVirtualMachineProfile(profile, dest, context); } + + @Override + public boolean applyNetworkACLs(Network network, final List<? extends NetworkACL> rules, List<? extends VirtualRouter> routers) + throws ResourceUnavailableException { + if (rules == null || rules.isEmpty()) { + s_logger.debug("No network ACLs to be applied for network " + network.getId()); + return true; + } + return applyRules(network, routers, "network acls", false, null, false, new RuleApplier() { + @Override + public boolean execute(Network network, VirtualRouter router) throws ResourceUnavailableException { + return sendNetworkACLs(router, (List<NetworkACL>)rules, network.getId()); + } + }); + } + + + protected boolean sendNetworkACLs(VirtualRouter router, List<NetworkACL> rules, long guestNetworkId) throws ResourceUnavailableException { + Commands cmds = new Commands(OnError.Continue); + createNetworkACLsCommands(rules, router, cmds, guestNetworkId); + return sendCommandsToRouter(router, cmds); + + } + + private void createNetworkACLsCommands(List<NetworkACL> rules, VirtualRouter router, Commands cmds, long guestNetworkId) { + List<NetworkACLTO> rulesTO = null; + String guestVlan = null; + Network guestNtwk = _networkDao.findById(guestNetworkId); + URI uri = guestNtwk.getBroadcastUri(); + if (uri != null) { + guestVlan = guestNtwk.getBroadcastUri().getHost(); + } + + if (rules != null) { + rulesTO = new ArrayList<NetworkACLTO>(); + + for (NetworkACL rule : rules) { + NetworkACLTO ruleTO = new NetworkACLTO(rule, guestVlan, rule.getTrafficType()); + rulesTO.add(ruleTO); + } + } + + SetNetworkACLCommand cmd = new SetNetworkACLCommand(rulesTO); + cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, getRouterControlIp(router.getId())); + cmd.setAccessDetail(NetworkElementCommand.ROUTER_GUEST_IP, getRouterIpInNetwork(guestNetworkId, router.getId())); + cmd.setAccessDetail(NetworkElementCommand.GUEST_VLAN_TAG, guestVlan); + cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName()); + DataCenterVO dcVo = _dcDao.findById(router.getDataCenterIdToDeployIn()); + cmd.setAccessDetail(NetworkElementCommand.ZONE_NETWORK_TYPE, dcVo.getNetworkType().toString()); + cmds.addCommand(cmd); + } }
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/374a6007/server/src/com/cloud/network/rules/FirewallManager.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/rules/FirewallManager.java b/server/src/com/cloud/network/rules/FirewallManager.java index 58e8750..abf4403 100644 --- a/server/src/com/cloud/network/rules/FirewallManager.java +++ b/server/src/com/cloud/network/rules/FirewallManager.java @@ -17,7 +17,6 @@ import java.util.List; import com.cloud.exception.NetworkRuleConflictException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.IPAddressVO; -import com.cloud.network.IpAddress; import com.cloud.network.firewall.FirewallService; import com.cloud.network.rules.FirewallRule.FirewallRuleType; import com.cloud.network.rules.FirewallRule.Purpose; @@ -37,13 +36,12 @@ public interface FirewallManager extends FirewallService { * * @param newRule * the new rule created. - * @param ipAddress - * ip address that back up the new rule. * @throws NetworkRuleConflictException */ - void detectRulesConflict(FirewallRule newRule, IpAddress ipAddress) throws NetworkRuleConflictException; + void detectRulesConflict(FirewallRule newRule) throws NetworkRuleConflictException; - void validateFirewallRule(Account caller, IPAddressVO ipAddress, Integer portStart, Integer portEnd, String proto, Purpose purpose, FirewallRuleType type); + void validateFirewallRule(Account caller, IPAddressVO ipAddress, Integer portStart, Integer portEnd, String proto, + Purpose purpose, FirewallRuleType type); boolean applyRules(List<? extends FirewallRule> rules, boolean continueOnError, boolean updateRulesInDB) throws ResourceUnavailableException; http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/374a6007/server/src/com/cloud/network/rules/FirewallRuleVO.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/rules/FirewallRuleVO.java b/server/src/com/cloud/network/rules/FirewallRuleVO.java index 7917463..a9834ec 100644 --- a/server/src/com/cloud/network/rules/FirewallRuleVO.java +++ b/server/src/com/cloud/network/rules/FirewallRuleVO.java @@ -32,6 +32,7 @@ import javax.persistence.Transient; import com.cloud.api.Identity; import com.cloud.network.dao.FirewallRulesCidrsDaoImpl; +import com.cloud.network.rules.FirewallRule.TrafficType; import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.db.GenericDao; import com.cloud.utils.net.NetUtils; @@ -40,7 +41,7 @@ import com.cloud.utils.net.NetUtils; @Table(name="firewall_rules") @Inheritance(strategy=InheritanceType.JOINED) @DiscriminatorColumn(name="purpose", discriminatorType=DiscriminatorType.STRING, length=32) -public class FirewallRuleVO implements FirewallRule, Identity { +public class FirewallRuleVO implements Identity, NetworkACL { protected final FirewallRulesCidrsDaoImpl _firewallRulesCidrsDao = ComponentLocator.inject(FirewallRulesCidrsDaoImpl.class); @Id @@ -59,7 +60,7 @@ public class FirewallRuleVO implements FirewallRule, Identity { long accountId; @Column(name="ip_address_id", updatable=false) - long sourceIpAddressId; + Long sourceIpAddressId; @Column(name="start_port", updatable=false) Integer sourcePortStart; @@ -98,6 +99,10 @@ public class FirewallRuleVO implements FirewallRule, Identity { @Enumerated(value=EnumType.STRING) FirewallRuleType type; + @Column(name="traffic_type") + @Enumerated(value=EnumType.STRING) + TrafficType trafficType; + // This is a delayed load value. If the value is null, // then this field has not been loaded yet. @@ -114,7 +119,7 @@ public class FirewallRuleVO implements FirewallRule, Identity { @Override public List<String> getSourceCidrList() { - if (sourceCidrs == null && purpose == Purpose.Firewall) { + if (sourceCidrs == null && (purpose == Purpose.Firewall || purpose == Purpose.NetworkACL)) { return _firewallRulesCidrsDao.getSourceCidrs(id); } return sourceCidrs; @@ -141,7 +146,7 @@ public class FirewallRuleVO implements FirewallRule, Identity { } @Override - public long getSourceIpAddressId() { + public Long getSourceIpAddressId() { return sourceIpAddressId; } @@ -191,13 +196,20 @@ public class FirewallRuleVO implements FirewallRule, Identity { this.uuid = UUID.randomUUID().toString(); } - 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) { + 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) { this.xId = UUID.randomUUID().toString(); } this.accountId = accountId; this.domainId = domainId; + + if (sourceIpAddressId == null) { + assert (purpose == Purpose.NetworkACL) : "ipAddressId can be null for " + Purpose.NetworkACL + " only"; + } + this.sourceIpAddressId = ipAddressId; this.sourcePortStart = portStart; this.sourcePortEnd = portEnd; @@ -216,10 +228,13 @@ public class FirewallRuleVO implements FirewallRule, Identity { this.related = related; this.uuid = UUID.randomUUID().toString(); this.type = FirewallRuleType.User; + this.trafficType = trafficType; } - public FirewallRuleVO(String xId, long ipAddressId, int port, String protocol, long networkId, long accountId, long domainId, Purpose purpose, List<String> sourceCidrs, Integer icmpCode, Integer icmpType, Long related) { - this(xId, ipAddressId, port, port, protocol, networkId, accountId, domainId, purpose, sourceCidrs, icmpCode, icmpType, related); + + public FirewallRuleVO(String xId, long ipAddressId, int port, String protocol, long networkId, long accountId, + long domainId, Purpose purpose, List<String> sourceCidrs, Integer icmpCode, Integer icmpType, Long related) { + this(xId, ipAddressId, port, port, protocol, networkId, accountId, domainId, purpose, sourceCidrs, icmpCode, icmpType, related, null); } @Override @@ -254,4 +269,9 @@ public class FirewallRuleVO implements FirewallRule, Identity { public void setType(FirewallRuleType type) { this.type = type; } + + @Override + public TrafficType getTrafficType() { + return trafficType; + } } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/374a6007/server/src/com/cloud/network/rules/PortForwardingRuleVO.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/rules/PortForwardingRuleVO.java b/server/src/com/cloud/network/rules/PortForwardingRuleVO.java index 848177e..6b76294 100644 --- a/server/src/com/cloud/network/rules/PortForwardingRuleVO.java +++ b/server/src/com/cloud/network/rules/PortForwardingRuleVO.java @@ -47,7 +47,7 @@ public class PortForwardingRuleVO extends FirewallRuleVO implements PortForwardi } public PortForwardingRuleVO(String xId, long srcIpId, int srcPortStart, int srcPortEnd, Ip dstIp, int dstPortStart, int dstPortEnd, String protocol, long networkId, long accountId, long domainId, long instanceId) { - super(xId, srcIpId, srcPortStart, srcPortEnd, protocol, networkId, accountId, domainId, Purpose.PortForwarding, null, null, null, null); + super(xId, srcIpId, srcPortStart, srcPortEnd, protocol, networkId, accountId, domainId, Purpose.PortForwarding, null, null, null, null, null); this.destinationIpAddress = dstIp; this.virtualMachineId = instanceId; this.destinationPortStart = dstPortStart; http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/374a6007/server/src/com/cloud/network/rules/RulesManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/rules/RulesManagerImpl.java b/server/src/com/cloud/network/rules/RulesManagerImpl.java index d000ac4..74d6940 100755 --- a/server/src/com/cloud/network/rules/RulesManagerImpl.java +++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java @@ -236,7 +236,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { } try { - _firewallMgr.detectRulesConflict(newRule, ipAddress); + _firewallMgr.detectRulesConflict(newRule); if (!_firewallDao.setStateToAdd(newRule)) { throw new CloudRuntimeException("Unable to update the state to add for " + newRule); } @@ -299,7 +299,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { txn.start(); FirewallRuleVO newRule = new FirewallRuleVO(rule.getXid(), rule.getSourceIpAddressId(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getProtocol().toLowerCase(), - networkId, accountId, domainId, rule.getPurpose(), null, null, null, null); + networkId, accountId, domainId, rule.getPurpose(), null, null, null, null, null); newRule = _firewallDao.persist(newRule); @@ -309,7 +309,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { } try { - _firewallMgr.detectRulesConflict(newRule, ipAddress); + _firewallMgr.detectRulesConflict(newRule); if (!_firewallDao.setStateToAdd(newRule)) { throw new CloudRuntimeException("Unable to update the state to add for " + newRule); } @@ -1009,7 +1009,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager { boolean success = false; try { for (FirewallRuleVO newRule : rules) { - _firewallMgr.detectRulesConflict(newRule, ip); + _firewallMgr.detectRulesConflict(newRule); } success = true; return rules; http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/374a6007/server/src/com/cloud/network/rules/StaticNatRuleImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/rules/StaticNatRuleImpl.java b/server/src/com/cloud/network/rules/StaticNatRuleImpl.java index 8cbf2b3..cf67839 100644 --- a/server/src/com/cloud/network/rules/StaticNatRuleImpl.java +++ b/server/src/com/cloud/network/rules/StaticNatRuleImpl.java @@ -90,7 +90,7 @@ public class StaticNatRuleImpl implements StaticNatRule{ } @Override - public long getSourceIpAddressId() { + public Long getSourceIpAddressId() { return sourceIpAddressId; } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/374a6007/setup/db/create-schema.sql ---------------------------------------------------------------------- diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index f2b4736..83c76c8 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -647,7 +647,7 @@ CREATE TABLE `cloud`.`op_dc_vnet_alloc` ( CREATE TABLE `cloud`.`firewall_rules` ( `id` bigint unsigned NOT NULL auto_increment COMMENT 'id', `uuid` varchar(40), - `ip_address_id` bigint unsigned NOT NULL COMMENT 'id of the corresponding ip address', + `ip_address_id` bigint unsigned COMMENT 'id of the corresponding ip address', `start_port` int(10) COMMENT 'starting port of a port range', `end_port` int(10) COMMENT 'end port of a port range', `state` char(32) NOT NULL COMMENT 'current state of this rule', @@ -662,12 +662,15 @@ CREATE TABLE `cloud`.`firewall_rules` ( `icmp_type` int(10) COMMENT 'The ICMP type (if protocol=ICMP). A value of -1 means all types.', `related` bigint unsigned COMMENT 'related to what other firewall rule', `type` varchar(10) NOT NULL DEFAULT 'USER', + `vpc_id` bigint unsigned COMMENT 'vpc the firewall rule is associated with', + `traffic_type` char(32) COMMENT 'the traffic type of the rule, can be Ingress or Egress', PRIMARY KEY (`id`), CONSTRAINT `fk_firewall_rules__ip_address_id` FOREIGN KEY(`ip_address_id`) REFERENCES `user_ip_address`(`id`), CONSTRAINT `fk_firewall_rules__network_id` FOREIGN KEY(`network_id`) REFERENCES `networks`(`id`) ON DELETE CASCADE, CONSTRAINT `fk_firewall_rules__account_id` FOREIGN KEY(`account_id`) REFERENCES `account`(`id`) ON DELETE CASCADE, CONSTRAINT `fk_firewall_rules__domain_id` FOREIGN KEY(`domain_id`) REFERENCES `domain`(`id`) ON DELETE CASCADE, CONSTRAINT `fk_firewall_rules__related` FOREIGN KEY(`related`) REFERENCES `firewall_rules`(`id`) ON DELETE CASCADE, + CONSTRAINT `fk_firewall_rules__vpc_id` FOREIGN KEY (`vpc_id`) REFERENCES `vpc`(`id`) ON DELETE CASCADE, INDEX `i_firewall_rules__purpose`(`purpose`), CONSTRAINT `uc_firewall_rules__uuid` UNIQUE (`uuid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
