CLOUDSTACK-299: Egress firewall rules feature for guest network on VR

This commit is contained in:
Jayapal 2013-01-31 11:20:23 +05:30 committed by Abhinandan Prateek
parent 48fdc25daa
commit b6727e5646
32 changed files with 538 additions and 180 deletions

View File

@ -50,7 +50,7 @@ public class FirewallRuleTO implements InternalIdentity {
FirewallRule.Purpose purpose;
private Integer icmpType;
private Integer icmpCode;
private FirewallRule.TrafficType trafficType;
protected FirewallRuleTO() {
}
@ -85,6 +85,7 @@ public class FirewallRuleTO implements InternalIdentity {
this.sourceCidrList = sourceCidr;
this.icmpType = icmpType;
this.icmpCode = icmpCode;
this.trafficType = null;
}
public FirewallRuleTO(FirewallRule rule, String srcVlanTag, String srcIp) {
this(rule.getId(),srcVlanTag, srcIp, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getState()==State.Revoke, rule.getState()==State.Active, rule.getPurpose(),rule.getSourceCidrList(),rule.getIcmpType(),rule.getIcmpCode());
@ -94,6 +95,23 @@ public class FirewallRuleTO implements InternalIdentity {
this(rule.getId(),null, srcIp, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getState()==State.Revoke, rule.getState()==State.Active, rule.getPurpose(),rule.getSourceCidrList(),rule.getIcmpType(),rule.getIcmpCode());
}
public FirewallRuleTO(FirewallRule rule, String srcVlanTag, String srcIp, FirewallRule.Purpose purpose) {
this(rule.getId(),srcVlanTag, srcIp, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getState()==State.Revoke, rule.getState()==State.Active, purpose,rule.getSourceCidrList(),rule.getIcmpType(),rule.getIcmpCode());
}
public FirewallRuleTO(FirewallRule rule, String srcVlanTag, String srcIp, FirewallRule.Purpose purpose, FirewallRule.TrafficType trafficType) {
this(rule.getId(),srcVlanTag, srcIp, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getState()==State.Revoke, rule.getState()==State.Active, purpose,rule.getSourceCidrList(),rule.getIcmpType(),rule.getIcmpCode());
this.trafficType = trafficType;
}
public FirewallRuleTO(FirewallRule rule, String srcVlanTag, String srcIp, FirewallRule.Purpose purpose, boolean revokeState, boolean alreadyAdded) {
this(rule.getId(),srcVlanTag, srcIp, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(), revokeState, alreadyAdded, purpose,rule.getSourceCidrList(),rule.getIcmpType(),rule.getIcmpCode());
}
public FirewallRule.TrafficType getTrafficType(){
return trafficType;
}
public long getId() {
return id;
}

View File

@ -48,7 +48,7 @@ public interface Network extends ControlledEntity, InternalIdentity, Identity {
public static final Service Dns = new Service("Dns", Capability.AllowDnsSuffixModification);
public static final Service Gateway = new Service("Gateway");
public static final Service Firewall = new Service("Firewall", Capability.SupportedProtocols,
Capability.MultipleIps, Capability.TrafficStatistics);
Capability.MultipleIps, Capability.TrafficStatistics, Capability.SupportedTrafficDirection, Capability.SupportedEgressProtocols);
public static final Service Lb = new Service("Lb", Capability.SupportedLBAlgorithms, Capability.SupportedLBIsolation,
Capability.SupportedProtocols, Capability.TrafficStatistics, Capability.LoadBalancingSupportedIps,
Capability.SupportedStickinessMethods, Capability.ElasticLb);
@ -173,6 +173,8 @@ public interface Network extends ControlledEntity, InternalIdentity, Identity {
public static final Capability ElasticLb = new Capability("ElasticLb");
public static final Capability AutoScaleCounters = new Capability("AutoScaleCounters");
public static final Capability InlineMode = new Capability("InlineMode");
public static final Capability SupportedTrafficDirection = new Capability("SupportedTrafficDirection");
public static final Capability SupportedEgressProtocols = new Capability("SupportedEgressProtocols");
private String name;
@ -287,6 +289,8 @@ public interface Network extends ControlledEntity, InternalIdentity, Identity {
void setPhysicalNetworkId(Long physicalNetworkId);
public void setTrafficType(TrafficType type);
ACLType getAclType();
boolean isRestartRequired();

View File

@ -226,4 +226,8 @@ public class NetworkProfile implements Network {
return vpcId;
}
@Override
public void setTrafficType(TrafficType type) {
this.trafficType = type;
}
}

View File

@ -27,7 +27,8 @@ import com.cloud.user.Account;
import com.cloud.utils.Pair;
public interface FirewallService {
FirewallRule createFirewallRule(FirewallRule rule) throws NetworkRuleConflictException;
FirewallRule createIngressFirewallRule(FirewallRule rule) throws NetworkRuleConflictException;
FirewallRule createEgressFirewallRule(FirewallRule rule) throws NetworkRuleConflictException;
Pair<List<? extends FirewallRule>, Integer> listFirewallRules(ListFirewallRulesCmd cmd);
@ -40,7 +41,8 @@ public interface FirewallService {
*/
boolean revokeFirewallRule(long ruleId, boolean apply);
boolean applyFirewallRules(long ipId, Account caller) throws ResourceUnavailableException;
boolean applyEgressFirewallRules (FirewallRule rule, Account caller) throws ResourceUnavailableException;
boolean applyIngressFirewallRules(long Ipid , Account caller) throws ResourceUnavailableException;
FirewallRule getFirewallRule(long ruleId);

View File

@ -122,7 +122,7 @@ public class CreateFirewallRuleCmd extends BaseAsyncCreateCmd implements Firewal
FirewallRule rule = _entityMgr.findById(FirewallRule.class, getEntityId());
try {
UserContext.current().setEventDetails("Rule Id: " + getEntityId());
success = _firewallService.applyFirewallRules(rule.getSourceIpAddressId(), callerContext.getCaller());
success = _firewallService.applyIngressFirewallRules(rule.getSourceIpAddressId(), callerContext.getCaller());
// State is different after the rule is applied, so get new object here
rule = _entityMgr.findById(FirewallRule.class, getEntityId());
@ -238,7 +238,7 @@ public class CreateFirewallRuleCmd extends BaseAsyncCreateCmd implements Firewal
}
try {
FirewallRule result = _firewallService.createFirewallRule(this);
FirewallRule result = _firewallService.createIngressFirewallRule(this);
setEntityId(result.getId());
setEntityUuid(result.getUuid());
} catch (NetworkRuleConflictException ex) {

View File

@ -163,7 +163,7 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P
UserContext.current().setEventDetails("Rule Id: " + getEntityId());
if (getOpenFirewall()) {
success = success && _firewallService.applyFirewallRules(ipAddressId, callerContext.getCaller());
success = success && _firewallService.applyIngressFirewallRules(ipAddressId, callerContext.getCaller());
}
success = success && _rulesService.applyPortForwardingRules(ipAddressId, callerContext.getCaller());

View File

@ -56,6 +56,10 @@ public class ListFirewallRulesCmd extends BaseListTaggedResourcesCmd {
return ipAddressId;
}
public FirewallRule.TrafficType getTrafficType () {
return FirewallRule.TrafficType.Ingress;
}
public Long getId() {
return id;
}

View File

@ -245,7 +245,7 @@ public class CreateLoadBalancerRuleCmd extends BaseAsyncCreateCmd /*implements
UserContext.current().setEventDetails("Rule Id: " + getEntityId());
if (getOpenFirewall()) {
success = success && _firewallService.applyFirewallRules(getSourceIpAddressId(), callerContext.getCaller());
success = success && _firewallService.applyIngressFirewallRules(getSourceIpAddressId(), callerContext.getCaller());
}
// State might be different after the rule is applied, so get new object here

View File

@ -115,7 +115,7 @@ public class CreateIpForwardingRuleCmd extends BaseAsyncCreateCmd implements Sta
UserContext.current().setEventDetails("Rule Id: "+ getEntityId());
if (getOpenFirewall()) {
result = result && _firewallService.applyFirewallRules(ipAddressId, UserContext.current().getCaller());
result = result && _firewallService.applyIngressFirewallRules(ipAddressId, UserContext.current().getCaller());
}
result = result && _rulesService.applyStaticNatRules(ipAddressId, UserContext.current().getCaller());

View File

@ -40,6 +40,9 @@ public class FirewallResponse extends BaseResponse {
@SerializedName(ApiConstants.IP_ADDRESS_ID) @Param(description="the public ip address id for the firewall rule")
private Long publicIpAddressId;
@SerializedName(ApiConstants.NETWORK_ID) @Param(description="the network id of the firewall rule")
private Long networkId;
@SerializedName(ApiConstants.IP_ADDRESS) @Param(description="the public ip address for the firewall rule")
private String publicIpAddress;
@ -82,6 +85,10 @@ public class FirewallResponse extends BaseResponse {
this.publicIpAddress = publicIpAddress;
}
public void setNetworkId(Long networkId) {
this.networkId = networkId;
}
public void setState(String state) {
this.state = state;
}

View File

@ -351,6 +351,11 @@ createFirewallRule=15
deleteFirewallRule=15
listFirewallRules=15
####
createEgressFirewallRule=15
deleteEgressFirewallRule=15
listEgressFirewallRules=15
#### hypervisor capabilities commands
updateHypervisorCapabilities=1
listHypervisorCapabilities=1

View File

@ -69,12 +69,14 @@ import com.cloud.agent.api.routing.SetStaticRouteCommand;
import com.cloud.agent.api.routing.Site2SiteVpnCfgCommand;
import com.cloud.agent.api.routing.VmDataCommand;
import com.cloud.agent.api.routing.VpnUsersCfgCommand;
import com.cloud.agent.api.to.FirewallRuleTO;
import com.cloud.agent.api.to.IpAddressTO;
import com.cloud.agent.api.to.PortForwardingRuleTO;
import com.cloud.agent.api.to.StaticNatRuleTO;
import com.cloud.exception.InternalErrorException;
import com.cloud.network.HAProxyConfigurator;
import com.cloud.network.LoadBalancerConfigurator;
import com.cloud.network.rules.FirewallRule;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.component.Manager;
import com.cloud.utils.net.NetUtils;
@ -214,11 +216,18 @@ public class VirtualRoutingResource implements Manager {
return new SetFirewallRulesAnswer(cmd, false, results);
}
FirewallRuleTO[] allrules = cmd.getRules();
FirewallRule.TrafficType trafficType = allrules[0].getTrafficType();
String[][] rules = cmd.generateFwRules();
final Script command = new Script(_firewallPath, _timeout, s_logger);
command.add(routerIp);
command.add("-F");
if (trafficType == FirewallRule.TrafficType.Egress){
command.add("-E");
}
StringBuilder sb = new StringBuilder();
String[] fwRules = rules[0];
if (fwRules.length > 0) {

View File

@ -24,6 +24,7 @@ COMMIT
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:FW_OUTBOUND - [0:0]
-A INPUT -d 224.0.0.18/32 -j ACCEPT
-A INPUT -d 225.0.0.50/32 -j ACCEPT
-A INPUT -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
@ -37,10 +38,11 @@ COMMIT
-A INPUT -i eth1 -p tcp -m state --state NEW --dport 3922 -j ACCEPT
-A INPUT -i eth0 -p tcp -m state --state NEW --dport 80 -j ACCEPT
-A FORWARD -i eth0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i eth0 -o eth2 -j ACCEPT
-A FORWARD -i eth2 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i eth0 -o eth0 -m state --state NEW -j ACCEPT
-A FORWARD -i eth0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i eth0 -o eth2 -j FW_OUTBOUND
-I FW_OUTBOUND -m state --state RELATED,ESTABLISHED -j ACCEPT
COMMIT
*mangle
:PREROUTING ACCEPT [0:0]

View File

@ -212,9 +212,9 @@ add_first_ip() {
ip_addr_add $ethDev $pubIp
sudo iptables -D FORWARD -i $ethDev -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -D FORWARD -i eth0 -o $ethDev -j ACCEPT
sudo iptables -D FORWARD -i eth0 -o $ethDev -j FW_OUTBOUND
sudo iptables -A FORWARD -i $ethDev -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o $ethDev -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o $ethDev -j FW_OUTBOUND
add_snat $1
if [ $? -gt 0 -a $? -ne 2 ]
@ -246,7 +246,7 @@ remove_first_ip() {
[ "$mask" == "" ] && mask="32"
sudo iptables -D FORWARD -i $ethDev -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -D FORWARD -i eth0 -o $ethDev -j ACCEPT
sudo iptables -D FORWARD -i eth0 -o $ethDev -j FW_OUTBOUND
remove_snat $1
sudo ip addr del dev $ethDev "$ipNoMask/$mask"

View File

@ -153,6 +153,7 @@ import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
import com.cloud.agent.api.storage.DestroyCommand;
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
import com.cloud.agent.api.to.FirewallRuleTO;
import com.cloud.agent.api.to.IpAddressTO;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.PortForwardingRuleTO;
@ -190,6 +191,7 @@ import com.cloud.network.HAProxyConfigurator;
import com.cloud.network.LoadBalancerConfigurator;
import com.cloud.network.Networks;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.rules.FirewallRule;
import com.cloud.resource.ServerResource;
import com.cloud.serializer.GsonHelper;
import com.cloud.storage.Storage;
@ -618,10 +620,16 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
protected SetFirewallRulesAnswer execute(SetFirewallRulesCommand cmd) {
String controlIp = getRouterSshControlIp(cmd);
String[] results = new String[cmd.getRules().length];
FirewallRuleTO[] allrules = cmd.getRules();
FirewallRule.TrafficType trafficType = allrules[0].getTrafficType();
String[][] rules = cmd.generateFwRules();
String args = "";
args += " -F ";
if (trafficType == FirewallRule.TrafficType.Egress){
args+= " -E ";
}
StringBuilder sb = new StringBuilder();
String[] fwRules = rules[0];
if (fwRules.length > 0) {
@ -634,13 +642,28 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
try {
VmwareManager mgr = getServiceContext().getStockObject(
VmwareManager.CONTEXT_STOCK_NAME);
Pair<Boolean, String> result = SshHelper.sshExecute(controlIp,
Pair<Boolean, String> result = null;
if (trafficType == FirewallRule.TrafficType.Egress){
result = SshHelper.sshExecute(controlIp,
DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(),
null, "/root/firewallRule_egress.sh " + args);
} else {
result = SshHelper.sshExecute(controlIp,
DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(),
null, "/root/firewall_rule.sh " + args);
}
if (s_logger.isDebugEnabled())
if (s_logger.isDebugEnabled()) {
if (trafficType == FirewallRule.TrafficType.Egress){
s_logger.debug("Executing script on domain router " + controlIp
+ ": /root/firewallRule_egress.sh " + args);
} else {
s_logger.debug("Executing script on domain router " + controlIp
+ ": /root/firewall_rule.sh " + args);
}
}
if (!result.first()) {
s_logger.error("SetFirewallRulesCommand failure on setting one rule. args: "

View File

@ -53,6 +53,8 @@ import javax.ejb.Local;
import javax.naming.ConfigurationException;
import javax.xml.parsers.DocumentBuilderFactory;
import com.cloud.agent.api.to.*;
import com.cloud.network.rules.FirewallRule;
import org.apache.log4j.Logger;
import org.apache.xmlrpc.XmlRpcException;
import org.w3c.dom.Document;
@ -7182,14 +7184,18 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
String callResult;
Connection conn = getConnection();
String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
FirewallRuleTO[] allrules = cmd.getRules();
FirewallRule.TrafficType trafficType = allrules[0].getTrafficType();
if (routerIp == null) {
return new SetFirewallRulesAnswer(cmd, false, results);
}
String[][] rules = cmd.generateFwRules();
String args = "";
args += routerIp + " -F ";
args += routerIp + " -F";
if (trafficType == FirewallRule.TrafficType.Egress){
args+= " -E";
}
StringBuilder sb = new StringBuilder();
String[] fwRules = rules[0];
if (fwRules.length > 0) {

View File

@ -277,6 +277,7 @@ public class JuniperSRXExternalFirewallElement extends ExternalFirewallDeviceMan
firewallCapabilities.put(Capability.SupportedProtocols, "tcp,udp,icmp");
firewallCapabilities.put(Capability.MultipleIps, "true");
firewallCapabilities.put(Capability.TrafficStatistics, "per public ip");
firewallCapabilities.put(Capability.SupportedTrafficDirection, "ingress");
capabilities.put(Service.Firewall, firewallCapabilities);
// Disabling VPN for Juniper in Acton as it 1) Was never tested 2) probably just doesn't work

View File

@ -46,28 +46,25 @@ then
exit 1
fi
fflag=
while getopts ':F' OPTION
eflag=
while getopts ':FE' OPTION
do
case $OPTION in
F) fflag=1
;;
E) eflag=1
;;
\?) ;;
esac
done
if [ -n "$fflag" ]
if [ -n "$eflag" ]
then
ssh -p 3922 -q -o StrictHostKeyChecking=no -i $cert root@$domRIp "/root/firewallRule_egress.sh $*"
elif [ -n "$fflag" ]
then
ssh -p 3922 -q -o StrictHostKeyChecking=no -i $cert root@$domRIp "/root/firewall_rule.sh $*"
else
ssh -p 3922 -q -o StrictHostKeyChecking=no -i $cert root@$domRIp "/root/firewall.sh $*"
fi
exit $?

View File

@ -2314,9 +2314,14 @@ public class ApiResponseHelper implements ResponseGenerator {
List<String> cidrs = ApiDBUtils.findFirewallSourceCidrs(fwRule.getId());
response.setCidrList(StringUtils.join(cidrs, ","));
if (fwRule.getTrafficType() == FirewallRule.TrafficType.Ingress) {
IpAddress ip = ApiDBUtils.findIpAddressById(fwRule.getSourceIpAddressId());
response.setPublicIpAddressId(ip.getId());
response.setPublicIpAddress(ip.getAddress().addr());
} else if (fwRule.getTrafficType() == FirewallRule.TrafficType.Egress) {
response.setPublicIpAddress(null);
response.setNetworkId(fwRule.getNetworkId());
}
FirewallRule.State state = fwRule.getState();
String stateToSet = state.toString();

View File

@ -2285,10 +2285,12 @@ public class NetworkManagerImpl implements NetworkManager, Manager, Listener {
boolean success = true;
Network network = _networksDao.findById(rules.get(0).getNetworkId());
FirewallRuleVO.TrafficType trafficType = rules.get(0).getTrafficType();
List<PublicIp> publicIps = new ArrayList<PublicIp>();
if (! (rules.get(0).getPurpose() == FirewallRule.Purpose.Firewall && trafficType == FirewallRule.TrafficType.Egress)) {
// get the list of public ip's owned by the network
List<IPAddressVO> userIps = _ipAddressDao.listByAssociatedNetwork(network.getId(), null);
List<PublicIp> publicIps = new ArrayList<PublicIp>();
if (userIps != null && !userIps.isEmpty()) {
for (IPAddressVO userIp : userIps) {
PublicIp publicIp = new PublicIp(userIp, _vlanDao.findById(userIp.getVlanId()), NetUtils.createSequenceBasedMacAddress(userIp.getMacAddress()));
@ -2299,6 +2301,7 @@ public class NetworkManagerImpl implements NetworkManager, Manager, Listener {
// rules can not programmed unless IP is associated with network service provider, so run IP assoication for
// the network so as to ensure IP is associated before applying rules (in add state)
applyIpAssociations(network, false, continueOnError, publicIps);
}
try {
applier.applyRules(network, purpose, rules);
@ -2310,8 +2313,10 @@ public class NetworkManagerImpl implements NetworkManager, Manager, Listener {
success = false;
}
if (! (rules.get(0).getPurpose() == FirewallRule.Purpose.Firewall && trafficType == FirewallRule.TrafficType.Egress) ) {
// if all the rules configured on public IP are revoked then dis-associate IP with network service provider
applyIpAssociations(network, true, continueOnError, publicIps);
}
return success;
}
@ -2460,9 +2465,15 @@ public class NetworkManagerImpl implements NetworkManager, Manager, Listener {
}
// apply firewall rules
List<FirewallRuleVO> firewallRulesToApply = _firewallDao.listByNetworkAndPurpose(networkId, Purpose.Firewall);
if (!_firewallMgr.applyFirewallRules(firewallRulesToApply, false, caller)) {
s_logger.warn("Failed to reapply firewall rule(s) as a part of network id=" + networkId + " restart");
List<FirewallRuleVO> firewallIngressRulesToApply = _firewallDao.listByNetworkPurposeTrafficType(networkId, Purpose.Firewall, FirewallRule.TrafficType.Ingress);
if (!_firewallMgr.applyFirewallRules(firewallIngressRulesToApply, false, caller)) {
s_logger.warn("Failed to reapply Ingress firewall rule(s) as a part of network id=" + networkId + " restart");
success = false;
}
List<FirewallRuleVO> firewallEgressRulesToApply = _firewallDao.listByNetworkPurposeTrafficType(networkId, Purpose.Firewall, FirewallRule.TrafficType.Egress);
if (!_firewallMgr.applyFirewallRules(firewallEgressRulesToApply, false, caller)) {
s_logger.warn("Failed to reapply firewall Egress rule(s) as a part of network id=" + networkId + " restart");
success = false;
}
@ -3027,23 +3038,43 @@ public class NetworkManagerImpl implements NetworkManager, Manager, Listener {
}
// revoke all firewall rules for the network w/o applying them on the DB
List<FirewallRuleVO> firewallRules = _firewallDao.listByNetworkAndPurpose(networkId, Purpose.Firewall);
List<FirewallRuleVO> firewallRules = _firewallDao.listByNetworkPurposeTrafficType(networkId, Purpose.Firewall, FirewallRule.TrafficType.Ingress);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Releasing " + firewallRules.size() + " firewall rules for network id=" + networkId + " as a part of shutdownNetworkRules");
s_logger.debug("Releasing " + firewallRules.size() + " firewall ingress rules for network id=" + networkId + " as a part of shutdownNetworkRules");
}
for (FirewallRuleVO firewallRule : firewallRules) {
s_logger.trace("Marking firewall rule " + firewallRule + " with Revoke state");
s_logger.trace("Marking firewall ingress rule " + firewallRule + " with Revoke state");
firewallRule.setState(FirewallRule.State.Revoke);
}
try {
if (!_firewallMgr.applyRules(firewallRules, true, false)) {
s_logger.warn("Failed to cleanup firewall rules as a part of shutdownNetworkRules");
s_logger.warn("Failed to cleanup firewall ingress rules as a part of shutdownNetworkRules");
success = false;
}
} catch (ResourceUnavailableException ex) {
s_logger.warn("Failed to cleanup firewall rules as a part of shutdownNetworkRules due to ", ex);
s_logger.warn("Failed to cleanup firewall ingress rules as a part of shutdownNetworkRules due to ", ex);
success = false;
}
List<FirewallRuleVO> firewallEgressRules = _firewallDao.listByNetworkPurposeTrafficType(networkId, Purpose.Firewall, FirewallRule.TrafficType.Egress);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Releasing " + firewallEgressRules.size() + " firewall egress rules for network id=" + networkId + " as a part of shutdownNetworkRules");
}
for (FirewallRuleVO firewallRule : firewallEgressRules) {
s_logger.trace("Marking firewall egress rule " + firewallRule + " with Revoke state");
firewallRule.setState(FirewallRule.State.Revoke);
}
try {
if (!_firewallMgr.applyRules(firewallEgressRules, true, false)) {
s_logger.warn("Failed to cleanup firewall egress rules as a part of shutdownNetworkRules");
success = false;
}
} catch (ResourceUnavailableException ex) {
s_logger.warn("Failed to cleanup firewall egress rules as a part of shutdownNetworkRules due to ", ex);
success = false;
}

View File

@ -56,6 +56,7 @@ public interface FirewallRulesDao extends GenericDao<FirewallRuleVO, Long> {
long countRulesByIpId(long sourceIpId);
List<FirewallRuleVO> listByNetworkPurposeTrafficTypeAndNotRevoked(long networkId, FirewallRule.Purpose purpose, FirewallRule.TrafficType trafficType);
List<FirewallRuleVO> listByNetworkPurposeTrafficType(long networkId, FirewallRule.Purpose purpose, FirewallRule.TrafficType trafficType);
List<FirewallRuleVO> listByIpAndPurposeWithState(Long addressId, FirewallRule.Purpose purpose, FirewallRule.State state);
}

View File

@ -67,6 +67,7 @@ public class FirewallRulesDaoImpl extends GenericDaoBase<FirewallRuleVO, Long> i
AllFieldsSearch.and("id", AllFieldsSearch.entity().getId(), Op.EQ);
AllFieldsSearch.and("networkId", AllFieldsSearch.entity().getNetworkId(), Op.EQ);
AllFieldsSearch.and("related", AllFieldsSearch.entity().getRelated(), Op.EQ);
AllFieldsSearch.and("trafficType", AllFieldsSearch.entity().getTrafficType(), Op.EQ);
AllFieldsSearch.done();
NotRevokedSearch = createSearchBuilder();
@ -161,6 +162,20 @@ public class FirewallRulesDaoImpl extends GenericDaoBase<FirewallRuleVO, Long> i
return listBy(sc);
}
@Override
public List<FirewallRuleVO> listByNetworkPurposeTrafficTypeAndNotRevoked(long networkId, FirewallRule.Purpose purpose, TrafficType trafficType) {
SearchCriteria<FirewallRuleVO> sc = NotRevokedSearch.create();
sc.setParameters("networkId", networkId);
sc.setParameters("state", State.Revoke);
if (purpose != null) {
sc.setParameters("purpose", purpose);
}
sc.setParameters("trafficType", trafficType);
return listBy(sc);
}
@Override
public boolean setStateToAdd(FirewallRuleVO rule) {
SearchCriteria<FirewallRuleVO> sc = AllFieldsSearch.create();
@ -275,10 +290,9 @@ public class FirewallRulesDaoImpl extends GenericDaoBase<FirewallRuleVO, Long> i
}
@Override
public List<FirewallRuleVO> listByNetworkPurposeTrafficTypeAndNotRevoked(long networkId, Purpose purpose, TrafficType trafficType) {
SearchCriteria<FirewallRuleVO> sc = NotRevokedSearch.create();
public List<FirewallRuleVO> listByNetworkPurposeTrafficType(long networkId, Purpose purpose, TrafficType trafficType) {
SearchCriteria<FirewallRuleVO> sc = AllFieldsSearch.create();
sc.setParameters("networkId", networkId);
sc.setParameters("state", State.Revoke);
if (purpose != null) {
sc.setParameters("purpose", purpose);
@ -288,6 +302,8 @@ public class FirewallRulesDaoImpl extends GenericDaoBase<FirewallRuleVO, Long> i
return listBy(sc);
}
@Override
@DB
public boolean remove(Long id) {
Transaction txn = Transaction.currentTxn();

View File

@ -565,6 +565,8 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl
Map<Capability, String> firewallCapabilities = new HashMap<Capability, String>();
firewallCapabilities.put(Capability.TrafficStatistics, "per public ip");
firewallCapabilities.put(Capability.SupportedProtocols, "tcp,udp,icmp");
firewallCapabilities.put(Capability.SupportedEgressProtocols, "tcp,udp,icmp, all");
firewallCapabilities.put(Capability.SupportedTrafficDirection, "ingress, egress");
firewallCapabilities.put(Capability.MultipleIps, "true");
capabilities.put(Service.Firewall, firewallCapabilities);

View File

@ -29,6 +29,12 @@ import javax.naming.ConfigurationException;
import org.apache.cloudstack.api.command.user.firewall.ListFirewallRulesCmd;
import org.apache.log4j.Logger;
import com.mysql.jdbc.ConnectionPropertiesImpl;
import org.apache.log4j.Logger;
import org.apache.cloudstack.api.BaseListCmd;
import org.apache.cloudstack.api.command.user.firewall.ListEgressFirewallRulesCmd;
import org.apache.cloudstack.api.command.user.firewall.ListFirewallRulesCmd;
import com.cloud.configuration.Config;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.domain.dao.DomainDao;
@ -43,8 +49,10 @@ import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.IPAddressVO;
import com.cloud.network.IpAddress;
import com.cloud.network.Network;
import com.cloud.network.NetworkVO;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.Service;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkModel;
import com.cloud.network.NetworkRuleApplier;
@ -166,31 +174,43 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ne
}
@Override
public FirewallRule createFirewallRule(FirewallRule rule) throws NetworkRuleConflictException {
public FirewallRule createEgressFirewallRule(FirewallRule rule) throws NetworkRuleConflictException {
Account caller = UserContext.current().getCaller();
return createFirewallRule(rule.getSourceIpAddressId(), caller, rule.getXid(), rule.getSourcePortStart(),
return createFirewallRule(null, caller, rule.getXid(), rule.getSourcePortStart(),
rule.getSourcePortEnd(), rule.getProtocol(), rule.getSourceCidrList(), rule.getIcmpCode(),
rule.getIcmpType(), null, rule.getType(), rule.getNetworkId());
rule.getIcmpType(), null, rule.getType(), rule.getNetworkId(), rule.getTrafficType());
}
public FirewallRule createIngressFirewallRule(FirewallRule rule) throws NetworkRuleConflictException {
Account caller = UserContext.current().getCaller();
Long sourceIpAddressId = rule.getSourceIpAddressId();
return createFirewallRule(sourceIpAddressId, caller, rule.getXid(), rule.getSourcePortStart(),
rule.getSourcePortEnd(), rule.getProtocol(), rule.getSourceCidrList(), rule.getIcmpCode(),
rule.getIcmpType(), null, rule.getType(), rule.getNetworkId(), rule.getTrafficType());
}
@DB
@Override
@ActionEvent(eventType = EventTypes.EVENT_FIREWALL_OPEN, eventDescription = "creating firewall rule", create = true)
public FirewallRule createFirewallRule(long ipAddrId, Account caller, String xId, Integer portStart,
public FirewallRule createFirewallRule(Long ipAddrId, Account caller, String xId, Integer portStart,
Integer portEnd, String protocol, List<String> sourceCidrList, Integer icmpCode, Integer icmpType,
Long relatedRuleId, FirewallRule.FirewallRuleType type, long networkId) throws NetworkRuleConflictException {
Long relatedRuleId, FirewallRule.FirewallRuleType type, Long networkId, FirewallRule.TrafficType trafficType) throws NetworkRuleConflictException {
IPAddressVO ipAddress = _ipAddressDao.findById(ipAddrId);
IPAddressVO ipAddress = null;
if (ipAddrId != null){
// this for ingress firewall rule, for egress id is null
ipAddress = _ipAddressDao.findById(ipAddrId);
// Validate ip address
if (ipAddress == null && type == FirewallRule.FirewallRuleType.User) {
throw new InvalidParameterValueException("Unable to create firewall rule; ip id=" + ipAddrId +
" doesn't exist in the system");
throw new InvalidParameterValueException("Unable to create firewall rule; " +
"couldn't locate IP address by id in the system");
}
_networkModel.checkIpForService(ipAddress, Service.Firewall, null);
}
_networkModel.checkIpForService(ipAddress, Service.Firewall, null);
validateFirewallRule(caller, ipAddress, portStart, portEnd, protocol, Purpose.Firewall, type);
validateFirewallRule(caller, ipAddress, portStart, portEnd, protocol, Purpose.Firewall, type, networkId, trafficType);
// icmp code and icmp type can't be passed in for any other protocol rather than icmp
if (!protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO) && (icmpCode != null || icmpType != null)) {
@ -205,15 +225,21 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ne
Long domainId = null;
if (ipAddress != null) {
//Ingress firewall rule
accountId = ipAddress.getAllocatedToAccountId();
domainId = ipAddress.getAllocatedInDomainId();
} else if (networkId != null) {
//egress firewall rule
Network network = _networkModel.getNetwork(networkId);
accountId = network.getAccountId();
domainId = network.getDomainId();
}
Transaction txn = Transaction.currentTxn();
txn.start();
FirewallRuleVO newRule = new FirewallRuleVO(xId, ipAddrId, portStart, portEnd, protocol.toLowerCase(), networkId,
accountId, domainId, Purpose.Firewall, sourceCidrList, icmpCode, icmpType, relatedRuleId, null);
accountId, domainId, Purpose.Firewall, sourceCidrList, icmpCode, icmpType, relatedRuleId, trafficType);
newRule.setType(type);
newRule = _firewallDao.persist(newRule);
@ -234,7 +260,9 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ne
public Pair<List<? extends FirewallRule>, Integer> listFirewallRules(ListFirewallRulesCmd cmd) {
Long ipId = cmd.getIpAddressId();
Long id = cmd.getId();
Long networkId = null;
Map<String, String> tags = cmd.getTags();
FirewallRule.TrafficType trafficType = cmd.getTrafficType();
Account caller = UserContext.current().getCaller();
List<Long> permittedAccounts = new ArrayList<Long>();
@ -258,7 +286,13 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ne
_accountMgr.buildACLSearchBuilder(sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);
sb.and("id", sb.entity().getId(), Op.EQ);
sb.and("trafficType", sb.entity().getTrafficType(), Op.EQ);
if (cmd instanceof ListEgressFirewallRulesCmd ) {
networkId =((ListEgressFirewallRulesCmd)cmd).getNetworkId();
sb.and("networkId", sb.entity().getNetworkId(), Op.EQ);
} else {
sb.and("ip", sb.entity().getSourceIpAddressId(), Op.EQ);
}
sb.and("purpose", sb.entity().getPurpose(), Op.EQ);
@ -293,9 +327,14 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ne
if (ipId != null) {
sc.setParameters("ip", ipId);
} else if (cmd instanceof ListEgressFirewallRulesCmd) {
if (networkId != null) {
sc.setParameters("networkId", networkId);
}
}
sc.setParameters("purpose", Purpose.Firewall);
sc.setParameters("trafficType", trafficType);
Pair<List<FirewallRuleVO>, Integer> result = _firewallDao.searchAndCount(sc, filter);
return new Pair<List<? extends FirewallRule>, Integer>(result.first(), result.second());
@ -303,10 +342,17 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ne
@Override
public void detectRulesConflict(FirewallRule newRule) throws NetworkRuleConflictException {
List<FirewallRuleVO> rules = _firewallDao.listByIpAndPurposeAndNotRevoked(newRule.getSourceIpAddressId(), null);
List<FirewallRuleVO> rules;
if(newRule.getSourceIpAddressId() != null){
rules = _firewallDao.listByIpAndPurposeAndNotRevoked(newRule.getSourceIpAddressId(), null);
assert (rules.size() >= 1) : "For network rules, we now always first persist the rule and then check for " +
"network conflicts so we should at least have one rule at this point.";
} else {
// fetches only firewall egress rules.
rules = _firewallDao.listByNetworkPurposeTrafficTypeAndNotRevoked(newRule.getNetworkId(), Purpose.Firewall, newRule.getTrafficType());
assert (rules.size() >= 1);
}
for (FirewallRuleVO rule : rules) {
if (rule.getId() == newRule.getId()) {
@ -394,7 +440,7 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ne
@Override
public void validateFirewallRule(Account caller, IPAddressVO ipAddress, Integer portStart, Integer portEnd,
String proto, Purpose purpose, FirewallRuleType type) {
String proto, Purpose purpose, FirewallRuleType type, Long networkId, FirewallRule.TrafficType trafficType ) {
if (portStart != null && !NetUtils.isValidPort(portStart)) {
throw new InvalidParameterValueException("publicPort is an invalid value: " + portStart);
}
@ -411,21 +457,23 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ne
return;
}
// Validate ip address
_accountMgr.checkAccess(caller, null, true, ipAddress);
Long networkId = null;
if (ipAddress!=null){
if (ipAddress.getAssociatedWithNetworkId() == null) {
throw new InvalidParameterValueException("Unable to create firewall rule ; ip id=" +
ipAddress.getId() + " is not associated with any network");
throw new InvalidParameterValueException("Unable to create firewall rule ; ip with specified id is not associated with any network");
} else {
networkId = ipAddress.getAssociatedWithNetworkId();
}
// Validate ip address
_accountMgr.checkAccess(caller, null, true, ipAddress);
Network network = _networkModel.getNetwork(networkId);
assert network != null : "Can't create port forwarding rule as network associated with public ip address is null?";
if (trafficType == FirewallRule.TrafficType.Egress) {
_accountMgr.checkAccess(caller, null, true, network);
}
// Verify that the network guru supports the protocol specified
Map<Network.Capability, String> caps = null;
@ -435,14 +483,30 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ne
}
} else if (purpose == Purpose.PortForwarding) {
caps = _networkModel.getNetworkServiceCapabilities(network.getId(), Service.PortForwarding);
}else if (purpose == Purpose.Firewall){
caps = _networkModel.getNetworkServiceCapabilities(network.getId(),Service.Firewall);
}
if (caps != null) {
String supportedProtocols = caps.get(Capability.SupportedProtocols).toLowerCase();
String supportedProtocols;
String supportedTrafficTypes = null;
if (purpose == FirewallRule.Purpose.Firewall) {
supportedTrafficTypes = caps.get(Capability.SupportedTrafficDirection).toLowerCase();
}
if (purpose == FirewallRule.Purpose.Firewall && trafficType == FirewallRule.TrafficType.Egress) {
supportedProtocols = caps.get(Capability.SupportedEgressProtocols).toLowerCase();
} else {
supportedProtocols = caps.get(Capability.SupportedProtocols).toLowerCase();
}
if (!supportedProtocols.contains(proto.toLowerCase())) {
throw new InvalidParameterValueException("Protocol " + proto + " is not supported in zone " + network.getDataCenterId());
} else if (proto.equalsIgnoreCase(NetUtils.ICMP_PROTO) && purpose != Purpose.Firewall) {
throw new InvalidParameterValueException("Protocol " + proto + " is currently supported only for rules with purpose " + Purpose.Firewall);
} else if (purpose == Purpose.Firewall && !supportedTrafficTypes.contains(trafficType.toString().toLowerCase())) {
throw new InvalidParameterValueException("Traffic Type " + trafficType + " is currently supported by Firewall in network " + networkId);
}
}
}
}
@ -536,11 +600,17 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ne
}
@Override
public boolean applyFirewallRules(long ipId, Account caller) throws ResourceUnavailableException {
public boolean applyIngressFirewallRules(long ipId, Account caller) throws ResourceUnavailableException {
List<FirewallRuleVO> rules = _firewallDao.listByIpAndPurpose(ipId, Purpose.Firewall);
return applyFirewallRules(rules, false, caller);
}
@Override
public boolean applyEgressFirewallRules (FirewallRule rule, Account caller) throws ResourceUnavailableException {
List<FirewallRuleVO> rules = _firewallDao.listByNetworkPurposeTrafficType(rule.getNetworkId(), Purpose.Firewall, FirewallRule.TrafficType.Egress);
return applyFirewallRules(rules, false, caller);
}
@Override
public boolean applyFirewallRules(List<FirewallRuleVO> rules, boolean continueOnError, Account caller) {
@ -588,10 +658,19 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ne
revokeRule(rule, caller, userId, false);
boolean success = false;
Long networkId = rule.getNetworkId();
if (apply) {
// ingress firewall rule
if (rule.getSourceIpAddressId() != null){
//feteches ingress firewall, ingress firewall rules associated with the ip
List<FirewallRuleVO> rules = _firewallDao.listByIpAndPurpose(rule.getSourceIpAddressId(), Purpose.Firewall);
return applyFirewallRules(rules, false, caller);
//egress firewall rule
} else if ( networkId != null){
List<FirewallRuleVO> rules = _firewallDao.listByNetworkPurposeTrafficType(rule.getNetworkId(), Purpose.Firewall, FirewallRule.TrafficType.Egress);
return applyFirewallRules(rules, false, caller);
}
} else {
success = true;
}
@ -686,7 +765,7 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ne
List<String> oneCidr = new ArrayList<String>();
oneCidr.add(NetUtils.ALL_CIDRS);
return createFirewallRule(ipAddrId, caller, null, startPort, endPort, protocol, oneCidr, icmpCode, icmpType,
relatedRuleId, FirewallRule.FirewallRuleType.User, networkId);
relatedRuleId, FirewallRule.FirewallRuleType.User, networkId, FirewallRule.TrafficType.Ingress);
}
@Override
@ -778,7 +857,7 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ne
for (Long ipId : ipsToReprogram) {
s_logger.debug("Applying firewall rules for ip address id=" + ipId + " as a part of vm expunge");
try {
success = success && applyFirewallRules(ipId, _accountMgr.getSystemAccount());
success = success && applyIngressFirewallRules(ipId, _accountMgr.getSystemAccount());
} catch (ResourceUnavailableException ex) {
s_logger.warn("Failed to apply port forwarding rules for ip id=" + ipId);
success = false;
@ -794,7 +873,7 @@ public class FirewallManagerImpl implements FirewallService, FirewallManager, Ne
for (FirewallRuleVO rule : systemRules) {
try {
this.createFirewallRule(ip.getId(), acct, rule.getXid(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getProtocol(),
rule.getSourceCidrList(), rule.getIcmpCode(), rule.getIcmpType(), rule.getRelated(), FirewallRuleType.System, rule.getNetworkId());
rule.getSourceCidrList(), rule.getIcmpCode(), rule.getIcmpType(), rule.getRelated(), FirewallRuleType.System, rule.getNetworkId(), rule.getTrafficType());
} catch (Exception e) {
s_logger.debug("Failed to add system wide firewall rule, due to:" + e.toString());
}

View File

@ -1054,9 +1054,6 @@ public class LoadBalancingRulesManagerImpl<Type> implements LoadBalancingRulesMa
throw ex;
}
_firewallMgr.validateFirewallRule(caller.getCaller(), ipAddr, srcPortStart, srcPortEnd, lb.getProtocol(),
Purpose.LoadBalancing, FirewallRuleType.User);
Long networkId = ipAddr.getAssociatedWithNetworkId();
if (networkId == null) {
InvalidParameterValueException ex = new InvalidParameterValueException("Unable to create load balancer rule ; specified sourceip id is not associated with any network");
@ -1064,6 +1061,10 @@ public class LoadBalancingRulesManagerImpl<Type> implements LoadBalancingRulesMa
throw ex;
}
_firewallMgr.validateFirewallRule(caller.getCaller(), ipAddr, srcPortStart, srcPortEnd, lb.getProtocol(),
Purpose.LoadBalancing, FirewallRuleType.User, networkId, null);
NetworkVO network = _networkDao.findById(networkId);
_accountMgr.checkAccess(caller.getCaller(), null, true, ipAddr);

View File

@ -40,8 +40,8 @@ import java.util.concurrent.TimeUnit;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import org.apache.cloudstack.api.command.admin.router.UpgradeRouterCmd;
import com.cloud.agent.api.to.*;
import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
@ -2224,13 +2224,25 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
s_logger.debug("Resending ipAssoc, port forwarding, load balancing rules as a part of Virtual router start");
ArrayList<? extends PublicIpAddress> publicIps = getPublicIpsToApply(router, provider, guestNetworkId);
List<FirewallRule> firewallRulesEgress = new ArrayList<FirewallRule>();
// Fetch firewall Egress rules.
if (_networkModel.isProviderSupportServiceInNetwork(guestNetworkId, Service.Firewall, provider)) {
firewallRulesEgress.addAll(_rulesDao.listByNetworkPurposeTrafficType(guestNetworkId, Purpose.Firewall,FirewallRule.TrafficType.Egress));
}
// Re-apply firewall Egress rules
s_logger.debug("Found " + firewallRulesEgress.size() + " firewall Egress rule(s) to apply as a part of domR " + router + " start.");
if (!firewallRulesEgress.isEmpty()) {
createFirewallRulesCommands(firewallRulesEgress, router, cmds, guestNetworkId);
}
if (publicIps != null && !publicIps.isEmpty()) {
List<RemoteAccessVpn> vpns = new ArrayList<RemoteAccessVpn>();
List<PortForwardingRule> pfRules = new ArrayList<PortForwardingRule>();
List<FirewallRule> staticNatFirewallRules = new ArrayList<FirewallRule>();
List<StaticNat> staticNats = new ArrayList<StaticNat>();
List<FirewallRule> firewallRules = new ArrayList<FirewallRule>();
List<FirewallRule> firewallRulesIngress = new ArrayList<FirewallRule>();
//Get information about all the rules (StaticNats and StaticNatRules; PFVPN to reapply on domR start)
for (PublicIpAddress ip : publicIps) {
@ -2241,7 +2253,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
staticNatFirewallRules.addAll(_rulesDao.listByIpAndPurpose(ip.getId(), Purpose.StaticNat));
}
if (_networkModel.isProviderSupportServiceInNetwork(guestNetworkId, Service.Firewall, provider)) {
firewallRules.addAll(_rulesDao.listByIpAndPurpose(ip.getId(), Purpose.Firewall));
firewallRulesIngress.addAll(_rulesDao.listByIpAndPurpose(ip.getId(), Purpose.Firewall));
}
if (_networkModel.isProviderSupportServiceInNetwork(guestNetworkId, Service.Vpn, provider)) {
@ -2260,16 +2272,16 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
}
}
//Re-apply static nats
// Re-apply static nats
s_logger.debug("Found " + staticNats.size() + " static nat(s) to apply as a part of domR " + router + " start.");
if (!staticNats.isEmpty()) {
createApplyStaticNatCommands(staticNats, router, cmds, guestNetworkId);
}
//Re-apply firewall rules
s_logger.debug("Found " + staticNats.size() + " firewall rule(s) to apply as a part of domR " + router + " start.");
if (!firewallRules.isEmpty()) {
createFirewallRulesCommands(firewallRules, router, cmds, guestNetworkId);
// Re-apply firewall Ingress rules
s_logger.debug("Found " + firewallRulesIngress.size() + " firewall Ingress rule(s) to apply as a part of domR " + router + " start.");
if (!firewallRulesIngress.isEmpty()) {
createFirewallRulesCommands(firewallRulesIngress, router, cmds, guestNetworkId);
}
// Re-apply port forwarding rules
@ -2926,7 +2938,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
int srcPort = rule.getSourcePortStart();
List<LbDestination> destinations = rule.getDestinations();
List<LbStickinessPolicy> stickinessPolicies = rule.getStickinessPolicies();
LoadBalancerTO lb = new LoadBalancerTO(uuid, srcIp, srcPort, protocol, algorithm, revoked, false, false, destinations, stickinessPolicies);
LoadBalancerTO lb = new LoadBalancerTO(uuid, srcIp, srcPort, protocol, algorithm, revoked, false, inline, destinations, stickinessPolicies);
lbs[i++] = lb;
}
String routerPublicIp = null;
@ -3254,10 +3266,18 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
if (rules != null) {
rulesTO = new ArrayList<FirewallRuleTO>();
for (FirewallRule rule : rules) {
FirewallRule.TrafficType traffictype = rule.getTrafficType();
if(traffictype == FirewallRule.TrafficType.Ingress){
IpAddress sourceIp = _networkModel.getIp(rule.getSourceIpAddressId());
FirewallRuleTO ruleTO = new FirewallRuleTO(rule, null, sourceIp.getAddress().addr());
FirewallRuleTO ruleTO = new FirewallRuleTO(rule, null, sourceIp.getAddress().addr(),Purpose.Firewall,traffictype);
rulesTO.add(ruleTO);
}
else if (rule.getTrafficType() == FirewallRule.TrafficType.Egress){
assert (rule.getSourceIpAddressId()==null) : "ipAddressId should be null for egress firewall rule. ";
FirewallRuleTO ruleTO = new FirewallRuleTO(rule, null,"",Purpose.Firewall,traffictype);
rulesTO.add(ruleTO);
}
}
}
SetFirewallRulesCommand cmd = new SetFirewallRulesCommand(rulesTO);

View File

@ -45,7 +45,7 @@ public interface FirewallManager extends FirewallService {
void detectRulesConflict(FirewallRule newRule) throws NetworkRuleConflictException;
void validateFirewallRule(Account caller, IPAddressVO ipAddress, Integer portStart, Integer portEnd, String proto,
Purpose purpose, FirewallRuleType type);
Purpose purpose, FirewallRuleType type, Long networkid, FirewallRule.TrafficType trafficType);
boolean applyRules(List<? extends FirewallRule> rules, boolean continueOnError, boolean updateRulesInDB) throws ResourceUnavailableException;
@ -68,8 +68,8 @@ public interface FirewallManager extends FirewallService {
*/
boolean revokeFirewallRule(long ruleId, boolean apply, Account caller, long userId);
FirewallRule createFirewallRule(long ipAddrId, Account caller, String xId, Integer portStart, Integer portEnd, String protocol, List<String> sourceCidrList, Integer icmpCode, Integer icmpType, Long relatedRuleId,
FirewallRule.FirewallRuleType type, long networkId)
FirewallRule createFirewallRule(Long ipAddrId, Account caller, String xId, Integer portStart, Integer portEnd, String protocol, List<String> sourceCidrList, Integer icmpCode, Integer icmpType, Long relatedRuleId,
FirewallRule.FirewallRuleType type, Long networkId, FirewallRule.TrafficType traffictype)
throws NetworkRuleConflictException;
FirewallRule createRuleForAllCidrs(long ipAddrId, Account caller, Integer startPort, Integer endPort, String protocol, Integer icmpCode, Integer icmpType, Long relatedRuleId, long networkId) throws NetworkRuleConflictException;

View File

@ -45,7 +45,7 @@ import org.apache.cloudstack.api.InternalIdentity;
@Table(name="firewall_rules")
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="purpose", discriminatorType=DiscriminatorType.STRING, length=32)
public class FirewallRuleVO implements FirewallRule {
public class FirewallRuleVO implements Identity, FirewallRule {
protected final FirewallRulesCidrsDaoImpl _firewallRulesCidrsDao = ComponentLocator.inject(FirewallRulesCidrsDaoImpl.class);
@Id
@ -87,7 +87,7 @@ public class FirewallRuleVO implements FirewallRule {
Date created;
@Column(name="network_id")
long networkId;
Long networkId;
@Column(name="icmp_code")
Integer icmpCode;
@ -209,11 +209,6 @@ public class FirewallRuleVO implements FirewallRule {
}
this.accountId = accountId;
this.domainId = domainId;
if (ipAddressId == null) {
assert (purpose == Purpose.NetworkACL) : "ipAddressId can be null for " + Purpose.NetworkACL + " only";
}
this.sourceIpAddressId = ipAddressId;
this.sourcePortStart = portStart;
this.sourcePortEnd = portEnd;

View File

@ -204,7 +204,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
try {
_firewallMgr.validateFirewallRule(caller, ipAddress, rule.getSourcePortStart(), rule.getSourcePortEnd(),
rule.getProtocol(), Purpose.PortForwarding, FirewallRuleType.User);
rule.getProtocol(), Purpose.PortForwarding, FirewallRuleType.User, networkId, rule.getTrafficType());
Long accountId = ipAddress.getAllocatedToAccountId();
Long domainId = ipAddress.getAllocatedInDomainId();
@ -323,7 +323,7 @@ public class RulesManagerImpl implements RulesManager, RulesService, Manager {
throw new NetworkRuleConflictException("Can't do static nat on ip address: " + ipAddress.getAddress());
}
_firewallMgr.validateFirewallRule(caller, ipAddress, rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getProtocol(), Purpose.StaticNat, FirewallRuleType.User);
_firewallMgr.validateFirewallRule(caller, ipAddress, rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getProtocol(), Purpose.StaticNat, FirewallRuleType.User,null, rule.getTrafficType() );
Long networkId = ipAddress.getAssociatedWithNetworkId();
Long accountId = ipAddress.getAllocatedToAccountId();

View File

@ -269,7 +269,7 @@ public class RemoteAccessVpnManagerImpl implements RemoteAccessVpnService, Manag
//now apply vpn rules on the backend
s_logger.debug("Reapplying firewall rules for ip id=" + ipId + " as a part of disable remote access vpn");
success = _firewallMgr.applyFirewallRules(ipId, caller);
success = _firewallMgr.applyIngressFirewallRules(ipId, caller);
}
if (success) {
@ -383,7 +383,7 @@ public class RemoteAccessVpnManagerImpl implements RemoteAccessVpnService, Manag
try {
boolean firewallOpened = true;
if (openFirewall) {
firewallOpened = _firewallMgr.applyFirewallRules(vpn.getServerAddressId(), caller);
firewallOpened = _firewallMgr.applyIngressFirewallRules(vpn.getServerAddressId(), caller);
}
if (firewallOpened) {

View File

@ -22,12 +22,22 @@ import com.cloud.utils.script.Script;
import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import org.apache.log4j.Logger;
/**
* @author htrippaers
*
*/
public class Upgrade40to41 implements DbUpgrade {
final static Logger s_logger = Logger.getLogger(Upgrade40to41.class);
/**
*
@ -78,7 +88,8 @@ public class Upgrade40to41 implements DbUpgrade {
*/
@Override
public void performDataMigration(Connection conn) {
upgradeEIPNetworkOfferings(conn);
upgradeEgressFirewallRules(conn);
}
/* (non-Javadoc)
@ -89,4 +100,104 @@ public class Upgrade40to41 implements DbUpgrade {
return new File[0];
}
private void upgradeEIPNetworkOfferings(Connection conn) {
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
pstmt = conn.prepareStatement("select id, elastic_ip_service from `cloud`.`network_offerings` where traffic_type='Guest'");
rs = pstmt.executeQuery();
while (rs.next()) {
long id = rs.getLong(1);
// check if elastic IP service is enabled for network offering
if (rs.getLong(2) != 0) {
//update network offering with eip_associate_public_ip set to true
pstmt = conn.prepareStatement("UPDATE `cloud`.`network_offerings` set eip_associate_public_ip=? where id=?");
pstmt.setBoolean(1, true);
pstmt.setLong(2, id);
pstmt.executeUpdate();
}
}
} catch (SQLException e) {
throw new CloudRuntimeException("Unable to set elastic_ip_service for network offerings with EIP service enabled.", e);
} finally {
try {
if (rs != null) {
rs.close();
}
if (pstmt != null) {
pstmt.close();
}
} catch (SQLException e) {
}
}
}
private void upgradeEgressFirewallRules(Connection conn) {
PreparedStatement pstmt = null;
ResultSet rs = null;
ResultSet rsId = null;
ResultSet rsNw = null;
try {
// update the existing ingress rules traffic type
pstmt = conn.prepareStatement("update `cloud`.`firewall_rules` set traffic_type='Ingress' where purpose='Firewall' and ip_address_id is not null and traffic_type is null");
s_logger.debug("Updating firewall Ingress rule traffic type: " + pstmt);
pstmt.executeUpdate();
pstmt = conn.prepareStatement("select network_id FROM `cloud`.`ntwk_service_map` where service='Firewall' and provider='VirtualRouter' ");
rs = pstmt.executeQuery();
while (rs.next()) {
long netId = rs.getLong(1);
//When upgraded from 2.2.14 to 3.0.6 guest_type is updated to Isolated in the 2214to30 clean up sql. clean up executes
//after this. So checking for Isolated OR Virtual
pstmt = conn.prepareStatement("select account_id, domain_id FROM `cloud`.`networks` where (guest_type='Isolated' OR guest_type='Virtual') and traffic_type='Guest' and vpc_id is NULL and (state='implemented' OR state='Shutdown') and id=? ");
pstmt.setLong(1, netId);
s_logger.debug("Getting account_id, domain_id from networks table: " + pstmt);
rsNw = pstmt.executeQuery();
if(rsNw.next()) {
long accountId = rsNw.getLong(1);
long domainId = rsNw.getLong(2);
//Add new rule for the existing networks
s_logger.debug("Adding default egress firewall rule for network " + netId);
pstmt = conn.prepareStatement("INSERT INTO firewall_rules (uuid, state, protocol, purpose, account_id, domain_id, network_id, xid, created, traffic_type) VALUES (?, 'Active', 'all', 'Firewall', ?, ?, ?, ?, now(), 'Egress')");
pstmt.setString(1, UUID.randomUUID().toString());
pstmt.setLong(2, accountId);
pstmt.setLong(3, domainId);
pstmt.setLong(4, netId);
pstmt.setString(5, UUID.randomUUID().toString());
s_logger.debug("Inserting default egress firewall rule " + pstmt);
pstmt.executeUpdate();
pstmt = conn.prepareStatement("select id from firewall_rules where protocol='all' and network_id=?");
pstmt.setLong(1, netId);
rsId = pstmt.executeQuery();
long firewallRuleId;
if(rsId.next()) {
firewallRuleId = rsId.getLong(1);
pstmt = conn.prepareStatement("insert into firewall_rules_cidrs (firewall_rule_id,source_cidr) values (?, '0.0.0.0/0')");
pstmt.setLong(1, firewallRuleId);
s_logger.debug("Inserting rule for cidr 0.0.0.0/0 for the new Firewall rule id=" + firewallRuleId + " with statement " + pstmt);
pstmt.executeUpdate();
}
}
}
} catch (SQLException e) {
throw new CloudRuntimeException("Unable to set egress firewall rules ", e);
} finally {
try {
if (rs != null) {
rs.close();
}
if (pstmt != null) {
pstmt.close();
}
} catch (SQLException e) {
}
}
}
}

View File

@ -32,6 +32,7 @@ import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.FirewallRuleVO;
import com.cloud.network.rules.FirewallRule.FirewallRuleType;
import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.network.rules.FirewallRule.TrafficType;
import com.cloud.user.Account;
import com.cloud.utils.Pair;
import com.cloud.utils.component.Manager;
@ -63,13 +64,6 @@ public class MockFirewallManagerImpl implements FirewallManager,
return null;
}
@Override
public FirewallRule createFirewallRule(FirewallRule rule)
throws NetworkRuleConflictException {
// TODO Auto-generated method stub
return null;
}
@Override
public Pair<List<? extends FirewallRule>, Integer> listFirewallRules(
ListFirewallRulesCmd cmd) {
@ -83,13 +77,6 @@ public class MockFirewallManagerImpl implements FirewallManager,
return false;
}
@Override
public boolean applyFirewallRules(long ipId, Account caller)
throws ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
}
@Override
public FirewallRule getFirewallRule(long ruleId) {
// TODO Auto-generated method stub
@ -109,14 +96,6 @@ public class MockFirewallManagerImpl implements FirewallManager,
}
@Override
public void validateFirewallRule(Account caller, IPAddressVO ipAddress,
Integer portStart, Integer portEnd, String proto, Purpose purpose,
FirewallRuleType type) {
// TODO Auto-generated method stub
}
@Override
public boolean applyRules(List<? extends FirewallRule> rules,
boolean continueOnError, boolean updateRulesInDB)
@ -153,16 +132,6 @@ public class MockFirewallManagerImpl implements FirewallManager,
return false;
}
@Override
public FirewallRule createFirewallRule(long ipAddrId, Account caller,
String xId, Integer portStart, Integer portEnd, String protocol,
List<String> sourceCidrList, Integer icmpCode, Integer icmpType,
Long relatedRuleId, FirewallRuleType type, long networkId)
throws NetworkRuleConflictException {
// TODO Auto-generated method stub
return null;
}
@Override
public FirewallRule createRuleForAllCidrs(long ipAddrId, Account caller,
Integer startPort, Integer endPort, String protocol,
@ -197,6 +166,52 @@ public class MockFirewallManagerImpl implements FirewallManager,
}
@Override
public FirewallRule createFirewallRule(Long ipAddrId, Account caller,
String xId, Integer portStart, Integer portEnd, String protocol,
List<String> sourceCidrList, Integer icmpCode, Integer icmpType,
Long relatedRuleId, FirewallRuleType type, Long networkId,
TrafficType traffictype) throws NetworkRuleConflictException {
// TODO Auto-generated method stub
return null;
}
@Override
public void validateFirewallRule(Account caller, IPAddressVO ipAddress,
Integer portStart, Integer portEnd, String proto, Purpose purpose,
FirewallRuleType type, Long networkid, TrafficType trafficType) {
// TODO Auto-generated method stub
}
@Override
public boolean applyEgressFirewallRules(FirewallRule rule, Account caller)
throws ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean applyIngressFirewallRules(long Ipid, Account caller)
throws ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
}
@Override
public FirewallRule createEgressFirewallRule(FirewallRule rule)
throws NetworkRuleConflictException {
// TODO Auto-generated method stub
return null;
}
@Override
public FirewallRule createIngressFirewallRule(FirewallRule rule)
throws NetworkRuleConflictException {
// TODO Auto-generated method stub
return null;
}
}